├── Makefile ├── README.md ├── convergence ├── filemonitor_convergence.py ├── live_plot_pcc_tcp_convergence.py ├── parameters_convergence.txt └── reset_convergence.py ├── demo_start_receiver.sh ├── demo_start_receiver_convergence.sh ├── filemonitor.py ├── live_plot_tcp_pcc.py ├── parameters.txt ├── receiver ├── LICENSE.txt ├── Makefile ├── app │ ├── Makefile │ ├── appclient.cpp │ ├── appserver.cpp │ ├── cc.h │ ├── cc_incast.h │ ├── incastserver.cpp │ ├── recvfile.cpp │ ├── sendfile.cpp │ ├── test.cpp │ └── test_util.h └── src │ ├── Makefile │ ├── api.cpp │ ├── api.h │ ├── buffer.cpp │ ├── buffer.h │ ├── cache.cpp │ ├── cache.h │ ├── ccc.cpp │ ├── ccc.h │ ├── channel.cpp │ ├── channel.h │ ├── common.cpp │ ├── common.h │ ├── core.cpp │ ├── core.h │ ├── epoll.cpp │ ├── epoll.h │ ├── list.cpp │ ├── list.h │ ├── md5.cpp │ ├── md5.h │ ├── packet.cpp │ ├── packet.h │ ├── queue.cpp │ ├── queue.h │ ├── udt.h │ ├── window.cpp │ └── window.h ├── run_demo_compare_tcp_and_pcc.sh ├── sender ├── LICENSE.txt ├── Makefile ├── app │ ├── Makefile │ ├── appclient.cpp │ ├── cc.h │ ├── cc_incast.h │ ├── cc_latency.h │ ├── cc_nosync.h │ ├── incast_client.cpp │ ├── recvfile.cpp │ ├── sendfile.cpp │ └── test.cpp └── src │ ├── Makefile │ ├── api.cpp │ ├── api.h │ ├── buffer.cpp │ ├── buffer.h │ ├── cache.cpp │ ├── cache.h │ ├── ccc.cpp │ ├── ccc.h │ ├── channel.cpp │ ├── channel.h │ ├── common.cpp │ ├── common.h │ ├── core.cpp │ ├── core.h │ ├── epoll.cpp │ ├── epoll.h │ ├── list.cpp │ ├── list.h │ ├── md5.cpp │ ├── md5.h │ ├── packet.cpp │ ├── packet.h │ ├── queue.cpp │ ├── queue.h │ ├── udt.h │ ├── window.cpp │ └── window.h ├── stop_demo_compare_tcp_and_pcc.sh ├── tune_bw_rtt_loss.py └── tune_bw_rtt_loss.sh /Makefile: -------------------------------------------------------------------------------- 1 | DIRS = sender receiver 2 | TARGETS = all clean install 3 | 4 | $(TARGETS): %: $(patsubst %, %.%, $(DIRS)) 5 | 6 | $(foreach TGT, $(TARGETS), $(patsubst %, %.$(TGT), $(DIRS))): 7 | $(MAKE) -C $(subst ., , $@) 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #PCC: Re-architecting Congestion Control for High Performance 2 | 3 | ###Read before use: 4 | The utility function in use in the current code base is a latency senstive one we are actively experimenting. To switch back to the default utility function, you just need one line of code change in cc.h. Uncomment cc.h:302 and comment out cc.h:303. And do a make clean;make (Proof of flexibility :)) 5 | 6 | ## How to use PCC 7 | 8 | ### Installation Guide 9 | Setup: 10 | For sender: 11 | 1. go to ./sender 12 | 13 | 2. make clean 14 | 15 | 3. make 16 | 17 | 4. export LD_LIBRARY_PATH=/path/to/install/sender/src 18 | 19 | For receiver: 20 | 21 | 1. go to ./receiver 22 | 23 | 2. make clean 24 | 25 | 3. make 26 | 27 | 4. export LD_LIBRARY_PATH=/path/to/install/receiver/src 28 | 29 | 30 | ### Replicate Demo with Emulab 31 | Comming soon 32 | 33 | ### Evaluate PCC in Your Network 34 | 1. Memory to Memory Data transfer speed test(without using disk): 35 | 36 | 1.1 On receiver, go to recever/app run ./appserver 37 | 38 | 1.2 On sender goto sender/app run ./appclient receiver's address 9000 2>monitor_log 39 | 40 | 2. File transfer software: 41 | 42 | 1.1 On receiver, run ./recvfile 43 | 44 | 1.2 on Sender, run ./sendfile dst_address 9000 file_to_send 2>monitor_log 45 | 46 | ## Known Issues 47 | 1. We recommend do test on FEDORA 15.0 STD system and a server with at least two cores, on which the performance is best. We have tested it on Unbuntu 12.04LTS and 14.04LTS, it normally works fine but there is an issue of UDP’s sendto() system call (sometimes sendto just slows down awfully) that may break the packet pacing PCC relies on. 48 | 49 | 2. Also, if you are running using a low-end CPU without constant time counter in hardware or running in a virtualized environment, especially KVM based VMs, please run it under static core binding using likwid-pin provided by google, otherwise, the timer will be messed up and the pacing will break. 50 | 51 | 3. You may notice that pacing is the main performance issue we have. You can turn on non_busy_waiting pacing in udt.h, it gives you inaccurate pacing but avoid PCC eating one core per flow. A better solution we are looking at is [SENIC](https://github.com/sivasankariit/qfq-rl). I would like to use SENIC to replace the pacing module of PCC. 52 | 53 | -------------------------------------------------------------------------------- /convergence/filemonitor_convergence.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | import logging 4 | from watchdog.observers import Observer 5 | from watchdog.events import FileSystemEventHandler 6 | import os 7 | class NewSnapshotEventHandler(FileSystemEventHandler): 8 | def __init__(self): 9 | self.flow1_start = False 10 | self.flow2_start = False 11 | 12 | def on_modified(self, event): 13 | if event.is_directory is True: 14 | return 15 | with open("./parameters_convergence.txt", "r") as f: 16 | param = f.read() 17 | lines = param.split("\n") 18 | for line in lines: 19 | # if line == "reset": 20 | # os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair3.UIUCScheduling.emulab.net \"killall appclient && echo "">/local/rate_pcc\"") 21 | # os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender2.demopair3.UIUCScheduling.emulab.net \"killall appclient && echo "">/local/rate_pcc\"") 22 | # os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair4.UIUCScheduling.emulab.net \"killall iperf && echo ""> /local/rate_tcp\"") 23 | # os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender2.demopair4.UIUCScheduling.emulab.net \"killall iperf && echo ""> /local/rate_tcp\"") 24 | # return 25 | if line != "": 26 | flow_name = line.split(" ")[0] 27 | action = line.split(" ")[1] 28 | if flow_name == "flow1": 29 | if self.flow1_start and action == "stop": 30 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair3.UIUCScheduling.emulab.net \"killall appclient\"") 31 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair4.UIUCScheduling.emulab.net \"killall iperf\"") 32 | self.flow1_start = False 33 | if not self.flow1_start and action == "start": 34 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair3.UIUCScheduling.emulab.net \"~/demo_run_pcc_convergence.sh 3 &\"") 35 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair4.UIUCScheduling.emulab.net \"~/demo_run_tcp_convergence.sh 3 &\"") 36 | self.flow1_start = True 37 | if flow_name == "flow2": 38 | if self.flow2_start and action == "stop": 39 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender2.demopair3.UIUCScheduling.emulab.net \"killall appclient\"") 40 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender2.demopair4.UIUCScheduling.emulab.net \"killall iperf\"") 41 | self.flow2_start = False 42 | if not self.flow2_start and action == "start": 43 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender2.demopair3.UIUCScheduling.emulab.net \"~/demo_run_pcc_convergence.sh 4 &\"") 44 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender2.demopair4.UIUCScheduling.emulab.net \"~/demo_run_tcp_convergence.sh 4 &\"") 45 | self.flow2_start = True 46 | 47 | 48 | if __name__ == "__main__": 49 | path = '.' 50 | event_handler = NewSnapshotEventHandler() 51 | observer = Observer() 52 | observer.daemon = True 53 | observer.schedule(event_handler, path, recursive=False) 54 | observer.start() 55 | try: 56 | while True: 57 | time.sleep(1) 58 | except KeyboardInterrupt: 59 | observer.stop() 60 | observer.join() 61 | -------------------------------------------------------------------------------- /convergence/live_plot_pcc_tcp_convergence.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import copy 3 | import matplotlib.animation as animation 4 | import time 5 | import os 6 | 7 | f, axarr = plt.subplots(2, 1, sharey=True, sharex=True) 8 | 9 | base_time_line = -1 10 | which_flow = 0 11 | 12 | time_offset = {} 13 | base_line = {} 14 | base_line["rate_tcp1"] = -1 15 | base_line["rate_tcp2"] = -1 16 | base_line["rate_pcc1"] = -1 17 | base_line["rate_pcc1"] = -1 18 | dataArray = {} 19 | 20 | def greater(a,b): 21 | if a == -1: 22 | return True 23 | if b == -1: 24 | return False 25 | return a>b 26 | 27 | def animate_together(i): 28 | os.system("scp modong2@sender1.demopair3.uiucscheduling.emulab.net:/local/rate_pcc /home/mo/pcc/convergence/rate_pcc1") 29 | os.system("scp modong2@sender2.demopair3.uiucscheduling.emulab.net:/local/rate_pcc /home/mo/pcc/convergence/rate_pcc2") 30 | os.system("scp modong2@sender1.demopair4.uiucscheduling.emulab.net:/local/rate_tcp /home/mo/pcc/convergence/rate_tcp1") 31 | os.system("scp modong2@sender2.demopair4.uiucscheduling.emulab.net:/local/rate_tcp /home/mo/pcc/convergence/rate_tcp2") 32 | 33 | pullData_tcp1 = open("rate_tcp1", "r") 34 | line = pullData_tcp1.readline() 35 | if line != "": 36 | base_line["tcp1"] = int(line) 37 | 38 | for k in range(6): 39 | pullData_tcp1.readline() 40 | dataArray["tcp1"] = pullData_tcp1.read().split("\n") 41 | pullData_tcp1.close() 42 | 43 | pullData_tcp2 = open("rate_tcp2", "r") 44 | line = pullData_tcp2.readline() 45 | if line != "": 46 | base_line["tcp2"] = int(line) 47 | 48 | for k in range(6): 49 | pullData_tcp2.readline() 50 | dataArray["tcp2"] = pullData_tcp2.read().split("\n") 51 | pullData_tcp2.close() 52 | 53 | pullData_pcc1 = open("rate_pcc1", "r") 54 | line = pullData_pcc1.readline() 55 | if line != "": 56 | base_line["pcc1"] = int(line) 57 | dataArray["pcc1"] = pullData_pcc1.read().split("\n") 58 | pullData_pcc1.close() 59 | 60 | 61 | pullData_pcc2 = open("rate_pcc2", "r") 62 | line = pullData_pcc2.readline() 63 | if line != "": 64 | base_line["pcc2"] = int(line) 65 | dataArray["pcc2"] = pullData_pcc2.read().split("\n") 66 | pullData_pcc2.close() 67 | base_point = -1 68 | 69 | for flow in base_line: 70 | if greater(base_point, base_line[flow]): 71 | base_point = base_line[flow] 72 | 73 | time_offset= copy.deepcopy(base_line) 74 | for flow in time_offset: 75 | time_offset[flow] = time_offset[flow] - base_point 76 | 77 | axarr[1].clear() 78 | axarr[1].set_xlabel("Time (s)") 79 | axarr[1].set_ylabel("Throughput (Mbit/s)") 80 | axarr[0].set_title("TCP convergence demo") 81 | axarr[0].clear() 82 | axarr[0].set_xlabel("Time (s)") 83 | axarr[0].set_ylabel("Throughput (Mbit/s)") 84 | axarr[0].set_title("PCC convergence demo") 85 | 86 | for flow in dataArray: 87 | xar = [] 88 | yar = [] 89 | if flow == "tcp1" or flow == "tcp2": 90 | for eachLine in dataArray[flow]: 91 | if eachLine != "": 92 | tmp = eachLine.split(" ") 93 | y = tmp[len(tmp)-2] 94 | yar.append(float(y)) 95 | for k in range(len(dataArray[flow])-1): 96 | xar.append(k+time_offset[flow]) 97 | axarr[1].plot(xar, yar) 98 | else: 99 | for eachLine in dataArray[flow]: 100 | if eachLine != "": 101 | x, y = eachLine.split(' ') 102 | xar.append(float(x) + time_offset[flow]) 103 | yar.append(float(y)) 104 | axarr[0].plot(xar, yar) 105 | 106 | 107 | ani = animation.FuncAnimation(f, animate_together, interval=2000) 108 | f.set_size_inches(8,6) 109 | mng = plt.get_current_fig_manager() 110 | plt.show() 111 | mng.frame.Maximize(True) 112 | -------------------------------------------------------------------------------- /convergence/parameters_convergence.txt: -------------------------------------------------------------------------------- 1 | flow1 stop 2 | flow2 stop 3 | 4 | -------------------------------------------------------------------------------- /convergence/reset_convergence.py: -------------------------------------------------------------------------------- 1 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair3.UIUCScheduling.emulab.net "killall appclient" 2 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair3.UIUCScheduling.emulab.net "rm /local/rate_pcc && touch /local/rate_pcc" 3 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender2.demopair3.UIUCScheduling.emulab.net "killall appclient" 4 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender2.demopair3.UIUCScheduling.emulab.net "rm /local/rate_pcc && touch /local/rate_pcc" 5 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair4.UIUCScheduling.emulab.net "killall iperf" 6 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair4.UIUCScheduling.emulab.net "rm /local/rate_tcp && touch /local/rate_tcp" 7 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender2.demopair4.UIUCScheduling.emulab.net "killall iperf" 8 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender2.demopair4.UIUCScheduling.emulab.net "rm /local/rate_tcp && touch /local/rate_tcp" 9 | -------------------------------------------------------------------------------- /demo_start_receiver.sh: -------------------------------------------------------------------------------- 1 | ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair2.uiucscheduling.emulab.net "killall iperf" 2 | ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair1.uiucscheduling.emulab.net "killall iperf" 3 | ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair2.uiucscheduling.emulab.net "~/demo_receiver_run.sh &" 4 | ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair1.uiucscheduling.emulab.net "~/demo_receiver_run.sh &" 5 | ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair1.uiucscheduling.emulab.net "nohup python ~/run_iperf.py &" 6 | ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair2.uiucscheduling.emulab.net "nohup python ~/run_iperf.py &" 7 | -------------------------------------------------------------------------------- /demo_start_receiver_convergence.sh: -------------------------------------------------------------------------------- 1 | for i in {1..4..1} 2 | do 3 | for j in {3..4..1} 4 | do 5 | ssh -t -t -o StrictHostKeyChecking=no modong2@receiver$i.demopair$j.uiucscheduling.emulab.net "killall iperf" 6 | ssh -t -t -o StrictHostKeyChecking=no modong2@receiver$i.demopair$j.uiucscheduling.emulab.net "~/demo_receiver_run.sh &" 7 | ssh -t -t -o StrictHostKeyChecking=no modong2@receiver$i.demopair$j.uiucscheduling.emulab.net "nohup python ~/run_iperf.py &" 8 | done 9 | done 10 | -------------------------------------------------------------------------------- /filemonitor.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | import logging 4 | from watchdog.observers import Observer 5 | from watchdog.events import FileSystemEventHandler 6 | import os 7 | class NewSnapshotEventHandler(FileSystemEventHandler): 8 | def __init__(self): 9 | self.param = {} 10 | self.param["Bandwidth"] = "100Mbit/s" 11 | self.param["RTT"] = "30ms" 12 | self.param["BufferSize"] = "50slots" 13 | self.param["LossRate"] = "0" 14 | self.is_start = False 15 | 16 | def on_modified(self, event): 17 | if event.is_directory is True: 18 | return 19 | with open("./parameters.txt", "r") as f: 20 | param = f.read() 21 | lines = param.split("\n") 22 | tmp_param = {} 23 | for line in lines: 24 | if line == "stop" and self.is_start: 25 | os.system("./stop_demo_compare_tcp_and_pcc.sh") 26 | self.is_start = False 27 | return 28 | elif line == "start" and not self.is_start: 29 | os.system("./run_demo_compare_tcp_and_pcc.sh") 30 | self.is_start = True 31 | elif line != "" and line !="start" and line != "stop": 32 | tmp_param[line.split(" ")[0]] = line.split(" ")[1] 33 | if tmp_param == self.param: 34 | return 35 | else: 36 | self.param = tmp_param 37 | if not self.is_start: 38 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair2.UIUCScheduling.emulab.net \"killall iperf && ./setup.bash {}\"".format(self.param["protocol"])) 39 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair2.UIUCScheduling.emulab.net \"nohup python ~/run_iperf.py &\"") 40 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair2.UIUCScheduling.emulab.net \"killall iperf && ./setup.bash {}\"".format(self.param["protocol"])) 41 | os.system("python ./tune_bw_rtt_loss.py -b {} -d {} -q {} -l {}".format(self.param["Bandwidth"], 42 | self.param["RTT"], 43 | self.param["BufferSize"], 44 | self.param["LossRate"])) 45 | 46 | if __name__ == "__main__": 47 | path = '.' 48 | event_handler = NewSnapshotEventHandler() 49 | observer = Observer() 50 | observer.daemon = True 51 | observer.schedule(event_handler, path, recursive=False) 52 | observer.start() 53 | try: 54 | while True: 55 | time.sleep(1) 56 | except KeyboardInterrupt: 57 | observer.stop() 58 | observer.join() 59 | -------------------------------------------------------------------------------- /live_plot_tcp_pcc.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import matplotlib.animation as animation 3 | import time 4 | import os 5 | 6 | f, axarr = plt.subplots(2, 1, sharey=True, sharex=False) 7 | 8 | def animate_tcp(i): 9 | os.system("scp modong2@sender1.congestion7.uiucscheduling.emulab.net:/local/rate /home/mo/pcc/rate") 10 | pullData = open("rate", "r") 11 | for k in range(6): 12 | pullData.readline() 13 | dataArray = pullData.read().split("\n") 14 | pullData.close() 15 | xar = [] 16 | yar = [] 17 | for eachLine in dataArray: 18 | if eachLine != "": 19 | tmp = eachLine.split(" ") 20 | y = tmp[len(tmp)-2] 21 | yar.append(float(y)) 22 | for k in range(len(dataArray)-1): 23 | xar.append(k*0.5) 24 | ax1.clear() 25 | ax1.plot(xar, yar) 26 | 27 | def animate2(i): 28 | os.system("scp modong2@sender1.congestion7.uiucscheduling.emulab.net:/local/utility /home/mo/pcc/utility") 29 | pullData = open("utility", "r") 30 | dataArray = pullData.read().split("\n") 31 | pullData.close() 32 | xar = [] 33 | yar1 = [] 34 | yar2 = [] 35 | seq = 1 36 | for eachLine in dataArray: 37 | if eachLine != "": 38 | y1 = eachLine.split('\t')[0] 39 | y2 = eachLine.split('\t')[1] 40 | xar.append(seq) 41 | seq = seq + 1 42 | yar1.append(float(y1)) 43 | yar2.append(float(y2)) 44 | ax1.clear() 45 | ax1.plot(xar, yar1, xar, yar2) 46 | 47 | 48 | 49 | 50 | 51 | def animate(i): 52 | os.system("scp modong2@sender1.congestion7.uiucscheduling.emulab.net:/local/rate /home/mo/pcc/rate") 53 | pullData = open("rate", "r") 54 | dataArray = pullData.read().split("\n") 55 | pullData.close() 56 | xar = [] 57 | yar = [] 58 | for eachLine in dataArray: 59 | if eachLine != "": 60 | x, y = eachLine.split(' ') 61 | xar.append(float(x)) 62 | yar.append(float(y)) 63 | ax1.clear() 64 | ax1.plot(xar, yar) 65 | 66 | 67 | counter = 0 68 | def animate_together(i): 69 | global counter 70 | #os.system("python ftpc.py sender1.demopair1.uiucscheduling.emulab.net 5050") 71 | #os.system("python ftpc.py sender1.demopair2.uiucscheduling.emulab.net 5050") 72 | counter = counter+1 73 | if counter == 1: 74 | print "clearing" 75 | axarr[1].clear() 76 | axarr[0].clear() 77 | axarr[1].set_xlabel("Time (s)") 78 | axarr[1].set_ylabel("Throughput (Mbit/s)") 79 | axarr[1].set_title("TCP's performance") 80 | axarr[0].set_xlabel("Time (s)") 81 | axarr[0].set_ylabel("Throughput (Mbit/s)") 82 | axarr[0].set_title("PCC's performance") 83 | counter = 0 84 | os.system("scp modong2@sender1.demopair1.uiucscheduling.emulab.net:/local/rate_pcc /home/mo/pcc/") 85 | os.system("scp modong2@sender1.demopair2.uiucscheduling.emulab.net:/local/rate_tcp /home/mo/pcc/") 86 | 87 | #os.system("scp modong2@155.98.38.139:/local/rate_pcc /home/mo/pcc/") 88 | #os.system("scp modong2@155.98.38.41:/local/rate_tcp /home/mo/pcc/") 89 | pullData_tcp = open("rate_tcp", "r") 90 | for k in range(6): 91 | pullData_tcp.readline() 92 | dataArray_tcp = pullData_tcp.read().split("\n") 93 | pullData_tcp.close() 94 | xar = [] 95 | yar = [] 96 | for eachLine in dataArray_tcp: 97 | if eachLine != "": 98 | tmp = eachLine.split(" ") 99 | y = tmp[len(tmp)-2] 100 | yar.append(float(y)) 101 | for k in range(len(dataArray_tcp)-1): 102 | xar.append(k) 103 | tcp = axarr[1].plot(xar, yar) 104 | plt.setp(tcp, color='b') 105 | avg_tcp = 1.0 106 | avg_pcc = 1.0 107 | if len(yar)>5: 108 | avg_tcp = sum(yar[-5:-1])/4 109 | 110 | pullData = open("rate_pcc", "r") 111 | dataArray = pullData.read().split("\n") 112 | pullData.close() 113 | xar = [] 114 | yar = [] 115 | #xar = [0, 0.5, 1, 1.5, 2.0, 2.5] 116 | #yar = [0, 37.3, 39.3, 37.2, 40.3, 42.9] 117 | count = 0 118 | for eachLine in dataArray: 119 | count = count+1 120 | if count > -1: 121 | if eachLine != "": 122 | x, y = eachLine.split(' ') 123 | xar.append(float(x)) 124 | yar.append(float(y)) 125 | if len(yar)>5: 126 | avg_pcc = sum(yar[-5:-1])/4 127 | 128 | if avg_tcp == 0: 129 | avg_tcp = 0.00001 130 | axarr[0].text(0.9, 1.1, 'improved by {:.2f}X'.format(avg_pcc/avg_tcp), 131 | verticalalignment='center', horizontalalignment='center', 132 | transform=axarr[0].transAxes, 133 | color='red', fontsize=15) 134 | axarr[0].text(0.8, 0.9, 'Tpt. {:.2f}Mps'.format(avg_pcc), 135 | verticalalignment='center', horizontalalignment='center', 136 | transform=axarr[0].transAxes, 137 | color='blue', fontsize=15) 138 | axarr[1].text(0.8, -0.3, 'Tpt. {:.2f}Mbps'.format(avg_tcp), 139 | verticalalignment='center', horizontalalignment='center', 140 | transform=axarr[0].transAxes, 141 | color='blue', fontsize=15) 142 | 143 | pcc = axarr[0].plot(xar, yar) 144 | plt.setp(pcc, color='b') 145 | 146 | axarr[1].clear() 147 | axarr[1].set_xlabel("Time (s)") 148 | axarr[1].set_ylabel("Throughput (Mbit/s)") 149 | axarr[1].set_title("TCP's performance") 150 | axarr[0].set_xlabel("Time (s)") 151 | axarr[0].set_ylabel("Throughput (Mbit/s)") 152 | axarr[0].set_title("PCC's performance") 153 | 154 | ani = animation.FuncAnimation(f, animate_together, interval=2000) 155 | plt.show() 156 | -------------------------------------------------------------------------------- /parameters.txt: -------------------------------------------------------------------------------- 1 | Bandwidth 120Mbit/s 2 | RTT 30ms 3 | BufferSize 75KB 4 | LossRate 0.01 5 | protocol cubic 6 | stop 7 | -------------------------------------------------------------------------------- /receiver/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above 9 | copyright notice, this list of conditions and the 10 | following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the 13 | above copyright notice, this list of conditions 14 | and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name of the University of Illinois 18 | nor the names of its contributors may be used to 19 | endorse or promote products derived from this 20 | software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 23 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 24 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /receiver/Makefile: -------------------------------------------------------------------------------- 1 | DIRS = src app 2 | TARGETS = all clean install 3 | 4 | $(TARGETS): %: $(patsubst %, %.%, $(DIRS)) 5 | 6 | $(foreach TGT, $(TARGETS), $(patsubst %, %.$(TGT), $(DIRS))): 7 | $(MAKE) -C $(subst ., , $@) 8 | -------------------------------------------------------------------------------- /receiver/app/Makefile: -------------------------------------------------------------------------------- 1 | C++ = g++ 2 | 3 | ifndef os 4 | os = LINUX 5 | endif 6 | 7 | ifndef arch 8 | arch = IA32 9 | endif 10 | 11 | CCFLAGS = -Wall -D$(os) -I../src -finline-functions -O3 12 | 13 | ifeq ($(arch), IA32) 14 | CCFLAGS += -DIA32 #-mcpu=pentiumpro -march=pentiumpro -mmmx -msse 15 | endif 16 | 17 | ifeq ($(arch), POWERPC) 18 | CCFLAGS += -mcpu=powerpc 19 | endif 20 | 21 | ifeq ($(arch), IA64) 22 | CCFLAGS += -DIA64 23 | endif 24 | 25 | ifeq ($(arch), SPARC) 26 | CCFLAGS += -DSPARC 27 | endif 28 | 29 | LDFLAGS = -L../src -ludt -lstdc++ -lpthread -lm 30 | 31 | ifeq ($(os), UNIX) 32 | LDFLAGS += -lsocket 33 | endif 34 | 35 | ifeq ($(os), SUNOS) 36 | LDFLAGS += -lrt -lsocket 37 | endif 38 | 39 | DIR = $(shell pwd) 40 | 41 | APP = appserver incastserver appclient sendfile recvfile test 42 | 43 | all: $(APP) 44 | 45 | %.o: %.cpp 46 | $(C++) $(CCFLAGS) $< -c 47 | 48 | appserver: appserver.o 49 | $(C++) $^ -o $@ $(LDFLAGS) 50 | incastserver: incastserver.o 51 | $(C++) $^ -o $@ $(LDFLAGS) 52 | appclient: appclient.o 53 | $(C++) $^ -o $@ $(LDFLAGS) 54 | sendfile: sendfile.o 55 | $(C++) $^ -o $@ $(LDFLAGS) 56 | recvfile: recvfile.o 57 | $(C++) $^ -o $@ $(LDFLAGS) 58 | test: test.o 59 | $(C++) $^ -o $@ $(LDFLAGS) 60 | 61 | clean: 62 | rm -f *.o $(APP) 63 | 64 | install: 65 | export PATH=$(DIR):$$PATH 66 | -------------------------------------------------------------------------------- /receiver/app/appclient.cpp: -------------------------------------------------------------------------------- 1 | #ifndef WIN32 2 | #include 3 | #include 4 | #include 5 | #include 6 | #else 7 | #include 8 | #include 9 | #include 10 | #endif 11 | #include 12 | #include 13 | #include "cc.h" 14 | #include "test_util.h" 15 | 16 | using namespace std; 17 | 18 | #ifndef WIN32 19 | void* monitor(void*); 20 | #else 21 | DWORD WINAPI monitor(LPVOID); 22 | #endif 23 | 24 | int main(int argc, char* argv[]) 25 | { 26 | if ((3 != argc) || (0 == atoi(argv[2]))) 27 | { 28 | cout << "usage: appclient server_ip server_port" << endl; 29 | return 0; 30 | } 31 | 32 | // Automatically start up and clean up UDT module. 33 | UDTUpDown _udt_; 34 | 35 | struct addrinfo hints, *local, *peer; 36 | 37 | memset(&hints, 0, sizeof(struct addrinfo)); 38 | 39 | hints.ai_flags = AI_PASSIVE; 40 | hints.ai_family = AF_INET; 41 | hints.ai_socktype = SOCK_STREAM; 42 | //hints.ai_socktype = SOCK_DGRAM; 43 | 44 | if (0 != getaddrinfo(NULL, "9000", &hints, &local)) 45 | { 46 | cout << "incorrect network address.\n" << endl; 47 | return 0; 48 | } 49 | 50 | UDTSOCKET client = UDT::socket(local->ai_family, local->ai_socktype, local->ai_protocol); 51 | 52 | // UDT Options 53 | //UDT::setsockopt(client, 0, UDT_CC, new CCCFactory, sizeof(CCCFactory)); 54 | //UDT::setsockopt(client, 0, UDT_MSS, new int(9000), sizeof(int)); 55 | //UDT::setsockopt(client, 0, UDT_SNDBUF, new int(10000000), sizeof(int)); 56 | //UDT::setsockopt(client, 0, UDP_SNDBUF, new int(10000000), sizeof(int)); 57 | //UDT::setsockopt(client, 0, UDT_MAXBW, new int64_t(12500000), sizeof(int)); 58 | 59 | // Windows UDP issue 60 | // For better performance, modify HKLM\System\CurrentControlSet\Services\Afd\Parameters\FastSendDatagramThreshold 61 | #ifdef WIN32 62 | UDT::setsockopt(client, 0, UDT_MSS, new int(1052), sizeof(int)); 63 | #endif 64 | 65 | // for rendezvous connection, enable the code below 66 | /* 67 | UDT::setsockopt(client, 0, UDT_RENDEZVOUS, new bool(true), sizeof(bool)); 68 | if (UDT::ERROR == UDT::bind(client, local->ai_addr, local->ai_addrlen)) 69 | { 70 | cout << "bind: " << UDT::getlasterror().getErrorMessage() << endl; 71 | return 0; 72 | } 73 | */ 74 | 75 | freeaddrinfo(local); 76 | 77 | if (0 != getaddrinfo(argv[1], argv[2], &hints, &peer)) 78 | { 79 | cout << "incorrect server/peer address. " << argv[1] << ":" << argv[2] << endl; 80 | return 0; 81 | } 82 | 83 | // connect to the server, implict bind 84 | if (UDT::ERROR == UDT::connect(client, peer->ai_addr, peer->ai_addrlen)) 85 | { 86 | cout << "connect: " << UDT::getlasterror().getErrorMessage() << endl; 87 | return 0; 88 | } 89 | 90 | freeaddrinfo(peer); 91 | 92 | // using CC method 93 | //CUDPBlast* cchandle = NULL; 94 | //int temp; 95 | //UDT::getsockopt(client, 0, UDT_CC, &cchandle, &temp); 96 | //if (NULL != cchandle) 97 | // cchandle->setRate(500); 98 | 99 | int size = 100000; 100 | char* data = new char[size]; 101 | 102 | #ifndef WIN32 103 | pthread_create(new pthread_t, NULL, monitor, &client); 104 | #else 105 | CreateThread(NULL, 0, monitor, &client, 0, NULL); 106 | #endif 107 | 108 | for (int i = 0; i < 1000000; i ++) 109 | { 110 | int ssize = 0; 111 | int ss; 112 | while (ssize < size) 113 | { 114 | if (UDT::ERROR == (ss = UDT::send(client, data + ssize, size - ssize, 0))) 115 | { 116 | cout << "send:" << UDT::getlasterror().getErrorMessage() << endl; 117 | break; 118 | } 119 | 120 | ssize += ss; 121 | } 122 | 123 | if (ssize < size) 124 | break; 125 | } 126 | 127 | UDT::close(client); 128 | delete [] data; 129 | return 0; 130 | } 131 | 132 | #ifndef WIN32 133 | void* monitor(void* s) 134 | #else 135 | DWORD WINAPI monitor(LPVOID s) 136 | #endif 137 | { 138 | UDTSOCKET u = *(UDTSOCKET*)s; 139 | 140 | UDT::TRACEINFO perf; 141 | 142 | cout << "SendRate(Mb/s)\tRTT(ms)\tCWnd\tPktSndPeriod(us)\tRecvACK\tRecvNAK" << endl; 143 | 144 | while (true) 145 | { 146 | #ifndef WIN32 147 | sleep(1); 148 | #else 149 | Sleep(1000); 150 | #endif 151 | 152 | if (UDT::ERROR == UDT::perfmon(u, &perf)) 153 | { 154 | cout << "perfmon: " << UDT::getlasterror().getErrorMessage() << endl; 155 | break; 156 | } 157 | 158 | cout << perf.mbpsSendRate << "\t\t" 159 | << perf.msRTT << "\t" 160 | << perf.pktCongestionWindow << "\t" 161 | << perf.usPktSndPeriod << "\t\t\t" 162 | << perf.pktRecvACK << "\t" 163 | << perf.pktRecvNAK << endl; 164 | } 165 | 166 | #ifndef WIN32 167 | return NULL; 168 | #else 169 | return 0; 170 | #endif 171 | } 172 | -------------------------------------------------------------------------------- /receiver/app/appserver.cpp: -------------------------------------------------------------------------------- 1 | #ifndef WIN32 2 | #include 3 | #include 4 | #include 5 | #include 6 | #else 7 | #include 8 | #include 9 | #include 10 | #endif 11 | #include 12 | #include 13 | #include "cc.h" 14 | #include "test_util.h" 15 | 16 | using namespace std; 17 | 18 | #ifndef WIN32 19 | void* recvdata(void*); 20 | void* monitor(void* s); 21 | #else 22 | DWORD WINAPI recvdata(LPVOID); 23 | #endif 24 | 25 | int main(int argc, char* argv[]) 26 | { 27 | if ((1 != argc) && ((2 != argc) || (0 == atoi(argv[1])))) 28 | { 29 | cout << "usage: appserver [server_port]" << endl; 30 | return 0; 31 | } 32 | 33 | // Automatically start up and clean up UDT module. 34 | UDTUpDown _udt_; 35 | 36 | addrinfo hints; 37 | addrinfo* res; 38 | 39 | memset(&hints, 0, sizeof(struct addrinfo)); 40 | 41 | hints.ai_flags = AI_PASSIVE; 42 | hints.ai_family = AF_INET; 43 | hints.ai_socktype = SOCK_STREAM; 44 | //hints.ai_socktype = SOCK_DGRAM; 45 | 46 | string service("9000"); 47 | if (2 == argc) 48 | service = argv[1]; 49 | 50 | if (0 != getaddrinfo(NULL, service.c_str(), &hints, &res)) 51 | { 52 | cout << "illegal port number or port is busy.\n" << endl; 53 | return 0; 54 | } 55 | 56 | UDTSOCKET serv = UDT::socket(res->ai_family, res->ai_socktype, res->ai_protocol); 57 | 58 | // UDT Options 59 | //UDT::setsockopt(serv, 0, UDT_CC, new CCCFactory, sizeof(CCCFactory)); 60 | //UDT::setsockopt(serv, 0, UDT_MSS, new int(9000), sizeof(int)); 61 | //UDT::setsockopt(serv, 0, UDT_RCVBUF, new int(10000000), sizeof(int)); 62 | //UDT::setsockopt(serv, 0, UDP_RCVBUF, new int(10000000), sizeof(int)); 63 | 64 | if (UDT::ERROR == UDT::bind(serv, res->ai_addr, res->ai_addrlen)) 65 | { 66 | cout << "bind: " << UDT::getlasterror().getErrorMessage() << endl; 67 | return 0; 68 | } 69 | 70 | freeaddrinfo(res); 71 | 72 | cout << "server is ready at port: " << service << endl; 73 | 74 | if (UDT::ERROR == UDT::listen(serv, 10)) 75 | { 76 | cout << "listen: " << UDT::getlasterror().getErrorMessage() << endl; 77 | return 0; 78 | } 79 | 80 | sockaddr_storage clientaddr; 81 | int addrlen = sizeof(clientaddr); 82 | 83 | UDTSOCKET recver; 84 | 85 | while (true) 86 | { 87 | if (UDT::INVALID_SOCK == (recver = UDT::accept(serv, (sockaddr*)&clientaddr, &addrlen))) 88 | { 89 | cout << "accept: " << UDT::getlasterror().getErrorMessage() << endl; 90 | return 0; 91 | } 92 | 93 | char clienthost[NI_MAXHOST]; 94 | char clientservice[NI_MAXSERV]; 95 | getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST|NI_NUMERICSERV); 96 | cout << "new connection: " << clienthost << ":" << clientservice << endl; 97 | 98 | #ifndef WIN32 99 | pthread_t rcvthread; 100 | pthread_create(&rcvthread, NULL, recvdata, new UDTSOCKET(recver)); 101 | pthread_detach(rcvthread); 102 | #else 103 | CreateThread(NULL, 0, recvdata, new UDTSOCKET(recver), 0, NULL); 104 | #endif 105 | } 106 | 107 | UDT::close(serv); 108 | 109 | return 0; 110 | } 111 | 112 | #ifndef WIN32 113 | void* recvdata(void* usocket) 114 | #else 115 | DWORD WINAPI recvdata(LPVOID usocket) 116 | #endif 117 | { 118 | UDTSOCKET recver = *(UDTSOCKET*)usocket; 119 | delete (UDTSOCKET*)usocket; 120 | pthread_create(new pthread_t, NULL, monitor, &recver); 121 | char* data; 122 | int size = 100000000; 123 | data = new char[size]; 124 | 125 | while (true) 126 | { 127 | int rsize = 0; 128 | int rs; 129 | while (rsize < size) 130 | { 131 | int rcv_size; 132 | int var_size = sizeof(int); 133 | UDT::getsockopt(recver, 0, UDT_RCVDATA, &rcv_size, &var_size); 134 | if (UDT::ERROR == (rs = UDT::recv(recver, data + rsize, size - rsize, 0))) 135 | { 136 | cout << "recv:" << UDT::getlasterror().getErrorMessage() << endl; 137 | break; 138 | } 139 | 140 | rsize += rs; 141 | } 142 | 143 | if (rsize < size) 144 | break; 145 | } 146 | 147 | delete [] data; 148 | 149 | UDT::close(recver); 150 | 151 | #ifndef WIN32 152 | return NULL; 153 | #else 154 | return 0; 155 | #endif 156 | } 157 | #ifndef WIN32 158 | void* monitor(void* s) 159 | #else 160 | DWORD WINAPI monitor(LPVOID s) 161 | #endif 162 | { 163 | UDTSOCKET u = *(UDTSOCKET*)s; 164 | 165 | UDT::TRACEINFO perf; 166 | 167 | cout << "SendRate(Mb/s)\tRTT(ms)\tCWnd\tPktSndPeriod(us)\tRecvACK\tRecvNAK" << endl; 168 | 169 | while (true) 170 | { 171 | #ifndef WIN32 172 | sleep(1); 173 | #else 174 | Sleep(1000); 175 | #endif 176 | 177 | if (UDT::ERROR == UDT::perfmon(u, &perf)) 178 | { 179 | cout << "perfmon: " << UDT::getlasterror().getErrorMessage() << endl; 180 | break; 181 | } 182 | 183 | //cout << perf.pktRecvTotal << "\t\t" 184 | // << perf.pktRecvNAKTotal << endl; 185 | } 186 | 187 | #ifndef WIN32 188 | return NULL; 189 | #else 190 | return 0; 191 | #endif 192 | } 193 | -------------------------------------------------------------------------------- /receiver/app/cc.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class CTCP: public CCC 5 | { 6 | public: 7 | void init() 8 | { 9 | m_bSlowStart = true; 10 | m_issthresh = 83333; 11 | 12 | m_dPktSndPeriod = 0.0; 13 | m_dCWndSize = 2.0; 14 | 15 | setACKInterval(2); 16 | setRTO(1000000); 17 | } 18 | 19 | virtual void onACK(const int& ack) 20 | { 21 | if (ack == m_iLastACK) 22 | { 23 | if (3 == ++ m_iDupACKCount) 24 | DupACKAction(); 25 | else if (m_iDupACKCount > 3) 26 | m_dCWndSize += 1.0; 27 | else 28 | ACKAction(); 29 | } 30 | else 31 | { 32 | if (m_iDupACKCount >= 3) 33 | m_dCWndSize = m_issthresh; 34 | 35 | m_iLastACK = ack; 36 | m_iDupACKCount = 1; 37 | 38 | ACKAction(); 39 | } 40 | } 41 | 42 | virtual void onTimeout() 43 | { 44 | m_issthresh = getPerfInfo()->pktFlightSize / 2; 45 | if (m_issthresh < 2) 46 | m_issthresh = 2; 47 | 48 | m_bSlowStart = true; 49 | m_dCWndSize = 2.0; 50 | } 51 | 52 | protected: 53 | virtual void ACKAction() 54 | { 55 | if (m_bSlowStart) 56 | { 57 | m_dCWndSize += 1.0; 58 | 59 | if (m_dCWndSize >= m_issthresh) 60 | m_bSlowStart = false; 61 | } 62 | else 63 | m_dCWndSize += 1.0/m_dCWndSize; 64 | } 65 | 66 | virtual void DupACKAction() 67 | { 68 | m_bSlowStart = false; 69 | 70 | m_issthresh = getPerfInfo()->pktFlightSize / 2; 71 | if (m_issthresh < 2) 72 | m_issthresh = 2; 73 | 74 | m_dCWndSize = m_issthresh + 3; 75 | } 76 | 77 | protected: 78 | int m_issthresh; 79 | bool m_bSlowStart; 80 | 81 | int m_iDupACKCount; 82 | int m_iLastACK; 83 | }; 84 | 85 | 86 | class CUDPBlast: public CCC 87 | { 88 | public: 89 | CUDPBlast() 90 | { 91 | m_dPktSndPeriod = 1000000; 92 | m_dCWndSize = 83333.0; 93 | } 94 | 95 | public: 96 | void setRate(double mbps) 97 | { 98 | m_dPktSndPeriod = (m_iMSS * 8.0) / mbps; 99 | } 100 | }; 101 | -------------------------------------------------------------------------------- /receiver/app/cc_incast.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | #include 6 | class CTCP: public CCC 7 | { 8 | 9 | public: 10 | 11 | int pktNum; 12 | void init() 13 | 14 | { first_time=1; 15 | m_bSlowStart = true; 16 | m_issthresh = 83333; 17 | old_seq=0; 18 | pktNum=0; 19 | m_dPktSndPeriod = 0.0; 20 | m_dCWndSize = 2.0; 21 | flag_receive=1; 22 | setACKInterval(1); 23 | setRTO(9000000); 24 | hastimeout=0; 25 | 26 | } 27 | 28 | virtual void onACK(const int& ack) 29 | { 30 | if (ack == m_iLastACK) 31 | { 32 | if (3 == ++ m_iDupACKCount) 33 | DupACKAction(); 34 | else if (m_iDupACKCount > 3) 35 | m_dCWndSize += 1.0; 36 | else 37 | ACKAction(); 38 | } 39 | else 40 | { 41 | if (m_iDupACKCount >= 3) 42 | m_dCWndSize = m_issthresh; 43 | 44 | m_iLastACK = ack; 45 | m_iDupACKCount = 1; 46 | 47 | ACKAction(); 48 | } 49 | } 50 | 51 | virtual void onTimeout() 52 | { 53 | cout<<"DINGDING@"<pktFlightSize / 2; 55 | if (m_issthresh < 2) 56 | m_issthresh = 2; 57 | 58 | m_bSlowStart = true; 59 | m_dCWndSize = 2.0; 60 | } 61 | 62 | protected: 63 | virtual void ACKAction() 64 | { 65 | if (m_bSlowStart) 66 | { 67 | m_dCWndSize += 1.0; 68 | 69 | if (m_dCWndSize >= m_issthresh) 70 | m_bSlowStart = false; 71 | } 72 | else 73 | m_dCWndSize += 1.0/m_dCWndSize; 74 | } 75 | 76 | virtual void DupACKAction() 77 | { 78 | m_bSlowStart = false; 79 | 80 | m_issthresh = getPerfInfo()->pktFlightSize / 2; 81 | if (m_issthresh < 2) 82 | m_issthresh = 2; 83 | 84 | m_dCWndSize = m_issthresh + 3; 85 | } 86 | int count; 87 | struct timeval show; 88 | 89 | virtual void onPktReceived(const CPacket* p){ //cout<m_iTimeStamp<m_iSeqNo-1; 92 | first_time=0; 93 | start=p->m_iSeqNo; 94 | count=0; 95 | gettimeofday(&begintime,NULL); 96 | } 97 | 98 | gettimeofday(&endtime ,NULL); 99 | 100 | } 101 | public: 102 | int m_issthresh; 103 | bool m_bSlowStart; 104 | int flag_receive; 105 | int m_iDupACKCount; 106 | int m_iLastACK; 107 | int32_t old_seq; 108 | int first_time; 109 | int32_t start; 110 | int32_t ends; 111 | int hastimeout; 112 | struct timeval endtime; 113 | struct timeval begintime; 114 | }; 115 | 116 | class CUDPBlast: public CCC 117 | { 118 | public: 119 | CUDPBlast() 120 | { 121 | m_dPktSndPeriod = 1000000; 122 | m_dCWndSize = 83333.0; 123 | } 124 | 125 | public: 126 | void setRate(double mbps) 127 | { 128 | m_dPktSndPeriod = (m_iMSS * 8.0) / mbps; 129 | } 130 | }; 131 | -------------------------------------------------------------------------------- /receiver/app/incastserver.cpp: -------------------------------------------------------------------------------- 1 | #ifndef WIN32 2 | #include 3 | #include 4 | #include 5 | #include 6 | #else 7 | #include 8 | #include 9 | #include 10 | #endif 11 | #include 12 | #include 13 | #include "cc_incast.h" 14 | 15 | using namespace std; 16 | 17 | #ifndef WIN32 18 | void* recvdata(void*); 19 | #else 20 | DWORD WINAPI recvdata(LPVOID); 21 | #endif 22 | 23 | 24 | int main(int argc, char* argv[]) 25 | { 26 | if ((1 != argc) && ((2 != argc) || (0 == atoi(argv[1])))) 27 | { 28 | cout << "usage: appserver [server_port]" << endl; 29 | return 0; 30 | } 31 | 32 | // use this function to initialize the UDT library 33 | UDT::startup(); 34 | 35 | addrinfo hints; 36 | addrinfo* res; 37 | 38 | memset(&hints, 0, sizeof(struct addrinfo)); 39 | 40 | hints.ai_flags = AI_PASSIVE; 41 | hints.ai_family = AF_INET; 42 | hints.ai_socktype = SOCK_STREAM; 43 | //hints.ai_socktype = SOCK_DGRAM; 44 | 45 | string service("9000"); 46 | if (2 == argc) 47 | service = argv[1]; 48 | 49 | if (0 != getaddrinfo(NULL, service.c_str(), &hints, &res)) 50 | { 51 | cout << "illegal port number or port is busy.\n" << endl; 52 | return 0; 53 | } 54 | 55 | UDTSOCKET serv = UDT::socket(res->ai_family, res->ai_socktype, res->ai_protocol); 56 | 57 | // UDT Options 58 | UDT::setsockopt(serv, 0, UDT_CC, new CCCFactory, sizeof(CCCFactory)); 59 | //UDT::setsockopt(serv, 0, UDT_MSS, new int(9000), sizeof(int)); 60 | //UDT::setsockopt(serv, 0, UDT_RCVBUF, new int(10000000), sizeof(int)); 61 | //UDT::setsockopt(serv, 0, UDP_RCVBUF, new int(10000000), sizeof(int)); 62 | 63 | if (UDT::ERROR == UDT::bind(serv, res->ai_addr, res->ai_addrlen)) 64 | { 65 | cout << "bind: " << UDT::getlasterror().getErrorMessage() << endl; 66 | return 0; 67 | } 68 | 69 | freeaddrinfo(res); 70 | 71 | cout << "server is ready at port: " << service << endl; 72 | 73 | if (UDT::ERROR == UDT::listen(serv, 10)) 74 | { 75 | cout << "listen: " << UDT::getlasterror().getErrorMessage() << endl; 76 | return 0; 77 | } 78 | 79 | sockaddr_storage clientaddr; 80 | int addrlen = sizeof(clientaddr); 81 | 82 | UDTSOCKET recver; 83 | 84 | while (true) 85 | { 86 | 87 | if (UDT::INVALID_SOCK == (recver = UDT::accept(serv, (sockaddr*)&clientaddr, &addrlen))) 88 | { 89 | cout << "accept: " << UDT::getlasterror().getErrorMessage() << endl; 90 | return 0; 91 | } 92 | 93 | char clienthost[NI_MAXHOST]; 94 | char clientservice[NI_MAXSERV]; 95 | getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST|NI_NUMERICSERV); 96 | //cout << "new connection: " << clienthost << ":" << clientservice << endl; 97 | 98 | #ifndef WIN32 99 | pthread_t rcvthread; 100 | pthread_create(&rcvthread, NULL, recvdata, new UDTSOCKET(recver)); 101 | pthread_detach(rcvthread); 102 | #else 103 | CreateThread(NULL, 0, recvdata, new UDTSOCKET(recver), 0, NULL); 104 | #endif 105 | } 106 | 107 | UDT::close(serv); 108 | 109 | // use this function to release the UDT library 110 | UDT::cleanup(); 111 | 112 | return 1; 113 | } 114 | 115 | #ifndef WIN32 116 | void* recvdata(void* usocket) 117 | #else 118 | DWORD WINAPI recvdata(LPVOID usocket) 119 | #endif 120 | { 121 | UDTSOCKET recver = *(UDTSOCKET*)usocket; 122 | delete (UDTSOCKET*)usocket; 123 | 124 | char* data; 125 | int size = 2000000; 126 | data = new char[size]; 127 | int count=0; 128 | CTCP* cchandle = NULL; 129 | int temp; 130 | UDT::getsockopt(recver, 0, UDT_CC, &cchandle, &temp); 131 | while (true) 132 | { 133 | int rsize = 0; 134 | int rs; 135 | // while (rsize < size) 136 | // { 137 | //usleep(1000000); 138 | if (UDT::ERROR == (rs = UDT::recv(recver, data + rsize, size - rsize, 0))) 139 | { 140 | // cout << "recv:" << UDT::getlasterror().getErrorMessage() << endl; 141 | break; 142 | } 143 | count+=rs/1456; 144 | //cout<hastimeout) 153 | //cout<ends<start<<","<ends<<","<begintime.tv_usec<<'.'<endtime.tv_usec< 3 | #include 4 | #else 5 | #include 6 | #include 7 | #endif 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | #ifndef WIN32 16 | void* sendfile(void*); 17 | #else 18 | DWORD WINAPI sendfile(LPVOID); 19 | #endif 20 | 21 | int main(int argc, char* argv[]) 22 | { 23 | if ((3 < argc) || ((2 == argc) && (0 == atoi(argv[1])))) 24 | { 25 | cout << "usage: recvfile [server_port] [bind_ip]" << endl; 26 | return 0; 27 | } 28 | 29 | // use this function to initialize the UDT library 30 | UDT::startup(); 31 | 32 | addrinfo hints; 33 | addrinfo* res; 34 | 35 | memset(&hints, 0, sizeof(struct addrinfo)); 36 | hints.ai_flags = AI_PASSIVE; 37 | hints.ai_family = AF_INET; 38 | hints.ai_socktype = SOCK_STREAM; 39 | 40 | string service("9000"); 41 | if (2 == argc) 42 | service = argv[1]; 43 | 44 | char * node = NULL; 45 | if (3 == argc) 46 | node = argv[2]; 47 | 48 | if (0 != getaddrinfo(node, service.c_str(), &hints, &res)) 49 | { 50 | cout << "illegal port number or port is busy.\n" << endl; 51 | return 0; 52 | } 53 | 54 | UDTSOCKET serv = UDT::socket(res->ai_family, res->ai_socktype, res->ai_protocol); 55 | 56 | // Windows UDP issue 57 | // For better performance, modify HKLM\System\CurrentControlSet\Services\Afd\Parameters\FastSendDatagramThreshold 58 | #ifdef WIN32 59 | int mss = 1052; 60 | UDT::setsockopt(serv, 0, UDT_MSS, &mss, sizeof(int)); 61 | #endif 62 | 63 | if (UDT::ERROR == UDT::bind(serv, res->ai_addr, res->ai_addrlen)) 64 | { 65 | cout << "bind: " << UDT::getlasterror().getErrorMessage() << endl; 66 | return 0; 67 | } 68 | 69 | freeaddrinfo(res); 70 | 71 | cout << "server is ready at port: " << service << endl; 72 | 73 | UDT::listen(serv, 10); 74 | 75 | sockaddr_storage clientaddr; 76 | int addrlen = sizeof(clientaddr); 77 | 78 | UDTSOCKET fhandle; 79 | 80 | while (true) 81 | { 82 | if (UDT::INVALID_SOCK == (fhandle = UDT::accept(serv, (sockaddr*)&clientaddr, &addrlen))) 83 | { 84 | cout << "accept: " << UDT::getlasterror().getErrorMessage() << endl; 85 | return 0; 86 | } 87 | 88 | char clienthost[NI_MAXHOST]; 89 | char clientservice[NI_MAXSERV]; 90 | getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST|NI_NUMERICSERV); 91 | cout << "new connection: " << clienthost << ":" << clientservice << endl; 92 | 93 | #ifndef WIN32 94 | pthread_t filethread; 95 | pthread_create(&filethread, NULL, sendfile, new UDTSOCKET(fhandle)); 96 | pthread_detach(filethread); 97 | #else 98 | CreateThread(NULL, 0, sendfile, new UDTSOCKET(fhandle), 0, NULL); 99 | #endif 100 | } 101 | 102 | UDT::close(serv); 103 | 104 | // use this function to release the UDT library 105 | UDT::cleanup(); 106 | 107 | return 0; 108 | } 109 | 110 | #ifndef WIN32 111 | void* sendfile(void* usocket) 112 | #else 113 | DWORD WINAPI sendfile(LPVOID usocket) 114 | #endif 115 | { 116 | UDTSOCKET fhandle = *(UDTSOCKET*)usocket; 117 | delete (UDTSOCKET*)usocket; 118 | 119 | // aquiring file name information from client 120 | char file[1024]="./file_received"; 121 | 122 | fstream ofs(file, ios::out | ios::binary | ios::trunc); 123 | 124 | // get size information 125 | int64_t size; 126 | 127 | if (UDT::ERROR == UDT::recv(fhandle, (char*)&size, sizeof(int64_t), 0)) 128 | { 129 | cout << "send: " << UDT::getlasterror().getErrorMessage() << endl; 130 | } 131 | 132 | if (size < 0) 133 | { 134 | cout << "no such file on the server\n"; 135 | } 136 | cout<<"size is "< 3 | #include 4 | #else 5 | #include 6 | #include 7 | #endif 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | #ifndef WIN32 16 | void* sendfile(void*); 17 | #else 18 | DWORD WINAPI sendfile(LPVOID); 19 | #endif 20 | 21 | int main(int argc, char* argv[]) 22 | { 23 | //usage: sendfile [server_port] 24 | if ((2 < argc) || ((2 == argc) && (0 == atoi(argv[1])))) 25 | { 26 | cout << "usage: sendfile [server_port]" << endl; 27 | return 0; 28 | } 29 | 30 | // use this function to initialize the UDT library 31 | UDT::startup(); 32 | 33 | addrinfo hints; 34 | addrinfo* res; 35 | 36 | memset(&hints, 0, sizeof(struct addrinfo)); 37 | hints.ai_flags = AI_PASSIVE; 38 | hints.ai_family = AF_INET; 39 | hints.ai_socktype = SOCK_STREAM; 40 | 41 | string service("9000"); 42 | if (2 == argc) 43 | service = argv[1]; 44 | 45 | if (0 != getaddrinfo(NULL, service.c_str(), &hints, &res)) 46 | { 47 | cout << "illegal port number or port is busy.\n" << endl; 48 | return 0; 49 | } 50 | 51 | UDTSOCKET serv = UDT::socket(res->ai_family, res->ai_socktype, res->ai_protocol); 52 | 53 | // Windows UDP issue 54 | // For better performance, modify HKLM\System\CurrentControlSet\Services\Afd\Parameters\FastSendDatagramThreshold 55 | #ifdef WIN32 56 | int mss = 1052; 57 | UDT::setsockopt(serv, 0, UDT_MSS, &mss, sizeof(int)); 58 | #endif 59 | 60 | if (UDT::ERROR == UDT::bind(serv, res->ai_addr, res->ai_addrlen)) 61 | { 62 | cout << "bind: " << UDT::getlasterror().getErrorMessage() << endl; 63 | return 0; 64 | } 65 | 66 | freeaddrinfo(res); 67 | 68 | cout << "server is ready at port: " << service << endl; 69 | 70 | UDT::listen(serv, 10); 71 | 72 | sockaddr_storage clientaddr; 73 | int addrlen = sizeof(clientaddr); 74 | 75 | UDTSOCKET fhandle; 76 | 77 | while (true) 78 | { 79 | if (UDT::INVALID_SOCK == (fhandle = UDT::accept(serv, (sockaddr*)&clientaddr, &addrlen))) 80 | { 81 | cout << "accept: " << UDT::getlasterror().getErrorMessage() << endl; 82 | return 0; 83 | } 84 | 85 | char clienthost[NI_MAXHOST]; 86 | char clientservice[NI_MAXSERV]; 87 | getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST|NI_NUMERICSERV); 88 | cout << "new connection: " << clienthost << ":" << clientservice << endl; 89 | 90 | #ifndef WIN32 91 | pthread_t filethread; 92 | pthread_create(&filethread, NULL, sendfile, new UDTSOCKET(fhandle)); 93 | pthread_detach(filethread); 94 | #else 95 | CreateThread(NULL, 0, sendfile, new UDTSOCKET(fhandle), 0, NULL); 96 | #endif 97 | } 98 | 99 | UDT::close(serv); 100 | 101 | // use this function to release the UDT library 102 | UDT::cleanup(); 103 | 104 | return 0; 105 | } 106 | 107 | #ifndef WIN32 108 | void* sendfile(void* usocket) 109 | #else 110 | DWORD WINAPI sendfile(LPVOID usocket) 111 | #endif 112 | { 113 | UDTSOCKET fhandle = *(UDTSOCKET*)usocket; 114 | delete (UDTSOCKET*)usocket; 115 | 116 | // aquiring file name information from client 117 | char file[1024]; 118 | int len; 119 | 120 | if (UDT::ERROR == UDT::recv(fhandle, (char*)&len, sizeof(int), 0)) 121 | { 122 | cout << "recv: " << UDT::getlasterror().getErrorMessage() << endl; 123 | return 0; 124 | } 125 | 126 | if (UDT::ERROR == UDT::recv(fhandle, file, len, 0)) 127 | { 128 | cout << "recv: " << UDT::getlasterror().getErrorMessage() << endl; 129 | return 0; 130 | } 131 | file[len] = '\0'; 132 | 133 | // open the file 134 | fstream ifs(file, ios::in | ios::binary); 135 | 136 | ifs.seekg(0, ios::end); 137 | int64_t size = ifs.tellg(); 138 | ifs.seekg(0, ios::beg); 139 | 140 | // send file size information 141 | if (UDT::ERROR == UDT::send(fhandle, (char*)&size, sizeof(int64_t), 0)) 142 | { 143 | cout << "send: " << UDT::getlasterror().getErrorMessage() << endl; 144 | return 0; 145 | } 146 | 147 | UDT::TRACEINFO trace; 148 | UDT::perfmon(fhandle, &trace); 149 | 150 | // send the file 151 | int64_t offset = 0; 152 | if (UDT::ERROR == UDT::sendfile(fhandle, ifs, offset, size)) 153 | { 154 | cout << "sendfile: " << UDT::getlasterror().getErrorMessage() << endl; 155 | return 0; 156 | } 157 | 158 | UDT::perfmon(fhandle, &trace); 159 | cout << "speed = " << trace.mbpsSendRate << "Mbits/sec" << endl; 160 | 161 | UDT::close(fhandle); 162 | 163 | ifs.close(); 164 | 165 | #ifndef WIN32 166 | return NULL; 167 | #else 168 | return 0; 169 | #endif 170 | } 171 | -------------------------------------------------------------------------------- /receiver/app/test_util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UDT_TEST_UTIL_H_ 2 | #define _UDT_TEST_UTIL_H_ 3 | 4 | struct UDTUpDown{ 5 | UDTUpDown() 6 | { 7 | // use this function to initialize the UDT library 8 | UDT::startup(); 9 | } 10 | ~UDTUpDown() 11 | { 12 | // use this function to release the UDT library 13 | UDT::cleanup(); 14 | } 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /receiver/src/Makefile: -------------------------------------------------------------------------------- 1 | C++ = g++ 2 | 3 | ifndef os 4 | os = LINUX 5 | endif 6 | 7 | ifndef arch 8 | arch = IA32 9 | endif 10 | 11 | CCFLAGS = -fPIC -Wall -Wextra -D$(os) -finline-functions -O3 -fno-strict-aliasing -fvisibility=hidden 12 | 13 | ifeq ($(arch), IA32) 14 | CCFLAGS += -DIA32 15 | endif 16 | 17 | ifeq ($(arch), POWERPC) 18 | CCFLAGS += -mcpu=powerpc 19 | endif 20 | 21 | ifeq ($(arch), SPARC) 22 | CCFLAGS += -DSPARC 23 | endif 24 | 25 | ifeq ($(arch), IA64) 26 | CCFLAGS += -DIA64 27 | endif 28 | 29 | ifeq ($(arch), AMD64) 30 | CCFLAGS += -DAMD64 31 | endif 32 | 33 | OBJS = api.o buffer.o cache.o ccc.o channel.o common.o core.o epoll.o list.o md5.o packet.o queue.o window.o 34 | DIR = $(shell pwd) 35 | 36 | all: libudt.so libudt.a udt 37 | 38 | %.o: %.cpp %.h udt.h 39 | $(C++) $(CCFLAGS) $< -c 40 | 41 | libudt.so: $(OBJS) 42 | ifneq ($(os), OSX) 43 | $(C++) -shared -o $@ $^ 44 | else 45 | $(C++) -dynamiclib -o libudt.dylib -lstdc++ -lpthread -lm $^ 46 | endif 47 | 48 | libudt.a: $(OBJS) 49 | ar -rcs $@ $^ 50 | 51 | udt: 52 | cp udt.h udt 53 | 54 | clean: 55 | rm -f *.o *.so *.dylib *.a udt 56 | 57 | install: 58 | export LD_LIBRARY_PATH=$(DIR):$$LD_LIBRARY_PATH 59 | -------------------------------------------------------------------------------- /receiver/src/cache.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 05/05/2009 39 | *****************************************************************************/ 40 | 41 | #ifdef WIN32 42 | #include 43 | #include 44 | #ifdef LEGACY_WIN32 45 | #include 46 | #endif 47 | #endif 48 | 49 | #include 50 | #include "cache.h" 51 | #include "core.h" 52 | 53 | using namespace std; 54 | 55 | CInfoBlock& CInfoBlock::operator=(const CInfoBlock& obj) 56 | { 57 | std::copy(obj.m_piIP, obj.m_piIP + 3, m_piIP); 58 | m_iIPversion = obj.m_iIPversion; 59 | m_ullTimeStamp = obj.m_ullTimeStamp; 60 | m_iRTT = obj.m_iRTT; 61 | m_iBandwidth = obj.m_iBandwidth; 62 | m_iLossRate = obj.m_iLossRate; 63 | m_iReorderDistance = obj.m_iReorderDistance; 64 | m_dInterval = obj.m_dInterval; 65 | m_dCWnd = obj.m_dCWnd; 66 | 67 | return *this; 68 | } 69 | 70 | bool CInfoBlock::operator==(const CInfoBlock& obj) 71 | { 72 | if (m_iIPversion != obj.m_iIPversion) 73 | return false; 74 | 75 | else if (m_iIPversion == AF_INET) 76 | return (m_piIP[0] == obj.m_piIP[0]); 77 | 78 | for (int i = 0; i < 4; ++ i) 79 | { 80 | if (m_piIP[i] != obj.m_piIP[i]) 81 | return false; 82 | } 83 | 84 | return true; 85 | } 86 | 87 | CInfoBlock* CInfoBlock::clone() 88 | { 89 | CInfoBlock* obj = new CInfoBlock; 90 | 91 | std::copy(m_piIP, m_piIP + 3, obj->m_piIP); 92 | obj->m_iIPversion = m_iIPversion; 93 | obj->m_ullTimeStamp = m_ullTimeStamp; 94 | obj->m_iRTT = m_iRTT; 95 | obj->m_iBandwidth = m_iBandwidth; 96 | obj->m_iLossRate = m_iLossRate; 97 | obj->m_iReorderDistance = m_iReorderDistance; 98 | obj->m_dInterval = m_dInterval; 99 | obj->m_dCWnd = m_dCWnd; 100 | 101 | return obj; 102 | } 103 | 104 | int CInfoBlock::getKey() 105 | { 106 | if (m_iIPversion == AF_INET) 107 | return m_piIP[0]; 108 | 109 | return m_piIP[0] + m_piIP[1] + m_piIP[2] + m_piIP[3]; 110 | } 111 | 112 | void CInfoBlock::convert(const sockaddr* addr, int ver, uint32_t ip[]) 113 | { 114 | if (ver == AF_INET) 115 | { 116 | ip[0] = ((sockaddr_in*)addr)->sin_addr.s_addr; 117 | ip[1] = ip[2] = ip[3] = 0; 118 | } 119 | else 120 | { 121 | memcpy((char*)ip, (char*)((sockaddr_in6*)addr)->sin6_addr.s6_addr, 16); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /receiver/src/cache.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/27/2011 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_CACHE_H__ 42 | #define __UDT_CACHE_H__ 43 | 44 | #include 45 | #include 46 | 47 | #include "common.h" 48 | #include "udt.h" 49 | 50 | class CCacheItem 51 | { 52 | public: 53 | virtual ~CCacheItem() {} 54 | 55 | public: 56 | virtual CCacheItem& operator=(const CCacheItem&) = 0; 57 | 58 | // The "==" operator SHOULD only compare key values. 59 | virtual bool operator==(const CCacheItem&) = 0; 60 | 61 | // Functionality: 62 | // get a deep copy clone of the current item 63 | // Parameters: 64 | // None. 65 | // Returned value: 66 | // Pointer to the new item, or NULL if failed. 67 | 68 | virtual CCacheItem* clone() = 0; 69 | 70 | // Functionality: 71 | // get a random key value between 0 and MAX_INT to be used for the hash in cache 72 | // Parameters: 73 | // None. 74 | // Returned value: 75 | // A random hash key. 76 | 77 | virtual int getKey() = 0; 78 | 79 | // If there is any shared resources between the cache item and its clone, 80 | // the shared resource should be released by this function. 81 | virtual void release() {} 82 | }; 83 | 84 | template class CCache 85 | { 86 | public: 87 | CCache(int size = 1024): 88 | m_iMaxSize(size), 89 | m_iHashSize(size * 3), 90 | m_iCurrSize(0) 91 | { 92 | m_vHashPtr.resize(m_iHashSize); 93 | CGuard::createMutex(m_Lock); 94 | } 95 | 96 | ~CCache() 97 | { 98 | clear(); 99 | CGuard::releaseMutex(m_Lock); 100 | } 101 | 102 | public: 103 | // Functionality: 104 | // find the matching item in the cache. 105 | // Parameters: 106 | // 0) [in/out] data: storage for the retrieved item; initially it must carry the key information 107 | // Returned value: 108 | // 0 if found a match, otherwise -1. 109 | 110 | int lookup(T* data) 111 | { 112 | CGuard cacheguard(m_Lock); 113 | 114 | int key = data->getKey(); 115 | if (key < 0) 116 | return -1; 117 | if (key >= m_iMaxSize) 118 | key %= m_iHashSize; 119 | 120 | const ItemPtrList& item_list = m_vHashPtr[key]; 121 | for (typename ItemPtrList::const_iterator i = item_list.begin(); i != item_list.end(); ++ i) 122 | { 123 | if (*data == ***i) 124 | { 125 | // copy the cached info 126 | *data = ***i; 127 | return 0; 128 | } 129 | } 130 | 131 | return -1; 132 | } 133 | 134 | // Functionality: 135 | // update an item in the cache, or insert one if it doesn't exist; oldest item may be removed 136 | // Parameters: 137 | // 0) [in] data: the new item to updated/inserted to the cache 138 | // Returned value: 139 | // 0 if success, otherwise -1. 140 | 141 | int update(T* data) 142 | { 143 | CGuard cacheguard(m_Lock); 144 | 145 | int key = data->getKey(); 146 | if (key < 0) 147 | return -1; 148 | if (key >= m_iMaxSize) 149 | key %= m_iHashSize; 150 | 151 | T* curr = NULL; 152 | 153 | ItemPtrList& item_list = m_vHashPtr[key]; 154 | for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i) 155 | { 156 | if (*data == ***i) 157 | { 158 | // update the existing entry with the new value 159 | ***i = *data; 160 | curr = **i; 161 | 162 | // remove the current entry 163 | m_StorageList.erase(*i); 164 | item_list.erase(i); 165 | 166 | // re-insert to the front 167 | m_StorageList.push_front(curr); 168 | item_list.push_front(m_StorageList.begin()); 169 | 170 | return 0; 171 | } 172 | } 173 | 174 | // create new entry and insert to front 175 | curr = data->clone(); 176 | m_StorageList.push_front(curr); 177 | item_list.push_front(m_StorageList.begin()); 178 | 179 | ++ m_iCurrSize; 180 | if (m_iCurrSize >= m_iMaxSize) 181 | { 182 | // Cache overflow, remove oldest entry. 183 | T* last_data = m_StorageList.back(); 184 | int last_key = last_data->getKey() % m_iHashSize; 185 | 186 | item_list = m_vHashPtr[last_key]; 187 | for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i) 188 | { 189 | if (*last_data == ***i) 190 | { 191 | item_list.erase(i); 192 | break; 193 | } 194 | } 195 | 196 | last_data->release(); 197 | delete last_data; 198 | m_StorageList.pop_back(); 199 | -- m_iCurrSize; 200 | } 201 | 202 | return 0; 203 | } 204 | 205 | // Functionality: 206 | // Specify the cache size (i.e., max number of items). 207 | // Parameters: 208 | // 0) [in] size: max cache size. 209 | // Returned value: 210 | // None. 211 | 212 | void setSizeLimit(int size) 213 | { 214 | m_iMaxSize = size; 215 | m_iHashSize = size * 3; 216 | m_vHashPtr.resize(m_iHashSize); 217 | } 218 | 219 | // Functionality: 220 | // Clear all entries in the cache, restore to initialization state. 221 | // Parameters: 222 | // None. 223 | // Returned value: 224 | // None. 225 | 226 | void clear() 227 | { 228 | for (typename std::list::iterator i = m_StorageList.begin(); i != m_StorageList.end(); ++ i) 229 | { 230 | (*i)->release(); 231 | delete *i; 232 | } 233 | m_StorageList.clear(); 234 | for (typename std::vector::iterator i = m_vHashPtr.begin(); i != m_vHashPtr.end(); ++ i) 235 | i->clear(); 236 | m_iCurrSize = 0; 237 | } 238 | 239 | private: 240 | std::list m_StorageList; 241 | typedef typename std::list::iterator ItemPtr; 242 | typedef std::list ItemPtrList; 243 | std::vector m_vHashPtr; 244 | 245 | int m_iMaxSize; 246 | int m_iHashSize; 247 | int m_iCurrSize; 248 | 249 | pthread_mutex_t m_Lock; 250 | 251 | private: 252 | CCache(const CCache&); 253 | CCache& operator=(const CCache&); 254 | }; 255 | 256 | 257 | class CInfoBlock 258 | { 259 | public: 260 | uint32_t m_piIP[4]; // IP address, machine read only, not human readable format 261 | int m_iIPversion; // IP version 262 | uint64_t m_ullTimeStamp; // last update time 263 | int m_iRTT; // RTT 264 | int m_iBandwidth; // estimated bandwidth 265 | int m_iLossRate; // average loss rate 266 | int m_iReorderDistance; // packet reordering distance 267 | double m_dInterval; // inter-packet time, congestion control 268 | double m_dCWnd; // congestion window size, congestion control 269 | 270 | public: 271 | virtual ~CInfoBlock() {} 272 | virtual CInfoBlock& operator=(const CInfoBlock& obj); 273 | virtual bool operator==(const CInfoBlock& obj); 274 | virtual CInfoBlock* clone(); 275 | virtual int getKey(); 276 | virtual void release() {} 277 | 278 | public: 279 | 280 | // Functionality: 281 | // convert sockaddr structure to an integer array 282 | // Parameters: 283 | // 0) [in] addr: network address 284 | // 1) [in] ver: IP version 285 | // 2) [out] ip: the result machine readable IP address in integer array 286 | // Returned value: 287 | // None. 288 | 289 | static void convert(const sockaddr* addr, int ver, uint32_t ip[]); 290 | }; 291 | 292 | 293 | #endif 294 | -------------------------------------------------------------------------------- /receiver/src/ccc.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 02/21/2013 39 | *****************************************************************************/ 40 | 41 | 42 | #include "core.h" 43 | #include "ccc.h" 44 | #include 45 | #include 46 | 47 | CCC::CCC(): 48 | m_iSYNInterval(CUDT::m_iSYNInterval), 49 | m_dPktSndPeriod(1.0), 50 | m_dCWndSize(10000.0), 51 | m_iBandwidth(), 52 | m_dMaxCWndSize(), 53 | m_iMSS(), 54 | m_iSndCurrSeqNo(), 55 | m_iRcvRate(), 56 | m_iRTT(), 57 | m_pcParam(NULL), 58 | m_iPSize(0), 59 | m_UDT(), 60 | m_iACKPeriod(0), 61 | m_iACKInterval(0), 62 | m_bUserDefinedRTO(false), 63 | m_iRTO(-1), 64 | m_PerfInfo() 65 | { 66 | } 67 | 68 | CCC::~CCC() 69 | { 70 | delete [] m_pcParam; 71 | } 72 | 73 | void CCC::setACKTimer(int msINT) 74 | { 75 | m_iACKPeriod = msINT > m_iSYNInterval ? m_iSYNInterval : msINT; 76 | } 77 | 78 | void CCC::setACKInterval(int pktINT) 79 | { 80 | m_iACKInterval = pktINT; 81 | } 82 | 83 | void CCC::setRTO(int usRTO) 84 | { 85 | m_bUserDefinedRTO = true; 86 | m_iRTO = usRTO; 87 | } 88 | 89 | void CCC::sendCustomMsg(CPacket& pkt) const 90 | { 91 | CUDT* u = CUDT::getUDTHandle(m_UDT); 92 | 93 | if (NULL != u) 94 | { 95 | pkt.m_iID = u->m_PeerID; 96 | u->m_pSndQueue->sendto(u->m_pPeerAddr, pkt); 97 | } 98 | } 99 | 100 | const CPerfMon* CCC::getPerfInfo() 101 | { 102 | try 103 | { 104 | CUDT* u = CUDT::getUDTHandle(m_UDT); 105 | if (NULL != u) 106 | u->sample(&m_PerfInfo, false); 107 | } 108 | catch (...) 109 | { 110 | return NULL; 111 | } 112 | 113 | return &m_PerfInfo; 114 | } 115 | 116 | void CCC::setMSS(int mss) 117 | { 118 | m_iMSS = mss; 119 | } 120 | 121 | void CCC::setBandwidth(int bw) 122 | { 123 | m_iBandwidth = bw; 124 | } 125 | 126 | void CCC::setSndCurrSeqNo(int32_t seqno) 127 | { 128 | m_iSndCurrSeqNo = seqno; 129 | } 130 | 131 | void CCC::setRcvRate(int rcvrate) 132 | { 133 | m_iRcvRate = rcvrate; 134 | } 135 | 136 | void CCC::setMaxCWndSize(int cwnd) 137 | { 138 | m_dMaxCWndSize = cwnd; 139 | } 140 | 141 | void CCC::setRTT(int rtt) 142 | { 143 | m_iRTT = rtt; 144 | } 145 | 146 | void CCC::setUserParam(const char* param, int size) 147 | { 148 | delete [] m_pcParam; 149 | m_pcParam = new char[size]; 150 | memcpy(m_pcParam, param, size); 151 | m_iPSize = size; 152 | } 153 | 154 | // 155 | CUDTCC::CUDTCC(): 156 | m_iRCInterval(), 157 | m_LastRCTime(), 158 | m_bSlowStart(), 159 | m_iLastAck(), 160 | m_bLoss(), 161 | m_iLastDecSeq(), 162 | m_dLastDecPeriod(), 163 | m_iNAKCount(), 164 | m_iDecRandom(), 165 | m_iAvgNAKNum(), 166 | m_iDecCount() 167 | { 168 | } 169 | 170 | void CUDTCC::init() 171 | { 172 | m_iRCInterval = m_iSYNInterval; 173 | m_LastRCTime = CTimer::getTime(); 174 | setACKTimer(m_iRCInterval); 175 | 176 | m_bSlowStart = true; 177 | m_iLastAck = m_iSndCurrSeqNo; 178 | m_bLoss = false; 179 | m_iLastDecSeq = CSeqNo::decseq(m_iLastAck); 180 | m_dLastDecPeriod = 1; 181 | m_iAvgNAKNum = 0; 182 | m_iNAKCount = 0; 183 | m_iDecRandom = 1; 184 | 185 | m_dCWndSize = 16; 186 | m_dPktSndPeriod = 1; 187 | } 188 | 189 | void CUDTCC::onACK(int32_t ack) 190 | { 191 | int64_t B = 0; 192 | double inc = 0; 193 | // Note: 1/24/2012 194 | // The minimum increase parameter is increased from "1.0 / m_iMSS" to 0.01 195 | // because the original was too small and caused sending rate to stay at low level 196 | // for long time. 197 | const double min_inc = 0.01; 198 | 199 | uint64_t currtime = CTimer::getTime(); 200 | if (currtime - m_LastRCTime < (uint64_t)m_iRCInterval) 201 | return; 202 | 203 | m_LastRCTime = currtime; 204 | 205 | if (m_bSlowStart) 206 | { 207 | m_dCWndSize += CSeqNo::seqlen(m_iLastAck, ack); 208 | m_iLastAck = ack; 209 | 210 | if (m_dCWndSize > m_dMaxCWndSize) 211 | { 212 | m_bSlowStart = false; 213 | if (m_iRcvRate > 0) 214 | m_dPktSndPeriod = 1000000.0 / m_iRcvRate; 215 | else 216 | m_dPktSndPeriod = (m_iRTT + m_iRCInterval) / m_dCWndSize; 217 | } 218 | } 219 | else 220 | m_dCWndSize = m_iRcvRate / 1000000.0 * (m_iRTT + m_iRCInterval) + 16; 221 | 222 | // During Slow Start, no rate increase 223 | if (m_bSlowStart) 224 | return; 225 | 226 | if (m_bLoss) 227 | { 228 | m_bLoss = false; 229 | return; 230 | } 231 | 232 | B = (int64_t)(m_iBandwidth - 1000000.0 / m_dPktSndPeriod); 233 | if ((m_dPktSndPeriod > m_dLastDecPeriod) && ((m_iBandwidth / 9) < B)) 234 | B = m_iBandwidth / 9; 235 | if (B <= 0) 236 | inc = min_inc; 237 | else 238 | { 239 | // inc = max(10 ^ ceil(log10( B * MSS * 8 ) * Beta / MSS, 1/MSS) 240 | // Beta = 1.5 * 10^(-6) 241 | 242 | inc = pow(10.0, ceil(log10(B * m_iMSS * 8.0))) * 0.0000015 / m_iMSS; 243 | 244 | if (inc < min_inc) 245 | inc = min_inc; 246 | } 247 | 248 | m_dPktSndPeriod = (m_dPktSndPeriod * m_iRCInterval) / (m_dPktSndPeriod * inc + m_iRCInterval); 249 | } 250 | 251 | void CUDTCC::onLoss(const int32_t* losslist, int) 252 | { 253 | //Slow Start stopped, if it hasn't yet 254 | if (m_bSlowStart) 255 | { 256 | m_bSlowStart = false; 257 | if (m_iRcvRate > 0) 258 | { 259 | // Set the sending rate to the receiving rate. 260 | m_dPktSndPeriod = 1000000.0 / m_iRcvRate; 261 | return; 262 | } 263 | // If no receiving rate is observed, we have to compute the sending 264 | // rate according to the current window size, and decrease it 265 | // using the method below. 266 | m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval); 267 | } 268 | 269 | m_bLoss = true; 270 | 271 | if (CSeqNo::seqcmp(losslist[0] & 0x7FFFFFFF, m_iLastDecSeq) > 0) 272 | { 273 | m_dLastDecPeriod = m_dPktSndPeriod; 274 | m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125); 275 | 276 | m_iAvgNAKNum = (int)ceil(m_iAvgNAKNum * 0.875 + m_iNAKCount * 0.125); 277 | m_iNAKCount = 1; 278 | m_iDecCount = 1; 279 | 280 | m_iLastDecSeq = m_iSndCurrSeqNo; 281 | 282 | // remove global synchronization using randomization 283 | srand(m_iLastDecSeq); 284 | m_iDecRandom = (int)ceil(m_iAvgNAKNum * (double(rand()) / RAND_MAX)); 285 | if (m_iDecRandom < 1) 286 | m_iDecRandom = 1; 287 | } 288 | else if ((m_iDecCount ++ < 5) && (0 == (++ m_iNAKCount % m_iDecRandom))) 289 | { 290 | // 0.875^5 = 0.51, rate should not be decreased by more than half within a congestion period 291 | m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125); 292 | m_iLastDecSeq = m_iSndCurrSeqNo; 293 | } 294 | } 295 | 296 | void CUDTCC::onTimeout() 297 | { 298 | if (m_bSlowStart) 299 | { 300 | m_bSlowStart = false; 301 | if (m_iRcvRate > 0) 302 | m_dPktSndPeriod = 1000000.0 / m_iRcvRate; 303 | else 304 | m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval); 305 | } 306 | else 307 | { 308 | /* 309 | m_dLastDecPeriod = m_dPktSndPeriod; 310 | m_dPktSndPeriod = ceil(m_dPktSndPeriod * 2); 311 | m_iLastDecSeq = m_iLastAck; 312 | */ 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /receiver/src/channel.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/27/2011 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_CHANNEL_H__ 42 | #define __UDT_CHANNEL_H__ 43 | 44 | 45 | #include "udt.h" 46 | #include "packet.h" 47 | 48 | 49 | class CChannel 50 | { 51 | public: 52 | CChannel(); 53 | CChannel(int version); 54 | ~CChannel(); 55 | 56 | // Functionality: 57 | // Open a UDP channel. 58 | // Parameters: 59 | // 0) [in] addr: The local address that UDP will use. 60 | // Returned value: 61 | // None. 62 | 63 | void open(const sockaddr* addr = NULL); 64 | 65 | // Functionality: 66 | // Open a UDP channel based on an existing UDP socket. 67 | // Parameters: 68 | // 0) [in] udpsock: UDP socket descriptor. 69 | // Returned value: 70 | // None. 71 | 72 | void open(UDPSOCKET udpsock); 73 | 74 | // Functionality: 75 | // Disconnect and close the UDP entity. 76 | // Parameters: 77 | // None. 78 | // Returned value: 79 | // None. 80 | 81 | void close() const; 82 | 83 | // Functionality: 84 | // Get the UDP sending buffer size. 85 | // Parameters: 86 | // None. 87 | // Returned value: 88 | // Current UDP sending buffer size. 89 | 90 | int getSndBufSize(); 91 | 92 | // Functionality: 93 | // Get the UDP receiving buffer size. 94 | // Parameters: 95 | // None. 96 | // Returned value: 97 | // Current UDP receiving buffer size. 98 | 99 | int getRcvBufSize(); 100 | 101 | // Functionality: 102 | // Set the UDP sending buffer size. 103 | // Parameters: 104 | // 0) [in] size: expected UDP sending buffer size. 105 | // Returned value: 106 | // None. 107 | 108 | void setSndBufSize(int size); 109 | 110 | // Functionality: 111 | // Set the UDP receiving buffer size. 112 | // Parameters: 113 | // 0) [in] size: expected UDP receiving buffer size. 114 | // Returned value: 115 | // None. 116 | 117 | void setRcvBufSize(int size); 118 | 119 | // Functionality: 120 | // Query the socket address that the channel is using. 121 | // Parameters: 122 | // 0) [out] addr: pointer to store the returned socket address. 123 | // Returned value: 124 | // None. 125 | 126 | void getSockAddr(sockaddr* addr) const; 127 | 128 | // Functionality: 129 | // Query the peer side socket address that the channel is connect to. 130 | // Parameters: 131 | // 0) [out] addr: pointer to store the returned socket address. 132 | // Returned value: 133 | // None. 134 | 135 | void getPeerAddr(sockaddr* addr) const; 136 | 137 | // Functionality: 138 | // Send a packet to the given address. 139 | // Parameters: 140 | // 0) [in] addr: pointer to the destination address. 141 | // 1) [in] packet: reference to a CPacket entity. 142 | // Returned value: 143 | // Actual size of data sent. 144 | 145 | int sendto(const sockaddr* addr, CPacket& packet) const; 146 | 147 | // Functionality: 148 | // Receive a packet from the channel and record the source address. 149 | // Parameters: 150 | // 0) [in] addr: pointer to the source address. 151 | // 1) [in] packet: reference to a CPacket entity. 152 | // Returned value: 153 | // Actual size of data received. 154 | 155 | int recvfrom(sockaddr* addr, CPacket& packet) const; 156 | 157 | private: 158 | void setUDPSockOpt(); 159 | 160 | private: 161 | int m_iIPversion; // IP version 162 | int m_iSockAddrSize; // socket address structure size (pre-defined to avoid run-time test) 163 | 164 | UDPSOCKET m_iSocket; // socket descriptor 165 | 166 | int m_iSndBufSize; // UDP sending buffer size 167 | int m_iRcvBufSize; // UDP receiving buffer size 168 | }; 169 | 170 | 171 | #endif 172 | -------------------------------------------------------------------------------- /receiver/src/epoll.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 08/20/2010 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_EPOLL_H__ 42 | #define __UDT_EPOLL_H__ 43 | 44 | 45 | #include 46 | #include 47 | #include "udt.h" 48 | 49 | 50 | struct CEPollDesc 51 | { 52 | int m_iID; // epoll ID 53 | std::set m_sUDTSocksOut; // set of UDT sockets waiting for write events 54 | std::set m_sUDTSocksIn; // set of UDT sockets waiting for read events 55 | std::set m_sUDTSocksEx; // set of UDT sockets waiting for exceptions 56 | 57 | int m_iLocalID; // local system epoll ID 58 | std::set m_sLocals; // set of local (non-UDT) descriptors 59 | 60 | std::set m_sUDTWrites; // UDT sockets ready for write 61 | std::set m_sUDTReads; // UDT sockets ready for read 62 | std::set m_sUDTExcepts; // UDT sockets with exceptions (connection broken, etc.) 63 | }; 64 | 65 | class CEPoll 66 | { 67 | friend class CUDT; 68 | friend class CRendezvousQueue; 69 | 70 | public: 71 | CEPoll(); 72 | ~CEPoll(); 73 | 74 | public: // for CUDTUnited API 75 | 76 | // Functionality: 77 | // create a new EPoll. 78 | // Parameters: 79 | // None. 80 | // Returned value: 81 | // new EPoll ID if success, otherwise an error number. 82 | 83 | int create(); 84 | 85 | // Functionality: 86 | // add a UDT socket to an EPoll. 87 | // Parameters: 88 | // 0) [in] eid: EPoll ID. 89 | // 1) [in] u: UDT Socket ID. 90 | // 2) [in] events: events to watch. 91 | // Returned value: 92 | // 0 if success, otherwise an error number. 93 | 94 | int add_usock(const int eid, const UDTSOCKET& u, const int* events = NULL); 95 | 96 | // Functionality: 97 | // add a system socket to an EPoll. 98 | // Parameters: 99 | // 0) [in] eid: EPoll ID. 100 | // 1) [in] s: system Socket ID. 101 | // 2) [in] events: events to watch. 102 | // Returned value: 103 | // 0 if success, otherwise an error number. 104 | 105 | int add_ssock(const int eid, const SYSSOCKET& s, const int* events = NULL); 106 | 107 | // Functionality: 108 | // remove a UDT socket event from an EPoll; socket will be removed if no events to watch 109 | // Parameters: 110 | // 0) [in] eid: EPoll ID. 111 | // 1) [in] u: UDT socket ID. 112 | // Returned value: 113 | // 0 if success, otherwise an error number. 114 | 115 | int remove_usock(const int eid, const UDTSOCKET& u); 116 | 117 | // Functionality: 118 | // remove a system socket event from an EPoll; socket will be removed if no events to watch 119 | // Parameters: 120 | // 0) [in] eid: EPoll ID. 121 | // 1) [in] s: system socket ID. 122 | // Returned value: 123 | // 0 if success, otherwise an error number. 124 | 125 | int remove_ssock(const int eid, const SYSSOCKET& s); 126 | 127 | // Functionality: 128 | // wait for EPoll events or timeout. 129 | // Parameters: 130 | // 0) [in] eid: EPoll ID. 131 | // 1) [out] readfds: UDT sockets available for reading. 132 | // 2) [out] writefds: UDT sockets available for writing. 133 | // 3) [in] msTimeOut: timeout threshold, in milliseconds. 134 | // 4) [out] lrfds: system file descriptors for reading. 135 | // 5) [out] lwfds: system file descriptors for writing. 136 | // Returned value: 137 | // number of sockets available for IO. 138 | 139 | int wait(const int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, std::set* lrfds, std::set* lwfds); 140 | 141 | // Functionality: 142 | // close and release an EPoll. 143 | // Parameters: 144 | // 0) [in] eid: EPoll ID. 145 | // Returned value: 146 | // 0 if success, otherwise an error number. 147 | 148 | int release(const int eid); 149 | 150 | public: // for CUDT to acknowledge IO status 151 | 152 | // Functionality: 153 | // Update events available for a UDT socket. 154 | // Parameters: 155 | // 0) [in] uid: UDT socket ID. 156 | // 1) [in] eids: EPoll IDs to be set 157 | // 1) [in] events: Combination of events to update 158 | // 1) [in] enable: true -> enable, otherwise disable 159 | // Returned value: 160 | // 0 if success, otherwise an error number 161 | 162 | int update_events(const UDTSOCKET& uid, std::set& eids, int events, bool enable); 163 | 164 | private: 165 | int m_iIDSeed; // seed to generate a new ID 166 | pthread_mutex_t m_SeedLock; 167 | 168 | std::map m_mPolls; // all epolls 169 | pthread_mutex_t m_EPollLock; 170 | }; 171 | 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /receiver/src/list.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/22/2011 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_LIST_H__ 42 | #define __UDT_LIST_H__ 43 | 44 | 45 | #include "udt.h" 46 | #include "common.h" 47 | 48 | 49 | class CSndLossList 50 | { 51 | public: 52 | CSndLossList(int size = 1024); 53 | ~CSndLossList(); 54 | 55 | // Functionality: 56 | // Insert a seq. no. into the sender loss list. 57 | // Parameters: 58 | // 0) [in] seqno1: sequence number starts. 59 | // 1) [in] seqno2: sequence number ends. 60 | // Returned value: 61 | // number of packets that are not in the list previously. 62 | 63 | int insert(int32_t seqno1, int32_t seqno2); 64 | 65 | // Functionality: 66 | // Remove ALL the seq. no. that are not greater than the parameter. 67 | // Parameters: 68 | // 0) [in] seqno: sequence number. 69 | // Returned value: 70 | // None. 71 | 72 | void remove(int32_t seqno); 73 | 74 | // Functionality: 75 | // Read the loss length. 76 | // Parameters: 77 | // None. 78 | // Returned value: 79 | // The length of the list. 80 | 81 | int getLossLength(); 82 | 83 | // Functionality: 84 | // Read the first (smallest) loss seq. no. in the list and remove it. 85 | // Parameters: 86 | // None. 87 | // Returned value: 88 | // The seq. no. or -1 if the list is empty. 89 | 90 | int32_t getLostSeq(); 91 | 92 | public: 93 | int32_t* m_piData1; // sequence number starts 94 | int32_t* m_piData2; // seqnence number ends 95 | int* m_piNext; // next node in the list 96 | 97 | int m_iHead; // first node 98 | int m_iLength; // loss length 99 | int m_iSize; // size of the static array 100 | int m_iLastInsertPos; // position of last insert node 101 | 102 | pthread_mutex_t m_ListLock; // used to synchronize list operation 103 | 104 | private: 105 | CSndLossList(const CSndLossList&); 106 | CSndLossList& operator=(const CSndLossList&); 107 | }; 108 | 109 | //////////////////////////////////////////////////////////////////////////////// 110 | 111 | class CRcvLossList 112 | { 113 | public: 114 | CRcvLossList(int size = 1024); 115 | ~CRcvLossList(); 116 | 117 | // Functionality: 118 | // Insert a series of loss seq. no. between "seqno1" and "seqno2" into the receiver's loss list. 119 | // Parameters: 120 | // 0) [in] seqno1: sequence number starts. 121 | // 1) [in] seqno2: seqeunce number ends. 122 | // Returned value: 123 | // None. 124 | 125 | void insert(int32_t seqno1, int32_t seqno2); 126 | 127 | // Functionality: 128 | // Remove a loss seq. no. from the receiver's loss list. 129 | // Parameters: 130 | // 0) [in] seqno: sequence number. 131 | // Returned value: 132 | // if the packet is removed (true) or no such lost packet is found (false). 133 | 134 | bool remove(int32_t seqno); 135 | 136 | // Functionality: 137 | // Remove all packets between seqno1 and seqno2. 138 | // Parameters: 139 | // 0) [in] seqno1: start sequence number. 140 | // 1) [in] seqno2: end sequence number. 141 | // Returned value: 142 | // if the packet is removed (true) or no such lost packet is found (false). 143 | 144 | bool remove(int32_t seqno1, int32_t seqno2); 145 | 146 | // Functionality: 147 | // Find if there is any lost packets whose sequence number falling seqno1 and seqno2. 148 | // Parameters: 149 | // 0) [in] seqno1: start sequence number. 150 | // 1) [in] seqno2: end sequence number. 151 | // Returned value: 152 | // True if found; otherwise false. 153 | 154 | bool find(int32_t seqno1, int32_t seqno2) const; 155 | 156 | // Functionality: 157 | // Read the loss length. 158 | // Parameters: 159 | // None. 160 | // Returned value: 161 | // the length of the list. 162 | 163 | int getLossLength() const; 164 | 165 | // Functionality: 166 | // Read the first (smallest) seq. no. in the list. 167 | // Parameters: 168 | // None. 169 | // Returned value: 170 | // the sequence number or -1 if the list is empty. 171 | 172 | int getFirstLostSeq() const; 173 | 174 | // Functionality: 175 | // Get a encoded loss array for NAK report. 176 | // Parameters: 177 | // 0) [out] array: the result list of seq. no. to be included in NAK. 178 | // 1) [out] physical length of the result array. 179 | // 2) [in] limit: maximum length of the array. 180 | // Returned value: 181 | // None. 182 | 183 | void getLossArray(int32_t* array, int& len, int limit, int & offset); 184 | 185 | public: 186 | int32_t* m_piData1; // sequence number starts 187 | int32_t* m_piData2; // sequence number ends 188 | int* m_piNext; // next node in the list 189 | int* m_piPrior; // prior node in the list; 190 | 191 | int m_iHead; // first node in the list 192 | int m_iTail; // last node in the list; 193 | int m_iLength; // loss length 194 | int m_iSize; // size of the static array 195 | 196 | private: 197 | CRcvLossList(const CRcvLossList&); 198 | CRcvLossList& operator=(const CRcvLossList&); 199 | }; 200 | 201 | 202 | #endif 203 | -------------------------------------------------------------------------------- /receiver/src/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* $Id: md5.h,v 1.2 2007/12/24 05:58:37 lilyco Exp $ */ 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321, whose 29 | text is available at 30 | http://www.ietf.org/rfc/rfc1321.txt 31 | The code is derived from the text of the RFC, including the test suite 32 | (section A.5) but excluding the rest of Appendix A. It does not include 33 | any code or documentation that is identified in the RFC as being 34 | copyrighted. 35 | 36 | The original and principal author of md5.h is L. Peter Deutsch 37 | . Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Removed support for non-ANSI compilers; removed 41 | references to Ghostscript; clarified derivation from RFC 1321; 42 | now handles byte order either statically or dynamically. 43 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 44 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); 45 | added conditionalization for C++ compilation from Martin 46 | Purschke . 47 | 1999-05-03 lpd Original version. 48 | */ 49 | 50 | #ifndef md5_INCLUDED 51 | # define md5_INCLUDED 52 | 53 | /* 54 | * This package supports both compile-time and run-time determination of CPU 55 | * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be 56 | * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is 57 | * defined as non-zero, the code will be compiled to run only on big-endian 58 | * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to 59 | * run on either big- or little-endian CPUs, but will run slightly less 60 | * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. 61 | */ 62 | 63 | typedef unsigned char md5_byte_t; /* 8-bit byte */ 64 | typedef unsigned int md5_word_t; /* 32-bit word */ 65 | 66 | /* Define the state of the MD5 Algorithm. */ 67 | typedef struct md5_state_s { 68 | md5_word_t count[2]; /* message length in bits, lsw first */ 69 | md5_word_t abcd[4]; /* digest buffer */ 70 | md5_byte_t buf[64]; /* accumulate block */ 71 | } md5_state_t; 72 | 73 | #ifdef __cplusplus 74 | extern "C" 75 | { 76 | #endif 77 | 78 | /* Initialize the algorithm. */ 79 | void md5_init(md5_state_t *pms); 80 | 81 | /* Append a string to the message. */ 82 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); 83 | 84 | /* Finish the message and return the digest. */ 85 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); 86 | 87 | #ifdef __cplusplus 88 | } /* end extern "C" */ 89 | #endif 90 | 91 | #endif /* md5_INCLUDED */ 92 | -------------------------------------------------------------------------------- /receiver/src/packet.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/02/2011 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_PACKET_H__ 42 | #define __UDT_PACKET_H__ 43 | 44 | 45 | #include "udt.h" 46 | 47 | #ifdef WIN32 48 | struct iovec 49 | { 50 | int iov_len; 51 | char* iov_base; 52 | }; 53 | #endif 54 | 55 | class CChannel; 56 | 57 | class CPacket 58 | { 59 | friend class CChannel; 60 | friend class CSndQueue; 61 | friend class CRcvQueue; 62 | 63 | public: 64 | int32_t& m_iSeqNo; // alias: sequence number 65 | int32_t& m_iMsgNo; // alias: message number 66 | int32_t& m_iTimeStamp; // alias: timestamp 67 | int32_t& m_iID; // alias: socket ID 68 | char*& m_pcData; // alias: data/control information 69 | 70 | static const int m_iPktHdrSize; // packet header size 71 | 72 | public: 73 | CPacket(); 74 | ~CPacket(); 75 | 76 | // Functionality: 77 | // Get the payload or the control information field length. 78 | // Parameters: 79 | // None. 80 | // Returned value: 81 | // the payload or the control information field length. 82 | 83 | int getLength() const; 84 | 85 | // Functionality: 86 | // Set the payload or the control information field length. 87 | // Parameters: 88 | // 0) [in] len: the payload or the control information field length. 89 | // Returned value: 90 | // None. 91 | 92 | void setLength(int len); 93 | 94 | // Functionality: 95 | // Pack a Control packet. 96 | // Parameters: 97 | // 0) [in] pkttype: packet type filed. 98 | // 1) [in] lparam: pointer to the first data structure, explained by the packet type. 99 | // 2) [in] rparam: pointer to the second data structure, explained by the packet type. 100 | // 3) [in] size: size of rparam, in number of bytes; 101 | // Returned value: 102 | // None. 103 | 104 | void pack(int pkttype, void* lparam = NULL, void* rparam = NULL, int size = 0); 105 | 106 | // Functionality: 107 | // Read the packet vector. 108 | // Parameters: 109 | // None. 110 | // Returned value: 111 | // Pointer to the packet vector. 112 | 113 | iovec* getPacketVector(); 114 | 115 | // Functionality: 116 | // Read the packet flag. 117 | // Parameters: 118 | // None. 119 | // Returned value: 120 | // packet flag (0 or 1). 121 | 122 | int getFlag() const; 123 | 124 | // Functionality: 125 | // Read the packet type. 126 | // Parameters: 127 | // None. 128 | // Returned value: 129 | // packet type filed (000 ~ 111). 130 | 131 | int getType() const; 132 | 133 | // Functionality: 134 | // Read the extended packet type. 135 | // Parameters: 136 | // None. 137 | // Returned value: 138 | // extended packet type filed (0x000 ~ 0xFFF). 139 | 140 | int getExtendedType() const; 141 | 142 | // Functionality: 143 | // Read the ACK-2 seq. no. 144 | // Parameters: 145 | // None. 146 | // Returned value: 147 | // packet header field (bit 16~31). 148 | 149 | int32_t getAckSeqNo() const; 150 | 151 | // Functionality: 152 | // Read the message boundary flag bit. 153 | // Parameters: 154 | // None. 155 | // Returned value: 156 | // packet header field [1] (bit 0~1). 157 | 158 | int getMsgBoundary() const; 159 | 160 | // Functionality: 161 | // Read the message inorder delivery flag bit. 162 | // Parameters: 163 | // None. 164 | // Returned value: 165 | // packet header field [1] (bit 2). 166 | 167 | bool getMsgOrderFlag() const; 168 | 169 | // Functionality: 170 | // Read the message sequence number. 171 | // Parameters: 172 | // None. 173 | // Returned value: 174 | // packet header field [1] (bit 3~31). 175 | 176 | int32_t getMsgSeq() const; 177 | 178 | // Functionality: 179 | // Clone this packet. 180 | // Parameters: 181 | // None. 182 | // Returned value: 183 | // Pointer to the new packet. 184 | 185 | CPacket* clone() const; 186 | 187 | protected: 188 | uint32_t m_nHeader[4]; // The 128-bit header field 189 | iovec m_PacketVector[2]; // The 2-demension vector of UDT packet [header, data] 190 | 191 | int32_t __pad; 192 | 193 | protected: 194 | CPacket& operator=(const CPacket&); 195 | }; 196 | 197 | //////////////////////////////////////////////////////////////////////////////// 198 | 199 | class CHandShake 200 | { 201 | public: 202 | CHandShake(); 203 | 204 | int serialize(char* buf, int& size); 205 | int deserialize(const char* buf, int size); 206 | 207 | public: 208 | static const int m_iContentSize; // Size of hand shake data 209 | 210 | public: 211 | int32_t m_iVersion; // UDT version 212 | int32_t m_iType; // UDT socket type 213 | int32_t m_iISN; // random initial sequence number 214 | int32_t m_iMSS; // maximum segment size 215 | int32_t m_iFlightFlagSize; // flow control window size 216 | int32_t m_iReqType; // connection request type: 1: regular connection request, 0: rendezvous connection request, -1/-2: response 217 | int32_t m_iID; // socket ID 218 | int32_t m_iCookie; // cookie 219 | uint32_t m_piPeerIP[4]; // The IP address that the peer's UDP port is bound to 220 | }; 221 | 222 | 223 | #endif 224 | -------------------------------------------------------------------------------- /receiver/src/window.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/22/2011 39 | *****************************************************************************/ 40 | 41 | #include 42 | #include "common.h" 43 | #include "window.h" 44 | #include 45 | 46 | using namespace std; 47 | 48 | CACKWindow::CACKWindow(int size): 49 | m_piACKSeqNo(NULL), 50 | m_piACK(NULL), 51 | m_pTimeStamp(NULL), 52 | m_iSize(size), 53 | m_iHead(0), 54 | m_iTail(0) 55 | { 56 | m_piACKSeqNo = new int32_t[m_iSize]; 57 | m_piACK = new int32_t[m_iSize]; 58 | m_pTimeStamp = new uint64_t[m_iSize]; 59 | 60 | m_piACKSeqNo[0] = -1; 61 | } 62 | 63 | CACKWindow::~CACKWindow() 64 | { 65 | delete [] m_piACKSeqNo; 66 | delete [] m_piACK; 67 | delete [] m_pTimeStamp; 68 | } 69 | 70 | void CACKWindow::store(int32_t seq, int32_t ack) 71 | { 72 | m_piACKSeqNo[m_iHead] = seq; 73 | m_piACK[m_iHead] = ack; 74 | m_pTimeStamp[m_iHead] = CTimer::getTime(); 75 | 76 | m_iHead = (m_iHead + 1) % m_iSize; 77 | 78 | // overwrite the oldest ACK since it is not likely to be acknowledged 79 | if (m_iHead == m_iTail) 80 | m_iTail = (m_iTail + 1) % m_iSize; 81 | } 82 | 83 | int CACKWindow::acknowledge(int32_t seq, int32_t& ack) 84 | { 85 | if (m_iHead >= m_iTail) 86 | { 87 | // Head has not exceeded the physical boundary of the window 88 | 89 | for (int i = m_iTail, n = m_iHead; i < n; ++ i) 90 | { 91 | // looking for indentical ACK Seq. No. 92 | if (seq == m_piACKSeqNo[i]) 93 | { 94 | // return the Data ACK it carried 95 | ack = m_piACK[i]; 96 | 97 | // calculate RTT 98 | int rtt = int(CTimer::getTime() - m_pTimeStamp[i]); 99 | 100 | if (i + 1 == m_iHead) 101 | { 102 | m_iTail = m_iHead = 0; 103 | m_piACKSeqNo[0] = -1; 104 | } 105 | else 106 | m_iTail = (i + 1) % m_iSize; 107 | 108 | return rtt; 109 | } 110 | } 111 | 112 | // Bad input, the ACK node has been overwritten 113 | return -1; 114 | } 115 | 116 | // Head has exceeded the physical window boundary, so it is behind tail 117 | for (int j = m_iTail, n = m_iHead + m_iSize; j < n; ++ j) 118 | { 119 | // looking for indentical ACK seq. no. 120 | if (seq == m_piACKSeqNo[j % m_iSize]) 121 | { 122 | // return Data ACK 123 | j %= m_iSize; 124 | ack = m_piACK[j]; 125 | 126 | // calculate RTT 127 | int rtt = int(CTimer::getTime() - m_pTimeStamp[j]); 128 | 129 | if (j == m_iHead) 130 | { 131 | m_iTail = m_iHead = 0; 132 | m_piACKSeqNo[0] = -1; 133 | } 134 | else 135 | m_iTail = (j + 1) % m_iSize; 136 | 137 | return rtt; 138 | } 139 | } 140 | 141 | // bad input, the ACK node has been overwritten 142 | return -1; 143 | } 144 | 145 | //////////////////////////////////////////////////////////////////////////////// 146 | 147 | CPktTimeWindow::CPktTimeWindow(int asize, int psize): 148 | m_iAWSize(asize), 149 | m_piPktWindow(NULL), 150 | m_iPktWindowPtr(0), 151 | m_iPWSize(psize), 152 | m_piProbeWindow(NULL), 153 | m_iProbeWindowPtr(0), 154 | m_iLastSentTime(0), 155 | m_iMinPktSndInt(1000000), 156 | m_LastArrTime(), 157 | m_CurrArrTime(), 158 | m_ProbeTime() 159 | { 160 | m_piPktWindow = new int[m_iAWSize]; 161 | m_piPktReplica = new int[m_iAWSize]; 162 | m_piProbeWindow = new int[m_iPWSize]; 163 | m_piProbeReplica = new int[m_iPWSize]; 164 | 165 | m_LastArrTime = CTimer::getTime(); 166 | 167 | for (int i = 0; i < m_iAWSize; ++ i) 168 | m_piPktWindow[i] = 1000000; 169 | 170 | for (int k = 0; k < m_iPWSize; ++ k) 171 | m_piProbeWindow[k] = 1000; 172 | } 173 | 174 | CPktTimeWindow::~CPktTimeWindow() 175 | { 176 | delete [] m_piPktWindow; 177 | delete [] m_piPktReplica; 178 | delete [] m_piProbeWindow; 179 | delete [] m_piProbeReplica; 180 | } 181 | 182 | int CPktTimeWindow::getMinPktSndInt() const 183 | { 184 | return m_iMinPktSndInt; 185 | } 186 | 187 | int CPktTimeWindow::getPktRcvSpeed() const 188 | { 189 | // get median value, but cannot change the original value order in the window 190 | std::copy(m_piPktWindow, m_piPktWindow + m_iAWSize - 1, m_piPktReplica); 191 | std::nth_element(m_piPktReplica, m_piPktReplica + (m_iAWSize / 2), m_piPktReplica + m_iAWSize - 1); 192 | int median = m_piPktReplica[m_iAWSize / 2]; 193 | 194 | int count = 0; 195 | int sum = 0; 196 | int upper = median << 3; 197 | int lower = median >> 3; 198 | 199 | // median filtering 200 | int* p = m_piPktWindow; 201 | for (int i = 0, n = m_iAWSize; i < n; ++ i) 202 | { 203 | if ((*p < upper) && (*p > lower)) 204 | { 205 | ++ count; 206 | sum += *p; 207 | } 208 | ++ p; 209 | } 210 | 211 | // claculate speed, or return 0 if not enough valid value 212 | if (count > (m_iAWSize >> 1)) 213 | return (int)ceil(1000000.0 / (sum / count)); 214 | else 215 | return 0; 216 | } 217 | 218 | int CPktTimeWindow::getBandwidth() const 219 | { 220 | // get median value, but cannot change the original value order in the window 221 | std::copy(m_piProbeWindow, m_piProbeWindow + m_iPWSize - 1, m_piProbeReplica); 222 | std::nth_element(m_piProbeReplica, m_piProbeReplica + (m_iPWSize / 2), m_piProbeReplica + m_iPWSize - 1); 223 | int median = m_piProbeReplica[m_iPWSize / 2]; 224 | 225 | int count = 1; 226 | int sum = median; 227 | int upper = median << 3; 228 | int lower = median >> 3; 229 | 230 | // median filtering 231 | int* p = m_piProbeWindow; 232 | for (int i = 0, n = m_iPWSize; i < n; ++ i) 233 | { 234 | if ((*p < upper) && (*p > lower)) 235 | { 236 | ++ count; 237 | sum += *p; 238 | } 239 | ++ p; 240 | } 241 | 242 | return (int)ceil(1000000.0 / (double(sum) / double(count))); 243 | } 244 | 245 | void CPktTimeWindow::onPktSent(int currtime) 246 | { 247 | int interval = currtime - m_iLastSentTime; 248 | 249 | if ((interval < m_iMinPktSndInt) && (interval > 0)) 250 | m_iMinPktSndInt = interval; 251 | 252 | m_iLastSentTime = currtime; 253 | } 254 | 255 | void CPktTimeWindow::onPktArrival() 256 | { 257 | m_CurrArrTime = CTimer::getTime(); 258 | 259 | // record the packet interval between the current and the last one 260 | *(m_piPktWindow + m_iPktWindowPtr) = int(m_CurrArrTime - m_LastArrTime); 261 | 262 | // the window is logically circular 263 | ++ m_iPktWindowPtr; 264 | if (m_iPktWindowPtr == m_iAWSize) 265 | m_iPktWindowPtr = 0; 266 | 267 | // remember last packet arrival time 268 | m_LastArrTime = m_CurrArrTime; 269 | } 270 | 271 | void CPktTimeWindow::probe1Arrival() 272 | { 273 | m_ProbeTime = CTimer::getTime(); 274 | } 275 | 276 | void CPktTimeWindow::probe2Arrival() 277 | { 278 | m_CurrArrTime = CTimer::getTime(); 279 | 280 | // record the probing packets interval 281 | *(m_piProbeWindow + m_iProbeWindowPtr) = int(m_CurrArrTime - m_ProbeTime); 282 | // the window is logically circular 283 | ++ m_iProbeWindowPtr; 284 | if (m_iProbeWindowPtr == m_iPWSize) 285 | m_iProbeWindowPtr = 0; 286 | } 287 | -------------------------------------------------------------------------------- /receiver/src/window.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/22/2011 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_WINDOW_H__ 42 | #define __UDT_WINDOW_H__ 43 | 44 | 45 | #ifndef WIN32 46 | #include 47 | #include 48 | #endif 49 | #include "udt.h" 50 | 51 | 52 | class CACKWindow 53 | { 54 | public: 55 | CACKWindow(int size = 1024); 56 | ~CACKWindow(); 57 | 58 | // Functionality: 59 | // Write an ACK record into the window. 60 | // Parameters: 61 | // 0) [in] seq: ACK seq. no. 62 | // 1) [in] ack: DATA ACK no. 63 | // Returned value: 64 | // None. 65 | 66 | void store(int32_t seq, int32_t ack); 67 | 68 | // Functionality: 69 | // Search the ACK-2 "seq" in the window, find out the DATA "ack" and caluclate RTT . 70 | // Parameters: 71 | // 0) [in] seq: ACK-2 seq. no. 72 | // 1) [out] ack: the DATA ACK no. that matches the ACK-2 no. 73 | // Returned value: 74 | // RTT. 75 | 76 | int acknowledge(int32_t seq, int32_t& ack); 77 | 78 | private: 79 | int32_t* m_piACKSeqNo; // Seq. No. for the ACK packet 80 | int32_t* m_piACK; // Data Seq. No. carried by the ACK packet 81 | uint64_t* m_pTimeStamp; // The timestamp when the ACK was sent 82 | 83 | int m_iSize; // Size of the ACK history window 84 | int m_iHead; // Pointer to the lastest ACK record 85 | int m_iTail; // Pointer to the oldest ACK record 86 | 87 | private: 88 | CACKWindow(const CACKWindow&); 89 | CACKWindow& operator=(const CACKWindow&); 90 | }; 91 | 92 | //////////////////////////////////////////////////////////////////////////////// 93 | 94 | class CPktTimeWindow 95 | { 96 | public: 97 | CPktTimeWindow(int asize = 16, int psize = 16); 98 | ~CPktTimeWindow(); 99 | 100 | // Functionality: 101 | // read the minimum packet sending interval. 102 | // Parameters: 103 | // None. 104 | // Returned value: 105 | // minimum packet sending interval (microseconds). 106 | 107 | int getMinPktSndInt() const; 108 | 109 | // Functionality: 110 | // Calculate the packes arrival speed. 111 | // Parameters: 112 | // None. 113 | // Returned value: 114 | // Packet arrival speed (packets per second). 115 | 116 | int getPktRcvSpeed() const; 117 | 118 | // Functionality: 119 | // Estimate the bandwidth. 120 | // Parameters: 121 | // None. 122 | // Returned value: 123 | // Estimated bandwidth (packets per second). 124 | 125 | int getBandwidth() const; 126 | 127 | // Functionality: 128 | // Record time information of a packet sending. 129 | // Parameters: 130 | // 0) currtime: timestamp of the packet sending. 131 | // Returned value: 132 | // None. 133 | 134 | void onPktSent(int currtime); 135 | 136 | // Functionality: 137 | // Record time information of an arrived packet. 138 | // Parameters: 139 | // None. 140 | // Returned value: 141 | // None. 142 | 143 | void onPktArrival(); 144 | 145 | // Functionality: 146 | // Record the arrival time of the first probing packet. 147 | // Parameters: 148 | // None. 149 | // Returned value: 150 | // None. 151 | 152 | void probe1Arrival(); 153 | 154 | // Functionality: 155 | // Record the arrival time of the second probing packet and the interval between packet pairs. 156 | // Parameters: 157 | // None. 158 | // Returned value: 159 | // None. 160 | 161 | void probe2Arrival(); 162 | 163 | private: 164 | int m_iAWSize; // size of the packet arrival history window 165 | int* m_piPktWindow; // packet information window 166 | int* m_piPktReplica; 167 | int m_iPktWindowPtr; // position pointer of the packet info. window. 168 | 169 | int m_iPWSize; // size of probe history window size 170 | int* m_piProbeWindow; // record inter-packet time for probing packet pairs 171 | int* m_piProbeReplica; 172 | int m_iProbeWindowPtr; // position pointer to the probing window 173 | 174 | int m_iLastSentTime; // last packet sending time 175 | int m_iMinPktSndInt; // Minimum packet sending interval 176 | 177 | uint64_t m_LastArrTime; // last packet arrival time 178 | uint64_t m_CurrArrTime; // current packet arrival time 179 | uint64_t m_ProbeTime; // arrival time of the first probing packet 180 | 181 | private: 182 | CPktTimeWindow(const CPktTimeWindow&); 183 | CPktTimeWindow &operator=(const CPktTimeWindow&); 184 | }; 185 | 186 | 187 | #endif 188 | -------------------------------------------------------------------------------- /run_demo_compare_tcp_and_pcc.sh: -------------------------------------------------------------------------------- 1 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair1.uiucscheduling.emulab.net "~/demo_run_pcc.sh 4 &" 2 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair2.uiucscheduling.emulab.net "~/demo_run_tcp.sh 4 &" 3 | -------------------------------------------------------------------------------- /sender/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above 9 | copyright notice, this list of conditions and the 10 | following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the 13 | above copyright notice, this list of conditions 14 | and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name of the University of Illinois 18 | nor the names of its contributors may be used to 19 | endorse or promote products derived from this 20 | software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 23 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 24 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /sender/Makefile: -------------------------------------------------------------------------------- 1 | DIRS = src app 2 | TARGETS = all clean install 3 | 4 | $(TARGETS): %: $(patsubst %, %.%, $(DIRS)) 5 | 6 | $(foreach TGT, $(TARGETS), $(patsubst %, %.$(TGT), $(DIRS))): 7 | $(MAKE) -C $(subst ., , $@) 8 | -------------------------------------------------------------------------------- /sender/app/Makefile: -------------------------------------------------------------------------------- 1 | C++ = g++ 2 | 3 | ifndef os 4 | os = LINUX 5 | endif 6 | 7 | ifndef arch 8 | arch = IA32 9 | endif 10 | 11 | CCFLAGS = -Wall -D$(os) -I../src -finline-functions -O3 12 | 13 | ifeq ($(arch), IA32) 14 | CCFLAGS += -DIA32 #-mcpu=pentiumpro -march=pentiumpro -mmmx -msse 15 | endif 16 | 17 | ifeq ($(arch), POWERPC) 18 | CCFLAGS += -mcpu=powerpc 19 | endif 20 | 21 | ifeq ($(arch), IA64) 22 | CCFLAGS += -DIA64 23 | endif 24 | 25 | ifeq ($(arch), SPARC) 26 | CCFLAGS += -DSPARC 27 | endif 28 | 29 | LDFLAGS = -L../src -ludt -lstdc++ -lpthread -lm 30 | 31 | ifeq ($(os), UNIX) 32 | LDFLAGS += -lsocket 33 | endif 34 | 35 | ifeq ($(os), SUNOS) 36 | LDFLAGS += -lrt -lsocket 37 | endif 38 | 39 | DIR = $(shell pwd) 40 | 41 | APP = incast_client appclient sendfile recvfile 42 | 43 | all: $(APP) 44 | 45 | %.o: %.cpp 46 | $(C++) $(CCFLAGS) $< -c 47 | 48 | appserver: appserver.o 49 | $(C++) $^ -o $@ $(LDFLAGS) 50 | appclient: appclient.o 51 | $(C++) $^ -o $@ $(LDFLAGS) 52 | sendfile: sendfile.o 53 | $(C++) $^ -o $@ $(LDFLAGS) 54 | recvfile: recvfile.o 55 | $(C++) $^ -o $@ $(LDFLAGS) 56 | incast_client: incast_client.o 57 | $(C++) $^ -o $@ $(LDFLAGS) 58 | 59 | clean: 60 | rm -f *.o $(APP) 61 | 62 | install: 63 | export PATH=$(DIR):$$PATH 64 | -------------------------------------------------------------------------------- /sender/app/appclient.cpp: -------------------------------------------------------------------------------- 1 | #ifndef WIN32 2 | #include 3 | #include 4 | #include 5 | #include 6 | #else 7 | #include 8 | #include 9 | #include 10 | #endif 11 | #include 12 | #include 13 | #include "cc.h" 14 | 15 | using namespace std; 16 | 17 | #ifndef WIN32 18 | void* monitor(void*); 19 | #else 20 | DWORD WINAPI monitor(LPVOID); 21 | #endif 22 | 23 | int main(int argc, char* argv[]) 24 | { 25 | if ((3 != argc) || (0 == atoi(argv[2]))) 26 | { 27 | cout << "usage: appclient server_ip server_port" << endl; 28 | return 0; 29 | } 30 | //sleep(1500); 31 | // use this function to initialize the UDT library 32 | UDT::startup(); 33 | 34 | struct addrinfo hints, *local, *peer; 35 | 36 | memset(&hints, 0, sizeof(struct addrinfo)); 37 | 38 | hints.ai_flags = AI_PASSIVE; 39 | hints.ai_family = AF_INET; 40 | hints.ai_socktype = SOCK_STREAM; 41 | //hints.ai_socktype = SOCK_DGRAM; 42 | 43 | if (0 != getaddrinfo(NULL, "9000", &hints, &local)) 44 | { 45 | cout << "incorrect network address.\n" << endl; 46 | return 0; 47 | } 48 | 49 | UDTSOCKET client = UDT::socket(local->ai_family, local->ai_socktype, local->ai_protocol); 50 | 51 | // UDT Options 52 | UDT::setsockopt(client, 0, UDT_CC, new CCCFactory, sizeof(CCCFactory)); 53 | //UDT::setsockopt(client, 0, UDT_MSS, new int(9000), sizeof(int)); 54 | //UDT::setsockopt(client, 0, UDT_SNDBUF, new int(10000000), sizeof(int)); 55 | //UDT::setsockopt(client, 0, UDP_SNDBUF, new int(10000000), sizeof(int)); 56 | 57 | // Windows UDP issue 58 | // For better performance, modify HKLM\System\CurrentControlSet\Services\Afd\Parameters\FastSendDatagramThreshold 59 | #ifdef WIN32 60 | UDT::setsockopt(client, 0, UDT_MSS, new int(1052), sizeof(int)); 61 | #endif 62 | 63 | /* 64 | UDT::setsockopt(client, 0, UDT_RENDEZVOUS, new bool(true), sizeof(bool)); 65 | if (UDT::ERROR == UDT::bind(client, local->ai_addr, local->ai_addrlen)) 66 | { 67 | cout << "bind: " << UDT::getlasterror().getErrorMessage() << endl; 68 | return 0; 69 | } 70 | */ 71 | 72 | freeaddrinfo(local); 73 | 74 | if (0 != getaddrinfo(argv[1], argv[2], &hints, &peer)) 75 | { 76 | cout << "incorrect server/peer address. " << argv[1] << ":" << argv[2] << endl; 77 | return 0; 78 | } 79 | 80 | // connect to the server, implict bind 81 | if (UDT::ERROR == UDT::connect(client, peer->ai_addr, peer->ai_addrlen)) 82 | { 83 | cout << "connect: " << UDT::getlasterror().getErrorMessage() << endl; 84 | return 0; 85 | } 86 | freeaddrinfo(peer); 87 | 88 | // using CC method 89 | BBCC* cchandle = NULL; 90 | int temp; 91 | UDT::getsockopt(client, 0, UDT_CC, &cchandle, &temp); 92 | // if (NULL != cchandle) 93 | // cchandle->setRate(1); 94 | 95 | int size = 100000; 96 | char* data = new char[size]; 97 | 98 | #ifndef WIN32 99 | pthread_create(new pthread_t, NULL, monitor, &client); 100 | #else 101 | CreateThread(NULL, 0, monitor, &client, 0, NULL); 102 | #endif 103 | 104 | for (int i = 0; i < 1000000; i ++) 105 | { 106 | int ssize = 0; 107 | int ss; 108 | while (ssize < size) 109 | { 110 | if (UDT::ERROR == (ss = UDT::send(client, data + ssize, size - ssize, 0))) 111 | { 112 | cout << "send:" << UDT::getlasterror().getErrorMessage() << endl; 113 | break; 114 | } 115 | 116 | ssize += ss; 117 | } 118 | 119 | if (ssize < size) 120 | break; 121 | } 122 | 123 | UDT::close(client); 124 | 125 | delete [] data; 126 | 127 | // use this function to release the UDT library 128 | UDT::cleanup(); 129 | 130 | return 1; 131 | } 132 | 133 | #ifndef WIN32 134 | void* monitor(void* s) 135 | #else 136 | DWORD WINAPI monitor(LPVOID s) 137 | #endif 138 | { 139 | UDTSOCKET u = *(UDTSOCKET*)s; 140 | 141 | UDT::TRACEINFO perf; 142 | 143 | cout << "SendRate(Mb/s)\tRTT(ms)\tCWnd\tPktSndPeriod(us)\tRecvACK\tRecvNAK" << endl; 144 | int i=0; 145 | while (true) 146 | { 147 | #ifndef WIN32 148 | usleep(1000000); 149 | #else 150 | Sleep(1000); 151 | #endif 152 | i++; 153 | if(i>10000) 154 | { 155 | exit(1); 156 | } 157 | if (UDT::ERROR == UDT::perfmon(u, &perf)) 158 | { 159 | cout << "perfmon: " << UDT::getlasterror().getErrorMessage() << endl; 160 | break; 161 | } 162 | cout << perf.mbpsSendRate << "\t\t" 163 | << perf.msRTT << "\t" 164 | << perf.pktSentTotal << "\t" 165 | << perf.pktSndLossTotal << "\t\t\t" 166 | << perf.pktRecvACKTotal << "\t" 167 | << perf.pktRecvNAKTotal << endl; 168 | 169 | } 170 | 171 | #ifndef WIN32 172 | return NULL; 173 | #else 174 | return 0; 175 | #endif 176 | } 177 | -------------------------------------------------------------------------------- /sender/app/incast_client.cpp: -------------------------------------------------------------------------------- 1 | #ifndef WIN32 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #else 10 | #include 11 | #include 12 | #include 13 | #endif 14 | #include 15 | #include 16 | #include "cc_incast.h" 17 | #include 18 | 19 | using namespace std; 20 | int windowsize; 21 | char argv1[50],argv2[50]; 22 | int Interval_avg; 23 | int tt; 24 | int trap; 25 | int safe; 26 | #ifndef WIN32 27 | void* monitor(void*); 28 | void* worker(void*); 29 | #else 30 | DWORD WINAPI monitor(LPVOID); 31 | #endif 32 | int count=0; 33 | double avg_fluc; 34 | struct timeval current; 35 | int start_s, start_us; 36 | int data_length; 37 | int main(int argc, char* argv[]) 38 | { 39 | //sendinginterval=0; 40 | start_s = atoi(argv[4]); 41 | start_us = atoi(argv[5]); 42 | pthread_t t; 43 | tt=0; 44 | Interval_avg=50; 45 | avg_fluc=0.25; 46 | strcpy(argv1,argv[1]); 47 | strcpy(argv2,argv[2]); 48 | data_length = atoi(argv[3]); 49 | // use this function to initialize the UDT library 50 | int i=0; 51 | while(i<1){ 52 | i++; 53 | pthread_create(&t, NULL, worker, NULL); 54 | pthread_join(t,NULL); 55 | 56 | } 57 | return 1; 58 | } 59 | void * worker(void * s) 60 | { 61 | cout<ai_family, local->ai_socktype, local->ai_protocol); 84 | 85 | // UDT Options 86 | UDT::setsockopt(client, 0, UDT_CC, new CCCFactory, sizeof(CCCFactory)); 87 | //UDT::setsockopt(client, 0, UDT_MSS, new int(9000), sizeof(int)); 88 | //UDT::setsockopt(client, 0, UDT_SNDBUF, new int(10000000), sizeof(int)); 89 | //UDT::setsockopt(client, 0, UDP_SNDBUF, new int(10000000), sizeof(int)); 90 | 91 | // Windows UDP issue 92 | // For better performance, modify HKLM\System\CurrentControlSet\Services\Afd\Parameters\FastSendDatagramThreshold 93 | #ifdef WIN32 94 | UDT::setsockopt(client, 0, UDT_MSS, new int(1052), sizeof(int)); 95 | #endif 96 | 97 | // for rendezvous connection, enable the code below 98 | /* 99 | UDT::setsockopt(client, 0, UDT_RENDEZVOUS, new bool(true), sizeof(bool)); 100 | if (UDT::ERROR == UDT::bind(client, local->ai_addr, local->ai_addrlen)) 101 | { 102 | cout << "bind: " << UDT::getlasterror().getErrorMessage() << endl; 103 | return 0; 104 | } 105 | */ 106 | 107 | freeaddrinfo(local); 108 | 109 | if (0 != getaddrinfo(argv1, argv2, &hints, &peer)) 110 | { 111 | cout << "incorrect server/peer address. " << argv1 << ":" << argv2 << endl; 112 | return 0; 113 | } 114 | 115 | 116 | // connect to the server, implict bind 117 | if (UDT::ERROR == UDT::connect(client, peer->ai_addr, peer->ai_addrlen)) 118 | { 119 | cout << "connect: " << UDT::getlasterror().getErrorMessage() << endl; 120 | return 0; 121 | } 122 | 123 | ; 124 | freeaddrinfo(peer); 125 | 126 | // using CC method 127 | BBCC* cchandle = NULL; 128 | int temp; 129 | UDT::getsockopt(client, 0, UDT_CC, &cchandle, &temp); 130 | // if (NULL != cchandle) 131 | // cout<<"notNULL!"<setRate(5); 133 | //cchandle->m_dCWndSize=windowsize+100; 134 | //cout<m_dCWndSize<m_dCWndSize<=start_s+2 && current.tv_usec>=start_us) 166 | break; 167 | } while(1); 168 | 169 | // cout<count2<m_dCWndSize<haslost<haslost) 184 | {cchandle->haslost=0; windowsize-=4;} 185 | if(cchandle->hasloss) 186 | {cchandle->hasloss=0; 187 | windowsize-=7; 188 | 189 | } 190 | windowsize+=2; 191 | 192 | if(ss==size) 193 | // cout<<"FINISH!"< 3 | #include 4 | #else 5 | #include 6 | #include 7 | #endif 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | if ((argc != 5) || (0 == atoi(argv[2]))) 19 | { 20 | cout << "usage: recvfile server_ip server_port remote_filename local_filename" << endl; 21 | return -1; 22 | } 23 | 24 | // use this function to initialize the UDT library 25 | UDT::startup(); 26 | 27 | struct addrinfo hints, *peer; 28 | 29 | memset(&hints, 0, sizeof(struct addrinfo)); 30 | hints.ai_flags = AI_PASSIVE; 31 | hints.ai_family = AF_INET; 32 | hints.ai_socktype = SOCK_STREAM; 33 | 34 | UDTSOCKET fhandle = UDT::socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol); 35 | 36 | if (0 != getaddrinfo(argv[1], argv[2], &hints, &peer)) 37 | { 38 | cout << "incorrect server/peer address. " << argv[1] << ":" << argv[2] << endl; 39 | return -1; 40 | } 41 | 42 | // connect to the server, implict bind 43 | if (UDT::ERROR == UDT::connect(fhandle, peer->ai_addr, peer->ai_addrlen)) 44 | { 45 | cout << "connect: " << UDT::getlasterror().getErrorMessage() << endl; 46 | return -1; 47 | } 48 | 49 | freeaddrinfo(peer); 50 | 51 | 52 | // send name information of the requested file 53 | int len = strlen(argv[3]); 54 | 55 | if (UDT::ERROR == UDT::send(fhandle, (char*)&len, sizeof(int), 0)) 56 | { 57 | cout << "send: " << UDT::getlasterror().getErrorMessage() << endl; 58 | return -1; 59 | } 60 | 61 | if (UDT::ERROR == UDT::send(fhandle, argv[3], len, 0)) 62 | { 63 | cout << "send: " << UDT::getlasterror().getErrorMessage() << endl; 64 | return -1; 65 | } 66 | 67 | // get size information 68 | int64_t size; 69 | 70 | if (UDT::ERROR == UDT::recv(fhandle, (char*)&size, sizeof(int64_t), 0)) 71 | { 72 | cout << "send: " << UDT::getlasterror().getErrorMessage() << endl; 73 | return -1; 74 | } 75 | 76 | if (size < 0) 77 | { 78 | cout << "no such file " << argv[3] << " on the server\n"; 79 | return -1; 80 | } 81 | 82 | // receive the file 83 | fstream ofs(argv[4], ios::out | ios::binary | ios::trunc); 84 | int64_t recvsize; 85 | int64_t offset = 0; 86 | 87 | if (UDT::ERROR == (recvsize = UDT::recvfile(fhandle, ofs, offset, size))) 88 | { 89 | cout << "recvfile: " << UDT::getlasterror().getErrorMessage() << endl; 90 | return -1; 91 | } 92 | 93 | UDT::close(fhandle); 94 | 95 | ofs.close(); 96 | 97 | // use this function to release the UDT library 98 | UDT::cleanup(); 99 | 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /sender/app/sendfile.cpp: -------------------------------------------------------------------------------- 1 | #ifndef WIN32 2 | #include 3 | #include 4 | #else 5 | #include 6 | #include 7 | #endif 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "cc.h" 14 | using namespace std; 15 | 16 | #ifndef WIN32 17 | void* sendfile(void*); 18 | #else 19 | DWORD WINAPI sendfile(LPVOID); 20 | #endif 21 | 22 | #ifndef WIN32 23 | void* monitor(void*); 24 | #else 25 | DWORD WINAPI monitor(LPVOID); 26 | #endif 27 | 28 | int main(int argc, char* argv[]) 29 | { 30 | 31 | if ((argc != 4) || (0 == atoi(argv[2]))) 32 | { 33 | cout << "usage: recvfile server_ip server_port file_to_send" << endl; 34 | return -1; 35 | } 36 | UDT::startup(); 37 | 38 | struct addrinfo hints, *peer; 39 | 40 | memset(&hints, 0, sizeof(struct addrinfo)); 41 | hints.ai_flags = AI_PASSIVE; 42 | hints.ai_family = AF_INET; 43 | hints.ai_socktype = SOCK_STREAM; 44 | 45 | UDTSOCKET fhandle = UDT::socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol); 46 | UDT::setsockopt(fhandle, 0, UDT_CC, new CCCFactory, sizeof(CCCFactory)); 47 | 48 | if (0 != getaddrinfo(argv[1], argv[2], &hints, &peer)) 49 | { 50 | cout << "incorrect server/peer address. " << argv[1] << ":" << argv[2] << endl; 51 | return -1; 52 | } 53 | 54 | // connect to the server, implict bind 55 | if (UDT::ERROR == UDT::connect(fhandle, peer->ai_addr, peer->ai_addrlen)) 56 | { 57 | cout << "connect: " << UDT::getlasterror().getErrorMessage() << endl; 58 | return -1; 59 | } 60 | 61 | #ifndef WIN32 62 | pthread_create(new pthread_t, NULL, monitor, &fhandle); 63 | #else 64 | CreateThread(NULL, 0, monitor, &client, 0, NULL); 65 | #endif 66 | 67 | freeaddrinfo(peer); 68 | // using CC method 69 | BBCC* cchandle = NULL; 70 | int temp; 71 | UDT::getsockopt(fhandle, 0, UDT_CC, &cchandle, &temp); 72 | if (NULL != cchandle) 73 | cchandle->setRate(1); 74 | 75 | char file[1024]; 76 | strcpy(file,argv[3]); 77 | fstream ifs(file, ios::in | ios::binary); 78 | 79 | ifs.seekg(0, ios::end); 80 | int64_t size = ifs.tellg(); 81 | ifs.seekg(0, ios::beg); 82 | cout<<"size is "<10000) 131 | { 132 | exit(1); 133 | } 134 | if (UDT::ERROR == UDT::perfmon(u, &perf)) 135 | { 136 | cout << "perfmon: " << UDT::getlasterror().getErrorMessage() << endl; 137 | break; 138 | } 139 | cout << perf.mbpsSendRate << "\t\t" 140 | << perf.msRTT << "\t" 141 | << perf.pktSentTotal << "\t" 142 | << perf.pktSndLossTotal << "\t\t\t" 143 | << perf.pktRecvACKTotal << "\t" 144 | << perf.pktRecvNAKTotal << endl; 145 | 146 | } 147 | 148 | #ifndef WIN32 149 | return NULL; 150 | #else 151 | return 0; 152 | #endif 153 | } 154 | 155 | -------------------------------------------------------------------------------- /sender/src/Makefile: -------------------------------------------------------------------------------- 1 | C++ = g++ -g 2 | 3 | ifndef os 4 | os = LINUX 5 | endif 6 | 7 | ifndef arch 8 | arch = IA32 9 | endif 10 | 11 | CCFLAGS = -fPIC -Wall -Wextra -D$(os) -finline-functions -O3 -fno-strict-aliasing #-msse3 12 | 13 | ifeq ($(arch), IA32) 14 | CCFLAGS += -DIA32 15 | endif 16 | 17 | ifeq ($(arch), POWERPC) 18 | CCFLAGS += -mcpu=powerpc 19 | endif 20 | 21 | ifeq ($(arch), SPARC) 22 | CCFLAGS += -DSPARC 23 | endif 24 | 25 | ifeq ($(arch), IA64) 26 | CCFLAGS += -DIA64 27 | endif 28 | 29 | ifeq ($(arch), AMD64) 30 | CCFLAGS += -DAMD64 31 | endif 32 | 33 | OBJS = md5.o common.o window.o list.o buffer.o packet.o channel.o queue.o ccc.o cache.o core.o epoll.o api.o 34 | DIR = $(shell pwd) 35 | 36 | all: libudt.so libudt.a udt 37 | 38 | %.o: %.cpp %.h udt.h 39 | $(C++) $(CCFLAGS) $< -c 40 | 41 | libudt.so: $(OBJS) 42 | ifneq ($(os), OSX) 43 | $(C++) -shared -o $@ $^ 44 | else 45 | $(C++) -dynamiclib -o libudt.dylib -lstdc++ -lpthread -lm $^ 46 | endif 47 | 48 | libudt.a: $(OBJS) 49 | ar -rcs $@ $^ 50 | 51 | udt: 52 | cp udt.h udt 53 | 54 | clean: 55 | rm -f *.o *.so *.dylib *.a udt 56 | 57 | install: 58 | export LD_LIBRARY_PATH=$(DIR):$$LD_LIBRARY_PATH 59 | -------------------------------------------------------------------------------- /sender/src/cache.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 05/05/2009 39 | *****************************************************************************/ 40 | 41 | #ifdef WIN32 42 | #include 43 | #include 44 | #ifdef LEGACY_WIN32 45 | #include 46 | #endif 47 | #endif 48 | 49 | #include 50 | #include "cache.h" 51 | #include "core.h" 52 | 53 | using namespace std; 54 | 55 | CInfoBlock& CInfoBlock::operator=(const CInfoBlock& obj) 56 | { 57 | std::copy(obj.m_piIP, obj.m_piIP + 3, m_piIP); 58 | m_iIPversion = obj.m_iIPversion; 59 | m_ullTimeStamp = obj.m_ullTimeStamp; 60 | m_iRTT = obj.m_iRTT; 61 | m_iBandwidth = obj.m_iBandwidth; 62 | m_iLossRate = obj.m_iLossRate; 63 | m_iReorderDistance = obj.m_iReorderDistance; 64 | m_dInterval = obj.m_dInterval; 65 | m_dCWnd = obj.m_dCWnd; 66 | 67 | return *this; 68 | } 69 | 70 | bool CInfoBlock::operator==(const CInfoBlock& obj) 71 | { 72 | if (m_iIPversion != obj.m_iIPversion) 73 | return false; 74 | 75 | else if (m_iIPversion == AF_INET) 76 | return (m_piIP[0] == obj.m_piIP[0]); 77 | 78 | for (int i = 0; i < 4; ++ i) 79 | { 80 | if (m_piIP[i] != obj.m_piIP[i]) 81 | return false; 82 | } 83 | 84 | return true; 85 | } 86 | 87 | CInfoBlock* CInfoBlock::clone() 88 | { 89 | CInfoBlock* obj = new CInfoBlock; 90 | 91 | std::copy(m_piIP, m_piIP + 3, obj->m_piIP); 92 | obj->m_iIPversion = m_iIPversion; 93 | obj->m_ullTimeStamp = m_ullTimeStamp; 94 | obj->m_iRTT = m_iRTT; 95 | obj->m_iBandwidth = m_iBandwidth; 96 | obj->m_iLossRate = m_iLossRate; 97 | obj->m_iReorderDistance = m_iReorderDistance; 98 | obj->m_dInterval = m_dInterval; 99 | obj->m_dCWnd = m_dCWnd; 100 | 101 | return obj; 102 | } 103 | 104 | int CInfoBlock::getKey() 105 | { 106 | if (m_iIPversion == AF_INET) 107 | return m_piIP[0]; 108 | 109 | return m_piIP[0] + m_piIP[1] + m_piIP[2] + m_piIP[3]; 110 | } 111 | 112 | void CInfoBlock::convert(const sockaddr* addr, const int& ver, uint32_t ip[]) 113 | { 114 | if (ver == AF_INET) 115 | { 116 | ip[0] = ((sockaddr_in*)addr)->sin_addr.s_addr; 117 | ip[1] = ip[2] = ip[3] = 0; 118 | } 119 | else 120 | { 121 | memcpy((char*)ip, (char*)((sockaddr_in6*)addr)->sin6_addr.s6_addr, 16); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /sender/src/cache.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/27/2011 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_CACHE_H__ 42 | #define __UDT_CACHE_H__ 43 | 44 | #include 45 | #include 46 | 47 | #include "common.h" 48 | #include "udt.h" 49 | 50 | class CCacheItem 51 | { 52 | public: 53 | virtual ~CCacheItem() {} 54 | 55 | public: 56 | virtual CCacheItem& operator=(const CCacheItem&) = 0; 57 | 58 | // The "==" operator SHOULD only compare key values. 59 | virtual bool operator==(const CCacheItem&) = 0; 60 | 61 | // Functionality: 62 | // get a deep copy clone of the current item 63 | // Parameters: 64 | // None. 65 | // Returned value: 66 | // Pointer to the new item, or NULL if failed. 67 | 68 | virtual CCacheItem* clone() = 0; 69 | 70 | // Functionality: 71 | // get a random key value between 0 and MAX_INT to be used for the hash in cache 72 | // Parameters: 73 | // None. 74 | // Returned value: 75 | // A random hash key. 76 | 77 | virtual int getKey() = 0; 78 | 79 | // If there is any shared resources between the cache item and its clone, 80 | // the shared resource should be released by this function. 81 | virtual void release() {} 82 | }; 83 | 84 | template class CCache 85 | { 86 | public: 87 | CCache(const int& size = 1024): 88 | m_iMaxSize(size), 89 | m_iHashSize(size * 3), 90 | m_iCurrSize(0) 91 | { 92 | m_vHashPtr.resize(m_iHashSize); 93 | CGuard::createMutex(m_Lock); 94 | } 95 | 96 | ~CCache() 97 | { 98 | clear(); 99 | CGuard::releaseMutex(m_Lock); 100 | } 101 | 102 | public: 103 | // Functionality: 104 | // find the matching item in the cache. 105 | // Parameters: 106 | // 0) [in/out] data: storage for the retrieved item; initially it must carry the key information 107 | // Returned value: 108 | // 0 if found a match, otherwise -1. 109 | 110 | int lookup(T* data) 111 | { 112 | CGuard cacheguard(m_Lock); 113 | 114 | int key = data->getKey(); 115 | if (key < 0) 116 | return -1; 117 | if (key >= m_iMaxSize) 118 | key %= m_iHashSize; 119 | 120 | const ItemPtrList& item_list = m_vHashPtr[key]; 121 | for (typename ItemPtrList::const_iterator i = item_list.begin(); i != item_list.end(); ++ i) 122 | { 123 | if (*data == ***i) 124 | { 125 | // copy the cached info 126 | *data = ***i; 127 | return 0; 128 | } 129 | } 130 | 131 | return -1; 132 | } 133 | 134 | // Functionality: 135 | // update an item in the cache, or insert one if it doesn't exist; oldest item may be removed 136 | // Parameters: 137 | // 0) [in] data: the new item to updated/inserted to the cache 138 | // Returned value: 139 | // 0 if success, otherwise -1. 140 | 141 | int update(T* data) 142 | { 143 | CGuard cacheguard(m_Lock); 144 | 145 | int key = data->getKey(); 146 | if (key < 0) 147 | return -1; 148 | if (key >= m_iMaxSize) 149 | key %= m_iHashSize; 150 | 151 | T* curr = NULL; 152 | 153 | ItemPtrList& item_list = m_vHashPtr[key]; 154 | for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i) 155 | { 156 | if (*data == ***i) 157 | { 158 | // update the existing entry with the new value 159 | ***i = *data; 160 | curr = **i; 161 | 162 | // remove the current entry 163 | m_StorageList.erase(*i); 164 | item_list.erase(i); 165 | 166 | // re-insert to the front 167 | m_StorageList.push_front(curr); 168 | item_list.push_front(m_StorageList.begin()); 169 | 170 | return 0; 171 | } 172 | } 173 | 174 | // create new entry and insert to front 175 | curr = data->clone(); 176 | m_StorageList.push_front(curr); 177 | item_list.push_front(m_StorageList.begin()); 178 | 179 | ++ m_iCurrSize; 180 | if (m_iCurrSize >= m_iMaxSize) 181 | { 182 | // Cache overflow, remove oldest entry. 183 | T* last_data = m_StorageList.back(); 184 | int last_key = last_data->getKey() % m_iHashSize; 185 | 186 | item_list = m_vHashPtr[last_key]; 187 | for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i) 188 | { 189 | if (*last_data == ***i) 190 | { 191 | item_list.erase(i); 192 | break; 193 | } 194 | } 195 | 196 | last_data->release(); 197 | delete last_data; 198 | m_StorageList.pop_back(); 199 | -- m_iCurrSize; 200 | } 201 | 202 | return 0; 203 | } 204 | 205 | // Functionality: 206 | // Specify the cache size (i.e., max number of items). 207 | // Parameters: 208 | // 0) [in] size: max cache size. 209 | // Returned value: 210 | // None. 211 | 212 | void setSizeLimit(const int& size) 213 | { 214 | m_iMaxSize = size; 215 | m_iHashSize = size * 3; 216 | m_vHashPtr.resize(m_iHashSize); 217 | } 218 | 219 | // Functionality: 220 | // Clear all entries in the cache, restore to initialization state. 221 | // Parameters: 222 | // None. 223 | // Returned value: 224 | // None. 225 | 226 | void clear() 227 | { 228 | for (typename std::list::iterator i = m_StorageList.begin(); i != m_StorageList.end(); ++ i) 229 | { 230 | (*i)->release(); 231 | delete *i; 232 | } 233 | m_StorageList.clear(); 234 | for (typename std::vector::iterator i = m_vHashPtr.begin(); i != m_vHashPtr.end(); ++ i) 235 | i->clear(); 236 | m_iCurrSize = 0; 237 | } 238 | 239 | private: 240 | std::list m_StorageList; 241 | typedef typename std::list::iterator ItemPtr; 242 | typedef std::list ItemPtrList; 243 | std::vector m_vHashPtr; 244 | 245 | int m_iMaxSize; 246 | int m_iHashSize; 247 | int m_iCurrSize; 248 | 249 | pthread_mutex_t m_Lock; 250 | 251 | private: 252 | CCache(const CCache&); 253 | CCache& operator=(const CCache&); 254 | }; 255 | 256 | 257 | class CInfoBlock 258 | { 259 | public: 260 | uint32_t m_piIP[4]; // IP address, machine read only, not human readable format 261 | int m_iIPversion; // IP version 262 | uint64_t m_ullTimeStamp; // last update time 263 | int m_iRTT; // RTT 264 | int m_iBandwidth; // estimated bandwidth 265 | int m_iLossRate; // average loss rate 266 | int m_iReorderDistance; // packet reordering distance 267 | double m_dInterval; // inter-packet time, congestion control 268 | double m_dCWnd; // congestion window size, congestion control 269 | 270 | public: 271 | virtual ~CInfoBlock() {} 272 | virtual CInfoBlock& operator=(const CInfoBlock& obj); 273 | virtual bool operator==(const CInfoBlock& obj); 274 | virtual CInfoBlock* clone(); 275 | virtual int getKey(); 276 | virtual void release() {} 277 | 278 | public: 279 | 280 | // Functionality: 281 | // convert sockaddr structure to an integer array 282 | // Parameters: 283 | // 0) [in] addr: network address 284 | // 1) [in] ver: IP version 285 | // 2) [out] ip: the result machine readable IP address in integer array 286 | // Returned value: 287 | // None. 288 | 289 | static void convert(const sockaddr* addr, const int& ver, uint32_t ip[]); 290 | }; 291 | 292 | 293 | #endif 294 | -------------------------------------------------------------------------------- /sender/src/ccc.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 03/17/2011 39 | *****************************************************************************/ 40 | 41 | 42 | #include "core.h" 43 | #include "ccc.h" 44 | #include 45 | #include 46 | 47 | CCC::CCC(): 48 | m_iSYNInterval(CUDT::m_iSYNInterval), 49 | m_dPktSndPeriod(1.0), 50 | m_dCWndSize(16.0), 51 | m_iBandwidth(), 52 | m_dMaxCWndSize(), 53 | m_iMSS(), 54 | m_iSndCurrSeqNo(), 55 | m_iRcvRate(), 56 | m_iRTT(), 57 | m_pcParam(NULL), 58 | m_iPSize(0), 59 | m_UDT(), 60 | m_iACKPeriod(0), 61 | m_iACKInterval(0), 62 | m_bUserDefinedRTO(true), 63 | m_iRTO(-1), 64 | m_PerfInfo() 65 | { 66 | } 67 | 68 | CCC::~CCC() 69 | { 70 | delete [] m_pcParam; 71 | } 72 | 73 | void CCC::setACKTimer(const int& msINT) 74 | { 75 | m_iACKPeriod = msINT; 76 | 77 | if (m_iACKPeriod > m_iSYNInterval) 78 | m_iACKPeriod = m_iSYNInterval; 79 | } 80 | 81 | void CCC::setACKInterval(const int& pktINT) 82 | { 83 | m_iACKInterval = pktINT; 84 | } 85 | 86 | void CCC::setRTO(const int& usRTO) 87 | { 88 | m_bUserDefinedRTO = true; 89 | m_iRTO = usRTO; 90 | } 91 | 92 | void CCC::sendCustomMsg(CPacket& pkt) const 93 | { 94 | CUDT* u = CUDT::getUDTHandle(m_UDT); 95 | 96 | if (NULL != u) 97 | { 98 | pkt.m_iID = u->m_PeerID; 99 | u->m_pSndQueue->sendto(u->m_pPeerAddr, pkt); 100 | } 101 | } 102 | 103 | const CPerfMon* CCC::getPerfInfo() 104 | { 105 | try 106 | { 107 | CUDT* u = CUDT::getUDTHandle(m_UDT); 108 | if (NULL != u) 109 | u->sample(&m_PerfInfo, false); 110 | } 111 | catch (...) 112 | { 113 | return NULL; 114 | } 115 | 116 | return &m_PerfInfo; 117 | } 118 | 119 | void CCC::setMSS(const int& mss) 120 | { 121 | m_iMSS = mss; 122 | } 123 | 124 | void CCC::setBandwidth(const int& bw) 125 | { 126 | m_iBandwidth = bw; 127 | } 128 | 129 | void CCC::setSndCurrSeqNo(const int32_t& seqno) 130 | { 131 | m_iSndCurrSeqNo = seqno; 132 | } 133 | 134 | void CCC::setRcvRate(const int& rcvrate) 135 | { 136 | m_iRcvRate = rcvrate; 137 | } 138 | 139 | void CCC::setMaxCWndSize(const int& cwnd) 140 | { 141 | m_dMaxCWndSize = cwnd; 142 | } 143 | 144 | void CCC::setRTT(const int& rtt) 145 | { 146 | m_iRTT = rtt; 147 | } 148 | 149 | void CCC::setUserParam(const char* param, const int& size) 150 | { 151 | delete [] m_pcParam; 152 | m_pcParam = new char[size]; 153 | memcpy(m_pcParam, param, size); 154 | m_iPSize = size; 155 | } 156 | 157 | // 158 | CUDTCC::CUDTCC(): 159 | m_iRCInterval(), 160 | m_LastRCTime(), 161 | m_bSlowStart(), 162 | m_iLastAck(), 163 | m_bLoss(), 164 | m_iLastDecSeq(), 165 | m_dLastDecPeriod(), 166 | m_iNAKCount(), 167 | m_iDecRandom(), 168 | m_iAvgNAKNum(), 169 | m_iDecCount() 170 | { 171 | } 172 | 173 | void CUDTCC::init() 174 | { 175 | m_iRCInterval = m_iSYNInterval; 176 | m_LastRCTime = CTimer::getTime(); 177 | setACKTimer(m_iRCInterval); 178 | 179 | m_bSlowStart = true; 180 | m_iLastAck = m_iSndCurrSeqNo; 181 | m_bLoss = false; 182 | m_iLastDecSeq = CSeqNo::decseq(m_iLastAck); 183 | m_dLastDecPeriod = 1; 184 | m_iAvgNAKNum = 0; 185 | m_iNAKCount = 0; 186 | m_iDecRandom = 1; 187 | 188 | m_dCWndSize = 16; 189 | m_dPktSndPeriod = 1; 190 | } 191 | 192 | void CUDTCC::onACK(const int32_t& ack) 193 | { 194 | int64_t B = 0; 195 | double inc = 0; 196 | 197 | uint64_t currtime = CTimer::getTime(); 198 | if (currtime - m_LastRCTime < (uint64_t)m_iRCInterval) 199 | return; 200 | 201 | m_LastRCTime = currtime; 202 | 203 | if (m_bSlowStart) 204 | { 205 | m_dCWndSize += CSeqNo::seqlen(m_iLastAck, ack); 206 | m_iLastAck = ack; 207 | 208 | if (m_dCWndSize > m_dMaxCWndSize) 209 | { 210 | m_bSlowStart = false; 211 | if (m_iRcvRate > 0) 212 | m_dPktSndPeriod = 1000000.0 / m_iRcvRate; 213 | else 214 | m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval); 215 | } 216 | } 217 | else 218 | m_dCWndSize = m_iRcvRate / 1000000.0 * (m_iRTT + m_iRCInterval) + 16; 219 | 220 | // During Slow Start, no rate increase 221 | if (m_bSlowStart) 222 | goto RATE_LIMIT; 223 | 224 | if (m_bLoss) 225 | { 226 | m_bLoss = false; 227 | goto RATE_LIMIT; 228 | } 229 | 230 | B = (int64_t)(m_iBandwidth - 1000000.0 / m_dPktSndPeriod); 231 | if ((m_dPktSndPeriod > m_dLastDecPeriod) && ((m_iBandwidth / 9) < B)) 232 | B = m_iBandwidth / 9; 233 | if (B <= 0) 234 | inc = 1.0 / m_iMSS; 235 | else 236 | { 237 | // inc = max(10 ^ ceil(log10( B * MSS * 8 ) * Beta / MSS, 1/MSS) 238 | // Beta = 1.5 * 10^(-6) 239 | 240 | inc = pow(10.0, ceil(log10(B * m_iMSS * 8.0))) * 0.0000015 / m_iMSS; 241 | 242 | if (inc < 1.0/m_iMSS) 243 | inc = 1.0/m_iMSS; 244 | } 245 | 246 | m_dPktSndPeriod = (m_dPktSndPeriod * m_iRCInterval) / (m_dPktSndPeriod * inc + m_iRCInterval); 247 | 248 | 249 | RATE_LIMIT: 250 | //set maximum transfer rate 251 | if ((NULL != m_pcParam) && (m_iPSize == 8)) 252 | { 253 | int64_t maxSR = *(int64_t*)m_pcParam; 254 | if (maxSR <= 0) 255 | return; 256 | 257 | double minSP = 1000000.0 / (double(maxSR) / m_iMSS); 258 | if (m_dPktSndPeriod < minSP) 259 | m_dPktSndPeriod = minSP; 260 | } 261 | } 262 | 263 | void CUDTCC::onLoss(const int32_t* losslist, const int&) 264 | { 265 | //Slow Start stopped, if it hasn't yet 266 | if (m_bSlowStart) 267 | { 268 | m_bSlowStart = false; 269 | if (m_iRcvRate > 0) 270 | m_dPktSndPeriod = 1000000.0 / m_iRcvRate; 271 | else 272 | m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval); 273 | } 274 | 275 | m_bLoss = true; 276 | 277 | if (CSeqNo::seqcmp(losslist[0] & 0x7FFFFFFF, m_iLastDecSeq) > 0) 278 | { 279 | m_dLastDecPeriod = m_dPktSndPeriod; 280 | m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125); 281 | 282 | m_iAvgNAKNum = (int)ceil(m_iAvgNAKNum * 0.875 + m_iNAKCount * 0.125); 283 | m_iNAKCount = 1; 284 | m_iDecCount = 1; 285 | 286 | m_iLastDecSeq = m_iSndCurrSeqNo; 287 | 288 | // remove global synchronization using randomization 289 | srand(m_iLastDecSeq); 290 | m_iDecRandom = (int)ceil(m_iAvgNAKNum * (double(rand()) / RAND_MAX)); 291 | if (m_iDecRandom < 1) 292 | m_iDecRandom = 1; 293 | } 294 | else if ((m_iDecCount ++ < 5) && (0 == (++ m_iNAKCount % m_iDecRandom))) 295 | { 296 | // 0.875^5 = 0.51, rate should not be decreased by more than half within a congestion period 297 | m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125); 298 | m_iLastDecSeq = m_iSndCurrSeqNo; 299 | } 300 | } 301 | 302 | void CUDTCC::onTimeout() 303 | { 304 | if (m_bSlowStart) 305 | { 306 | m_bSlowStart = false; 307 | if (m_iRcvRate > 0) 308 | m_dPktSndPeriod = 1000000.0 / m_iRcvRate; 309 | else 310 | m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval); 311 | } 312 | else 313 | { 314 | /* 315 | m_dLastDecPeriod = m_dPktSndPeriod; 316 | m_dPktSndPeriod = ceil(m_dPktSndPeriod * 2); 317 | m_iLastDecSeq = m_iLastAck; 318 | */ 319 | } 320 | } 321 | -------------------------------------------------------------------------------- /sender/src/channel.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/27/2011 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_CHANNEL_H__ 42 | #define __UDT_CHANNEL_H__ 43 | 44 | 45 | #include "udt.h" 46 | #include "packet.h" 47 | 48 | 49 | class CChannel 50 | { 51 | public: 52 | CChannel(); 53 | CChannel(const int& version); 54 | ~CChannel(); 55 | 56 | // Functionality: 57 | // Opne a UDP channel. 58 | // Parameters: 59 | // 0) [in] addr: The local address that UDP will use. 60 | // Returned value: 61 | // None. 62 | 63 | void open(const sockaddr* addr = NULL); 64 | 65 | // Functionality: 66 | // Opne a UDP channel based on an existing UDP socket. 67 | // Parameters: 68 | // 0) [in] udpsock: UDP socket descriptor. 69 | // Returned value: 70 | // None. 71 | 72 | void open(UDPSOCKET udpsock); 73 | 74 | // Functionality: 75 | // Disconnect and close the UDP entity. 76 | // Parameters: 77 | // None. 78 | // Returned value: 79 | // None. 80 | 81 | void close() const; 82 | 83 | // Functionality: 84 | // Get the UDP sending buffer size. 85 | // Parameters: 86 | // None. 87 | // Returned value: 88 | // Current UDP sending buffer size. 89 | 90 | int getSndBufSize(); 91 | 92 | // Functionality: 93 | // Get the UDP receiving buffer size. 94 | // Parameters: 95 | // None. 96 | // Returned value: 97 | // Current UDP receiving buffer size. 98 | 99 | int getRcvBufSize(); 100 | 101 | // Functionality: 102 | // Set the UDP sending buffer size. 103 | // Parameters: 104 | // 0) [in] size: expected UDP sending buffer size. 105 | // Returned value: 106 | // None. 107 | 108 | void setSndBufSize(const int& size); 109 | 110 | // Functionality: 111 | // Set the UDP receiving buffer size. 112 | // Parameters: 113 | // 0) [in] size: expected UDP receiving buffer size. 114 | // Returned value: 115 | // None. 116 | 117 | void setRcvBufSize(const int& size); 118 | 119 | // Functionality: 120 | // Query the socket address that the channel is using. 121 | // Parameters: 122 | // 0) [out] addr: pointer to store the returned socket address. 123 | // Returned value: 124 | // None. 125 | 126 | void getSockAddr(sockaddr* addr) const; 127 | 128 | // Functionality: 129 | // Query the peer side socket address that the channel is connect to. 130 | // Parameters: 131 | // 0) [out] addr: pointer to store the returned socket address. 132 | // Returned value: 133 | // None. 134 | 135 | void getPeerAddr(sockaddr* addr) const; 136 | 137 | // Functionality: 138 | // Send a packet to the given address. 139 | // Parameters: 140 | // 0) [in] addr: pointer to the destination address. 141 | // 1) [in] packet: reference to a CPacket entity. 142 | // Returned value: 143 | // Actual size of data sent. 144 | 145 | int sendto(const sockaddr* addr, CPacket& packet) const; 146 | 147 | // Functionality: 148 | // Receive a packet from the channel and record the source address. 149 | // Parameters: 150 | // 0) [in] addr: pointer to the source address. 151 | // 1) [in] packet: reference to a CPacket entity. 152 | // Returned value: 153 | // Actual size of data received. 154 | 155 | int recvfrom(sockaddr* addr, CPacket& packet) const; 156 | 157 | private: 158 | void setUDPSockOpt(); 159 | 160 | private: 161 | int m_iIPversion; // IP version 162 | int m_iSockAddrSize; // socket address structure size (pre-defined to avoid run-time test) 163 | 164 | UDPSOCKET m_iSocket; // socket descriptor 165 | 166 | int m_iSndBufSize; // UDP sending buffer size 167 | int m_iRcvBufSize; // UDP receiving buffer size 168 | }; 169 | 170 | 171 | #endif 172 | -------------------------------------------------------------------------------- /sender/src/epoll.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 08/20/2010 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_EPOLL_H__ 42 | #define __UDT_EPOLL_H__ 43 | 44 | 45 | #include 46 | #include 47 | #include "udt.h" 48 | 49 | 50 | struct CEPollDesc 51 | { 52 | int m_iID; // epoll ID 53 | std::set m_sUDTSocksOut; // set of UDT sockets waiting for write events 54 | std::set m_sUDTSocksIn; // set of UDT sockets waiting for read events 55 | 56 | int m_iLocalID; // local system epoll ID 57 | std::set m_sLocals; // set of local (non-UDT) descriptors 58 | 59 | std::set m_sUDTWrites; // UDT sockets ready for write 60 | std::set m_sUDTReads; // UDT sockets ready for read 61 | }; 62 | 63 | class CEPoll 64 | { 65 | friend class CUDT; 66 | friend class CRendezvousQueue; 67 | 68 | public: 69 | CEPoll(); 70 | ~CEPoll(); 71 | 72 | public: // for CUDTUnited API 73 | 74 | // Functionality: 75 | // create a new EPoll. 76 | // Parameters: 77 | // None. 78 | // Returned value: 79 | // new EPoll ID if success, otherwise an error number. 80 | 81 | int create(); 82 | 83 | // Functionality: 84 | // add a UDT socket to an EPoll. 85 | // Parameters: 86 | // 0) [in] eid: EPoll ID. 87 | // 1) [in] u: UDT Socket ID. 88 | // 2) [in] events: events to watch. 89 | // Returned value: 90 | // 0 if success, otherwise an error number. 91 | 92 | int add_usock(const int eid, const UDTSOCKET& u, const int* events = NULL); 93 | 94 | // Functionality: 95 | // add a system socket to an EPoll. 96 | // Parameters: 97 | // 0) [in] eid: EPoll ID. 98 | // 1) [in] s: system Socket ID. 99 | // 2) [in] events: events to watch. 100 | // Returned value: 101 | // 0 if success, otherwise an error number. 102 | 103 | int add_ssock(const int eid, const SYSSOCKET& s, const int* events = NULL); 104 | 105 | // Functionality: 106 | // remove a UDT socket event from an EPoll; socket will be removed if no events to watch 107 | // Parameters: 108 | // 0) [in] eid: EPoll ID. 109 | // 1) [in] u: UDT socket ID. 110 | // Returned value: 111 | // 0 if success, otherwise an error number. 112 | 113 | int remove_usock(const int eid, const UDTSOCKET& u); 114 | 115 | // Functionality: 116 | // remove a system socket event from an EPoll; socket will be removed if no events to watch 117 | // Parameters: 118 | // 0) [in] eid: EPoll ID. 119 | // 1) [in] s: system socket ID. 120 | // Returned value: 121 | // 0 if success, otherwise an error number. 122 | 123 | int remove_ssock(const int eid, const SYSSOCKET& s); 124 | 125 | // Functionality: 126 | // wait for EPoll events or timeout. 127 | // Parameters: 128 | // 0) [in] eid: EPoll ID. 129 | // 1) [out] readfds: UDT sockets available for reading. 130 | // 2) [out] writefds: UDT sockets available for writing. 131 | // 3) [in] msTimeOut: timeout threshold, in milliseconds. 132 | // 4) [out] lrfds: system file descriptors for reading. 133 | // 5) [out] lwfds: system file descriptors for writing. 134 | // Returned value: 135 | // number of sockets available for IO. 136 | 137 | int wait(const int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, std::set* lrfds, std::set* lwfds); 138 | 139 | // Functionality: 140 | // close and release an EPoll. 141 | // Parameters: 142 | // 0) [in] eid: EPoll ID. 143 | // Returned value: 144 | // 0 if success, otherwise an error number. 145 | 146 | int release(const int eid); 147 | 148 | public: // for CUDT to acknowledge IO status 149 | 150 | // Functionality: 151 | // set a UDT socket writable. 152 | // Parameters: 153 | // 0) [in] uid: UDT socket ID. 154 | // 1) [in] eids: EPoll IDs to be set 155 | // Returned value: 156 | // 0 if success, otherwise an error number. 157 | 158 | int enable_write(const UDTSOCKET& uid, std::set& eids); 159 | 160 | // Functionality: 161 | // set a UDT socket readable. 162 | // Parameters: 163 | // 0) [in] uid: UDT socket ID. 164 | // 1) [in] eids: EPoll IDs to be set 165 | // Returned value: 166 | // 0 if success, otherwise an error number. 167 | 168 | int enable_read(const UDTSOCKET& uid, std::set& eids); 169 | 170 | // Functionality: 171 | // reset a the writable status of a UDT socket. 172 | // Parameters: 173 | // 0) [in] uid: UDT socket ID. 174 | // 1) [in] eids: EPoll IDs to be set 175 | // Returned value: 176 | // 0 if success, otherwise an error number. 177 | 178 | int disable_write(const UDTSOCKET& uid, std::set& eids); 179 | 180 | // Functionality: 181 | // reset a the readable status of a UDT socket. 182 | // Parameters: 183 | // 0) [in] uid: UDT socket ID. 184 | // 1) [in] eids: EPoll IDs to be set 185 | // Returned value: 186 | // 0 if success, otherwise an error number. 187 | 188 | int disable_read(const UDTSOCKET& uid, std::set& eids); 189 | 190 | private: 191 | int m_iIDSeed; // seed to generate a new ID 192 | pthread_mutex_t m_SeedLock; 193 | 194 | std::map m_mPolls; // all epolls 195 | pthread_mutex_t m_EPollLock; 196 | }; 197 | 198 | 199 | #endif 200 | -------------------------------------------------------------------------------- /sender/src/list.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/22/2011 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_LIST_H__ 42 | #define __UDT_LIST_H__ 43 | 44 | 45 | #include "udt.h" 46 | #include "common.h" 47 | #include 48 | using namespace std; 49 | class CSndLossList 50 | { 51 | public: 52 | CSndLossList(const int& size = 500000); 53 | ~CSndLossList(); 54 | 55 | // Functionality: 56 | // Insert a seq. no. into the sender loss list. 57 | // Parameters: 58 | // 0) [in] seqno1: sequence number starts. 59 | // 1) [in] seqno2: sequence number ends. 60 | // Returned value: 61 | // number of packets that are not in the list previously. 62 | 63 | int insert(const int32_t& seqno1, const int32_t& seqno2); 64 | 65 | // Functionality: 66 | // Remove ALL the seq. no. that are not greater than the parameter. 67 | // Parameters: 68 | // 0) [in] seqno: sequence number. 69 | // Returned value: 70 | // None. 71 | 72 | void remove(const int32_t& seqno); 73 | 74 | // Functionality: 75 | // Read the loss length. 76 | // Parameters: 77 | // None. 78 | // Returned value: 79 | // The length of the list. 80 | 81 | int getLossLength(); 82 | 83 | // Functionality: 84 | // Read the first (smallest) loss seq. no. in the list and remove it. 85 | // Parameters: 86 | // None. 87 | // Returned value: 88 | // The seq. no. or -1 if the list is empty. 89 | 90 | int32_t getLostSeq(); 91 | 92 | public: 93 | int32_t* m_piData1; // sequence number starts 94 | int32_t* m_piData2; // seqnence number ends 95 | int* m_piNext; // next node in the list 96 | 97 | int m_iHead; // first node 98 | int m_iLength; // loss length 99 | int m_iSize; // size of the static array 100 | int m_iLastInsertPos; // position of last insert node 101 | 102 | pthread_mutex_t m_ListLock; // used to synchronize list operation 103 | 104 | private: 105 | CSndLossList(const CSndLossList&); 106 | CSndLossList& operator=(const CSndLossList&); 107 | }; 108 | 109 | //////////////////////////////////////////////////////////////////////////////// 110 | 111 | class CRcvLossList 112 | { 113 | public: 114 | CRcvLossList(const int& size = 500000); 115 | ~CRcvLossList(); 116 | 117 | // Functionality: 118 | // Insert a series of loss seq. no. between "seqno1" and "seqno2" into the receiver's loss list. 119 | // Parameters: 120 | // 0) [in] seqno1: sequence number starts. 121 | // 1) [in] seqno2: seqeunce number ends. 122 | // Returned value: 123 | // None. 124 | 125 | void insert(const int32_t& seqno1, const int32_t& seqno2); 126 | 127 | // Functionality: 128 | // Remove a loss seq. no. from the receiver's loss list. 129 | // Parameters: 130 | // 0) [in] seqno: sequence number. 131 | // Returned value: 132 | // if the packet is removed (true) or no such lost packet is found (false). 133 | 134 | int remove(const int32_t& seqno); 135 | 136 | // Functionality: 137 | // Remove all packets between seqno1 and seqno2. 138 | // Parameters: 139 | // 0) [in] seqno1: start sequence number. 140 | // 1) [in] seqno2: end sequence number. 141 | // Returned value: 142 | // if the packet is removed (true) or no such lost packet is found (false). 143 | 144 | int remove(const int32_t& seqno1, const int32_t& seqno2); 145 | 146 | // Functionality: 147 | // Find if there is any lost packets whose sequence number falling seqno1 and seqno2. 148 | // Parameters: 149 | // 0) [in] seqno1: start sequence number. 150 | // 1) [in] seqno2: end sequence number. 151 | // Returned value: 152 | // True if found; otherwise false. 153 | 154 | bool find(const int32_t& seqno1, const int32_t& seqno2) const; 155 | 156 | // Functionality: 157 | // Read the loss length. 158 | // Parameters: 159 | // None. 160 | // Returned value: 161 | // the length of the list. 162 | 163 | int getLossLength() const; 164 | 165 | // Functionality: 166 | // Read the first (smallest) seq. no. in the list. 167 | // Parameters: 168 | // None. 169 | // Returned value: 170 | // the sequence number or -1 if the list is empty. 171 | 172 | int getFirstLostSeq() const; 173 | 174 | // Functionality: 175 | // Get a encoded loss array for NAK report. 176 | // Parameters: 177 | // 0) [out] array: the result list of seq. no. to be included in NAK. 178 | // 1) [out] physical length of the result array. 179 | // 2) [in] limit: maximum length of the array. 180 | // Returned value: 181 | // None. 182 | 183 | void getLossArray(int32_t* array, int& len, const int& limit); 184 | 185 | public: 186 | int32_t* m_piData1; // sequence number starts 187 | int32_t* m_piData2; // sequence number ends 188 | int* m_piNext; // next node in the list 189 | int* m_piPrior; // prior node in the list; 190 | 191 | int m_iHead; // first node in the list 192 | int m_iTail; // last node in the list; 193 | int m_iLength; // loss length 194 | int m_iSize; // size of the static array 195 | 196 | private: 197 | CRcvLossList(const CRcvLossList&); 198 | CRcvLossList& operator=(const CRcvLossList&); 199 | }; 200 | 201 | 202 | #endif 203 | -------------------------------------------------------------------------------- /sender/src/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* $Id: md5.h,v 1.2 2007/12/24 05:58:37 lilyco Exp $ */ 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321, whose 29 | text is available at 30 | http://www.ietf.org/rfc/rfc1321.txt 31 | The code is derived from the text of the RFC, including the test suite 32 | (section A.5) but excluding the rest of Appendix A. It does not include 33 | any code or documentation that is identified in the RFC as being 34 | copyrighted. 35 | 36 | The original and principal author of md5.h is L. Peter Deutsch 37 | . Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Removed support for non-ANSI compilers; removed 41 | references to Ghostscript; clarified derivation from RFC 1321; 42 | now handles byte order either statically or dynamically. 43 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 44 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); 45 | added conditionalization for C++ compilation from Martin 46 | Purschke . 47 | 1999-05-03 lpd Original version. 48 | */ 49 | 50 | #ifndef md5_INCLUDED 51 | # define md5_INCLUDED 52 | 53 | /* 54 | * This package supports both compile-time and run-time determination of CPU 55 | * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be 56 | * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is 57 | * defined as non-zero, the code will be compiled to run only on big-endian 58 | * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to 59 | * run on either big- or little-endian CPUs, but will run slightly less 60 | * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. 61 | */ 62 | 63 | typedef unsigned char md5_byte_t; /* 8-bit byte */ 64 | typedef unsigned int md5_word_t; /* 32-bit word */ 65 | 66 | /* Define the state of the MD5 Algorithm. */ 67 | typedef struct md5_state_s { 68 | md5_word_t count[2]; /* message length in bits, lsw first */ 69 | md5_word_t abcd[4]; /* digest buffer */ 70 | md5_byte_t buf[64]; /* accumulate block */ 71 | } md5_state_t; 72 | 73 | #ifdef __cplusplus 74 | extern "C" 75 | { 76 | #endif 77 | 78 | /* Initialize the algorithm. */ 79 | void md5_init(md5_state_t *pms); 80 | 81 | /* Append a string to the message. */ 82 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); 83 | 84 | /* Finish the message and return the digest. */ 85 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); 86 | 87 | #ifdef __cplusplus 88 | } /* end extern "C" */ 89 | #endif 90 | 91 | #endif /* md5_INCLUDED */ 92 | -------------------------------------------------------------------------------- /sender/src/packet.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/02/2011 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_PACKET_H__ 42 | #define __UDT_PACKET_H__ 43 | 44 | 45 | #include "udt.h" 46 | 47 | #ifdef WIN32 48 | struct iovec 49 | { 50 | int iov_len; 51 | char* iov_base; 52 | }; 53 | #endif 54 | 55 | class CChannel; 56 | 57 | class CPacket 58 | { 59 | friend class CChannel; 60 | friend class CSndQueue; 61 | friend class CRcvQueue; 62 | 63 | public: 64 | int32_t& m_iSeqNo; // alias: sequence number 65 | int32_t& m_iMsgNo; // alias: message number 66 | int32_t& m_iTimeStamp; // alias: timestamp 67 | int32_t& m_iID; // alias: socket ID 68 | char*& m_pcData; // alias: data/control information 69 | 70 | static const int m_iPktHdrSize; // packet header size 71 | 72 | public: 73 | CPacket(); 74 | ~CPacket(); 75 | 76 | // Functionality: 77 | // Get the payload or the control information field length. 78 | // Parameters: 79 | // None. 80 | // Returned value: 81 | // the payload or the control information field length. 82 | 83 | int getLength() const; 84 | 85 | // Functionality: 86 | // Set the payload or the control information field length. 87 | // Parameters: 88 | // 0) [in] len: the payload or the control information field length. 89 | // Returned value: 90 | // None. 91 | 92 | void setLength(const int& len); 93 | 94 | // Functionality: 95 | // Pack a Control packet. 96 | // Parameters: 97 | // 0) [in] pkttype: packet type filed. 98 | // 1) [in] lparam: pointer to the first data structure, explained by the packet type. 99 | // 2) [in] rparam: pointer to the second data structure, explained by the packet type. 100 | // 3) [in] size: size of rparam, in number of bytes; 101 | // Returned value: 102 | // None. 103 | 104 | void pack(const int& pkttype, void* lparam = NULL, void* rparam = NULL, const int& size = 0); 105 | 106 | // Functionality: 107 | // Read the packet vector. 108 | // Parameters: 109 | // None. 110 | // Returned value: 111 | // Pointer to the packet vector. 112 | 113 | iovec* getPacketVector(); 114 | 115 | // Functionality: 116 | // Read the packet flag. 117 | // Parameters: 118 | // None. 119 | // Returned value: 120 | // packet flag (0 or 1). 121 | 122 | int getFlag() const; 123 | 124 | // Functionality: 125 | // Read the packet type. 126 | // Parameters: 127 | // None. 128 | // Returned value: 129 | // packet type filed (000 ~ 111). 130 | 131 | int getType() const; 132 | 133 | // Functionality: 134 | // Read the extended packet type. 135 | // Parameters: 136 | // None. 137 | // Returned value: 138 | // extended packet type filed (0x000 ~ 0xFFF). 139 | 140 | int getExtendedType() const; 141 | 142 | // Functionality: 143 | // Read the ACK-2 seq. no. 144 | // Parameters: 145 | // None. 146 | // Returned value: 147 | // packet header field (bit 16~31). 148 | 149 | int32_t getAckSeqNo() const; 150 | 151 | // Functionality: 152 | // Read the message boundary flag bit. 153 | // Parameters: 154 | // None. 155 | // Returned value: 156 | // packet header field [1] (bit 0~1). 157 | 158 | int getMsgBoundary() const; 159 | 160 | // Functionality: 161 | // Read the message inorder delivery flag bit. 162 | // Parameters: 163 | // None. 164 | // Returned value: 165 | // packet header field [1] (bit 2). 166 | 167 | bool getMsgOrderFlag() const; 168 | 169 | // Functionality: 170 | // Read the message sequence number. 171 | // Parameters: 172 | // None. 173 | // Returned value: 174 | // packet header field [1] (bit 3~31). 175 | 176 | int32_t getMsgSeq() const; 177 | 178 | // Functionality: 179 | // Clone this packet. 180 | // Parameters: 181 | // None. 182 | // Returned value: 183 | // Pointer to the new packet. 184 | 185 | CPacket* clone() const; 186 | 187 | protected: 188 | uint32_t m_nHeader[4]; // The 128-bit header field 189 | iovec m_PacketVector[2]; // The 2-demension vector of UDT packet [header, data] 190 | 191 | int32_t __pad; 192 | 193 | protected: 194 | CPacket& operator=(const CPacket&); 195 | }; 196 | 197 | //////////////////////////////////////////////////////////////////////////////// 198 | 199 | class CHandShake 200 | { 201 | public: 202 | CHandShake(); 203 | 204 | int serialize(char* buf, int& size); 205 | int deserialize(const char* buf, const int& size); 206 | 207 | public: 208 | static const int m_iContentSize; // Size of hand shake data 209 | 210 | public: 211 | int32_t m_iVersion; // UDT version 212 | int32_t m_iType; // UDT socket type 213 | int32_t m_iISN; // random initial sequence number 214 | int32_t m_iMSS; // maximum segment size 215 | int32_t m_iFlightFlagSize; // flow control window size 216 | int32_t m_iReqType; // connection request type: 1: regular connection request, 0: rendezvous connection request, -1/-2: response 217 | int32_t m_iID; // socket ID 218 | int32_t m_iCookie; // cookie 219 | uint32_t m_piPeerIP[4]; // The IP address that the peer's UDP port is bound to 220 | }; 221 | 222 | 223 | #endif 224 | -------------------------------------------------------------------------------- /sender/src/window.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/22/2011 39 | *****************************************************************************/ 40 | 41 | #include 42 | #include "common.h" 43 | #include "window.h" 44 | #include 45 | 46 | using namespace std; 47 | 48 | CACKWindow::CACKWindow(const int& size): 49 | m_piACKSeqNo(NULL), 50 | m_piACK(NULL), 51 | m_pTimeStamp(NULL), 52 | m_iSize(size), 53 | m_iHead(0), 54 | m_iTail(0) 55 | { 56 | m_piACKSeqNo = new int32_t[m_iSize]; 57 | m_piACK = new int32_t[m_iSize]; 58 | m_pTimeStamp = new uint64_t[m_iSize]; 59 | 60 | m_piACKSeqNo[0] = -1; 61 | } 62 | 63 | CACKWindow::~CACKWindow() 64 | { 65 | delete [] m_piACKSeqNo; 66 | delete [] m_piACK; 67 | delete [] m_pTimeStamp; 68 | } 69 | 70 | void CACKWindow::store(const int32_t& seq, const int32_t& ack) 71 | { 72 | m_piACKSeqNo[m_iHead] = seq; 73 | m_piACK[m_iHead] = ack; 74 | m_pTimeStamp[m_iHead] = CTimer::getTime(); 75 | 76 | m_iHead = (m_iHead + 1) % m_iSize; 77 | 78 | // overwrite the oldest ACK since it is not likely to be acknowledged 79 | if (m_iHead == m_iTail) 80 | m_iTail = (m_iTail + 1) % m_iSize; 81 | } 82 | 83 | int CACKWindow::acknowledge(const int32_t& seq, int32_t& ack) 84 | { 85 | if (m_iHead >= m_iTail) 86 | { 87 | // Head has not exceeded the physical boundary of the window 88 | 89 | for (int i = m_iTail, n = m_iHead; i < n; ++ i) 90 | { 91 | // looking for indentical ACK Seq. No. 92 | if (seq == m_piACKSeqNo[i]) 93 | { 94 | // return the Data ACK it carried 95 | ack = m_piACK[i]; 96 | 97 | // calculate RTT 98 | int rtt = int(CTimer::getTime() - m_pTimeStamp[i]); 99 | 100 | if (i + 1 == m_iHead) 101 | { 102 | m_iTail = m_iHead = 0; 103 | m_piACKSeqNo[0] = -1; 104 | } 105 | else 106 | m_iTail = (i + 1) % m_iSize; 107 | 108 | return rtt; 109 | } 110 | } 111 | 112 | // Bad input, the ACK node has been overwritten 113 | return -1; 114 | } 115 | 116 | // Head has exceeded the physical window boundary, so it is behind tail 117 | for (int j = m_iTail, n = m_iHead + m_iSize; j < n; ++ j) 118 | { 119 | // looking for indentical ACK seq. no. 120 | if (seq == m_piACKSeqNo[j % m_iSize]) 121 | { 122 | // return Data ACK 123 | j %= m_iSize; 124 | ack = m_piACK[j]; 125 | 126 | // calculate RTT 127 | int rtt = int(CTimer::getTime() - m_pTimeStamp[j]); 128 | 129 | if (j == m_iHead) 130 | { 131 | m_iTail = m_iHead = 0; 132 | m_piACKSeqNo[0] = -1; 133 | } 134 | else 135 | m_iTail = (j + 1) % m_iSize; 136 | 137 | return rtt; 138 | } 139 | } 140 | 141 | // bad input, the ACK node has been overwritten 142 | return -1; 143 | } 144 | 145 | //////////////////////////////////////////////////////////////////////////////// 146 | 147 | CPktTimeWindow::CPktTimeWindow(const int& asize, const int& psize): 148 | m_iAWSize(asize), 149 | m_piPktWindow(NULL), 150 | m_iPktWindowPtr(0), 151 | m_iPWSize(psize), 152 | m_piProbeWindow(NULL), 153 | m_iProbeWindowPtr(0), 154 | m_iLastSentTime(0), 155 | m_iMinPktSndInt(1000000), 156 | m_LastArrTime(), 157 | m_CurrArrTime(), 158 | m_ProbeTime() 159 | { 160 | m_piPktWindow = new int[m_iAWSize]; 161 | m_piPktReplica = new int[m_iAWSize]; 162 | m_piProbeWindow = new int[m_iPWSize]; 163 | m_piProbeReplica = new int[m_iPWSize]; 164 | 165 | m_LastArrTime = CTimer::getTime(); 166 | 167 | for (int i = 0; i < m_iAWSize; ++ i) 168 | m_piPktWindow[i] = 1000000; 169 | 170 | for (int k = 0; k < m_iPWSize; ++ k) 171 | m_piProbeWindow[k] = 1000; 172 | } 173 | 174 | CPktTimeWindow::~CPktTimeWindow() 175 | { 176 | delete [] m_piPktWindow; 177 | delete [] m_piPktReplica; 178 | delete [] m_piProbeWindow; 179 | delete [] m_piProbeReplica; 180 | } 181 | 182 | int CPktTimeWindow::getMinPktSndInt() const 183 | { 184 | return m_iMinPktSndInt; 185 | } 186 | 187 | int CPktTimeWindow::getPktRcvSpeed() const 188 | { 189 | // get median value, but cannot change the original value order in the window 190 | std::copy(m_piPktWindow, m_piPktWindow + m_iAWSize - 1, m_piPktReplica); 191 | std::nth_element(m_piPktReplica, m_piPktReplica + (m_iAWSize / 2), m_piPktReplica + m_iAWSize - 1); 192 | int median = m_piPktReplica[m_iAWSize / 2]; 193 | 194 | int count = 0; 195 | int sum = 0; 196 | int upper = median << 3; 197 | int lower = median >> 3; 198 | 199 | // median filtering 200 | int* p = m_piPktWindow; 201 | for (int i = 0, n = m_iAWSize; i < n; ++ i) 202 | { 203 | if ((*p < upper) && (*p > lower)) 204 | { 205 | ++ count; 206 | sum += *p; 207 | } 208 | ++ p; 209 | } 210 | 211 | // claculate speed, or return 0 if not enough valid value 212 | if (count > (m_iAWSize >> 1)) 213 | return (int)ceil(1000000.0 / (sum / count)); 214 | else 215 | return 0; 216 | } 217 | 218 | int CPktTimeWindow::getBandwidth() const 219 | { 220 | // get median value, but cannot change the original value order in the window 221 | std::copy(m_piProbeWindow, m_piProbeWindow + m_iPWSize - 1, m_piProbeReplica); 222 | std::nth_element(m_piProbeReplica, m_piProbeReplica + (m_iPWSize / 2), m_piProbeReplica + m_iPWSize - 1); 223 | int median = m_piProbeReplica[m_iPWSize / 2]; 224 | 225 | int count = 1; 226 | int sum = median; 227 | int upper = median << 3; 228 | int lower = median >> 3; 229 | 230 | // median filtering 231 | int* p = m_piProbeWindow; 232 | for (int i = 0, n = m_iPWSize; i < n; ++ i) 233 | { 234 | if ((*p < upper) && (*p > lower)) 235 | { 236 | ++ count; 237 | sum += *p; 238 | } 239 | ++ p; 240 | } 241 | 242 | return (int)ceil(1000000.0 / (double(sum) / double(count))); 243 | } 244 | 245 | void CPktTimeWindow::onPktSent(const int& currtime) 246 | { 247 | int interval = currtime - m_iLastSentTime; 248 | 249 | if ((interval < m_iMinPktSndInt) && (interval > 0)) 250 | m_iMinPktSndInt = interval; 251 | 252 | m_iLastSentTime = currtime; 253 | } 254 | 255 | void CPktTimeWindow::onPktArrival() 256 | { 257 | m_CurrArrTime = CTimer::getTime(); 258 | 259 | // record the packet interval between the current and the last one 260 | *(m_piPktWindow + m_iPktWindowPtr) = int(m_CurrArrTime - m_LastArrTime); 261 | 262 | // the window is logically circular 263 | ++ m_iPktWindowPtr; 264 | if (m_iPktWindowPtr == m_iAWSize) 265 | m_iPktWindowPtr = 0; 266 | 267 | // remember last packet arrival time 268 | m_LastArrTime = m_CurrArrTime; 269 | } 270 | 271 | void CPktTimeWindow::probe1Arrival() 272 | { 273 | m_ProbeTime = CTimer::getTime(); 274 | } 275 | 276 | void CPktTimeWindow::probe2Arrival() 277 | { 278 | m_CurrArrTime = CTimer::getTime(); 279 | 280 | // record the probing packets interval 281 | *(m_piProbeWindow + m_iProbeWindowPtr) = int(m_CurrArrTime - m_ProbeTime); 282 | // the window is logically circular 283 | ++ m_iProbeWindowPtr; 284 | if (m_iProbeWindowPtr == m_iPWSize) 285 | m_iProbeWindowPtr = 0; 286 | } 287 | -------------------------------------------------------------------------------- /sender/src/window.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the 14 | above copyright notice, this list of conditions 15 | and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name of the University of Illinois 19 | nor the names of its contributors may be used to 20 | endorse or promote products derived from this 21 | software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | *****************************************************************************/ 35 | 36 | /***************************************************************************** 37 | written by 38 | Yunhong Gu, last updated 01/22/2011 39 | *****************************************************************************/ 40 | 41 | #ifndef __UDT_WINDOW_H__ 42 | #define __UDT_WINDOW_H__ 43 | 44 | 45 | #ifndef WIN32 46 | #include 47 | #include 48 | #endif 49 | #include "udt.h" 50 | 51 | 52 | class CACKWindow 53 | { 54 | public: 55 | CACKWindow(const int& size = 1024); 56 | ~CACKWindow(); 57 | 58 | // Functionality: 59 | // Write an ACK record into the window. 60 | // Parameters: 61 | // 0) [in] seq: ACK seq. no. 62 | // 1) [in] ack: DATA ACK no. 63 | // Returned value: 64 | // None. 65 | 66 | void store(const int32_t& seq, const int32_t& ack); 67 | 68 | // Functionality: 69 | // Search the ACK-2 "seq" in the window, find out the DATA "ack" and caluclate RTT . 70 | // Parameters: 71 | // 0) [in] seq: ACK-2 seq. no. 72 | // 1) [out] ack: the DATA ACK no. that matches the ACK-2 no. 73 | // Returned value: 74 | // RTT. 75 | 76 | int acknowledge(const int32_t& seq, int32_t& ack); 77 | 78 | private: 79 | int32_t* m_piACKSeqNo; // Seq. No. for the ACK packet 80 | int32_t* m_piACK; // Data Seq. No. carried by the ACK packet 81 | uint64_t* m_pTimeStamp; // The timestamp when the ACK was sent 82 | 83 | int m_iSize; // Size of the ACK history window 84 | int m_iHead; // Pointer to the lastest ACK record 85 | int m_iTail; // Pointer to the oldest ACK record 86 | 87 | private: 88 | CACKWindow(const CACKWindow&); 89 | CACKWindow& operator=(const CACKWindow&); 90 | }; 91 | 92 | //////////////////////////////////////////////////////////////////////////////// 93 | 94 | class CPktTimeWindow 95 | { 96 | public: 97 | CPktTimeWindow(const int& asize = 16, const int& psize = 16); 98 | ~CPktTimeWindow(); 99 | 100 | // Functionality: 101 | // read the minimum packet sending interval. 102 | // Parameters: 103 | // None. 104 | // Returned value: 105 | // minimum packet sending interval (microseconds). 106 | 107 | int getMinPktSndInt() const; 108 | 109 | // Functionality: 110 | // Calculate the packes arrival speed. 111 | // Parameters: 112 | // None. 113 | // Returned value: 114 | // Packet arrival speed (packets per second). 115 | 116 | int getPktRcvSpeed() const; 117 | 118 | // Functionality: 119 | // Estimate the bandwidth. 120 | // Parameters: 121 | // None. 122 | // Returned value: 123 | // Estimated bandwidth (packets per second). 124 | 125 | int getBandwidth() const; 126 | 127 | // Functionality: 128 | // Record time information of a packet sending. 129 | // Parameters: 130 | // 0) currtime: timestamp of the packet sending. 131 | // Returned value: 132 | // None. 133 | 134 | void onPktSent(const int& currtime); 135 | 136 | // Functionality: 137 | // Record time information of an arrived packet. 138 | // Parameters: 139 | // None. 140 | // Returned value: 141 | // None. 142 | 143 | void onPktArrival(); 144 | 145 | // Functionality: 146 | // Record the arrival time of the first probing packet. 147 | // Parameters: 148 | // None. 149 | // Returned value: 150 | // None. 151 | 152 | void probe1Arrival(); 153 | 154 | // Functionality: 155 | // Record the arrival time of the second probing packet and the interval between packet pairs. 156 | // Parameters: 157 | // None. 158 | // Returned value: 159 | // None. 160 | 161 | void probe2Arrival(); 162 | 163 | private: 164 | int m_iAWSize; // size of the packet arrival history window 165 | int* m_piPktWindow; // packet information window 166 | int* m_piPktReplica; 167 | int m_iPktWindowPtr; // position pointer of the packet info. window. 168 | 169 | int m_iPWSize; // size of probe history window size 170 | int* m_piProbeWindow; // record inter-packet time for probing packet pairs 171 | int* m_piProbeReplica; 172 | int m_iProbeWindowPtr; // position pointer to the probing window 173 | 174 | int m_iLastSentTime; // last packet sending time 175 | int m_iMinPktSndInt; // Minimum packet sending interval 176 | 177 | uint64_t m_LastArrTime; // last packet arrival time 178 | uint64_t m_CurrArrTime; // current packet arrival time 179 | uint64_t m_ProbeTime; // arrival time of the first probing packet 180 | 181 | private: 182 | CPktTimeWindow(const CPktTimeWindow&); 183 | CPktTimeWindow &operator=(const CPktTimeWindow&); 184 | }; 185 | 186 | 187 | #endif 188 | -------------------------------------------------------------------------------- /stop_demo_compare_tcp_and_pcc.sh: -------------------------------------------------------------------------------- 1 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair1.uiucscheduling.emulab.net "killall appclient" 2 | ssh -t -t -o StrictHostKeyChecking=no modong2@sender1.demopair2.uiucscheduling.emulab.net "killall iperf" 3 | -------------------------------------------------------------------------------- /tune_bw_rtt_loss.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def do_args(): 5 | import argparse 6 | p = argparse.ArgumentParser() 7 | p.add_argument("-b", "--bandwidth", dest="bw", default="100Mbit/s", 8 | help="URL of rabbitmq server") 9 | p.add_argument("-d","--delay", dest="delay", default="30ms", 10 | help="URL of rabbitmq server") 11 | p.add_argument("-q","--buffer", dest="queue", default="50slots", 12 | help="user name for the rabbitmq server") 13 | p.add_argument("-l", '--loss', dest='loss', default="0", 14 | help="password for rabbitmq server") 15 | return p.parse_args() 16 | 17 | def main(): 18 | opts = do_args() 19 | if opts.loss != "0": 20 | print "I am here" 21 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair1.uiucscheduling.emulab.net \"~/setloss.sh {}\"".format(opts.loss)) 22 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair2.uiucscheduling.emulab.net \"~/setloss.sh {}\"".format(opts.loss)) 23 | elif opts.loss == "0": 24 | print "iiiiiii" 25 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair1.uiucscheduling.emulab.net \"sudo iptables -F\"") 26 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair2.uiucscheduling.emulab.net \"sudo iptables -F\"") 27 | 28 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@bridge0.demopair1.uiucscheduling.emulab.net \"~/setpipe.sh {} {} {} {}\"".format("bw", 29 | opts.bw, 30 | "delay", 31 | opts.delay)) 32 | 33 | if opts.queue != "50slots": 34 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@bridge0.demopair2.uiucscheduling.emulab.net \"~/setpipe.sh {} {} {} {} {} {}\"".format("bw", 35 | opts.bw, 36 | "delay", 37 | opts.delay, 38 | "queue", 39 | opts.queue)) 40 | else: 41 | os.system("ssh -t -t -o StrictHostKeyChecking=no modong2@bridge0.demopair2.uiucscheduling.emulab.net \"~/setpipe.sh {} {} {} {}\"".format("bw", 42 | opts.bw, 43 | "delay", 44 | opts.delay)) 45 | 46 | 47 | 48 | 49 | if __name__ == "__main__": 50 | main() 51 | -------------------------------------------------------------------------------- /tune_bw_rtt_loss.sh: -------------------------------------------------------------------------------- 1 | ssh -t -t -o StrictHostKeyChecking=no modong2@bridge0.demopair1.uiucscheduling.emulab.net "~/setpipe.sh $1 $2 $3 $4 $5 $6" 2 | ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair1.uiucscheduling.emulab.net "~/setloss.sh $8" 3 | ssh -t -t -o StrictHostKeyChecking=no modong2@bridge0.demopair2.uiucscheduling.emulab.net "~/setpipe.sh $1 $2 $3 $4 $5 $6" 4 | ssh -t -t -o StrictHostKeyChecking=no modong2@receiver1.demopair2.uiucscheduling.emulab.net "~/setloss.sh $8" 5 | 6 | --------------------------------------------------------------------------------