├── GNULICENSE ├── README.md ├── examples ├── tcp-stream.cc └── wscript ├── helper ├── tcp-stream-helper.cc └── tcp-stream-helper.h ├── model ├── festive.cc ├── festive.h ├── panda.cc ├── panda.h ├── tcp-stream-adaptation-algorithm.cc ├── tcp-stream-adaptation-algorithm.h ├── tcp-stream-client.cc ├── tcp-stream-client.h ├── tcp-stream-interface.h ├── tcp-stream-server.cc ├── tcp-stream-server.h ├── tobasco2.cc └── tobasco2.h ├── segmentSizes.txt └── wscript /GNULICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DASH-NS3 2 | A simulation model for HTTP-based adaptive streaming applications 3 | 4 | If you use the model, please reference "Simulation Framework for HTTP-Based Adaptive Streaming Applications" by Harald Ott, Konstantin Miller, and Adam Wolisz, 2017 5 | 6 | ## NEEDED FILES 7 | Just drop the repository into the contrib/ folder of ns-3 (only works with ns version between 3.27 and 3.30) 8 | 9 | Since I've already received a lot of questions about errors that arise from this mistake: 10 | 11 | ![#f03c15](https://via.placeholder.com/15/f03c15/000000?text=+) ![#f03c15](https://via.placeholder.com/15/f03c15/000000?text=+) !! DO NOT RENAME THE FOLDER !! ![#f03c15](https://via.placeholder.com/15/f03c15/000000?text=+) ![#f03c15](https://via.placeholder.com/15/f03c15/000000?text=+) 12 | 13 | Its name needs to remain 'dash' 14 | 15 | ## PROGRAM EXECUTION 16 | The following parameters have to be specified for program execution: 17 | - simulationId: The Id of this simulation, to distinguish it from others, with same algorithm and number of clients, for logging purposes. 18 | - numberOfClients: The number of streaming clients used for this simulation. 19 | - segmentDuration: The duration of a segment in microseconds. 20 | - adaptationAlgo: The name of the adaptation algorithm the client uses for the simulation. The 'pre-installed' algorithms are tobasco, festive and panda. 21 | - segmentSizeFile: The relative path (from the ns-3.x/ folder) of the file containing the sizes of the segments of the video. The segment sizes have to be provided as a (n, m) matrix, with n being the number of representation levels and m being the total number of segments. A two-segment long, three representations containing segment size file would look like the following: 22 | 23 | 1564 22394 24 | 1627 46529 25 | 1987 121606 26 | 27 | One possible execution of the program would be: 28 | ```bash 29 | ./waf --run="tcp-stream --simulationId=1 --numberOfClients=3 --adaptationAlgo=panda --segmentDuration=2000000 --segmentSizeFile=contrib/dash/segmentSizes.txt" 30 | ``` 31 | 32 | 33 | ## ADDING NEW ADAPTATION ALGORITHMS 34 | The adaptation algorithm base class is located in src/applications/model/adaptation-algorithm/. If it is desired to implement a new adaptation algorithm, a separate source and header file for the algorithm can be created in the adaptation-algorithm/ folder. An example of how a header file looks like can be seen here: 35 | 36 | ```c++ 37 | #ifndef NEW_ALGORITHM_H 38 | #define NEW_ALGORITHM_H 39 | 40 | #include "tcp-stream-adaptation-algorithm.h" 41 | 42 | namespace ns3 { 43 | /** 44 | * \ingroup tcpStream 45 | * \brief Implementation of a new adaptation algorithm 46 | */ 47 | class NewAdaptationAlgorithm : public AdaptationAlgorithm 48 | { 49 | public: 50 | 51 | NewAdaptationAlgorithm ( const videoData &videoData, 52 | const playbackData & playbackData, 53 | const bufferData & bufferData, 54 | const throughputData & throughput ); 55 | 56 | algorithmReply GetNextRep ( const int64_t segmentCounter ); 57 | }; 58 | } // namespace ns3 59 | #endif /* NEW_ALGORITHM_H */ 60 | ``` 61 | 62 | An adaptation algorithm must return a data structure 'algorithmReply' containing the following members: 63 | 64 | ```c++ 65 | int64_t nextRepIndex; // representation level index of the next segement to be downloaded by the client 66 | int64_t nextDownloadDelay; // delay time in microseconds when the next segment shall be requested from the server 67 | int64_t decisionTime; // time in microsends when the adaptation algorithm decided which segment to download next, only for logging purposes 68 | int64_t decisionCase; // indicate in which part of the adaptation algorithm's code the decision was made, which representation level to request next, only for logging purposes 69 | int64_t delayDecisionCase; // indicate in which part of the adaptation algorithm's code the decision was made, how much time in microsends to wait until the segment shall be requested from server, only for logging purposes 70 | ``` 71 | 72 | Next, it is necessary to include the following lines to the top of the source file. 73 | 74 | ```c++ 75 | NS_LOG_COMPONENT_DEFINE ("NewAdaptationAlgorithm"); 76 | NS_OBJECT_ENSURE_REGISTERED (NewAdaptationAlgorithm); 77 | ``` 78 | 79 | It is obligatory to inherit from AdaptationAlgorithm and implement the algorithmReply GetNextRep ( const int64_t segmentCounter ) function. Then, the header and source files need to be added to src/applications/wscript. Open wscript and add the files with their path, just like the other algorithm files have been added. Additionally, it is necessary to add the name of the algorithm to the if-else-if block in the TcpStreamClient::Initialise (std::string algorithm) function, just like the other implemented algorithms have been added, see the following code taken from tcp-stream-client.cc: 80 | 81 | ```c++ 82 | if (algorithm == "tobasco") 83 | { 84 | algo = new TobascoAlgorithm (m_videoData, m_playbackData, m_bufferData, m_throughput); 85 | } 86 | else if (algorithm == "panda") 87 | { 88 | algo = new PandaAlgorithm (m_videoData, m_playbackData, m_bufferData, m_throughput); 89 | } 90 | else if (algorithm == "festive") 91 | { 92 | algo = new FestiveAlgorithm (m_videoData, m_playbackData, m_bufferData, m_throughput); 93 | } 94 | else 95 | { 96 | // Stop program 97 |  } 98 | ``` 99 | Lastly, the header file of the newly implemented adaptation algorithm needs to be included in the TcpStreamClient header file. 100 | 101 | The resulting logfiles will be written to mylogs/algorithmName/numberOfClients/ 102 | -------------------------------------------------------------------------------- /examples/tcp-stream.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | // - TCP Stream server and user-defined number of clients connected with an AP 20 | // - WiFi connection 21 | // - Tracing of throughput, packet information is done in the client 22 | 23 | #include "ns3/point-to-point-helper.h" 24 | #include 25 | #include "ns3/core-module.h" 26 | #include "ns3/applications-module.h" 27 | #include "ns3/internet-module.h" 28 | #include "ns3/point-to-point-module.h" 29 | #include "ns3/network-module.h" 30 | #include "ns3/wifi-module.h" 31 | #include "ns3/mobility-module.h" 32 | #include 33 | #include "ns3/building-position-allocator.h" 34 | #include 35 | #include 36 | #include 37 | #include "ns3/flow-monitor-module.h" 38 | #include "ns3/tcp-stream-helper.h" 39 | #include "ns3/tcp-stream-interface.h" 40 | 41 | template 42 | std::string ToString(T val) 43 | { 44 | std::stringstream stream; 45 | stream << val; 46 | return stream.str(); 47 | } 48 | 49 | using namespace ns3; 50 | 51 | NS_LOG_COMPONENT_DEFINE ("TcpStreamExample"); 52 | 53 | int 54 | main (int argc, char *argv[]) 55 | { 56 | // 57 | // Users may find it convenient to turn on explicit debugging 58 | // for selected modules; the below lines suggest how to do this 59 | // 60 | // #if 1 61 | // LogComponentEnable ("TcpStreamExample", LOG_LEVEL_INFO); 62 | // LogComponentEnable ("TcpStreamClientApplication", LOG_LEVEL_INFO); 63 | // LogComponentEnable ("TcpStreamServerApplication", LOG_LEVEL_INFO); 64 | // #endif 65 | 66 | uint64_t segmentDuration; 67 | // The simulation id is used to distinguish log file results from potentially multiple consequent simulation runs. 68 | uint32_t simulationId; 69 | uint32_t numberOfClients; 70 | std::string adaptationAlgo; 71 | std::string segmentSizeFilePath; 72 | 73 | bool shortGuardInterval = true; 74 | 75 | CommandLine cmd; 76 | cmd.Usage ("Simulation of streaming with DASH.\n"); 77 | cmd.AddValue ("simulationId", "The simulation's index (for logging purposes)", simulationId); 78 | cmd.AddValue ("numberOfClients", "The number of clients", numberOfClients); 79 | cmd.AddValue ("segmentDuration", "The duration of a video segment in microseconds", segmentDuration); 80 | cmd.AddValue ("adaptationAlgo", "The adaptation algorithm that the client uses for the simulation", adaptationAlgo); 81 | cmd.AddValue ("segmentSizeFile", "The relative path (from ns-3.x directory) to the file containing the segment sizes in bytes", segmentSizeFilePath); 82 | cmd.Parse (argc, argv); 83 | 84 | 85 | Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue (1446)); 86 | Config::SetDefault("ns3::TcpSocket::SndBufSize", UintegerValue (524288)); 87 | Config::SetDefault("ns3::TcpSocket::RcvBufSize", UintegerValue (524288)); 88 | 89 | WifiHelper wifiHelper; 90 | wifiHelper.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ); 91 | wifiHelper.SetRemoteStationManager ("ns3::MinstrelHtWifiManager");// 92 | 93 | 94 | /* Set up Legacy Channel */ 95 | YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default (); 96 | // We do not set an explicit propagation loss model here, we just use the default ones that get applied with the building model. 97 | 98 | /* Setup Physical Layer */ 99 | YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default (); 100 | wifiPhy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO); 101 | wifiPhy.Set ("TxPowerStart", DoubleValue (20.0));// 102 | wifiPhy.Set ("TxPowerEnd", DoubleValue (20.0));// 103 | wifiPhy.Set ("TxPowerLevels", UintegerValue (1));// 104 | wifiPhy.Set ("TxGain", DoubleValue (0));// 105 | wifiPhy.Set ("RxGain", DoubleValue (0));// 106 | wifiPhy.SetErrorRateModel ("ns3::YansErrorRateModel");// 107 | wifiPhy.SetChannel (wifiChannel.Create ()); 108 | wifiPhy.Set("ShortGuardEnabled", BooleanValue(shortGuardInterval)); 109 | wifiPhy.Set ("Antennas", UintegerValue (4)); 110 | // wifiPhy.Set ("RxAntennas", UintegerValue (4)); 111 | 112 | /* Create Nodes */ 113 | NodeContainer networkNodes; 114 | networkNodes.Create (numberOfClients + 2); 115 | 116 | /* Determin access point and server node */ 117 | Ptr apNode = networkNodes.Get (0); 118 | Ptr serverNode = networkNodes.Get (1); 119 | 120 | /* Configure clients as STAs in the WLAN */ 121 | NodeContainer staContainer; 122 | /* Begin at +2, because position 0 is the access point and position 1 is the server */ 123 | for (NodeContainer::Iterator i = networkNodes.Begin () + 2; i != networkNodes.End (); ++i) 124 | { 125 | staContainer.Add (*i); 126 | } 127 | 128 | /* Determin client nodes for object creation with client helper class */ 129 | std::vector , std::string> > clients; 130 | for (NodeContainer::Iterator i = networkNodes.Begin () + 2; i != networkNodes.End (); ++i) 131 | { 132 | std::pair , std::string> client (*i, adaptationAlgo); 133 | clients.push_back (client); 134 | } 135 | 136 | /* Set up WAN link between server node and access point*/ 137 | PointToPointHelper p2p; 138 | p2p.SetDeviceAttribute ("DataRate", StringValue ("100000kb/s")); // This must not be more than the maximum throughput in 802.11n 139 | p2p.SetDeviceAttribute ("Mtu", UintegerValue (1500)); 140 | p2p.SetChannelAttribute ("Delay", StringValue ("45ms")); 141 | NetDeviceContainer wanIpDevices; 142 | wanIpDevices = p2p.Install (serverNode, apNode); 143 | 144 | /* create MAC layers */ 145 | WifiMacHelper wifiMac; 146 | /* WLAN configuration */ 147 | Ssid ssid = Ssid ("network"); 148 | /* Configure STAs for WLAN*/ 149 | 150 | wifiMac.SetType ("ns3::StaWifiMac", 151 | "Ssid", SsidValue (ssid)); 152 | NetDeviceContainer staDevices; 153 | staDevices = wifiHelper.Install (wifiPhy, wifiMac, staContainer); 154 | 155 | /* Configure AP for WLAN*/ 156 | wifiMac.SetType ("ns3::ApWifiMac", 157 | "Ssid", SsidValue (ssid)); 158 | NetDeviceContainer apDevice; 159 | apDevice = wifiHelper.Install (wifiPhy, wifiMac, apNode); 160 | 161 | 162 | 163 | Config::Set ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", UintegerValue (40)); 164 | 165 | /* Determin WLAN devices (AP and STAs) */ 166 | NetDeviceContainer wlanDevices; 167 | wlanDevices.Add (staDevices); 168 | wlanDevices.Add (apDevice); 169 | 170 | /* Internet stack */ 171 | InternetStackHelper stack; 172 | stack.Install (networkNodes); 173 | 174 | /* Assign IP addresses */ 175 | Ipv4AddressHelper address; 176 | 177 | /* IPs for WAN */ 178 | address.SetBase ("76.1.1.0", "255.255.255.0"); 179 | Ipv4InterfaceContainer wanInterface = address.Assign (wanIpDevices); 180 | Address serverAddress = Address(wanInterface.GetAddress (0)); 181 | 182 | /* IPs for WLAN (STAs and AP) */ 183 | address.SetBase ("192.168.1.0", "255.255.255.0"); 184 | address.Assign (wlanDevices); 185 | 186 | /* Populate routing table */ 187 | Ipv4GlobalRoutingHelper::PopulateRoutingTables (); 188 | uint16_t port = 9; 189 | 190 | 191 | ////////////////////////////////////////////////////////////////////////////////////////////////// 192 | //// Set up Building 193 | ////////////////////////////////////////////////////////////////////////////////////////////////// 194 | double roomHeight = 3; 195 | double roomLength = 6; 196 | double roomWidth = 5; 197 | uint32_t xRooms = 8; 198 | uint32_t yRooms = 3; 199 | uint32_t nFloors = 6; 200 | 201 | Ptr b = CreateObject (); 202 | b->SetBoundaries (Box ( 0.0, xRooms * roomWidth, 203 | 0.0, yRooms * roomLength, 204 | 0.0, nFloors * roomHeight)); 205 | b->SetBuildingType (Building::Office); 206 | b->SetExtWallsType (Building::ConcreteWithWindows); 207 | b->SetNFloors (6); 208 | b->SetNRoomsX (8); 209 | b->SetNRoomsY (3); 210 | 211 | Vector posAp = Vector ( 1.0, 1.0, 1.0); 212 | // give the server node any position, it does not have influence on the simulation, it has to be set though, 213 | // because when we do: mobility.Install (networkNodes);, there has to be a position as place holder for the server 214 | // because otherwise the first client would not get assigned the desired position. 215 | Vector posServer = Vector (1.5, 1.5, 1.5); 216 | 217 | /* Set up positions of nodes (AP and server) */ 218 | Ptr positionAlloc = CreateObject (); 219 | positionAlloc->Add (posAp); 220 | positionAlloc->Add (posServer); 221 | 222 | 223 | Ptr randPosAlloc = CreateObject (); 224 | randPosAlloc->AssignStreams (simulationId); 225 | 226 | // create folder so we can log the positions of the clients 227 | const char * mylogsDir = dashLogDirectory.c_str(); 228 | mkdir (mylogsDir, 0775); 229 | std::string algodirstr (dashLogDirectory + adaptationAlgo ); 230 | const char * algodir = algodirstr.c_str(); 231 | mkdir (algodir, 0775); 232 | std::string dirstr (dashLogDirectory + adaptationAlgo + "/" + ToString (numberOfClients) + "/"); 233 | const char * dir = dirstr.c_str(); 234 | mkdir(dir, 0775); 235 | 236 | std::ofstream clientPosLog; 237 | std::string clientPos = dashLogDirectory + "/" + adaptationAlgo + "/" + ToString (numberOfClients) + "/" + "sim" + ToString (simulationId) + "_" + "clientPos.txt"; 238 | clientPosLog.open (clientPos.c_str()); 239 | NS_ASSERT_MSG (clientPosLog.is_open(), "Couldn't open clientPosLog file"); 240 | 241 | // allocate clients to positions 242 | for (uint i = 0; i < numberOfClients; i++) 243 | { 244 | Vector pos = Vector (randPosAlloc->GetNext()); 245 | positionAlloc->Add (pos); 246 | 247 | // log client positions 248 | clientPosLog << ToString(pos.x) << ", " << ToString(pos.y) << ", " << ToString(pos.z) << "\n"; 249 | clientPosLog.flush (); 250 | } 251 | 252 | 253 | MobilityHelper mobility; 254 | mobility.SetPositionAllocator (positionAlloc); 255 | mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); 256 | // install all of the nodes that have been added to positionAlloc to the mobility model 257 | mobility.Install (networkNodes); 258 | BuildingsHelper::Install (networkNodes); // networkNodes contains all nodes, stations and ap 259 | BuildingsHelper::MakeMobilityModelConsistent (); 260 | 261 | // if logging of the packets between AP---Server or AP and the STAs is wanted, these two lines can be activated 262 | 263 | // p2p.EnablePcapAll ("p2p-", true); 264 | // wifiPhy.EnablePcapAll ("wifi-", true); 265 | 266 | 267 | 268 | /* Install TCP Receiver on the access point */ 269 | TcpStreamServerHelper serverHelper (port); 270 | ApplicationContainer serverApp = serverHelper.Install (serverNode); 271 | serverApp.Start (Seconds (1.0)); 272 | /* Install TCP/UDP Transmitter on the station */ 273 | TcpStreamClientHelper clientHelper (serverAddress, port); 274 | clientHelper.SetAttribute ("SegmentDuration", UintegerValue (segmentDuration)); 275 | clientHelper.SetAttribute ("SegmentSizeFilePath", StringValue (segmentSizeFilePath)); 276 | clientHelper.SetAttribute ("NumberOfClients", UintegerValue(numberOfClients)); 277 | clientHelper.SetAttribute ("SimulationId", UintegerValue (simulationId)); 278 | ApplicationContainer clientApps = clientHelper.Install (clients); 279 | for (uint i = 0; i < clientApps.GetN (); i++) 280 | { 281 | double startTime = 2.0 + ((i * 3) / 100.0); 282 | clientApps.Get (i)->SetStartTime (Seconds (startTime)); 283 | } 284 | 285 | 286 | NS_LOG_INFO ("Run Simulation."); 287 | NS_LOG_INFO ("Sim: " << simulationId << "Clients: " << numberOfClients); 288 | Simulator::Run (); 289 | Simulator::Destroy (); 290 | NS_LOG_INFO ("Done."); 291 | 292 | } 293 | -------------------------------------------------------------------------------- /examples/wscript: -------------------------------------------------------------------------------- 1 | # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- 2 | 3 | def build(bld): 4 | obj = bld.create_ns3_program('tcp-stream', ['dash', 'internet', 'wifi', 'buildings', 'applications', 'point-to-point']) 5 | obj.source = 'tcp-stream.cc' 6 | -------------------------------------------------------------------------------- /helper/tcp-stream-helper.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2008 INRIA 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | * 18 | * Author: Mathieu Lacage 19 | */ 20 | #include "tcp-stream-helper.h" 21 | #include "ns3/tcp-stream-server.h" 22 | #include "ns3/tcp-stream-client.h" 23 | #include "ns3/uinteger.h" 24 | #include "ns3/names.h" 25 | 26 | namespace ns3 { 27 | 28 | TcpStreamServerHelper::TcpStreamServerHelper (uint16_t port) 29 | { 30 | m_factory.SetTypeId (TcpStreamServer::GetTypeId ()); 31 | SetAttribute ("Port", UintegerValue (port)); 32 | } 33 | 34 | void 35 | TcpStreamServerHelper::SetAttribute ( 36 | std::string name, 37 | const AttributeValue &value) 38 | { 39 | m_factory.Set (name, value); 40 | } 41 | 42 | ApplicationContainer 43 | TcpStreamServerHelper::Install (Ptr node) const 44 | { 45 | return ApplicationContainer (InstallPriv (node)); 46 | } 47 | 48 | ApplicationContainer 49 | TcpStreamServerHelper::Install (std::string nodeName) const 50 | { 51 | Ptr node = Names::Find (nodeName); 52 | return ApplicationContainer (InstallPriv (node)); 53 | } 54 | 55 | ApplicationContainer 56 | TcpStreamServerHelper::Install (NodeContainer c) const 57 | { 58 | ApplicationContainer apps; 59 | for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) 60 | { 61 | apps.Add (InstallPriv (*i)); 62 | } 63 | 64 | return apps; 65 | } 66 | 67 | Ptr 68 | TcpStreamServerHelper::InstallPriv (Ptr node) const 69 | { 70 | Ptr app = m_factory.Create (); 71 | node->AddApplication (app); 72 | 73 | return app; 74 | } 75 | 76 | TcpStreamClientHelper::TcpStreamClientHelper (Address address, uint16_t port) 77 | { 78 | m_factory.SetTypeId (TcpStreamClient::GetTypeId ()); 79 | SetAttribute ("RemoteAddress", AddressValue (address)); 80 | SetAttribute ("RemotePort", UintegerValue (port)); 81 | } 82 | 83 | TcpStreamClientHelper::TcpStreamClientHelper (Ipv4Address address, uint16_t port) 84 | { 85 | m_factory.SetTypeId (TcpStreamClient::GetTypeId ()); 86 | SetAttribute ("RemoteAddress", AddressValue (Address(address))); 87 | SetAttribute ("RemotePort", UintegerValue (port)); 88 | } 89 | 90 | TcpStreamClientHelper::TcpStreamClientHelper (Ipv6Address address, uint16_t port) 91 | { 92 | m_factory.SetTypeId (TcpStreamClient::GetTypeId ()); 93 | SetAttribute ("RemoteAddress", AddressValue (Address(address))); 94 | SetAttribute ("RemotePort", UintegerValue (port)); 95 | } 96 | 97 | void 98 | TcpStreamClientHelper::SetAttribute (std::string name, const AttributeValue &value) 99 | { 100 | m_factory.Set (name, value); 101 | } 102 | 103 | ApplicationContainer 104 | TcpStreamClientHelper::Install (std::vector , std::string> > clients) const 105 | { 106 | ApplicationContainer apps; 107 | for (uint i = 0; i < clients.size (); i++) 108 | { 109 | apps.Add (InstallPriv (clients.at (i).first, clients.at (i).second, i)); 110 | } 111 | 112 | return apps; 113 | } 114 | 115 | Ptr 116 | TcpStreamClientHelper::InstallPriv (Ptr node, std::string algo, uint16_t clientId) const 117 | { 118 | Ptr app = m_factory.Create (); 119 | app->GetObject ()->SetAttribute ("ClientId", UintegerValue (clientId)); 120 | app->GetObject ()->Initialise (algo, clientId); 121 | node->AddApplication (app); 122 | return app; 123 | } 124 | 125 | } // namespace ns3 126 | -------------------------------------------------------------------------------- /helper/tcp-stream-helper.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2008 INRIA 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | * 18 | * Author: Mathieu Lacage 19 | */ 20 | #ifndef TCP_STREAM_HELPER_H 21 | #define TCP_STREAM_HELPER_H 22 | 23 | #include 24 | #include "ns3/application-container.h" 25 | #include "ns3/node-container.h" 26 | #include "ns3/object-factory.h" 27 | #include "ns3/ipv4-address.h" 28 | #include "ns3/ipv6-address.h" 29 | 30 | namespace ns3 { 31 | 32 | /** 33 | * \ingroup TcpStream 34 | * \brief Create a server application which waits for input UDP packets 35 | * and sends them back to the original sender. 36 | */ 37 | class TcpStreamServerHelper 38 | { 39 | public: 40 | /** 41 | * Create TcpStreamServerHelper which will make life easier for people trying 42 | * to set up simulations with echos. 43 | * 44 | * \param port The port the server will wait on for incoming packets 45 | */ 46 | TcpStreamServerHelper (uint16_t port); 47 | 48 | /** 49 | * Record an attribute to be set in each Application after it is is created. 50 | * 51 | * \param name the name of the attribute to set 52 | * \param value the value of the attribute to set 53 | */ 54 | void SetAttribute (std::string name, const AttributeValue &value); 55 | 56 | /** 57 | * Create a TcpStreamServerApplication on the specified Node. 58 | * 59 | * \param node The node on which to create the Application. The node is 60 | * specified by a Ptr. 61 | * 62 | * \returns An ApplicationContainer holding the Application created, 63 | */ 64 | ApplicationContainer Install (Ptr node) const; 65 | 66 | /** 67 | * Create a TcpStreamServerApplication on specified node 68 | * 69 | * \param nodeName The node on which to create the application. The node 70 | * is specified by a node name previously registered with 71 | * the Object Name Service. 72 | * 73 | * \returns An ApplicationContainer holding the Application created. 74 | */ 75 | ApplicationContainer Install (std::string nodeName) const; 76 | 77 | /** 78 | * \param c The nodes on which to create the Applications. The nodes 79 | * are specified by a NodeContainer. 80 | * 81 | * Create one tcp stream server application on each of the Nodes in the 82 | * NodeContainer. 83 | * 84 | * \returns The applications created, one Application per Node in the 85 | * NodeContainer. 86 | */ 87 | ApplicationContainer Install (NodeContainer c) const; 88 | 89 | private: 90 | /** 91 | * Install an ns3::TcpStreamServer on the node configured with all the 92 | * attributes set with SetAttribute. 93 | * 94 | * \param node The node on which an TcpStreamServer will be installed. 95 | * \returns Ptr to the application installed. 96 | */ 97 | Ptr InstallPriv (Ptr node) const; 98 | 99 | ObjectFactory m_factory; //!< Object factory. 100 | }; 101 | 102 | /** 103 | * \ingroup TcpStream 104 | * \brief Create an application which sends a UDP packet and waits for an echo of this packet 105 | */ 106 | class TcpStreamClientHelper 107 | { 108 | public: 109 | /** 110 | * Create TcpStreamClientHelper which will make life easier for people trying 111 | * to set up simulations with echos. 112 | * 113 | * \param ip The IP address of the remote tcp stream server 114 | * \param port The port number of the remote tcp stream server 115 | */ 116 | TcpStreamClientHelper (Address ip, uint16_t port); 117 | /** 118 | * Create TcpStreamClientHelper which will make life easier for people trying 119 | * to set up simulations with echos. 120 | * 121 | * \param ip The IPv4 address of the remote tcp stream server 122 | * \param port The port number of the remote tcp stream server 123 | */ 124 | TcpStreamClientHelper (Ipv4Address ip, uint16_t port); 125 | /** 126 | * Create TcpStreamClientHelper which will make life easier for people trying 127 | * to set up simulations with echos. 128 | * 129 | * \param ip The IPv6 address of the remote tcp stream server 130 | * \param port The port number of the remote tcp stream server 131 | */ 132 | TcpStreamClientHelper (Ipv6Address ip, uint16_t port); 133 | 134 | /** 135 | * Record an attribute to be set in each Application after it is is created. 136 | * 137 | * \param name the name of the attribute to set 138 | * \param value the value of the attribute to set 139 | */ 140 | void SetAttribute (std::string name, const AttributeValue &value); 141 | 142 | /** 143 | * \param clients the nodes with the name of the adaptation algorithm to be used 144 | * 145 | * Create one tcp stream client application on each of the input nodes and 146 | * instantiate an adaptation algorithm on each of the tcp stream client according 147 | * to the given string. 148 | * 149 | * \returns the applications created, one application per input node. 150 | */ 151 | ApplicationContainer Install (std::vector , std::string> > clients) const; 152 | 153 | private: 154 | /** 155 | * Install an ns3::TcpStreamClient on the node configured with all the 156 | * attributes set with SetAttribute. 157 | * 158 | * \param node The node on which an TcpStreamClient will be installed. 159 | * \param algo A string containing the name of the adaptation algorithm to be used on this client 160 | * \param clientId distinguish this client object from other parallel running clients, for logging purposes 161 | * \param simulationId distinguish this simulation from other subsequently started simulations, for logging purposes 162 | * \returns Ptr to the application installed. 163 | */ 164 | Ptr InstallPriv (Ptr node, std::string algo, uint16_t clientId) const; 165 | ObjectFactory m_factory; //!< Object factory. 166 | }; 167 | 168 | } // namespace ns3 169 | 170 | #endif /* TCP_STREAM_HELPER_H */ 171 | -------------------------------------------------------------------------------- /model/festive.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #include "festive.h" 20 | 21 | namespace ns3 { 22 | 23 | NS_LOG_COMPONENT_DEFINE ("FestiveAlgorithm"); 24 | 25 | NS_OBJECT_ENSURE_REGISTERED (FestiveAlgorithm); 26 | 27 | FestiveAlgorithm::FestiveAlgorithm ( const videoData &videoData, 28 | const playbackData & playbackData, 29 | const bufferData & bufferData, 30 | const throughputData & throughput) : 31 | AdaptationAlgorithm (videoData, playbackData, bufferData, throughput), 32 | m_targetBuf (30000000), 33 | m_delta (m_videoData.segmentDuration), 34 | m_alpha (12.0), 35 | m_highestRepIndex (videoData.averageBitrate.size () - 1), 36 | m_thrptThrsh (0.85) 37 | { 38 | NS_LOG_INFO (this); 39 | m_smooth.push_back (5); // after how many steps switch up is possible 40 | m_smooth.push_back (1); // switch up by how many representatations at once 41 | NS_ASSERT_MSG (m_highestRepIndex >= 0, "The highest quality representation index should be => 0"); 42 | } 43 | 44 | algorithmReply 45 | FestiveAlgorithm::GetNextRep (const int64_t segmentCounter, int64_t clientId) 46 | { 47 | int64_t timeNow = Simulator::Now ().GetMicroSeconds (); 48 | bool decisionMade = false; 49 | algorithmReply answer; 50 | answer.decisionTime = timeNow; 51 | answer.nextDownloadDelay = 0; 52 | answer.delayDecisionCase = 0; 53 | 54 | if (segmentCounter == 0) 55 | { 56 | answer.nextRepIndex = 0; 57 | answer.decisionCase = 0; 58 | return answer; 59 | } 60 | int64_t bufferNow = m_bufferData.bufferLevelNew.back () - (timeNow - m_throughput.transmissionEnd.back ()); 61 | 62 | // not enough completed requests, select nextRepIndex 63 | if (m_throughput.transmissionEnd.size () < 20) 64 | { 65 | answer.nextRepIndex = 0; 66 | answer.decisionCase = 1; 67 | return answer; 68 | } 69 | 70 | // compute throughput estimation 71 | std::vector thrptEstimationTmp; 72 | for (unsigned sd = m_playbackData.playbackIndex.size (); sd-- > 0; ) 73 | { 74 | if (m_throughput.bytesReceived.at (sd) == 0) 75 | { 76 | continue; 77 | } 78 | else 79 | { 80 | thrptEstimationTmp.push_back ((8.0 * m_throughput.bytesReceived.at (sd)) 81 | / ((double)((m_throughput.transmissionEnd.at (sd) - m_throughput.transmissionRequested.at (sd)) / 1000000.0))); 82 | } 83 | if (thrptEstimationTmp.size () == 20) 84 | { 85 | break; 86 | } 87 | } 88 | // calculate harmonic mean of values in thrptEstimationTmp 89 | double harmonicMeanDenominator = 0; 90 | for (uint i = 0; i < thrptEstimationTmp.size (); i++) 91 | { 92 | harmonicMeanDenominator += 1 / (thrptEstimationTmp.at (i)); 93 | } 94 | double thrptEstimation = thrptEstimationTmp.size () / harmonicMeanDenominator; 95 | 96 | // compute b_delay 97 | int64_t lowerBound = m_targetBuf - m_delta; 98 | int64_t upperBound = m_targetBuf + m_delta; 99 | int64_t randBuf = (int64_t) lowerBound + ( std::rand () % ( upperBound - (lowerBound) + 1 ) ); 100 | if (bufferNow > randBuf) 101 | { 102 | answer.nextDownloadDelay = bufferNow - randBuf; 103 | answer.delayDecisionCase = 1; 104 | } 105 | 106 | // select reference bit rate 107 | int64_t currentRepIndex = m_playbackData.playbackIndex.back (); 108 | int64_t refIndex = currentRepIndex; 109 | 110 | // decide if we need to decrease 111 | if (currentRepIndex > 0 112 | && m_videoData.averageBitrate.at (currentRepIndex) > thrptEstimation * m_thrptThrsh) 113 | { 114 | refIndex = currentRepIndex - 1; 115 | answer.decisionCase = 1; 116 | decisionMade = true; 117 | } 118 | 119 | // decide if we need to increase 120 | assert (m_smooth.at (0) > 0); 121 | assert (m_smooth.at (1) == 1); 122 | if (currentRepIndex < m_highestRepIndex && !decisionMade) 123 | { 124 | int count = 0; 125 | for (unsigned _sd = m_playbackData.playbackIndex.size () - 1; _sd-- > 0; ) 126 | { 127 | if (currentRepIndex == m_playbackData.playbackIndex.at (_sd)) 128 | { 129 | count++; 130 | if (count >= m_smooth.at (0)) 131 | { 132 | break; 133 | } 134 | } 135 | else 136 | { 137 | break; 138 | } 139 | } 140 | if (count >= m_smooth.at (0) 141 | && (double) m_videoData.averageBitrate.at (currentRepIndex + 1) <= thrptEstimation) 142 | { 143 | refIndex = currentRepIndex + 1; 144 | answer.decisionCase = 1; 145 | decisionMade = true; 146 | } 147 | } 148 | 149 | // neither did we increase nor decrease, so we stay at the same rep index 150 | if (!decisionMade) 151 | { 152 | answer.nextRepIndex = currentRepIndex; 153 | answer.decisionCase = 3; 154 | return answer; 155 | } 156 | 157 | // compute number of bit rate switches in the last 20 seconds 158 | int64_t numberOfSwitches = 0; 159 | std::vector foundIndices; 160 | for (unsigned _sd = m_playbackData.playbackStart.size () - 1; _sd-- > 0; ) 161 | { 162 | if (m_playbackData.playbackStart.at (_sd) < timeNow) 163 | { 164 | break; 165 | } 166 | else if (currentRepIndex != m_playbackData.playbackIndex.at (_sd)) 167 | { 168 | if (std::find (foundIndices.begin (), foundIndices.end (), currentRepIndex) != foundIndices.end ()) 169 | { 170 | continue; 171 | } 172 | numberOfSwitches++; 173 | foundIndices.push_back (currentRepIndex); 174 | } 175 | } 176 | double scoreEfficiencyCurrent = std::abs ((double)m_videoData.averageBitrate.at (currentRepIndex) 177 | / double(std::min (thrptEstimation, (double)m_videoData.averageBitrate.at (refIndex))) - 1.0); 178 | 179 | double scoreEfficiencyRef = std::abs ((double)m_videoData.averageBitrate.at (refIndex) 180 | / double(std::min (thrptEstimation, (double)m_videoData.averageBitrate.at (refIndex))) - 1.0); 181 | 182 | double scoreStabilityCurrent = pow (2.0, (double)numberOfSwitches); 183 | double scoreStabilityRef = pow (2.0, ((double)numberOfSwitches)) + 1.0; 184 | 185 | if ((scoreStabilityCurrent + m_alpha * scoreEfficiencyCurrent) < scoreStabilityRef + m_alpha * scoreEfficiencyRef) 186 | { 187 | answer.nextRepIndex = currentRepIndex; 188 | answer.decisionCase = 4; 189 | return answer; 190 | } 191 | else 192 | { 193 | answer.nextRepIndex = refIndex; 194 | return answer; 195 | } 196 | 197 | } 198 | } // namespace ns3 -------------------------------------------------------------------------------- /model/festive.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #ifndef FESTIVE_ALGORITHM_H 20 | #define FESTIVE_ALGORITHM_H 21 | 22 | #include "tcp-stream-adaptation-algorithm.h" 23 | 24 | namespace ns3 { 25 | 26 | /** 27 | * \ingroup tcpStream 28 | * \brief Implementation of the Festive adaptation algorithm 29 | */ 30 | class FestiveAlgorithm : public AdaptationAlgorithm 31 | { 32 | public: 33 | FestiveAlgorithm ( const videoData &videoData, 34 | const playbackData & playbackData, 35 | const bufferData & bufferData, 36 | const throughputData & throughput); 37 | 38 | algorithmReply GetNextRep (const int64_t segmentCounter, int64_t clientId); 39 | 40 | private: 41 | const int64_t m_targetBuf; 42 | const int64_t m_delta; 43 | const double m_alpha; 44 | const int64_t m_highestRepIndex; 45 | const double m_thrptThrsh; 46 | std::vector m_smooth; 47 | }; 48 | 49 | } // namespace ns3 50 | #endif /* FESTIVE_ALGORITHM_H */ -------------------------------------------------------------------------------- /model/panda.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #include "panda.h" 20 | 21 | 22 | namespace ns3 { 23 | 24 | NS_LOG_COMPONENT_DEFINE ("PandaAlgorithm"); 25 | 26 | NS_OBJECT_ENSURE_REGISTERED (PandaAlgorithm); 27 | 28 | PandaAlgorithm::PandaAlgorithm ( const videoData &videoData, 29 | const playbackData & playbackData, 30 | const bufferData & bufferData, 31 | const throughputData & throughput) : 32 | AdaptationAlgorithm (videoData, playbackData, bufferData, throughput), 33 | m_kappa (0.28), 34 | m_omega (0.3), 35 | m_alpha (0.2), 36 | m_beta (0.2), 37 | m_epsilon (0.15), 38 | m_bMin (26), 39 | m_highestRepIndex (videoData.averageBitrate.size () - 1) 40 | { 41 | NS_LOG_INFO (this); 42 | NS_ASSERT_MSG (m_highestRepIndex >= 0, "The highest quality representation index should be => 0"); 43 | } 44 | 45 | algorithmReply 46 | PandaAlgorithm::GetNextRep (const int64_t segmentCounter, int64_t clientId) 47 | { 48 | const int64_t timeNow = Simulator::Now ().GetMicroSeconds (); 49 | int64_t delay = 0; 50 | if (segmentCounter == 0) 51 | { 52 | m_lastVideoIndex = 0; 53 | m_lastBuffer = (m_videoData.segmentDuration) / 1e6; 54 | m_lastTargetInterrequestTime = 0; 55 | 56 | algorithmReply answer; 57 | answer.nextRepIndex = 0; 58 | answer.nextDownloadDelay = 0; 59 | answer.decisionTime = timeNow; 60 | answer.decisionCase = 0; 61 | answer.delayDecisionCase = 0; 62 | return answer; 63 | } 64 | 65 | // estimate the bandwidth share 66 | double throughputMeasured = ((double)(m_videoData.averageBitrate.at (m_lastVideoIndex) * (m_videoData.segmentDuration / 1e6) ) 67 | / (double)((m_throughput.transmissionEnd.back () - m_throughput.transmissionRequested.back ()) / 1e6)) / 1e6; 68 | 69 | if (segmentCounter == 1) 70 | { 71 | m_lastBandwidthShare = throughputMeasured; 72 | m_lastSmoothBandwidthShare = m_lastBandwidthShare; 73 | } 74 | 75 | double actualInterrequestTime; 76 | if (timeNow - m_throughput.transmissionRequested.back () > m_lastTargetInterrequestTime * 1e6 ) 77 | { 78 | actualInterrequestTime = (timeNow - m_throughput.transmissionRequested.back ()) / 1e6; 79 | } 80 | else 81 | { 82 | actualInterrequestTime = m_lastTargetInterrequestTime; 83 | } 84 | 85 | double bandwidthShare = (m_kappa * (m_omega - std::max (0.0, m_lastBandwidthShare - throughputMeasured + m_omega))) 86 | * actualInterrequestTime + m_lastBandwidthShare; 87 | if (bandwidthShare < 0) 88 | { 89 | bandwidthShare = 0; 90 | } 91 | m_lastBandwidthShare = bandwidthShare; 92 | 93 | double smoothBandwidthShare; 94 | smoothBandwidthShare = ((-m_alpha 95 | * (m_lastSmoothBandwidthShare - bandwidthShare)) 96 | * actualInterrequestTime) 97 | + m_lastSmoothBandwidthShare; 98 | 99 | m_lastSmoothBandwidthShare = smoothBandwidthShare; 100 | 101 | double deltaUp = m_omega + m_epsilon * smoothBandwidthShare; 102 | double deltaDown = m_omega; 103 | int rUp = FindLargest (smoothBandwidthShare, segmentCounter - 1, deltaUp); 104 | int rDown = FindLargest (smoothBandwidthShare, segmentCounter - 1, deltaDown); 105 | 106 | 107 | int videoIndex; 108 | if ((m_videoData.averageBitrate.at (m_lastVideoIndex)) 109 | < (m_videoData.averageBitrate.at (rUp))) 110 | { 111 | videoIndex = rUp; 112 | } 113 | else if ((m_videoData.averageBitrate.at (rUp)) 114 | <= (m_videoData.averageBitrate.at (m_lastVideoIndex)) 115 | && (m_videoData.averageBitrate.at (m_lastVideoIndex)) 116 | <= (m_videoData.averageBitrate.at (rDown))) 117 | { 118 | videoIndex = m_lastVideoIndex; 119 | } 120 | else 121 | { 122 | videoIndex = rDown; 123 | } 124 | m_lastVideoIndex = videoIndex; 125 | 126 | // schedule next download request 127 | 128 | double targetInterrequestTime = std::max (0.0, ((double) ((m_videoData.averageBitrate.at (videoIndex) * (m_videoData.segmentDuration / 1e6)) / 1e6) 129 | / smoothBandwidthShare) + m_beta * (m_lastBuffer - m_bMin)); 130 | 131 | if (m_throughput.transmissionEnd.back () - m_throughput.transmissionRequested.back () < m_lastTargetInterrequestTime * 1e6) 132 | { 133 | delay = 1e6 * m_lastTargetInterrequestTime - (m_throughput.transmissionEnd.back () - m_throughput.transmissionRequested.back ()); 134 | } 135 | else 136 | { 137 | delay = 0; 138 | } 139 | 140 | m_lastTargetInterrequestTime = targetInterrequestTime; 141 | 142 | m_lastBuffer = (m_bufferData.bufferLevelNew.back () - (timeNow - m_throughput.transmissionEnd.back ())) / 1e6; 143 | 144 | algorithmReply answer; 145 | answer.nextRepIndex = videoIndex; 146 | answer.nextDownloadDelay = delay; 147 | answer.decisionTime = timeNow; 148 | answer.decisionCase = 0; 149 | answer.delayDecisionCase = 0; 150 | return answer; 151 | } 152 | 153 | int 154 | PandaAlgorithm::FindLargest (const double smoothBandwidthShare, const int64_t segmentCounter, const double delta) 155 | { 156 | int64_t largestBitrateIndex = 0; 157 | for (int i = 0; i <= m_highestRepIndex; i++) 158 | { 159 | int64_t currentBitrate = m_videoData.averageBitrate.at (i) / 1e6; 160 | if (currentBitrate <= (smoothBandwidthShare - delta)) 161 | { 162 | largestBitrateIndex = i; 163 | } 164 | } 165 | return largestBitrateIndex; 166 | } 167 | 168 | } // namespace ns3 -------------------------------------------------------------------------------- /model/panda.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #ifndef PANDA_ALGORITHM_H 20 | #define PANDA_ALGORITHM_H 21 | 22 | #include "tcp-stream-adaptation-algorithm.h" 23 | 24 | namespace ns3 { 25 | 26 | /** 27 | * \ingroup tcpStream 28 | * \brief Implementation of the Panda adaptation algorithm 29 | */ 30 | class PandaAlgorithm : public AdaptationAlgorithm 31 | { 32 | public: 33 | PandaAlgorithm ( const videoData &videoData, 34 | const playbackData & playbackData, 35 | const bufferData & bufferData, 36 | const throughputData & throughput); 37 | 38 | algorithmReply GetNextRep (const int64_t segmentCounter, int64_t clientId); 39 | 40 | private: 41 | int FindLargest (const double smoothBandwidthShare, const int64_t segmentCounter, const double delta); 42 | const double m_kappa; 43 | const double m_omega; 44 | const double m_alpha; 45 | const double m_beta; 46 | const double m_epsilon; 47 | const int64_t m_bMin; 48 | const int64_t m_highestRepIndex; 49 | int64_t m_lastBuffer; 50 | double m_lastTargetInterrequestTime; 51 | double m_lastBandwidthShare; 52 | double m_lastSmoothBandwidthShare; 53 | double m_lastVideoIndex; 54 | }; 55 | 56 | } // namespace ns3 57 | #endif /* PANDA_ALGORITHM_H */ -------------------------------------------------------------------------------- /model/tcp-stream-adaptation-algorithm.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | #include "tcp-stream-adaptation-algorithm.h" 19 | 20 | namespace ns3 { 21 | 22 | NS_LOG_COMPONENT_DEFINE ("AdaptationAlgorithm"); 23 | 24 | NS_OBJECT_ENSURE_REGISTERED (AdaptationAlgorithm); 25 | 26 | AdaptationAlgorithm::AdaptationAlgorithm ( const videoData & videoData, 27 | const playbackData & playbackData, 28 | const bufferData & bufferData, 29 | const throughputData & throughput) : 30 | m_videoData (videoData), 31 | m_bufferData (bufferData), 32 | m_throughput (throughput), 33 | m_playbackData (playbackData) 34 | { 35 | } 36 | 37 | } // namespace ns3 -------------------------------------------------------------------------------- /model/tcp-stream-adaptation-algorithm.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | #ifndef ADAPTATION_ALGORITHM_H 19 | #define ADAPTATION_ALGORITHM_H 20 | 21 | #include "ns3/application.h" 22 | #include 23 | #include 24 | #include "ns3/log.h" 25 | #include "ns3/nstime.h" 26 | #include "ns3/simulator.h" 27 | #include 28 | #include "tcp-stream-interface.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace ns3 { 36 | /** 37 | * \ingroup tcpStream 38 | * \brief A base class for adaptation algorithms 39 | * 40 | */ 41 | class AdaptationAlgorithm : public Object 42 | { 43 | public: 44 | AdaptationAlgorithm ( const videoData &videoData, 45 | const playbackData & playbackData, 46 | const bufferData & bufferData, 47 | const throughputData & throughput ); 48 | 49 | /** 50 | * \ingroup tcpStream 51 | * \brief Compute the next representation index 52 | * 53 | * Every Adaptation algorithm must overwrite the method. 54 | * 55 | * \return struct containig the index of next representation to be downloaded and the inter-request delay. 56 | */ 57 | virtual algorithmReply GetNextRep ( const int64_t segmentCounter, int64_t clientId) = 0; 58 | 59 | protected: 60 | const videoData & m_videoData; 61 | const bufferData & m_bufferData; 62 | const throughputData & m_throughput; 63 | const playbackData & m_playbackData; 64 | }; 65 | } // namespace ns3 66 | 67 | #endif /* ADAPTATION_ALGORITHM_H */ -------------------------------------------------------------------------------- /model/tcp-stream-client.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | #include "ns3/log.h" 19 | #include "ns3/ipv4-address.h" 20 | #include "ns3/ipv6-address.h" 21 | #include "ns3/nstime.h" 22 | #include "ns3/inet-socket-address.h" 23 | #include "ns3/inet6-socket-address.h" 24 | #include "ns3/socket.h" 25 | #include "ns3/simulator.h" 26 | #include "ns3/socket-factory.h" 27 | #include "ns3/packet.h" 28 | #include "ns3/uinteger.h" 29 | #include "ns3/trace-source-accessor.h" 30 | #include "tcp-stream-client.h" 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "ns3/global-value.h" 36 | #include 37 | #include "tcp-stream-server.h" 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | namespace ns3 { 49 | 50 | template 51 | std::string ToString (T val) 52 | { 53 | std::stringstream stream; 54 | stream << val; 55 | return stream.str (); 56 | } 57 | 58 | NS_LOG_COMPONENT_DEFINE ("TcpStreamClientApplication"); 59 | 60 | NS_OBJECT_ENSURE_REGISTERED (TcpStreamClient); 61 | 62 | void 63 | TcpStreamClient::Controller (controllerEvent event) 64 | { 65 | NS_LOG_FUNCTION (this); 66 | if (state == initial) 67 | { 68 | RequestRepIndex (); 69 | state = downloading; 70 | Send (m_videoData.segmentSize.at (m_currentRepIndex).at (m_segmentCounter)); 71 | return; 72 | } 73 | 74 | if (state == downloading) 75 | { 76 | PlaybackHandle (); 77 | if (m_currentPlaybackIndex <= m_lastSegmentIndex) 78 | { 79 | /* e_d */ 80 | m_segmentCounter++; 81 | RequestRepIndex (); 82 | state = downloadingPlaying; 83 | Send (m_videoData.segmentSize.at (m_currentRepIndex).at (m_segmentCounter)); 84 | } 85 | else 86 | { 87 | /* e_df */ 88 | state = playing; 89 | } 90 | controllerEvent ev = playbackFinished; 91 | // std::cerr << "Client " << m_clientId << " " << Simulator::Now ().GetSeconds () << "\n"; 92 | Simulator::Schedule (MicroSeconds (m_videoData.segmentDuration), &TcpStreamClient::Controller, this, ev); 93 | return; 94 | } 95 | 96 | 97 | else if (state == downloadingPlaying) 98 | { 99 | if (event == downloadFinished) 100 | { 101 | if (m_segmentCounter < m_lastSegmentIndex) 102 | { 103 | m_segmentCounter++; 104 | RequestRepIndex (); 105 | } 106 | 107 | if (m_bDelay > 0 && m_segmentCounter <= m_lastSegmentIndex) 108 | { 109 | /* e_dirs */ 110 | state = playing; 111 | controllerEvent ev = irdFinished; 112 | Simulator::Schedule (MicroSeconds (m_bDelay), &TcpStreamClient::Controller, this, ev); 113 | } 114 | else if (m_segmentCounter == m_lastSegmentIndex) 115 | { 116 | /* e_df */ 117 | state = playing; 118 | } 119 | else 120 | { 121 | /* e_d */ 122 | Send (m_videoData.segmentSize.at (m_currentRepIndex).at (m_segmentCounter)); 123 | } 124 | } 125 | else if (event == playbackFinished) 126 | { 127 | if (!PlaybackHandle ()) 128 | { 129 | /* e_pb */ 130 | controllerEvent ev = playbackFinished; 131 | // std::cerr << "FIRST CASE. Client " << m_clientId << " " << Simulator::Now ().GetSeconds () << "\n"; 132 | Simulator::Schedule (MicroSeconds (m_videoData.segmentDuration), &TcpStreamClient::Controller, this, ev); 133 | } 134 | else 135 | { 136 | /* e_pu */ 137 | state = downloading; 138 | } 139 | } 140 | return; 141 | } 142 | 143 | 144 | else if (state == playing) 145 | { 146 | if (event == irdFinished) 147 | { 148 | /* e_irc */ 149 | state = downloadingPlaying; 150 | Send (m_videoData.segmentSize.at (m_currentRepIndex).at (m_segmentCounter)); 151 | } 152 | else if (event == playbackFinished && m_currentPlaybackIndex < m_lastSegmentIndex) 153 | { 154 | /* e_pb */ 155 | // std::cerr << "SECOND CASE. Client " << m_clientId << " " << Simulator::Now ().GetSeconds () << "\n"; 156 | PlaybackHandle (); 157 | controllerEvent ev = playbackFinished; 158 | Simulator::Schedule (MicroSeconds (m_videoData.segmentDuration), &TcpStreamClient::Controller, this, ev); 159 | } 160 | else if (event == playbackFinished && m_currentPlaybackIndex == m_lastSegmentIndex) 161 | { 162 | PlaybackHandle (); 163 | /* e_pf */ 164 | state = terminal; 165 | StopApplication (); 166 | } 167 | return; 168 | } 169 | } 170 | 171 | TypeId 172 | TcpStreamClient::GetTypeId (void) 173 | { 174 | static TypeId tid = TypeId ("ns3::TcpStreamClient") 175 | .SetParent () 176 | .SetGroupName ("Applications") 177 | .AddConstructor () 178 | .AddAttribute ("RemoteAddress", 179 | "The destination Address of the outbound packets", 180 | AddressValue (), 181 | MakeAddressAccessor (&TcpStreamClient::m_peerAddress), 182 | MakeAddressChecker ()) 183 | .AddAttribute ("RemotePort", 184 | "The destination port of the outbound packets", 185 | UintegerValue (0), 186 | MakeUintegerAccessor (&TcpStreamClient::m_peerPort), 187 | MakeUintegerChecker ()) 188 | .AddAttribute ("SegmentDuration", 189 | "The duration of a segment in microseconds", 190 | UintegerValue (2000000), 191 | MakeUintegerAccessor (&TcpStreamClient::m_segmentDuration), 192 | MakeUintegerChecker ()) 193 | .AddAttribute ("SegmentSizeFilePath", 194 | "The relative path (from ns-3.x directory) to the file containing the segment sizes in bytes", 195 | StringValue ("bitrates.txt"), 196 | MakeStringAccessor (&TcpStreamClient::m_segmentSizeFilePath), 197 | MakeStringChecker ()) 198 | .AddAttribute ("SimulationId", 199 | "The ID of the current simulation, for logging purposes", 200 | UintegerValue (0), 201 | MakeUintegerAccessor (&TcpStreamClient::m_simulationId), 202 | MakeUintegerChecker ()) 203 | .AddAttribute ("NumberOfClients", 204 | "The total number of clients for this simulation, for logging purposes", 205 | UintegerValue (1), 206 | MakeUintegerAccessor (&TcpStreamClient::m_numberOfClients), 207 | MakeUintegerChecker ()) 208 | .AddAttribute ("ClientId", 209 | "The ID of the this client object, for logging purposes", 210 | UintegerValue (0), 211 | MakeUintegerAccessor (&TcpStreamClient::m_clientId), 212 | MakeUintegerChecker ()) 213 | ; 214 | return tid; 215 | } 216 | 217 | TcpStreamClient::TcpStreamClient () 218 | { 219 | NS_LOG_FUNCTION (this); 220 | m_socket = 0; 221 | m_data = 0; 222 | m_dataSize = 0; 223 | state = initial; 224 | 225 | m_currentRepIndex = 0; 226 | m_segmentCounter = 0; 227 | m_bDelay = 0; 228 | m_bytesReceived = 0; 229 | m_segmentsInBuffer = 0; 230 | m_bufferUnderrun = false; 231 | m_currentPlaybackIndex = 0; 232 | 233 | } 234 | 235 | void 236 | TcpStreamClient::Initialise (std::string algorithm, uint16_t clientId) 237 | { 238 | NS_LOG_FUNCTION (this); 239 | m_videoData.segmentDuration = m_segmentDuration; 240 | if (ReadInBitrateValues (ToString (m_segmentSizeFilePath)) == -1) 241 | { 242 | NS_LOG_ERROR ("Opening test bitrate file failed. Terminating.\n"); 243 | Simulator::Stop (); 244 | Simulator::Destroy (); 245 | } 246 | m_lastSegmentIndex = (int64_t) m_videoData.segmentSize.at (0).size () - 1; 247 | m_highestRepIndex = m_videoData.averageBitrate.size () - 1; 248 | if (algorithm == "tobasco") 249 | { 250 | algo = new TobascoAlgorithm (m_videoData, m_playbackData, m_bufferData, m_throughput); 251 | } 252 | else if (algorithm == "panda") 253 | { 254 | algo = new PandaAlgorithm (m_videoData, m_playbackData, m_bufferData, m_throughput); 255 | } 256 | else if (algorithm == "festive") 257 | { 258 | algo = new FestiveAlgorithm (m_videoData, m_playbackData, m_bufferData, m_throughput); 259 | } 260 | else 261 | { 262 | NS_LOG_ERROR ("Invalid algorithm name entered. Terminating."); 263 | StopApplication (); 264 | Simulator::Stop (); 265 | Simulator::Destroy (); 266 | } 267 | 268 | m_algoName = algorithm; 269 | 270 | InitializeLogFiles (ToString (m_simulationId), ToString (m_clientId), ToString (m_numberOfClients)); 271 | 272 | } 273 | 274 | TcpStreamClient::~TcpStreamClient () 275 | { 276 | NS_LOG_FUNCTION (this); 277 | m_socket = 0; 278 | 279 | delete algo; 280 | algo = NULL; 281 | delete [] m_data; 282 | m_data = 0; 283 | m_dataSize = 0; 284 | } 285 | 286 | void 287 | TcpStreamClient::RequestRepIndex () 288 | { 289 | NS_LOG_FUNCTION (this); 290 | algorithmReply answer; 291 | 292 | answer = algo->GetNextRep ( m_segmentCounter, m_clientId ); 293 | m_currentRepIndex = answer.nextRepIndex; 294 | NS_ASSERT_MSG (answer.nextRepIndex <= m_highestRepIndex, "The algorithm returned a representation index that's higher than the maximum"); 295 | 296 | m_playbackData.playbackIndex.push_back (answer.nextRepIndex); 297 | m_bDelay = answer.nextDownloadDelay; 298 | // std::cerr << m_segmentCounter << "\n"; 299 | LogAdaptation (answer); 300 | } 301 | 302 | template 303 | void 304 | TcpStreamClient::Send (T & message) 305 | { 306 | NS_LOG_FUNCTION (this); 307 | PreparePacket (message); 308 | Ptr p; 309 | p = Create (m_data, m_dataSize); 310 | m_downloadRequestSent = Simulator::Now ().GetMicroSeconds (); 311 | m_socket->Send (p); 312 | } 313 | 314 | void 315 | TcpStreamClient::HandleRead (Ptr socket) 316 | { 317 | NS_LOG_FUNCTION (this << socket); 318 | Ptr packet; 319 | if (m_bytesReceived == 0) 320 | { 321 | m_transmissionStartReceivingSegment = Simulator::Now ().GetMicroSeconds (); 322 | } 323 | uint32_t packetSize; 324 | while ( (packet = socket->Recv ()) ) 325 | { 326 | packetSize = packet->GetSize (); 327 | LogThroughput (packetSize); 328 | m_bytesReceived += packetSize; 329 | if (m_bytesReceived == m_videoData.segmentSize.at (m_currentRepIndex).at (m_segmentCounter)) 330 | { 331 | SegmentReceivedHandle (); 332 | } 333 | } 334 | } 335 | 336 | int 337 | TcpStreamClient::ReadInBitrateValues (std::string segmentSizeFile) 338 | { 339 | NS_LOG_FUNCTION (this); 340 | std::ifstream myfile; 341 | myfile.open (segmentSizeFile.c_str ()); 342 | if (!myfile) 343 | { 344 | return -1; 345 | } 346 | std::string temp; 347 | int64_t averageByteSizeTemp = 0; 348 | while (std::getline (myfile, temp)) 349 | { 350 | if (temp.empty ()) 351 | { 352 | break; 353 | } 354 | std::istringstream buffer (temp); 355 | std::vector line ((std::istream_iterator (buffer)), 356 | std::istream_iterator()); 357 | m_videoData.segmentSize.push_back (line); 358 | averageByteSizeTemp = (int64_t) std::accumulate ( line.begin (), line.end (), 0.0) / line.size (); 359 | m_videoData.averageBitrate.push_back ((8.0 * averageByteSizeTemp) / (m_videoData.segmentDuration / 1000000.0)); 360 | } 361 | NS_ASSERT_MSG (!m_videoData.segmentSize.empty (), "No segment sizes read from file."); 362 | return 1; 363 | } 364 | 365 | void 366 | TcpStreamClient::SegmentReceivedHandle () 367 | { 368 | NS_LOG_FUNCTION (this); 369 | m_transmissionEndReceivingSegment = Simulator::Now ().GetMicroSeconds (); 370 | 371 | 372 | m_bufferData.timeNow.push_back (m_transmissionEndReceivingSegment); 373 | if (m_segmentCounter > 0) 374 | { //if a buffer underrun is encountered, the old buffer level will be set to 0, because the buffer can not be negative 375 | m_bufferData.bufferLevelOld.push_back (std::max (m_bufferData.bufferLevelNew.back () - 376 | (m_transmissionEndReceivingSegment - m_throughput.transmissionEnd.back ()), (int64_t)0)); 377 | } 378 | else //first segment 379 | { 380 | m_bufferData.bufferLevelOld.push_back (0); 381 | } 382 | m_bufferData.bufferLevelNew.push_back (m_bufferData.bufferLevelOld.back () + m_videoData.segmentDuration); 383 | 384 | m_throughput.bytesReceived.push_back (m_videoData.segmentSize.at (m_currentRepIndex).at (m_segmentCounter)); 385 | m_throughput.transmissionStart.push_back (m_transmissionStartReceivingSegment); 386 | m_throughput.transmissionRequested.push_back (m_downloadRequestSent); 387 | m_throughput.transmissionEnd.push_back (m_transmissionEndReceivingSegment); 388 | 389 | LogDownload (); 390 | 391 | LogBuffer (); 392 | 393 | m_segmentsInBuffer++; 394 | m_bytesReceived = 0; 395 | if (m_segmentCounter == m_lastSegmentIndex) 396 | { 397 | m_bDelay = 0; 398 | } 399 | 400 | controllerEvent event = downloadFinished; 401 | Controller (event); 402 | 403 | } 404 | 405 | bool 406 | TcpStreamClient::PlaybackHandle () 407 | { 408 | NS_LOG_FUNCTION (this); 409 | int64_t timeNow = Simulator::Now ().GetMicroSeconds (); 410 | // if we got called and there are no segments left in the buffer, there is a buffer underrun 411 | if (m_segmentsInBuffer == 0 && m_currentPlaybackIndex < m_lastSegmentIndex && !m_bufferUnderrun) 412 | { 413 | m_bufferUnderrun = true; 414 | bufferUnderrunLog << std::setfill (' ') << std::setw (26) << timeNow / (double)1000000 << " "; 415 | bufferUnderrunLog.flush (); 416 | return true; 417 | } 418 | else if (m_segmentsInBuffer > 0) 419 | { 420 | if (m_bufferUnderrun) 421 | { 422 | m_bufferUnderrun = false; 423 | bufferUnderrunLog << std::setfill (' ') << std::setw (13) << timeNow / (double)1000000 << "\n"; 424 | bufferUnderrunLog.flush (); 425 | } 426 | m_playbackData.playbackStart.push_back (timeNow); 427 | LogPlayback (); 428 | m_segmentsInBuffer--; 429 | m_currentPlaybackIndex++; 430 | return false; 431 | } 432 | 433 | return true; 434 | } 435 | 436 | void 437 | TcpStreamClient::SetRemote (Address ip, uint16_t port) 438 | { 439 | NS_LOG_FUNCTION (this << ip << port); 440 | m_peerAddress = ip; 441 | m_peerPort = port; 442 | } 443 | 444 | void 445 | TcpStreamClient::SetRemote (Ipv4Address ip, uint16_t port) 446 | { 447 | NS_LOG_FUNCTION (this << ip << port); 448 | m_peerAddress = Address (ip); 449 | m_peerPort = port; 450 | } 451 | 452 | void 453 | TcpStreamClient::SetRemote (Ipv6Address ip, uint16_t port) 454 | { 455 | NS_LOG_FUNCTION (this << ip << port); 456 | m_peerAddress = Address (ip); 457 | m_peerPort = port; 458 | } 459 | 460 | void 461 | TcpStreamClient::DoDispose (void) 462 | { 463 | NS_LOG_FUNCTION (this); 464 | Application::DoDispose (); 465 | } 466 | 467 | void 468 | TcpStreamClient::StartApplication (void) 469 | { 470 | NS_LOG_FUNCTION (this); 471 | if (m_socket == 0) 472 | { 473 | TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory"); 474 | m_socket = Socket::CreateSocket (GetNode (), tid); 475 | if (Ipv4Address::IsMatchingType (m_peerAddress) == true) 476 | { 477 | m_socket->Connect (InetSocketAddress (Ipv4Address::ConvertFrom (m_peerAddress), m_peerPort)); 478 | } 479 | else if (Ipv6Address::IsMatchingType (m_peerAddress) == true) 480 | { 481 | m_socket->Connect (Inet6SocketAddress (Ipv6Address::ConvertFrom (m_peerAddress), m_peerPort)); 482 | } 483 | m_socket->SetConnectCallback ( 484 | MakeCallback (&TcpStreamClient::ConnectionSucceeded, this), 485 | MakeCallback (&TcpStreamClient::ConnectionFailed, this)); 486 | m_socket->SetRecvCallback (MakeCallback (&TcpStreamClient::HandleRead, this)); 487 | } 488 | } 489 | 490 | void 491 | TcpStreamClient::StopApplication () 492 | { 493 | NS_LOG_FUNCTION (this); 494 | 495 | if (m_socket != 0) 496 | { 497 | m_socket->Close (); 498 | m_socket->SetRecvCallback (MakeNullCallback > ()); 499 | m_socket = 0; 500 | } 501 | downloadLog.close (); 502 | playbackLog.close (); 503 | adaptationLog.close (); 504 | bufferLog.close (); 505 | throughputLog.close (); 506 | bufferUnderrunLog.close (); 507 | } 508 | 509 | 510 | template 511 | void 512 | TcpStreamClient::PreparePacket (T & message) 513 | { 514 | NS_LOG_FUNCTION (this << message); 515 | std::ostringstream ss; 516 | ss << message; 517 | ss.str (); 518 | uint32_t dataSize = ss.str ().size () + 1; 519 | 520 | if (dataSize != m_dataSize) 521 | { 522 | delete [] m_data; 523 | m_data = new uint8_t [dataSize]; 524 | m_dataSize = dataSize; 525 | } 526 | memcpy (m_data, ss.str ().c_str (), dataSize); 527 | } 528 | 529 | void 530 | TcpStreamClient::ConnectionSucceeded (Ptr socket) 531 | { 532 | NS_LOG_FUNCTION (this << socket); 533 | NS_LOG_LOGIC ("Tcp Stream Client connection succeeded"); 534 | controllerEvent event = init; 535 | Controller (event); 536 | } 537 | 538 | void 539 | TcpStreamClient::ConnectionFailed (Ptr socket) 540 | { 541 | NS_LOG_FUNCTION (this << socket); 542 | NS_LOG_LOGIC ("Tcp Stream Client connection failed"); 543 | } 544 | 545 | void 546 | TcpStreamClient::LogThroughput (uint32_t packetSize) 547 | { 548 | NS_LOG_FUNCTION (this); 549 | throughputLog << std::setfill (' ') << std::setw (13) << Simulator::Now ().GetMicroSeconds () / (double) 1000000 << " " 550 | << std::setfill (' ') << std::setw (13) << packetSize << "\n"; 551 | throughputLog.flush (); 552 | } 553 | 554 | void 555 | TcpStreamClient::LogDownload () 556 | { 557 | NS_LOG_FUNCTION (this); 558 | downloadLog << std::setfill (' ') << std::setw (13) << m_segmentCounter << " " 559 | << std::setfill (' ') << std::setw (21) << m_downloadRequestSent / (double)1000000 << " " 560 | << std::setfill (' ') << std::setw (14) << m_transmissionStartReceivingSegment / (double)1000000 << " " 561 | << std::setfill (' ') << std::setw (12) << m_transmissionEndReceivingSegment / (double)1000000 << " " 562 | << std::setfill (' ') << std::setw (12) << m_videoData.segmentSize.at (m_currentRepIndex).at (m_segmentCounter) << " " 563 | << std::setfill (' ') << std::setw (12) << "Y\n"; 564 | downloadLog.flush (); 565 | } 566 | 567 | void 568 | TcpStreamClient::LogBuffer () 569 | { 570 | NS_LOG_FUNCTION (this); 571 | bufferLog << std::setfill (' ') << std::setw (13) << m_transmissionEndReceivingSegment / (double)1000000 << " " 572 | << std::setfill (' ') << std::setw (13) << m_bufferData.bufferLevelOld.back () / (double)1000000 << "\n" 573 | << std::setfill (' ') << std::setw (13) << m_transmissionEndReceivingSegment / (double)1000000 << " " 574 | << std::setfill (' ') << std::setw (13) << m_bufferData.bufferLevelNew.back () / (double)1000000 << "\n"; 575 | bufferLog.flush (); 576 | } 577 | 578 | void 579 | TcpStreamClient::LogAdaptation (algorithmReply answer) 580 | { 581 | NS_LOG_FUNCTION (this); 582 | adaptationLog << std::setfill (' ') << std::setw (13) << m_segmentCounter << " " 583 | << std::setfill (' ') << std::setw (9) << m_currentRepIndex << " " 584 | << std::setfill (' ') << std::setw (22) << answer.decisionTime / (double)1000000 << " " 585 | << std::setfill (' ') << std::setw (4) << answer.decisionCase << " " 586 | << std::setfill (' ') << std::setw (9) << answer.delayDecisionCase << "\n"; 587 | adaptationLog.flush (); 588 | } 589 | 590 | void 591 | TcpStreamClient::LogPlayback () 592 | { 593 | NS_LOG_FUNCTION (this); 594 | playbackLog << std::setfill (' ') << std::setw (13) << m_currentPlaybackIndex << " " 595 | << std::setfill (' ') << std::setw (14) << Simulator::Now ().GetMicroSeconds () / (double)1000000 << " " 596 | << std::setfill (' ') << std::setw (13) << m_playbackData.playbackIndex.at (m_currentPlaybackIndex) << "\n"; 597 | playbackLog.flush (); 598 | } 599 | 600 | void 601 | TcpStreamClient::InitializeLogFiles (std::string simulationId, std::string clientId, std::string numberOfClients) 602 | { 603 | NS_LOG_FUNCTION (this); 604 | 605 | std::string dLog = dashLogDirectory + m_algoName + "/" + numberOfClients + "/sim" + simulationId + "_" + "cl" + clientId + "_" + "downloadLog.txt"; 606 | downloadLog.open (dLog.c_str ()); 607 | downloadLog << "Segment_Index Download_Request_Sent Download_Start Download_End Segment_Size Download_OK\n"; 608 | downloadLog.flush (); 609 | 610 | std::string pLog = dashLogDirectory + m_algoName + "/" + numberOfClients + "/sim" + simulationId + "_" + "cl" + clientId + "_" + "playbackLog.txt"; 611 | playbackLog.open (pLog.c_str ()); 612 | playbackLog << "Segment_Index Playback_Start Quality_Level\n"; 613 | playbackLog.flush (); 614 | 615 | std::string aLog = dashLogDirectory + m_algoName + "/" + numberOfClients + "/sim" + simulationId + "_" + "cl" + clientId + "_" + "adaptationLog.txt"; 616 | adaptationLog.open (aLog.c_str ()); 617 | adaptationLog << "Segment_Index Rep_Level Decision_Point_Of_Time Case DelayCase\n"; 618 | adaptationLog.flush (); 619 | 620 | std::string bLog = dashLogDirectory + m_algoName + "/" + numberOfClients + "/sim" + simulationId + "_" + "cl" + clientId + "_" + "bufferLog.txt"; 621 | bufferLog.open (bLog.c_str ()); 622 | bufferLog << " Time_Now Buffer_Level \n"; 623 | bufferLog.flush (); 624 | 625 | std::string tLog = dashLogDirectory + m_algoName + "/" + numberOfClients + "/sim" + simulationId + "_" + "cl" + clientId + "_" + "throughputLog.txt"; 626 | throughputLog.open (tLog.c_str ()); 627 | throughputLog << " Time_Now Bytes Received \n"; 628 | throughputLog.flush (); 629 | 630 | std::string buLog = dashLogDirectory + m_algoName + "/" + numberOfClients + "/sim" + simulationId + "_" + "cl" + clientId + "_" + "bufferUnderrunLog.txt"; 631 | bufferUnderrunLog.open (buLog.c_str ()); 632 | bufferUnderrunLog << ("Buffer_Underrun_Started_At Until \n"); 633 | bufferUnderrunLog.flush (); 634 | } 635 | 636 | } // Namespace ns3 637 | -------------------------------------------------------------------------------- /model/tcp-stream-client.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #ifndef TCP_STREAM_CLIENT_H 20 | #define TCP_STREAM_CLIENT_H 21 | 22 | #include "ns3/application.h" 23 | #include "ns3/event-id.h" 24 | #include "ns3/ptr.h" 25 | #include "ns3/ipv4-address.h" 26 | #include "ns3/traced-callback.h" 27 | #include 28 | #include 29 | #include "tcp-stream-adaptation-algorithm.h" 30 | #include "tcp-stream-interface.h" 31 | #include "tobasco2.h" 32 | #include "festive.h" 33 | #include "panda.h" 34 | 35 | 36 | namespace ns3 { 37 | 38 | class Socket; 39 | class Packet; 40 | 41 | /** 42 | * \ingroup tcpStream 43 | * \brief A Tcp Stream client 44 | * 45 | * Every segment size request sent is returned by the server and received here. 46 | */ 47 | class TcpStreamClient : public Application 48 | { 49 | 50 | public: 51 | /** 52 | * \brief Get the type ID. 53 | * \return the object TypeId 54 | */ 55 | static TypeId GetTypeId (void); 56 | TcpStreamClient (); 57 | virtual ~TcpStreamClient (); 58 | 59 | /** 60 | * \brief Set the adaptation algorithm which this client instance should use. 61 | * 62 | * A new adaptation algorithm object is created, by calling a constructor of an existing subclass of 63 | * AdaptationAlgorithm. 64 | * 65 | * \param algorithm the name of the algorithm to use for instantiating an adaptation algorithm object. 66 | */ 67 | void Initialise (std::string algorithm, uint16_t clientId); 68 | 69 | /** 70 | * \brief Set the remote address and port 71 | * \param ip remote IPv4 address 72 | * \param port remote port 73 | */ 74 | void SetRemote (Ipv4Address ip, uint16_t port); 75 | /** 76 | * \brief Set the remote address and port 77 | * \param ip remote IPv6 address 78 | * \param port remote port 79 | */ 80 | void SetRemote (Ipv6Address ip, uint16_t port); 81 | /** 82 | * \brief Set the remote address and port 83 | * \param ip remote IP address 84 | * \param port remote port 85 | */ 86 | void SetRemote (Address ip, uint16_t port); 87 | 88 | protected: 89 | virtual void DoDispose (void); 90 | 91 | private: 92 | /** 93 | * \brief This enum is used to define the states of the state machine which controls the behaviour of the client. 94 | */ 95 | enum controllerState 96 | { 97 | initial, downloading, downloadingPlaying, playing, terminal 98 | }; 99 | controllerState state; 100 | 101 | /** 102 | * \brief This enum is used to define the controller events of the state machine which controls the behaviour of the client. 103 | */ 104 | enum controllerEvent 105 | { 106 | downloadFinished, playbackFinished, irdFinished, init 107 | }; 108 | AdaptationAlgorithm *algo; 109 | 110 | virtual void StartApplication (void); 111 | virtual void StopApplication (void); 112 | 113 | /** 114 | * \brief Finite state machine controlling the client. 115 | * 116 | * When a client object is created, it is initiated as follows and finds itself in state initial: 117 | * - It creates an adaptation algorithm object of the kind specified for this particular simulation. 118 | * - The reduced version of the MPD, containing the duration of a segment in microseconds and a (n x m) matrix consisting of n representations and m segment sizes, denoted in bytes, is being read in from the file specified at program start. 119 | * - The log files are being initialised. 120 | * 121 | * After these initialisations, which take place at object creation, a TCP connection to the server is initiated and the callbacks for a succeeded connection and for receiving are set. Then, the controller does the transition initial init-> downloading by calling RequestRepIndex (), thus obtaining the next representation level to be downloaded. The client then requests the determined segment size from the server by sending it a string composed of the number of bytes of the segment. After the request is processed by the server, it starts sending the first TCP packet to the client. The receiving of a packet notifies the socket that new data is available to be read, so the aforementioned SetRcvCallback is triggered and the client stars receiving packets. Meanwhile all arrived packets are being logged. This is repeated until the received amount of data matches the requested segment size. Then, the throughput is logged and the receive function calls the controller with the event downloadFinished. 122 | * The controller then adds a segment to the buffer and calls the PlaybackHandle() function. Here, the segment buffer is decremented by one segment, thus simulating the beginning of playback. Then, the function returns to the controller, where a timer of m_segmentDuration microseconds is set to call PlaybackHandle() again, after playback of the prior segment is finished. Next, the requests the next segment as described before. Therefore, the controller does the transition downloading downloadfinished-> downloadingPlaying. 123 | 124 | * Now being in state downloadingPlaying, the next possible transitions are 125 | * - downloadingPlaying downloadFinished-> downloadingPlaying: download of a segment is finished. The download of the next segment is started. 126 | * - downloadingPlaying playbackFinished-> downloadingPlaying: playback of a segment is finished. The controller calls PlaybackHandle(), which happens through the beforehand set timer; if the number of segments in the buffer is > 0, the segment buffer is decremented by 1, and the timer is set to call PlaybackHandle() in m_segmentDuration microseconds. 127 | * - downloadingPlaying downloadFinished-> playing: download of a segment is finished. The controller will request the next representation level from the adaptation algorithm. If m_bDelay > 0, the controller delays the download of the next segment by m_bDelay. Streaming session is now performing playback only. 128 | * - downloadingPlaying playbackFinished-> downloading: playback of a segment is finished. This event is triggered by the beforehand set timer. The controller calls PlaybackHandle(); if the number of segments in the buffer is == 0, a buffer underrun is logged. 129 | * - downloadingPlaying downloadFinished-> playing: download of the last segment is finished. Playback of the remaining segment(s) in the buffer continues. After finishing playback of all remaining segments in the buffer, playing playbackFinished-> terminal is performed, thus closing the client's socket, the streaming session for this client ends. 130 | * Assuming that a buffer underrun has just been encountered and the client is currently in state downloading, the client is currently busy downloading the next segment. After the segment is fully downloaded, the controller is notified, PlaybackHandle() is called, thus starting the playback of the just downloaded segment and the transition downloading downloadFinished-> downloadingPlaying is performed. If the just downloaded segment (after the buffer underrun) was the streaming session's last segment, downloading downloadFinished-> playing is performed, the last segment is played and playing playbackFinished-> terminal is performed, as explained before. 131 | */ 132 | void Controller (controllerEvent action); 133 | /** 134 | * Set the data fill of the packet (what is actually sent as data to the server with m_data) to 135 | * the zero-terminated contents of the T & message string. 136 | * 137 | * \param message The amount of bytes the server shall send as a respond. 138 | */ 139 | template 140 | void PreparePacket (T & message); 141 | /** 142 | * \brief Send a packet to the server. 143 | * 144 | * Before a packet is sent, PreparePacket( T & message) is called to fill the packet with 145 | * a string, containig the number of bytes requested from the server. 146 | */ 147 | template 148 | void Send (T & message); 149 | /** 150 | * \brief Handle a packet reception. 151 | * 152 | * This function is called by lower layers, triggered by SetRecvCallback. 153 | * It increments m_bytesReceived by the number of bytes received and calls SegmentReceivedHandle() 154 | * when m_bytesReceived == size of segment that is expected to be received. 155 | * 156 | * \param socket the socket the packet was received to. 157 | */ 158 | void HandleRead (Ptr socket); 159 | /** 160 | * \brief triggered by SetConnectCallback if a connection to a host was established. 161 | */ 162 | void ConnectionSucceeded (Ptr socket); 163 | /** 164 | * \brief triggered by SetConnectCallback if a connection to a host could not be established. 165 | */ 166 | void ConnectionFailed (Ptr socket); 167 | /** 168 | * Called after a segment was completely received from the server, meaning that the received number 169 | * of bytes == the requested number of bytes. Throughput data and buffer data is logged. 170 | */ 171 | void SegmentReceivedHandle (); 172 | /** 173 | * \brief Read in bitrate values 174 | * 175 | * The test bitrate values to be read must be provided in bytes in absolute sizes (not per second!) 176 | * as a 2x2 matrix, with spaces separating the segment sizes and newlines for every representation level. 177 | */ 178 | int ReadInBitrateValues (std::string segmentSizeFile); 179 | /* 180 | * \brief Controls / simulates playback process 181 | * 182 | * Gets called by a timer, when the simulated playback of a segment is finished. 183 | * If m_segmentsInBuffer > 0, then m_segmentsInBuffer is decremented and m_currentPlaybackIndex 184 | * is incremented. Also, if there was a buffer underrun before, m_bufferUnderrun is set to false 185 | * and the end of a buffer underrun is logged. If m_segmentsInBuffer == 0, a buffer underrun is 186 | * registered by writing the event in the bufferUnderrun logfile and m_bufferUnderrun is set to true. 187 | * 188 | * \return true if there is a buffer underrun 189 | */ 190 | bool PlaybackHandle (); 191 | /* 192 | * \brief Request the next representation index from algorithm. 193 | * 194 | * The client requests the next representation index by calling algo->GetNextRep (int64_t m_segmentCounter), which is the interface between an adaptation algorithm 195 | * and a client, specifying the current segment index as an argument. 196 | * The algorithm returns an algorithmReply struct, the received values are stored in local variables for logging purposes. 197 | */ 198 | void RequestRepIndex (); 199 | /* 200 | * \brief Log segment download information 201 | * 202 | * - segment index 203 | * - point in time when download request was sent to server 204 | * - point in time when transmission started, i.e. arrival of first packet of the whole segment 205 | * - point in time when transmission ended, i.e. arrival of last packet of the whole segment 206 | * - size of current segment in bits 207 | * - confirmation if segment was downloaded, Y for yes, N for no 208 | */ 209 | void LogDownload (); 210 | /* 211 | * \brief Log buffer level 212 | * 213 | * Logging the arrival time of fully downloaded segment and logging the buffer level by 214 | * adding m_segmentDuration on the buffer level. 215 | * 216 | * - point in time when segment fully downloaded 217 | * - buffer level before segment is added to buffer 218 | * - point in time when segment fully downloaded 219 | * - buffer level after segment is added to buffer 220 | */ 221 | void LogBuffer (); 222 | /* 223 | * \brief Log throughput information about single arriving TCP packets 224 | * 225 | * - arrival time of packet 226 | * - size of packet 227 | */ 228 | void LogThroughput (uint32_t packetSize); 229 | /* 230 | * \brief Log information about playback process 231 | * 232 | * - index of segment of which playback will start next 233 | * - point in time when playback of above mentioned segment starts 234 | */ 235 | void LogPlayback (); 236 | /* 237 | * \brief Log information about adaptation algorithm. 238 | * 239 | * - current segment index 240 | * - the point in time when the decision in the algorithm was made which representation to download next 241 | * - the case in which the decision was made which representation to download next 242 | * - the case in which the decision was made if the next download should be delayed 243 | * \param answer containing the answer the adaptation algorithm has provided. 244 | */ 245 | void LogAdaptation (algorithmReply answer); 246 | /* 247 | * \brief Open log output files with streams. 248 | * 249 | * The output streams defined in TcpStreamClient are opened, 250 | * and log files containing the used adaptation algorithm are created for output. 251 | */ 252 | void InitializeLogFiles (std::string simulationId, std::string clientId, std::string numberOfClients); 253 | 254 | uint32_t m_dataSize; //!< packet payload size 255 | uint8_t *m_data; //!< packet payload data 256 | 257 | Ptr m_socket; //!< Socket 258 | Address m_peerAddress; //!< Remote peer address 259 | uint16_t m_peerPort; //!< Remote peer port 260 | 261 | uint16_t m_clientId; //!< The Id of this client, for logging purposes 262 | uint16_t m_simulationId; //!< The Id of this simulation, for logging purposes 263 | uint16_t m_numberOfClients; //!< The total number of clients for this simulation, for logging purposes 264 | std::string m_segmentSizeFilePath; //!< The relative path (from ns-3.x directory) to the file containing the segment sizes in bytes 265 | std::string m_algoName;//!< Name of the apation algorithm's class which this client will use for the simulation 266 | bool m_bufferUnderrun; //!< True if there is currently a buffer underrun in the simulated playback 267 | int64_t m_currentPlaybackIndex; //!< The index of the segment that is currently being played 268 | int64_t m_segmentsInBuffer; //!< The number of segments that are currently in the buffer 269 | int64_t m_currentRepIndex; //!< The index of the currently requested segment quality 270 | int64_t m_lastSegmentIndex;//!< The index of the last segment, i.e. the total number of segments-1 271 | int64_t m_segmentCounter; //!< The index of the next segment to be downloaded 272 | int64_t m_transmissionStartReceivingSegment; //!< The point in time in microseconds when the transmission of a segment begins 273 | int64_t m_transmissionEndReceivingSegment; //!< The point in time in microseconds when the transmission of a segment is finished 274 | int64_t m_bytesReceived; //!< Counts the amount of received bytes of the current packet 275 | int64_t m_bDelay; //!< Minimum buffer level in microseconds of playback when the next download must be started 276 | int64_t m_highestRepIndex; //!< This is the index of the highest representation 277 | uint64_t m_segmentDuration; //!< The duration of a segment in microseconds 278 | 279 | std::ofstream adaptationLog; //!< Output stream for logging adaptation information 280 | std::ofstream downloadLog; //!< Output stream for logging download information 281 | std::ofstream playbackLog; //!< Output stream for logging playback information 282 | std::ofstream bufferLog; //!< Output stream for logging buffer course 283 | std::ofstream throughputLog; //!< Output stream for logging throughput information 284 | std::ofstream bufferUnderrunLog; //!< Output stream for logging starting and ending of buffer underruns 285 | 286 | uint64_t m_downloadRequestSent; //!< Logging the point in time in microseconds when a download request was sent to the server 287 | 288 | throughputData m_throughput; //!< Tracking the throughput 289 | bufferData m_bufferData; //!< Keep track of the buffer level 290 | playbackData m_playbackData; //!< Tracking the simulated playback of segments 291 | videoData m_videoData; //!< Information about segment sizes, average bitrates of representation levels and segment duration in microseconds 292 | 293 | }; 294 | 295 | } // namespace ns3 296 | 297 | #endif /* TCP_STREAM_CLIENT_H */ 298 | -------------------------------------------------------------------------------- /model/tcp-stream-interface.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | #ifndef TCP_STREAM_INTERFACE_H 19 | #define TCP_STREAM_INTERFACE_H 20 | 21 | namespace ns3 { 22 | 23 | std::string const dashLogDirectory = "dash-log-files/"; 24 | 25 | /*! \class algorithmReply tcp-stream-interface.h "model/tcp-stream-interface.h" 26 | * \ingroup tcpStream 27 | * \brief This struct contains the reply an adaptation algorithm returns to the client 28 | * 29 | * Data structure that an adaptation algorithm returns to the client, containing all the information 30 | * the client needs for deciding which representation index to request from the server next, and when 31 | * to schedule the next request in microseconds. Optionally the following variables can be used for logging: when the algorithm 32 | * made the decision and at which part of the code it decided which representation index and inter-request 33 | * time to select. 34 | */ 35 | struct algorithmReply 36 | { 37 | int64_t nextRepIndex; //!< representation level index of the next segement to be downloaded by the client 38 | int64_t nextDownloadDelay; //!< delay time in microseconds when the next segment shall be requested from the server 39 | int64_t decisionTime; //!< time in microsends when the adaptation algorithm decided which segment to download next, only for logging purposes 40 | int64_t decisionCase; //!< indicate in which part of the adaptation algorithm's code the decision was made, which representation level to request next, only for logging purposes 41 | int64_t delayDecisionCase; //!< indicate in which part of the adaptation algorithm's code the decision was made, how much time in microsends to wait until the segment shall be requested from server, only for logging purposes 42 | }; 43 | 44 | 45 | /*! \class throughputData tcp-stream-interface.h "model/tcp-stream-interface.h" 46 | * \ingroup tcpStream 47 | * \brief This is a struct containing throughput data. 48 | * 49 | * Contains throughput data that the adaptation algorithm is provided by the client. These values are 50 | * needed to compute the next representation index based on previous throughput. 51 | */ 52 | struct throughputData 53 | { 54 | std::vector transmissionRequested; //!< Simulation time in microseconds when a segment was requested by the client 55 | std::vector transmissionStart; //!< Simulation time in microseconds when the first packet of a segment was received 56 | std::vector transmissionEnd; //!< Simulation time in microseconds when the last packet of a segment was received 57 | std::vector bytesReceived; //!< Number of bytes received, i.e. segment size 58 | }; 59 | 60 | /*! \class bufferData tcp-stream-interface.h "model/tcp-stream-interface.h" 61 | * \ingroup tcpStream 62 | * \brief This is a struct containing buffer data. 63 | * 64 | * Tracks the status of the buffer level. 65 | */ 66 | struct bufferData 67 | { 68 | std::vector timeNow; //!< current simulation time 69 | std::vector bufferLevelOld; //!< buffer level in microseconds before adding segment duration (in microseconds) of just downloaded segment 70 | std::vector bufferLevelNew; //!< buffer level in microseconds after adding segment duration (in microseconds) of just downloaded segment 71 | }; 72 | 73 | /*! \class videoData tcp-stream-interface.h "model/tcp-stream-interface.h" 74 | * \ingroup tcpStream 75 | * \brief This is a struct containing video data. 76 | * 77 | * Reduced version of a MPEG-DASH Media Presentation Description (MPD), containing a 2D [i][j] matrix 78 | * containing the size of every segment j in representation level i, the average bitrate of every 79 | * representation level and the duration of a segment in microseconds. 80 | */ 81 | struct videoData 82 | { 83 | std::vector < std::vector > segmentSize; //!< vector holding representation levels in the first dimension and their particular segment sizes in bytes in the second dimension 84 | std::vector < double > averageBitrate; //!< holding the average bitrate of a segment in representation i in bits 85 | int64_t segmentDuration; //!< duration of a segment in microseconds 86 | }; 87 | 88 | /*! \class playbackData tcp-stream-interface.h "model/tcp-stream-interface.h" 89 | * \ingroup tcpStream 90 | * \brief This is a struct containing playback data. 91 | * 92 | * A pair of values, playbackIndex representing the index of a segment: multiplication with segmentDuration 93 | * yields the point in time in microseconds where on the timeline of the video file the start of this segment 94 | * can be found. playbackStart however, indicates the start of the playback (in the streaming process) 95 | * of the segment in microseconds in simulation time. 96 | */ 97 | struct playbackData 98 | { 99 | std::vector playbackIndex; //!< Index of the video segment 100 | std::vector playbackStart; //!< Point in time in microseconds when playback of this segment started 101 | }; 102 | 103 | } // namespace ns3 104 | 105 | #endif /* TCP_STREAM_CLIENT_H */ 106 | -------------------------------------------------------------------------------- /model/tcp-stream-server.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #include "ns3/log.h" 20 | #include "ns3/ipv4-address.h" 21 | #include "ns3/ipv6-address.h" 22 | #include "ns3/address-utils.h" 23 | #include "ns3/nstime.h" 24 | #include "ns3/inet-socket-address.h" 25 | #include "ns3/inet6-socket-address.h" 26 | #include "ns3/socket.h" 27 | #include "ns3/tcp-socket.h" 28 | #include "ns3/simulator.h" 29 | #include "ns3/socket-factory.h" 30 | #include "ns3/packet.h" 31 | #include "ns3/uinteger.h" 32 | #include "ns3/tcp-socket-factory.h" 33 | #include "tcp-stream-server.h" 34 | #include "ns3/global-value.h" 35 | #include 36 | #include "tcp-stream-client.h" 37 | #include "ns3/trace-source-accessor.h" 38 | 39 | namespace ns3 { 40 | 41 | NS_LOG_COMPONENT_DEFINE ("TcpStreamServerApplication"); 42 | 43 | NS_OBJECT_ENSURE_REGISTERED (TcpStreamServer); 44 | 45 | TypeId 46 | TcpStreamServer::GetTypeId (void) 47 | { 48 | static TypeId tid = TypeId ("ns3::TcpStreamServer") 49 | .SetParent () 50 | .SetGroupName ("Applications") 51 | .AddConstructor () 52 | .AddAttribute ("Port", "Port on which we listen for incoming packets.", 53 | UintegerValue (9), 54 | MakeUintegerAccessor (&TcpStreamServer::m_port), 55 | MakeUintegerChecker ()) 56 | ; 57 | return tid; 58 | } 59 | 60 | TcpStreamServer::TcpStreamServer () 61 | { 62 | NS_LOG_FUNCTION (this); 63 | } 64 | 65 | TcpStreamServer::~TcpStreamServer () 66 | { 67 | NS_LOG_FUNCTION (this); 68 | m_socket = 0; 69 | m_socket6 = 0; 70 | } 71 | 72 | void 73 | TcpStreamServer::DoDispose (void) 74 | { 75 | NS_LOG_FUNCTION (this); 76 | Application::DoDispose (); 77 | } 78 | 79 | void 80 | TcpStreamServer::StartApplication (void) 81 | { 82 | NS_LOG_FUNCTION (this); 83 | 84 | if (m_socket == 0) 85 | { 86 | TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory"); 87 | m_socket = Socket::CreateSocket (GetNode (), tid); 88 | InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), m_port); 89 | m_socket->Bind (local); 90 | m_socket->Listen (); 91 | } 92 | 93 | if (m_socket6 == 0) 94 | { 95 | TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory"); 96 | m_socket6 = Socket::CreateSocket (GetNode (), tid); 97 | Inet6SocketAddress local6 = Inet6SocketAddress (Ipv6Address::GetAny (), m_port); 98 | m_socket6->Bind (local6); 99 | m_socket->Listen (); 100 | } 101 | 102 | // Accept connection requests from remote hosts. 103 | m_socket->SetAcceptCallback (MakeNullCallback, const Address &> (), 104 | MakeCallback (&TcpStreamServer::HandleAccept,this)); 105 | m_socket->SetCloseCallbacks ( 106 | MakeCallback (&TcpStreamServer::HandlePeerClose, this), 107 | MakeCallback (&TcpStreamServer::HandlePeerError, this)); 108 | } 109 | 110 | void 111 | TcpStreamServer::StopApplication () 112 | { 113 | NS_LOG_FUNCTION (this); 114 | 115 | if (m_socket != 0) 116 | { 117 | m_socket->Close (); 118 | m_socket->SetRecvCallback (MakeNullCallback > ()); 119 | } 120 | if (m_socket6 != 0) 121 | { 122 | m_socket6->Close (); 123 | m_socket6->SetRecvCallback (MakeNullCallback > ()); 124 | } 125 | } 126 | 127 | void 128 | TcpStreamServer::HandleRead (Ptr socket) 129 | { 130 | NS_LOG_FUNCTION (this << socket); 131 | Ptr packet; 132 | Address from; 133 | packet = socket->RecvFrom (from); 134 | int64_t packetSizeToReturn = GetCommand (packet); 135 | // these values will be accessible by the clients Address from. 136 | m_callbackData [from].currentTxBytes = 0; 137 | m_callbackData [from].packetSizeToReturn = packetSizeToReturn; 138 | m_callbackData [from].send = true; 139 | 140 | HandleSend (socket, socket->GetTxAvailable ()); 141 | 142 | } 143 | 144 | void 145 | TcpStreamServer::HandleSend (Ptr socket, uint32_t txSpace) 146 | { 147 | Address from; 148 | socket->GetPeerName (from); 149 | // look up values for the connected client and whose values are stored in from 150 | if (m_callbackData [from].currentTxBytes == m_callbackData [from].packetSizeToReturn) 151 | { 152 | m_callbackData [from].currentTxBytes = 0; 153 | m_callbackData [from].packetSizeToReturn = 0; 154 | m_callbackData [from].send = false; 155 | return; 156 | } 157 | if (socket->GetTxAvailable () > 0 && m_callbackData [from].send) 158 | { 159 | int32_t toSend; 160 | toSend = std::min (socket->GetTxAvailable (), m_callbackData [from].packetSizeToReturn - m_callbackData [from].currentTxBytes); 161 | Ptr packet = Create (toSend); 162 | int amountSent = socket->Send (packet, 0); 163 | if (amountSent > 0) 164 | { 165 | m_callbackData [from].currentTxBytes += amountSent; 166 | } 167 | // We exit this part, when no bytes have been sent, as the send side buffer is full. 168 | // The "HandleSend" callback will fire when some buffer space has freed up. 169 | else 170 | { 171 | return; 172 | } 173 | } 174 | } 175 | 176 | void 177 | TcpStreamServer::HandleAccept (Ptr s, const Address& from) 178 | { 179 | NS_LOG_FUNCTION (this << s << from); 180 | callbackData cbd; 181 | cbd.currentTxBytes = 0; 182 | cbd.packetSizeToReturn = 0; 183 | cbd.send = false; 184 | m_callbackData [from] = cbd; 185 | m_connectedClients.push_back (from); 186 | s->SetRecvCallback (MakeCallback (&TcpStreamServer::HandleRead, this)); 187 | s->SetSendCallback ( MakeCallback (&TcpStreamServer::HandleSend, this)); 188 | } 189 | 190 | void 191 | TcpStreamServer::HandlePeerClose (Ptr socket) 192 | { 193 | NS_LOG_FUNCTION (this << socket); 194 | Address from; 195 | socket->GetPeerName (from); 196 | for (std::vector
::iterator it = m_connectedClients.begin (); it != m_connectedClients.end (); ++it) 197 | { 198 | if (*it == from) 199 | { 200 | m_connectedClients.erase (it); 201 | // No more clients left in m_connectedClients, simulation is done. 202 | if (m_connectedClients.size () == 0) 203 | { 204 | Simulator::Stop (); 205 | } 206 | return; 207 | } 208 | } 209 | } 210 | 211 | void 212 | TcpStreamServer::HandlePeerError (Ptr socket) 213 | { 214 | NS_LOG_FUNCTION (this << socket); 215 | } 216 | 217 | int64_t 218 | TcpStreamServer::GetCommand (Ptr packet) 219 | { 220 | int64_t packetSizeToReturn; 221 | uint8_t *buffer = new uint8_t [packet->GetSize ()]; 222 | packet->CopyData (buffer, packet->GetSize ()); 223 | std::stringstream ss; 224 | ss << buffer; 225 | std::string str; 226 | ss >> str; 227 | std::stringstream convert (str); 228 | convert >> packetSizeToReturn; 229 | return packetSizeToReturn; 230 | } 231 | } // Namespace ns3 232 | -------------------------------------------------------------------------------- /model/tcp-stream-server.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #ifndef TCP_STREAM_SERVER_H 20 | #define TCP_STREAM_SERVER_H 21 | 22 | #include "ns3/application.h" 23 | #include "ns3/event-id.h" 24 | #include "ns3/ptr.h" 25 | #include "ns3/address.h" 26 | #include "ns3/traced-callback.h" 27 | #include 28 | #include "ns3/random-variable-stream.h" 29 | 30 | namespace ns3 { 31 | 32 | 33 | 34 | class Socket; 35 | class Packet; 36 | class PropagationDelayModel; 37 | 38 | /** 39 | * \ingroup applications 40 | * \defgroup tcpStream TcpStream 41 | */ 42 | 43 | /** 44 | * \ingroup tcpStream 45 | * \brief data strucute the server uses to manage the following data for every client separately. 46 | */ 47 | struct callbackData 48 | { 49 | uint32_t currentTxBytes;//!< already sent bytes for this particular segment, set to 0 if sent bytes == packetSizeToReturn, so transmission for this segment is over 50 | uint32_t packetSizeToReturn;//!< total amount of bytes that have to be returned to the client 51 | bool send;//!< true as long as there are still bytes left to be sent for the current segment 52 | }; 53 | 54 | /** 55 | * \ingroup tcpStream 56 | * \brief A Tcp Stream server 57 | * 58 | * Clients sent messages with the amount of bytes they want the server to return to them. 59 | */ 60 | class TcpStreamServer : public Application 61 | { 62 | public: 63 | /** 64 | * \brief Get the type ID. 65 | * \return the object TypeId 66 | */ 67 | static TypeId GetTypeId (void); 68 | TcpStreamServer (); 69 | virtual ~TcpStreamServer (); 70 | 71 | protected: 72 | virtual void DoDispose (void); 73 | 74 | private: 75 | virtual void StartApplication (void); 76 | virtual void StopApplication (void); 77 | 78 | /** 79 | * \brief Handle a packet reception, and set SendCallback to HandlSend. 80 | * 81 | * This function is called by lower layers. The received packet's content 82 | * gets deserialized by GetCommand (Ptr packet). If the packets content 83 | * contains a string composed of an int with 84 | * value n, then n bytes will be sent back to the sender. 85 | * 86 | * \param socket the socket the packet was received to. 87 | */ 88 | void HandleRead (Ptr socket); 89 | 90 | /** 91 | * \brief send packetSizeToReturn bytes to the client connected to socket. 92 | * 93 | * This function is called once by HandleRead (Ptr socket) after a send of n (i.e. 94 | * a segment of n) bytes was requested by the client. If n > socket->GetTxAvailable (), 95 | * (this is the current space available in the buffer in bytes), then socket->GetTxAvailable () bytes 96 | * are written into the buffer. This function will get called again through the SendCallback when 97 | * space in the buffer has freed up. 98 | * The amount of sent bytes for this particular segment and for the client connected with 99 | * this socket is stored in m_callbackData [from].currentTxBytes, so the server can access the already sent bytes 100 | * through the value of from, which is provided by socket, because there is a socket instance for every connected client. 101 | * m_callbackData [from].send indicates for the client with address from that the server has not yet sent 102 | * m_callbackData [from].packetSizeToReturn bytes. When the number of bytes should be sent is 103 | * reached, m_callbackData [from].send will be set to false and the server stops sending 104 | * bytes to the client until he requests another segment. 105 | * 106 | * \param socket the socket the request for a segment was received to and where the server will send packetSizeToReturn bytes to. 107 | * \param packetSizeToReturn the full segment size in bytes that has to be returned to the client 108 | */ 109 | void HandleSend (Ptr socket, uint32_t packetSizeToReturn); 110 | 111 | /** 112 | * \brief Set callback functions for receive and send. 113 | * Add the newly connected client to m_connectedClients and allocate callbackData structure for this client. 114 | */ 115 | void HandleAccept (Ptr s, const Address& from); 116 | 117 | void HandlePeerClose (Ptr socket); 118 | void HandlePeerError (Ptr socket); 119 | 120 | /** 121 | * \brief Deserialize what the client has sent us. 122 | * \param packet the data the client has sent us 123 | * \return the deserialized packet content as a string 124 | */ 125 | int64_t GetCommand (Ptr packet); 126 | 127 | uint16_t m_port; //!< Port on which we listen for incoming packets. 128 | Ptr m_socket; //!< IPv4 Socket 129 | Ptr m_socket6; //!< IPv6 Socket 130 | std::map m_callbackData; //!< With this it is possible to access the currentTxBytes, the packetSizeToReturn and the send boolean through the from value of the client. 131 | std::vector
m_connectedClients; //!< Vector which holds the list of currently connected clients. 132 | 133 | 134 | }; 135 | 136 | } // namespace ns3 137 | 138 | #endif /* TCP_STREAM_SERVER_H */ 139 | 140 | -------------------------------------------------------------------------------- /model/tobasco2.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #include "tobasco2.h" 20 | 21 | namespace ns3 { 22 | 23 | NS_LOG_COMPONENT_DEFINE ("TobascoAlgorithm"); 24 | 25 | NS_OBJECT_ENSURE_REGISTERED (TobascoAlgorithm); 26 | 27 | TobascoAlgorithm::TobascoAlgorithm ( const videoData &videoData, 28 | const playbackData & playbackData, 29 | const bufferData & bufferData, 30 | const throughputData & throughput) : 31 | AdaptationAlgorithm (videoData, playbackData, bufferData, throughput), 32 | m_a1 (0.75), 33 | m_a2 (0.33), 34 | m_a3 (0.5), 35 | m_a4 (0.75), 36 | m_a5 (0.9), 37 | m_bMin (5000000), 38 | m_bLow (20000000), 39 | m_bHigh (40000000), 40 | m_bOpt ((int64_t)(0.5 * (m_bLow + m_bHigh))), 41 | m_deltaBeta (1000000), 42 | m_deltaTime (10000000), 43 | m_highestRepIndex (videoData.averageBitrate.size () - 1) 44 | { 45 | NS_LOG_INFO (this); 46 | m_runningFastStart = true; 47 | NS_ASSERT_MSG (m_highestRepIndex >= 0, "The highest quality representation index should be >= 0"); 48 | } 49 | 50 | algorithmReply 51 | TobascoAlgorithm::GetNextRep ( const int64_t segmentCounter, int64_t clientId) 52 | { 53 | int64_t decisionCase = 0; 54 | int64_t delayDecision = 0; 55 | int64_t nextRepIndex = 0; 56 | int64_t bDelay = 0; 57 | // we use timeFactor, to divide the absolute size of a segment that is given in bits with the duration of a 58 | // segment in seconds, so that we get bitrate per seconds 59 | double timeFactor = m_videoData.segmentDuration / 1000000; 60 | const int64_t timeNow = Simulator::Now ().GetMicroSeconds (); 61 | int64_t bufferNow = 0; 62 | // for the first segment the algorithm returns the lowest index 0 by definition, so we directly jump to the return part 63 | if (segmentCounter != 0) 64 | { 65 | nextRepIndex = m_lastRepIndex; 66 | bufferNow = m_bufferData.bufferLevelNew.back () - (timeNow - m_throughput.transmissionEnd.back ()); 67 | double averageSegmentThroughput = AverageSegmentThroughput (timeNow - m_deltaTime, timeNow); 68 | double nextHighestRepBitrate; 69 | if (m_lastRepIndex < m_highestRepIndex) 70 | { 71 | nextHighestRepBitrate = (8.0 * m_videoData.averageBitrate.at (m_lastRepIndex + 1)) / timeFactor; 72 | } 73 | else 74 | { 75 | nextHighestRepBitrate = (8.0 * m_videoData.averageBitrate.at (m_lastRepIndex)) / timeFactor; 76 | } 77 | 78 | if (m_runningFastStart 79 | && m_lastRepIndex != m_highestRepIndex 80 | && MinimumBufferLevelObserved () 81 | && ((8.0 * m_videoData.averageBitrate.at (m_lastRepIndex)) / timeFactor <= m_a1 * averageSegmentThroughput)) 82 | { 83 | /* --------- running fast start phase --------- */ 84 | if (bufferNow < m_bMin) 85 | { 86 | if (nextHighestRepBitrate <= (m_a2 * averageSegmentThroughput)) 87 | { 88 | decisionCase = 1; 89 | nextRepIndex = m_lastRepIndex + 1; 90 | } 91 | } 92 | else if (bufferNow < m_bLow) 93 | { 94 | if (nextHighestRepBitrate <= (m_a3 * averageSegmentThroughput)) 95 | { 96 | decisionCase = 2; 97 | nextRepIndex = m_lastRepIndex + 1; 98 | } 99 | } 100 | else 101 | { 102 | if (nextHighestRepBitrate <= (m_a4 * averageSegmentThroughput)) 103 | { 104 | decisionCase = 3; 105 | nextRepIndex = m_lastRepIndex + 1; 106 | } 107 | if (bufferNow > m_bHigh) 108 | { 109 | delayDecision = 1; 110 | bDelay = m_bHigh - m_videoData.segmentDuration; 111 | } 112 | } 113 | } 114 | /* --------- /running_fast start phase --------- */ 115 | else 116 | { 117 | m_runningFastStart = false; 118 | if (bufferNow < m_bMin) 119 | { 120 | decisionCase = 4; 121 | nextRepIndex = 0; 122 | } 123 | else if (bufferNow < m_bLow) 124 | { 125 | double lastSegmentThroughput = (8.0 * m_videoData.segmentSize.at (m_lastRepIndex).at (segmentCounter - 1)) 126 | / ((double)(m_throughput.transmissionEnd.at (segmentCounter - 1) - m_throughput.transmissionStart.at (segmentCounter - 1)) / 1000000.0); 127 | 128 | if ((m_lastRepIndex != 0) 129 | && ((8.0 * m_videoData.segmentSize.at (m_lastRepIndex).at (segmentCounter - 1)) / timeFactor >= lastSegmentThroughput)) 130 | { 131 | decisionCase = 5; 132 | for (int i = m_highestRepIndex; i >= 0; i--) 133 | { 134 | if ((8.0 * m_videoData.segmentSize.at (i).at (segmentCounter - 1)) / timeFactor >= lastSegmentThroughput) 135 | { 136 | continue; 137 | } 138 | else 139 | { 140 | nextRepIndex = i; 141 | break; 142 | } 143 | } 144 | if (nextRepIndex >= m_lastRepIndex) 145 | { 146 | nextRepIndex = m_lastRepIndex - 1; 147 | } 148 | } 149 | } 150 | else if (bufferNow < m_bHigh) 151 | { 152 | if ((m_lastRepIndex == m_highestRepIndex) 153 | || (nextHighestRepBitrate >= m_a5 * averageSegmentThroughput)) 154 | { 155 | delayDecision = 2; 156 | bDelay = (int64_t)(std::max (bufferNow - m_videoData.segmentDuration, m_bOpt)); 157 | } 158 | } 159 | else 160 | { 161 | if ((m_lastRepIndex == m_highestRepIndex) 162 | || (nextHighestRepBitrate >= m_a5 * averageSegmentThroughput)) 163 | { 164 | delayDecision = 3; 165 | bDelay = (int64_t)(std::max (bufferNow - m_videoData.segmentDuration, m_bOpt)); 166 | } 167 | else 168 | { 169 | decisionCase = 6; 170 | nextRepIndex = m_lastRepIndex + 1; 171 | } 172 | } 173 | } 174 | } 175 | 176 | if (segmentCounter != 0 && delayDecision != 0) 177 | { 178 | if (bDelay > bufferNow) 179 | { 180 | bDelay = 0; 181 | } 182 | else 183 | { 184 | bDelay = bufferNow - bDelay; 185 | } 186 | } 187 | m_lastRepIndex = nextRepIndex; 188 | algorithmReply answer; 189 | answer.nextRepIndex = nextRepIndex; 190 | answer.nextDownloadDelay = bDelay; 191 | answer.decisionTime = timeNow; 192 | answer.decisionCase = decisionCase; 193 | answer.delayDecisionCase = delayDecision; 194 | return answer; 195 | } 196 | 197 | bool 198 | TobascoAlgorithm::MinimumBufferLevelObserved () 199 | { 200 | if (m_throughput.transmissionEnd.size () < 2) 201 | { 202 | return true; 203 | } 204 | int64_t lastPackage = m_throughput.transmissionEnd.end ()[-1]; 205 | int64_t secondToLastPackage = m_throughput.transmissionEnd.end ()[-2]; 206 | 207 | if (m_deltaBeta < m_videoData.segmentDuration) 208 | { 209 | if (lastPackage - secondToLastPackage < m_deltaBeta) 210 | { 211 | return true; 212 | } 213 | else 214 | { 215 | return false; 216 | } 217 | } 218 | else 219 | { 220 | if (lastPackage - secondToLastPackage < m_videoData.segmentDuration) 221 | { 222 | return true; 223 | } 224 | else 225 | { 226 | return false; 227 | } 228 | } 229 | } 230 | 231 | double 232 | TobascoAlgorithm::AverageSegmentThroughput (int64_t t_1, int64_t t_2) 233 | { 234 | if (t_1 < 0) 235 | { 236 | t_1 = 0; 237 | } 238 | if (m_throughput.transmissionEnd.size () < 1) 239 | { 240 | return 0; 241 | } 242 | 243 | 244 | // First, we have to find the index of the start of the download of the first downloaded segment in 245 | // the interval [t_1, t_2] 246 | uint index = 0; 247 | for (uint i = 0; i <= m_throughput.transmissionEnd.size () - 1; i++) 248 | { 249 | if (m_throughput.transmissionEnd.at (i) < t_1) 250 | { 251 | continue; 252 | } 253 | else 254 | { 255 | index = i; 256 | break; 257 | } 258 | } 259 | 260 | double lengthOfInterval; 261 | double sumThroughput = 0.0; 262 | double transmissionTime = 0.0; 263 | if (m_throughput.transmissionRequested.at (index) < t_1) 264 | { 265 | lengthOfInterval = m_throughput.transmissionEnd.at (index) - t_1; 266 | sumThroughput += (m_videoData.averageBitrate.at (m_playbackData.playbackIndex.at (index)) * ((m_throughput.transmissionEnd.at (index) - t_1) 267 | / (m_throughput.transmissionEnd.at (index) - m_throughput.transmissionRequested.at (index)))) * lengthOfInterval; 268 | transmissionTime += lengthOfInterval; 269 | index++; 270 | if (index >= m_throughput.transmissionEnd.size ()) 271 | { 272 | return (sumThroughput / (double)transmissionTime); 273 | } 274 | } 275 | // Compute the average download-time of all the fully completed segment downloads during [t_1, t_2]. 276 | while (m_throughput.transmissionEnd.at (index) <= t_2) 277 | { 278 | lengthOfInterval = m_throughput.transmissionEnd.at (index) - m_throughput.transmissionRequested.at (index); 279 | sumThroughput += ((m_videoData.averageBitrate.at (m_playbackData.playbackIndex.at (index)) * m_videoData.segmentDuration) 280 | / lengthOfInterval) * lengthOfInterval; 281 | transmissionTime += lengthOfInterval; 282 | index++; 283 | if (index > m_throughput.transmissionEnd.size () - 1) 284 | { 285 | break; 286 | } 287 | } 288 | return (sumThroughput / (double)transmissionTime); 289 | 290 | } 291 | } // namespace ns3 292 | 293 | -------------------------------------------------------------------------------- /model/tobasco2.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright 2016 Technische Universitaet Berlin 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #ifndef TOBASCO_ALGORITHM_H 20 | #define TOBASCO_ALGORITHM_H 21 | 22 | #include "tcp-stream-adaptation-algorithm.h" 23 | 24 | namespace ns3 { 25 | 26 | /** 27 | * \ingroup tcpStream 28 | * \brief Implementation of the Tobasco adaptation algorithm 29 | */ 30 | class TobascoAlgorithm : public AdaptationAlgorithm 31 | { 32 | public: 33 | TobascoAlgorithm ( const videoData &videoData, 34 | const playbackData & playbackData, 35 | const bufferData & bufferData, 36 | const throughputData & throughput); 37 | 38 | algorithmReply GetNextRep ( const int64_t segmentCounter, int64_t clientId); 39 | 40 | private: 41 | /** 42 | * \brief Average segment throughput during the time interval [t1, t2] 43 | */ 44 | double AverageSegmentThroughput (int64_t t1, int64_t t2); 45 | 46 | 47 | /** 48 | * Was the minimum buffer level observed during a time interval with duration delta_beta 49 | * for a given t_n, at every point of time t_i <= t_(i+1) for every t_i < t_n ? 50 | * 51 | * \return if true is returned, then the above described situation holds, else false 52 | * 53 | */ 54 | bool MinimumBufferLevelObserved (); 55 | 56 | const double m_a1; 57 | const double m_a2; 58 | const double m_a3; 59 | const double m_a4; 60 | const double m_a5; 61 | const int64_t m_bMin; 62 | const int64_t m_bLow; 63 | const int64_t m_bHigh; 64 | const int64_t m_bOpt; 65 | const int64_t m_deltaBeta; 66 | const int64_t m_deltaTime; 67 | const int64_t m_highestRepIndex; 68 | int64_t m_lastRepIndex; 69 | bool m_runningFastStart; 70 | }; 71 | } // namespace ns3 72 | #endif /* TOBASCO_ALGORITHM_H */ -------------------------------------------------------------------------------- /segmentSizes.txt: -------------------------------------------------------------------------------- 1 | 3128 44788 83412 92274 56210 56494 43658 32596 41642 33180 38444 33376 32942 22196 25740 44300 42024 48390 56032 54032 54978 104786 88554 74040 58278 51942 54466 57920 50548 50132 35914 43436 50348 17618 35476 14770 19032 23214 23874 23626 28048 25910 27172 27830 14566 20498 25212 21066 25702 15526 14732 4586 25076 59710 80200 93142 90404 56704 56710 25188 56370 57462 36636 41498 49256 36086 20736 28548 24040 44330 42074 31408 34858 22094 2796 54622 81862 94040 66898 82440 78726 95142 76192 84038 90522 71640 58264 49978 79054 82070 77228 99042 72644 62406 79684 29094 88842 85974 48720 59144 72972 46104 45178 26312 25598 36894 79762 69020 48820 30548 26146 23994 12224 11696 12276 14194 31302 36298 59268 56456 76406 55058 44538 24702 93498 98178 81998 93400 74280 62274 44244 40108 52166 48884 29734 40142 33368 45168 33810 43746 26816 41468 80300 64990 64958 60696 46818 50306 32004 27488 41278 41946 49376 45900 42748 28464 28446 62654 59458 33120 42218 82674 63882 44478 38636 35516 73540 65978 63916 40792 19212 24276 30198 24728 14770 17556 14726 11684 6630 5538 6360 7124 8220 8376 15726 11092 11278 20974 19852 74100 89036 87316 94966 88848 110198 65018 37536 12188 26070 20856 22958 21922 35856 29890 23744 18206 25584 24192 33970 31446 4310 10046 16976 21824 26016 25736 39942 55574 2102 11340 11588 18214 2 | 3254 93058 163088 184294 120228 114716 85260 65960 83530 66028 76042 67382 62090 42838 51568 85324 82874 94430 110584 104602 112556 204056 170788 142026 114824 104946 108484 110226 99396 101116 67794 83276 99018 36942 75570 32924 43240 50264 51086 48716 57456 53162 54614 55394 30372 41060 50072 42254 49934 32318 27812 8220 57908 132460 166780 192670 167894 121326 116214 48080 109116 110272 70822 84180 105136 71566 40222 52800 43902 93854 88366 62454 67110 36762 3824 114990 171732 192844 139044 173528 161996 175128 147730 161990 172352 138154 118588 101082 153670 167472 161560 198274 139164 124784 161960 54998 174302 168968 93616 126708 148610 95462 83590 52654 50824 73528 153224 129158 95846 56610 50946 44076 23104 20568 22040 24454 55826 69968 108398 100606 139476 100874 81024 42872 183654 187280 170708 175712 155286 119708 95028 77210 98160 86178 56280 74100 59754 84992 71436 81260 50676 86028 160358 128552 125230 121230 96776 103386 67572 53752 78554 71286 86924 83790 74348 48266 51718 116614 109474 61126 78338 161928 124958 83558 74708 67126 140636 131860 121860 81668 43740 45724 57410 47622 29324 37482 31204 26378 16998 13782 16728 17554 15500 13632 28896 19802 23810 47304 43434 161956 184748 172478 189518 180516 211928 125598 70186 31330 58454 44908 48772 44564 71230 59212 43556 36388 49546 47296 60528 59694 8604 20652 34230 40842 52144 52720 80096 106706 2778 21566 22260 40074 3 | 3974 243212 402968 457150 347976 312058 231512 171470 222158 192482 213442 184750 163092 101006 118826 208244 226456 242842 275916 268708 311018 489240 412512 367926 309250 287796 288064 280296 259990 260812 180962 219144 260346 116350 198060 100054 125546 125504 130818 124748 146250 139352 159678 144444 82282 107600 130496 114272 136428 89652 72460 22300 169740 338154 397714 467468 467194 396154 346844 139204 275762 309528 181334 228152 291186 195054 112692 112390 96952 279304 276954 163606 192418 104860 6794 235822 471608 504234 394274 421662 434594 390128 333200 395056 392216 312520 292432 263816 348104 384630 401768 536448 364506 298930 506754 153908 381116 430718 217872 382100 439114 282490 214572 138920 143526 187834 359676 333208 248296 149318 134352 116894 59076 50036 55758 61884 130606 176968 297708 250518 353984 253842 185970 95426 445862 460636 465384 417982 378544 301320 254788 218542 252372 206826 146240 188846 128668 186988 171006 206884 134354 205924 431032 339186 318504 317828 265252 290840 197574 131034 202736 165992 209230 211488 184376 124870 132330 302242 294734 159622 193844 419782 302198 210180 181536 172052 349658 321490 341510 237236 160800 125790 149700 136100 92636 100488 85618 77924 56736 45296 53680 53206 40396 36306 66902 53066 64408 132932 118128 475542 450956 437324 502958 437952 502030 355916 213238 108484 170664 120082 138940 120556 190374 137808 107436 88314 125676 117442 132230 139322 19192 57604 87566 96368 137902 130998 204088 248552 5776 62032 61562 132582 4 | 4496 499214 825296 981130 733942 639638 488296 349962 468860 407504 423708 397076 362400 218644 271614 432530 450424 502640 582204 574158 634288 986196 796780 776022 649422 632654 610536 594824 540494 543780 372834 447436 544846 282550 429728 231128 288106 259568 267158 262252 320112 325766 337610 311068 183118 228512 268660 250930 306064 216892 162990 58192 434928 780428 806510 1049902 905668 845636 712994 286844 566994 699506 385138 488782 658572 398404 243534 213104 166854 599198 630786 338794 429164 218206 9128 487818 887212 988738 831436 927058 954128 728684 677420 767956 711404 599408 545456 607032 803392 888836 833016 1061446 771184 624886 1042920 368014 772124 899156 489618 756886 892690 635282 412054 377892 335894 423870 721890 630878 507862 308708 280204 251086 119590 98320 111942 125666 288890 391040 581496 454238 678236 483200 354484 177536 876408 908216 858274 826538 760088 606134 508100 421640 502270 401606 310696 382828 246226 364590 366294 419886 276350 397564 871142 672570 652402 669492 558668 644556 454568 268256 394072 320422 402174 404798 352830 242336 277468 643386 586404 321830 407130 857050 608912 450308 396032 384834 734186 635976 714816 498648 380772 269934 317514 287150 247714 215854 180738 189282 144052 111166 127046 129496 89084 76352 135678 117608 143608 284656 270246 1052512 880550 972786 1041308 889826 1066060 763484 461268 279728 388022 257770 295600 257474 375854 268818 203832 174950 247914 224606 243528 261690 39538 130388 187660 190616 276098 283796 415324 494980 9990 133710 140966 350948 5 | 6408 1006390 1841772 2099710 1531106 1303354 967638 751908 936996 883384 890872 830152 765002 481596 602644 889364 968034 1102734 1295478 1338370 1397536 1917062 1563234 1655234 1370872 1401124 1329350 1168552 1147554 1163788 817018 976766 1161540 698234 905140 490738 634470 518874 529286 515898 660316 669498 717700 643228 384562 477904 589022 539598 717554 521114 345114 141080 958252 1787280 1613708 2125048 2015250 1814240 1498414 651980 1287846 1711582 915990 993484 1352482 848530 585962 383728 287802 1350204 1515590 782468 1070150 486094 14296 989948 1776506 2033208 1814206 1852666 1996606 1434576 1328280 1515308 1278040 1102240 1136032 1242512 1601626 1937714 1676352 2326452 1536728 1235472 2217278 763824 1636062 1881846 1075266 1452782 1870676 1264732 819002 794940 821986 989774 1432070 1323784 1224324 741860 603878 507256 231316 195314 217788 243370 609564 846388 1241018 849472 1287740 901818 667334 344224 1950346 1618930 1583354 1510930 1472128 1218834 1009640 832688 1026946 835284 674002 842368 447766 750858 816138 913214 549862 963196 1665542 1346368 1341050 1319788 1158838 1415672 927420 484348 798722 660962 794788 804462 721140 486548 597914 1368330 1158858 662344 829650 1722928 1209426 1046072 860692 861758 1471654 1328104 1470408 1155658 923144 636330 700600 718670 696622 414728 384730 457902 355580 267092 330582 309736 201442 169954 276514 239632 304248 654422 595154 2097618 1940922 2057210 2078328 2012278 2381974 1634170 1083096 655162 892450 523218 632704 544830 785478 503244 388446 321488 471416 424558 449990 500632 80508 294050 405442 364588 568062 637698 848614 942380 20648 331500 370406 850512 6 | 10938 1909944 3562992 4145746 2826254 2411580 1846876 1458456 1862256 1639262 1762162 1728436 1632720 931898 1068962 1664806 1860726 2226064 2508828 2697114 2778562 3438364 2744388 3098524 2781476 2725820 2531100 2133572 2153536 2287890 1703198 1954122 2221892 1489546 1728682 1009416 1235548 967432 994276 991678 1198642 1260468 1355492 1216606 769760 998702 1138672 1103682 1441186 1162574 701398 267270 1911638 3809514 2908998 4124046 3757420 3646514 2863936 1413148 2735758 3605436 1927798 1810158 2468234 1644128 1283582 645554 476182 2849792 3157680 1655086 2422030 865194 21740 1672964 3429076 3619938 3495936 3793936 3642068 2613222 2477740 2844468 2238952 1856964 2104104 2565686 3164702 4017534 2964310 4405610 3078792 2660794 4577932 1670978 3121956 3711576 2113830 3165496 3884196 2339512 1472964 1552708 1649486 1928648 2664290 2382926 2641274 1726200 1066390 861156 383238 325736 355820 437786 1120514 1565278 2246054 1439812 2092608 1562956 1099550 545526 3348426 2548652 2609818 2441370 2479116 2120604 1720670 1489034 1899890 1716682 1443298 1649440 749824 1287512 1621168 1811462 990190 1832646 3125862 2439334 2302404 2283298 2083042 2638298 1888154 838810 1465628 1321054 1531564 1536356 1427612 974274 1210618 2505438 2106386 1258916 1591920 3256720 2220868 2200020 1604814 1672490 2891308 2614254 2805362 2344458 2213208 1347990 1383444 1657150 1616186 791876 751246 911254 750422 603632 733442 690840 472776 341294 483174 453708 605806 1494720 1272124 4046808 3740994 3928406 4131498 3843068 4500754 3162366 2076624 1308272 1768866 936694 1201910 1023084 1361640 830002 654374 569596 820790 764302 787636 910580 152604 547486 784306 730232 1078612 1150454 1633210 1790694 42398 707788 869078 1822590 7 | 17156 4558232 8464440 9880024 6815232 5800546 4410872 3556972 4325380 4136900 4561474 4558050 4424170 2475356 2818674 4262348 4745676 5371768 6714188 6834746 6777406 7169380 5829902 7445994 6680016 6923654 5779600 5054764 5091644 5717128 4683302 4676456 4947434 3823108 4021130 2672626 3294710 2371476 2483134 2402176 3073966 3354800 3386394 2745306 2035694 2548164 2951676 2810914 3905126 3405868 1922972 737200 4752738 8527054 7697808 9737424 9012976 9409366 7691190 3602870 7112776 8926608 4893090 4411542 6075804 4308440 3460970 1426454 1051374 6650934 7918856 4176020 5786550 1923896 37088 3635360 8654442 8776046 8102772 9722294 9609384 5252370 5225936 6490310 4852056 4148502 5010908 7163198 7585548 10126692 6930482 11127882 7279548 6359458 11685180 4534484 7127392 7978342 5155032 8009532 10367848 5836330 3131786 4112218 4706564 4846722 6111416 5587704 7334824 4916198 2488000 2005750 770086 641594 747634 920510 2547680 3729996 4815334 2843380 4299244 3195050 2242844 1165214 6800018 5045272 5010970 4716982 5041212 4422072 3766422 3155806 4153232 4274608 3903466 4194944 1640676 2766674 3932322 4199492 2107740 4117966 6963336 5620138 5305968 5409740 4772436 6135164 4579268 1795422 3444382 3450010 3269908 3467588 3308552 2244422 2926848 5592628 4413426 2796880 3660504 7533248 5010154 5411976 3869402 4344394 6905924 5947576 6182400 6475082 6455982 3714282 3994506 4209008 4729682 1848218 1983640 2567612 2404088 2106070 2660432 2403346 1534600 913140 1110714 1103382 1653844 3939210 3738582 9606526 8941710 9684976 10111356 8788462 11637172 7949250 5374578 3452472 4571072 2247484 2899326 2508070 3180516 1835380 1493684 1353300 1930332 1771204 1765204 2117030 382526 1477660 2094178 1983954 3019654 3459742 4165700 3760282 118290 2046476 2623830 5588586 8 | 35018 10235930 18957124 22219182 14794028 11957970 10124214 8383694 9830090 9713614 10278768 10425366 10677716 6283256 6512442 9084532 9672028 11615626 14954150 17136488 15418258 14383494 11579136 16460822 14244350 15099710 12200530 10798346 11094208 13084368 11684344 11169524 11486054 9171790 8993872 6156126 7977944 5220406 5245888 5221218 6902860 7926558 7805012 6082434 4874134 6330848 7333500 6993030 8817036 7678526 4416706 1798418 11742546 19486360 17718196 23212644 19391182 21495352 15863080 8751256 14435318 19594342 11329054 10042974 14512238 9848024 8366936 2982452 2190212 15120154 18618318 9768628 12922748 4111798 66926 8221272 15701826 18699098 18377726 22807920 21392602 10585780 10684620 13481218 9758932 8524946 10922262 16283780 17141832 23730118 14560080 25866224 15802312 14010948 26738996 15027888 10784318 16110598 11883792 19816548 24248456 14209622 6921350 10304036 10308264 10976386 13046246 11174754 17255980 11603680 5120670 3992342 1420626 1199994 1454620 1843162 5395278 8168992 9974842 5488362 8211000 6164490 4355994 2435876 13851114 9981854 9573406 9036964 10075310 8630012 7297118 6491214 8515722 9689286 9442052 9144470 3271160 5884304 9079930 9247056 4375760 8075920 14388390 11854134 11215582 11948452 9916000 13423416 9729186 3662858 7124672 8388538 7723012 7651092 7351602 5476322 6770748 11893712 8973116 6281286 7918956 16437064 10867234 13103546 8760986 10014120 14922866 12769984 13082100 15941850 18280530 9043636 9004972 10426466 12418858 4457100 5280662 6997744 7122338 6110772 7806250 6941706 4371516 1966578 2687180 2517442 4022880 9164254 8849584 21860800 19393306 21562418 23722018 19095328 25992730 17888574 11734566 7301988 9348936 4615452 6584812 5648632 6612280 3732166 3243628 2896218 3796552 3591768 3795876 4525652 944736 3514482 4793272 4637182 6589082 7641392 9230992 7549558 286170 5276008 7267534 13926930 -------------------------------------------------------------------------------- /wscript: -------------------------------------------------------------------------------- 1 | ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- 2 | 3 | def build(bld): 4 | module = bld.create_ns3_module('dash', ['internet','config-store','stats']) 5 | module.includes = '.' 6 | module.source = [ 7 | 'model/tcp-stream-client.cc', 8 | 'model/tcp-stream-server.cc', 9 | 'model/tcp-stream-adaptation-algorithm.cc', 10 | 'model/festive.cc', 11 | 'model/panda.cc', 12 | 'model/tobasco2.cc', 13 | 'helper/tcp-stream-helper.cc', 14 | ] 15 | 16 | headers = bld(features='ns3header') 17 | headers.module = 'dash' 18 | headers.source = [ 19 | 'model/tcp-stream-client.h', 20 | 'model/tcp-stream-server.h', 21 | 'model/tcp-stream-interface.h', 22 | 'model/tcp-stream-adaptation-algorithm.h', 23 | 'model/festive.h', 24 | 'model/panda.h', 25 | 'model/tobasco2.h', 26 | 'helper/tcp-stream-helper.h', 27 | ] 28 | 29 | if bld.env['ENABLE_EXAMPLES']: 30 | bld.recurse('examples') 31 | 32 | bld.ns3_python_bindings() 33 | --------------------------------------------------------------------------------