[
  {
    "path": ".travis.yml",
    "content": "language: c\naddons:\n  apt:\n    packages:\n    - flex\n    - bison\n\n"
  },
  {
    "path": "Credits",
    "content": "vtrunkd (c) 2015-2016 Vrayo Systems Ltd. team (http://vrayo.com)\n\nAuthor of vtrunkd core algorithm is Andrew Gryaznov <realgrandrew@gmail.com>\nwith help of Andrey Kuznetsov <andreykyz@gmail.com>\n\nAuthor of the original vtun package is Maxim Krasnyansky <max_mk@yahoo.com>.\n\nA lot of thanks to the following people for their suggestions and \ncontributions (original vtun):\n\nGayaneh Krasnyanskaya(Max's Wife) <gayaneh@yahoo.com> \n\tInitial Web site creation. And a lot of other help :)))  \n\nAlex Korenkov <alex@uznet.net> \n\tTesting, bug reports.\n\nShukhrat Zakhidov <shukhrat@ishonch.uz>\n\tTesting, bug reports, suggestions.\n\nDag Wieers <dag@mind.be>\n\tInitial RPM packager specification file. \n\tRedHat startup script. \n\tSeveral bug reports. \n\tSOCKS support suggestions.\n\nTed Rolle <ted@acacia.datacomm.com> \n\tSpelling fixes.\n\nCraig Sanders <cas@taz.net.au> \n\tDebian startup script.\n\nCatalin Ciocoiu <catalin@ccp.pub.ro> \n\tReported compilation problems. \n\nTimur Danyarhojaev <tid@podolsk.ru> \n\tAdded client source address option.\n\nAndreas Kainz <aka@gams.at>\n\tRPM package improvements.\n\nChris Todd <christ@insynq.com>\n\tIdea of challenge based authentication. \n\tInitial BlowFish encryption code. \n\tSuggestions.\n\nGaret Krampe <garet@satix.net> \n\tA lot of great ideas. Mailing list.\n\tWeb site mirror.\n\nDenis Zapolsky <denis@granch.com.my> \n\tTesting. \n\nVadim Zaliva <lord@crocodile.org>\n\tSolaris patches.  Suggestions.\n\nHurricane Floyd <floyd@hurricanes.org> \n\tMax had several vacations.\n\tBishop had no power or water, and was able\n\t   to experience the Third World.\n\t:)))))))))))))))))))\n\nJames B. MacLean <macleajb@Trademart-1.EDnet.NS.CA> \n\tClient persist mode fix. Suggestions.\n\nPaul <xerox@httpd.net> \n\tStress tests, bug reports, suggestions.\n\nMaksim Yevenkin <m_evmenkin@yahoo.com>\n\tTAP driver for FreeBSD.\n\nAnthon Walters <anthon@ws.co.za>\n\tWeb site mirror. Testing. Initial FAQ.\n\nRyan Defelice <ryand@mobiletel.com> \n\tOpenBSD package maintainer. Provided OpenBSD server for \n\tdevelopment and testing\n\nAlexander Bergolth <leo@strike.wu-wien.ac.at>\n\tInitial multiple connection handling and host lock functionalities.\n\tImprovements and fixes of source address option. Incorrect error \n\thandling fix. Ideas. Suggestions.\n\nHubert Feyrer <feyrer@rfhs8012.fh-regensburg.de>\n\tNetBSD package.\n\nHiroharu Tamaru <tamaru@ap.t.u-tokyo.ac.jp>\n\tUpdated FreeBSD 4.0 TUN driver support. \n\nTerry Donaldson <tsd@geo-mis.com>\n\tProvided Solaris 8.0 server for development and testing.\n\nDaniel Podlejski <underley@underley.eu.org>\n\tTUN/TAP driver modifications for 2.3.99-pre5 kernel.\n\nMichael Tokarev <mjt@tls.msk.ru>\n\tFile descriptors and memory leaks fix. \n\tTons of other bug fixes and patches. Suggestions. Ideas.\n\nXavier <xavier@bru-noc.net>\n\tEuropean web site mirror.\n\nChris Snell <chris@bikeworld.com>\n\tMailing list archives.\n\nRobert Stone <talby@trap.mtview.ca.us>\n\tSecurity enhancements. Suggestions. Ideas.\n\tEncryption and other subsystems rework for 3.X.\n\nSteinar H. Gunderson <sgunderson@bigfoot.com>\n\tTons of stability fixes and problem reports. \n\tIdeas and suggestions.\n\nYan Seiner <yan@cardinalengineering.com>\n\tTesting. Bug reports. Suggestions.\n\nJames Yonan <jim@funnybee.ntlp.com>\n\tEncryption and other fixes. Suggestions.\n\nGreg Olszewski <noop@nwonknu.org>\n\tConfig parser and other fixes. Suggestions.\n\nKevin P. Fleming <kevin@labsysgrp.com>\n\tMakefile and config parser enhancement.\n\tOther minor fixes and suggestions.\n\nRobert R. Wal <rrw@hell.pl>\n\tAdded support for iproute command.\n\nWillems Luc <willems.luc@pandora.be>\n\tInitial SuSE packaging.  Testing.\n\nNickolai Zeldovich <nickolai@cs.stanford.edu>\n\tmlockall() support to prevent VM collapse.\n\nDale Fountain <dpf-vtun@fountainbay.com>\n\tAdded multiple cipher support.\n\tAdded multiple cipher modes support.\n\tAdded support for different sized keys.\n\tRe-sync ciphers when using non-ECB modes over a UDP connection.\n\tFixed Bug#908824 (persist=keep not re-applying routes)\n\nAlan Grow <agrow-at-thegotonerd.com>\n\tAdded a Listening Address/Interface (rfe936523)\n\tCleaned up the code around that portion of the config.\n"
  },
  {
    "path": "INSTALL",
    "content": "System requirements:\n\n- Linux. Kernel 2.6.25+ recommended\n- Additional software:\n   bison\n   flex\n   zlib-dev\n   liblzo-dev\n   libssl-dev\n\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "Makefile.in",
    "content": "#\n#   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n#\n#   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n#\n#   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n#   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n#\n#   This program is free software; you can redistribute it and/or modify\n#   it under the terms of the GNU General Public License as published by\n#   the Free Software Foundation; either version 2 of the License, or\n#   (at your option) any later version.\n#\n#   This program is distributed in the hope that it will be useful,\n#   but WITHOUT ANY WARRANTY; without even the implied warranty of\n#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n#   GNU General Public License for more details.\n#\n#   Makefile.in,v 1.6.2.4.2.1 2006/11/16 04:03:44 mtbishop Exp\n#  \n\nVERSION=\\\"$(shell git describe --abbrev=4 --dirty --always)\\\"\nCC = @CC@\nCFLAGS = @CFLAGS@ @CPPFLAGS@ -W\nLDFLAGS = @LIBS@ -lm\n\nYACC = @YACC@\nYACCFLAGS = -d\n\nLEX = @LEX@\nLEXFLAGS = -t \n\nINSTALL = @INSTALL@\nINSTALL_OWNER = -o root -g 0\n\nprefix = @prefix@\nexec_prefix = @exec_prefix@\n\nSBIN_DIR = @sbindir@\nMAN_DIR  = @mandir@\nETC_DIR  = @sysconfdir@\nVAR_DIR  = @localstatedir@\n\nPID_FILE = ${VAR_DIR}/run/vtrunkd.pid\nCFG_FILE = ${ETC_DIR}/vtrunkd.conf\nSTAT_DIR = ${VAR_DIR}/log/vtrunkd\nLOCK_DIR = ${VAR_DIR}/lock/vtrunkd\n\nDEFS = -DVTUN_CONFIG_FILE=\\\"$(CFG_FILE)\\\" -DVTUN_PID_FILE=\\\"$(PID_FILE)\\\" \\\n       -DVTUN_STAT_DIR=\\\"$(STAT_DIR)\\\" -DVTUN_LOCK_DIR=\\\"$(LOCK_DIR)\\\" \\\n       -DVERSION_NUMBER=$(VERSION)\n\nOBJS = main.o cfg_file.tab.o cfg_file.lex.o server.o client.o lib.o \\\n       frame_llist.o llist.o auth.o tunnel.o lock.o netlib.o  \\\n       tun_dev.o tap_dev.o pty_dev.o pipe_dev.o \\\n       tcp_proto.o udp_proto.o log.o \\\n       linkfd.o lfd_shaper.o lfd_zlib.o lfd_lzo.o lfd_encrypt.o speed_algo.o timer.o packet_code.o udp_states.o pid.o\n\nCONFIGURE_FILES = Makefile config.status config.cache config.h config.log \n\n%.o: %.c vtun.h lib.h log.h\n\t$(CC) $(CFLAGS) $(DEFS) -c $<\n\nall: vtrunkd \n\nvtrunkd: $(OBJS)\n\t$(CC) $(CFLAGS) -o vtrunkd $(OBJS) $(FSSOBJS) $(LFD_OBJS) $(LDFLAGS)\n\nvshm_start_debug: $(OBJS)\n\t$(CC) $(CFLAGS) -o vshm_debug_enable vshm_start_debug.c $(LDFLAGS)\n\nget_cong_status: $(OBJS)\n\t$(CC) $(CFLAGS) -o get_cong_status get_cong_status.c $(LDFLAGS)\n\ncfg_file.tab.c: cfg_file.y cfg_kwords.h config.h\n\t$(YACC) $(YACCFLAGS) -b cfg_file cfg_file.y\n\ncfg_file.lex.c: cfg_file.l cfg_kwords.h config.h\n\t$(LEX) $(LEXFLAGS) cfg_file.l > cfg_file.lex.c \n\ndepend:\n\tmakedepend -- $(CFLAGS) -- *.c\n\nclean:\n\trm -f core cfg_file.tab.* cfg_file.lex.* *.o *~ *.bak vtrunkd vshm_debug_enable get_cong_status\n\ndistclean: clean\n\trm -f $(CONFIGURE_FILES)\n\trm -f `cat vtun.drivers`\t\n\ninstall_man: \n\t$(INSTALL) -d -m 755 $(INSTALL_OWNER) $(DESTDIR)$(MAN_DIR)/man8\n\t$(INSTALL) -m 644 $(INSTALL_OWNER) vtrunkd.8 $(DESTDIR)$(MAN_DIR)/man8\n\t$(INSTALL) -d -m 755 $(INSTALL_OWNER) $(DESTDIR)$(MAN_DIR)/man5\n\t$(INSTALL) -m 644 $(INSTALL_OWNER) vtrunkd.conf.5 $(DESTDIR)$(MAN_DIR)/man5\n\trm -f $(DESTDIR)$(MAN_DIR)/man8/vtrunkd.8 \n\tln -s vtrunkd.8 $(DESTDIR)$(MAN_DIR)/man8/vtrunkd.8 \n\ninstall_config: \n\t$(INSTALL) -d -m 755 $(INSTALL_OWNER) $(DESTDIR)$(ETC_DIR)\n\tif [ ! -f $(ETC_DIR)/vtrunkd.conf ]; then \\\n\t  $(INSTALL) -m 600 $(INSTALL_OWNER) vtrunkd.conf $(DESTDIR)$(ETC_DIR)/; \\\n\tfi\n\t#if [ ! -f $(ETC_DIR)/vtrunkd-srv.test.conf ]; then \\\n\t#  $(INSTALL) -m 600 $(INSTALL_OWNER) test/vtrunkd-srv.test.conf $(DESTDIR)$(ETC_DIR)/; \\\n\t#fi\n\t#if [ ! -f $(ETC_DIR)/vtrunkd-cli.test.conf ]; then \\\n\t#  $(INSTALL) -m 600 $(INSTALL_OWNER) test/vtrunkd-cli.test.conf $(DESTDIR)$(ETC_DIR)/; \\\n\t#fi\ninstall_scripts:\n\t#if [ ! -f $(prefix)/cli.sh ]; then \\\n\t#  $(INSTALL) -m 755 $(INSTALL_OWNER) test/cli.sh $(DESTDIR)$(prefix)/; \\\n\t#fi\n\t#if [ ! -f $(prefix)/srv.sh ]; then \\\n\t#  $(INSTALL) -m 755 $(INSTALL_OWNER) test/srv.sh $(DESTDIR)$(prefix)/; \\\n\t#fi\n\n\ninstall: vtrunkd install_config install_man install_scripts\n\t$(INSTALL) -d -m 755 $(INSTALL_OWNER) $(DESTDIR)$(VAR_DIR)/run\n\t$(INSTALL) -d -m 755 $(INSTALL_OWNER) $(DESTDIR)$(STAT_DIR)\n\t$(INSTALL) -d -m 755 $(INSTALL_OWNER) $(DESTDIR)$(LOCK_DIR)\n\t$(INSTALL) -d -m 755 $(INSTALL_OWNER) $(DESTDIR)$(SBIN_DIR)\n\t$(INSTALL) -m 755 $(INSTALL_OWNER) vtrunkd $(DESTDIR)$(SBIN_DIR)/\n\n# DO NOT DELETE THIS LINE -- make depend depends on it.\nremove: remove_config remove_start_bin remove_docs\n\nremove_config:\n\trm -f $(DESTDIR)$(ETC_DIR)/vtrunkd*\nremove_start_bin:\n\trm -f $(DESTDIR)$(prefix)/srv.sh\n\trm -f $(DESTDIR)$(prefix)/cli.sh\n\trm -f $(DESTDIR)$(prefix)/sbin/vtrunkd\nremove_docs:\n\trm -f $(DESTDIR)$(MAN_DIR)/man5/vtrunkd.conf.5\n\trm -f $(DESTDIR)$(MAN_DIR)/man8/vtrunkd.8 \n"
  },
  {
    "path": "README.md",
    "content": "[![Build Status](https://travis-ci.org/VrayoSystems/vtrunkd.svg?branch=master)](https://travis-ci.org/VrayoSystems/vtrunkd)\n\n# vtrunkd - universal network link bonding and multichannel VPN.\n\nCopyright (C) 2015-2016 Vrayo Systems team, http://vrayo.com/\n\nVtrunkd is a Linux VPN daemon used to combine several connection paths \ninto one aggregated channel. Features latency, reordering and jitter \nmanagement, behaviour analysis optimizations for encapsulated protocols, \nbufferbloat control, packet redundancy, and multiple cpu cores utilization. \nUp to 30 heterogenous links bonding supported. Used for live streaming, \nLTE/3G/Wi-Fi link bonding. 32/64-bit, x86, MIPS and ARM supported. \nSupports python plug-ins for new algorithms implementation. \n\n\n## Compilation and Installation:\n\nIn order to compile vtrunkd you need several software packages.\nRequired packages: \n  - Good C compiler (gcc, egcs, etc)\n  - GNU Make (make)\n  - GNU libtool (libtool)\n  - Lexical Analyzer (flex, lex)\n  - YACC (yacc, bison, byacc)\n  - Universal TUN/TAP driver \thttp://vtun.sourceforge.net/tun\n  \nOn ubuntu, run: \n\n    $ sudo apt-get install build-essential flex bison\n    $ ./configure --prefix=\n    $ make\n    $ sudo make install\n\n## Support\n\nIf you have any suggestions, ideas, wishes send them to \n\n- Andrew Gryaznov \n   - ag@vrayo.com, \n   - https://www.linkedin.com/in/grandrew\n- Commercial support available from Vrayo Systems team. \n   - For more info, please visit http://vrayo.com/support/\n  \n----\n\nvtrunkd and vtrunkd algorithm (C) Andrew Gryaznov\n\nBased on Vtun (C) 1998-2004 Maxim Krasnyansky\n\nThis product includes software developed by the OpenSSL Project\nfor use in the OpenSSL Toolkit. (http://www.openssl.org/).\nCopyright (c) 1998-2004 The OpenSSL Project.  All rights reserved.\n"
  },
  {
    "path": "aclocal.m4",
    "content": "dnl Test files\nAC_DEFUN( AC_TEST_FILES,\n[\n    ac_file_found=yes\n    for f in $1; do\n\tif test ! -f $2/$f; then\n    \t   ac_file_found=no\n\t   break;\n\tfi\n    done\n\n    if test \"$ac_file_found\" = \"yes\" ; then\n\tifelse([$3], , :,[$3])\n    else\n\tifelse([$4], , :,[$4])\n    fi\n])\n\ndnl Search for headers, add path to CPPFLAGS if found \nAC_DEFUN( AC_SEARCH_HEADERS, \n[\n    AC_MSG_CHECKING(\"for $1\") \n    ac_hdr_found=no\n    for p in $2; do\n\tif test -n \"$p\"; then\n\t  dir=\"$p\"\n\telse\n\t  dir=\"/usr/include\"\n\tfi\n\tAC_TEST_FILES($1, $dir, \n\t    [ \n     \t       ac_hdr_found=yes\n\t       break\n\t    ]\n\t)\n    done \n    if test \"$ac_hdr_found\" = \"yes\" ; then\n\tif test -n \"$p\"; then\n\t  CPPFLAGS=\"$CPPFLAGS -I$p\"\n\tfi\n        AC_MSG_RESULT( [($dir) yes] ) \n\tifelse([$3], , :,[$3])\n    else\n        AC_MSG_RESULT(\"no\") \n\tifelse([$4], , :,[$4])\n    fi\n])\n\n\ndnl Create links to all files($1) in the directory($2)\nAC_DEFUN( AC_LINK_DIR, \n[\n    for i in $1; do\n      if test -f $2/$i -a ! -f $i; then\n         AC_MSG_RESULT(linking $2/$i  to  $i)\n         ln -f -s $2/$i $i\n      fi\n    done \n])\n\ndnl Create driver and protocol links\ndnl $1 - drivers list, $2 - os dir\nAC_DEFUN( AC_LINK_DRV, \n[\n    AC_MSG_RESULT( creating driver and protocol links ... )\n\n    if test \"$2\" != \"\"; then\n       AC_LINK_DIR($1, $2)\n    fi\n    AC_LINK_DIR($1, generic)\n])\n"
  },
  {
    "path": "auth.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * auth.c,v 1.2.2.7.2.3 2006/11/16 04:02:33 mtbishop Exp\n */ \n\n/*\n * Challenge based authentication. \n * Thanx to Chris Todd<christ@insynq.com> for the good idea.\n *\n * Jim Yonan, 05/24/2001\n * \tgen_chal rewrite to use better random number generator \n */ \n\n#include \"config.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <signal.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <signal.h>\n#include <syslog.h>\n#include <time.h>\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\n#ifdef HAVE_NETINET_TCP_H\n#include <netinet/tcp.h>\n#endif\n\n#ifdef HAVE_ARPA_INET_H\n#include <arpa/inet.h>\n#endif\n\n#include \"vtun.h\"\n#include \"lib.h\"\n#include \"lock.h\"\n#include \"auth.h\"\n\n/* Encryption and Decryption of the challenge key */\n#ifdef HAVE_SSL\n\n#include <openssl/md5.h>\n#include <openssl/blowfish.h>\n#include <openssl/rand.h>\n\nvoid gen_chal(char *buf)\n{\n   RAND_bytes(buf, VTUN_CHAL_SIZE);\n}\n\nvoid encrypt_chal(char *chal, char *pwd)\n{ \n   register int i;\n   BF_KEY key;\n\n   BF_set_key(&key, 16, MD5(pwd,strlen(pwd),NULL));\n\n   for(i=0; i < VTUN_CHAL_SIZE; i += 8 )\n      BF_ecb_encrypt(chal + i,  chal + i, &key, BF_ENCRYPT);\n}\n\nvoid decrypt_chal(char *chal, char *pwd)\n{ \n   register int i;\n   BF_KEY key;\n\n   BF_set_key(&key, 16, MD5(pwd,strlen(pwd),NULL));\n\n   for(i=0; i < VTUN_CHAL_SIZE; i += 8 )\n      BF_ecb_encrypt(chal + i,  chal + i, &key, BF_DECRYPT);\n}\n\n#else /* HAVE_SSL */\n\nvoid encrypt_chal(char *chal, char *pwd)\n{ \n   char * xor_msk = pwd;\n   register int i, xor_len = strlen(xor_msk);\n\n   for(i=0; i < VTUN_CHAL_SIZE; i++)\n      chal[i] ^= xor_msk[i%xor_len];\n}\n\nvoid decrypt_chal(char *chal, char *pwd)\n{ \n   encrypt_chal(chal, pwd);\n}\n\n/* Generate PSEUDO random challenge key. */\nvoid gen_chal(char *buf)\n{\n   register int i;\n \n   srand(time(NULL));\n\n   for(i=0; i < VTUN_CHAL_SIZE; i++)\n      buf[i] = (unsigned int)(255.0 * rand()/RAND_MAX);\n}\n#endif /* HAVE_SSL */\n\n/* \n * Functions to convert binary flags to character string.\n * string format:  <CS64> \n * C - compression, S - speed for shaper and so on.\n */ \n\nchar *bf2cf(struct vtun_host *host)\n{\n     static char str[20], *ptr = str;\n\n     *(ptr++) = '<';\n\n     switch( host->flags & VTUN_PROT_MASK ){\n\tcase VTUN_TCP:\n\t   *(ptr++) = 'T';\n\t   break;\n\n\tcase VTUN_UDP:\n\t   *(ptr++) = 'U';\n\t   break;\n     }\n\n     switch( host->flags & VTUN_TYPE_MASK ){\n\tcase VTUN_TTY:\n\t   *(ptr++) = 't'; \t\n\t   break;\n\n\tcase VTUN_PIPE:\n\t   *(ptr++) = 'p';\n\t   break; \t\n\n\tcase VTUN_ETHER:\n\t   *(ptr++) = 'e';\n\t   break;\n\n\tcase VTUN_TUN:\n\t   *(ptr++) = 'u';\n\t   break;\n     } \n\n     if( (host->flags & VTUN_SHAPE) /* && host->spd_in */)\n\tptr += sprintf(ptr,\"S%d\",host->spd_in);\n\n     if( host->flags & VTUN_ZLIB )\n\tptr += sprintf(ptr,\"C%d\", host->zlevel);\n\n     if( host->flags & VTUN_LZO )\n\tptr += sprintf(ptr,\"L%d\", host->zlevel);\n\n     if( host->flags & VTUN_KEEP_ALIVE )\n\t*(ptr++) = 'K';\n\n     if( host->flags & VTUN_ENCRYPT )\n\tptr += sprintf(ptr,\"E%d\", host->cipher);\n\n     strcat(ptr,\">\");\n\n     return str;\n}\n\n/* return 1 on success, otherwise 0 */\n\nint cf2bf(char *str, struct vtun_host *host)\n{\n     char *ptr, *p;\n     int s;\n\n     if( (ptr = strchr(str,'<')) ){ \n\tptr++;\n\twhile(*ptr){  \n\t   switch(*ptr++){\n\t     case 't':\n\t\thost->flags |= VTUN_TTY;\n\t\tbreak;\n\t     case 'p':\n\t\thost->flags |= VTUN_PIPE;\n\t\tbreak;\n\t     case 'e':\n\t\thost->flags |= VTUN_ETHER;\n\t\tbreak;\n\t     case 'u':\n\t\thost->flags |= VTUN_TUN;\n\t\tbreak;\n\t     case 'U':\n\t\thost->flags &= ~VTUN_PROT_MASK;\n\t\thost->flags |= VTUN_UDP;\n\t\tbreak;\n\t     case 'T':\n\t\thost->flags &= ~VTUN_PROT_MASK;\n\t\thost->flags |= VTUN_TCP;\n\t\tbreak;\n\t     case 'K':\n\t\thost->flags |= VTUN_KEEP_ALIVE;\n\t\tbreak;\n\t     case 'C':\n\t\tif((s = strtol(ptr,&p,10)) == ERANGE || ptr == p) \n\t\t   return 0;\n\t\thost->flags |= VTUN_ZLIB;\n\t\thost->zlevel = s; \n\t\tptr = p;\n\t\tbreak;\n\t     case 'L':\n\t\tif((s = strtol(ptr,&p,10)) == ERANGE || ptr == p) \n\t\t   return 0;\n\t\thost->flags |= VTUN_LZO;\n\t\thost->zlevel = s; \n\t\tptr = p;\n\t\tbreak;\n\t     case 'E':\n\t\tif((s = strtol(ptr,&p,10)) == ERANGE || ptr == p) \n\t\t   return 0;\n\t\thost->flags |= VTUN_ENCRYPT;\n\t\thost->cipher = s; \n\t\tptr = p;\n\t\tbreak;\n     \t     case 'S':\n\t\tif((s = strtol(ptr,&p,10)) == ERANGE || ptr == p) \n\t\t   return 0;\n\t\tif( s ){\n\t    \t   host->flags |= VTUN_SHAPE;\n\t\t   host->spd_out = s; \n\t\t}\n\t\tptr = p;\n\t\tbreak;\n\t     case '>':\n\t        return 1;\n\t     default:\n\t\treturn 0;\n\t   }\n\t}\n     }\n     return 0;\n}\n\n/* \n * Functions to convert binary key data to character string.\n * string format:  <char_data> \n */ \n\nchar *cl2cs(char *chal)\n{\n     static char str[VTUN_CHAL_SIZE*2+3], *chr=\"abcdefghijklmnop\";\n     register char *ptr = str;\n     register int i;\n\n     *(ptr++) = '<';\n     for(i=0; i<VTUN_CHAL_SIZE; i++){\n\t*(ptr++) = chr[ ((chal[i] & 0xf0) >> 4) ];  \n\t*(ptr++) = chr[ (chal[i] & 0x0f) ];\n     }  \n\n     *(ptr++) = '>';\n     *ptr = '\\0';\n\n     return str;\n}\n\nint cs2cl(char *str, char *chal)\n{\n     register char *ptr = str;\n     register int i;\n\n     if( !(ptr = strchr(str,'<')) ) \n        return 0;\n     ptr++;\n     if( !strtok(ptr,\">\") || strlen(ptr) != VTUN_CHAL_SIZE*2 )\n        return 0;\n\n     for(i=0; i<VTUN_CHAL_SIZE && *ptr; i++, ptr+=2) {\n\tchal[i]  = (*ptr - 'a') << 4;  \n\tchal[i] |= *(ptr+1) - 'a';\n     }\n\n     return 1;\n}   \n\n/* Authentication (Server side) */\nstruct vtun_host * auth_server(int fd, int *reason)\n{\n        char chal_req[VTUN_CHAL_SIZE], chal_res[VTUN_CHAL_SIZE];\t\n\tchar buf[VTUN_MESG_SIZE], *str1, *str2;\n        struct vtun_host *h = NULL;\n\tchar *host = NULL;\n\tint  stage;\n\n        set_title(\"authentication\");\n\n    print_p(fd, \"VTRUNKD server ver %s\\n\", VERSION);\n\n\tstage = ST_HOST;\n    *reason = D_NOREAD;\n\twhile( readn_t(fd, buf, VTUN_MESG_SIZE, vtun.timeout) > 0 ){\n        *reason = D_OTHER;\n\t   buf[sizeof(buf)-1]='\\0';\n\t   strtok(buf,\"\\r\\n\");\n\n\t   if( !(str1=strtok(buf,\" :\")) ) {\n            *reason = D_NOSHAKE1;\n\t        break;\n          }\n\t   if( !(str2=strtok(NULL,\" :\")) ) {\n            *reason = D_NOSHAKE2;\n\t        break;\n          }\n\n\t   switch( stage ){\n\t     case ST_HOST:\n\t        if( !strcmp(str1,\"HOST\") ){\n\t\t   host = strdup(str2);\n\n\t\t   gen_chal(chal_req);\n\t\t   print_p(fd,\"OK CHAL: %s\\n\", cl2cs(chal_req));\n\n\t\t   stage = ST_CHAL;\n\t\t   continue;\n\t        }\n        *reason = D_ST_CHAL;\n\t\tbreak;\n\t     case ST_CHAL:\n\t        if( !strcmp(str1,\"CHAL\") ){\n\t\t   if( !cs2cl(str2,chal_res) ) {\n                *reason = D_CHAL;\n\t\t        break; \n              }\n\t\t   \n\t\t   if( !(h = find_host(host)) ) {\n                *reason = D_NOHOST;\n\t    \t      break;\n              }\n\n\t\t   decrypt_chal(chal_res, h->passwd);   \t\t\n\t\n\t\t   if( !memcmp(chal_req, chal_res, VTUN_CHAL_SIZE) ){\n\t\t      /* Auth successeful. */\n\n\t\t      /* Lock host */\t\n\t\t      if( lock_host(h) < 0 ){\n\t\t         /* Multiple connections are denied */\n\t\t         h = NULL;\n                 *reason = D_NOMULT;\n\t\t         break;\n\t\t      }\t\n\t\t      print_p(fd,\"OK FLAGS: %s\\n\", bf2cf(h)); \n \t\t   } else\n\t\t      h = NULL;\n\t        }\n\t\tbreak;\n \t   }\n\t   break;\n\t}\n\n\tif( host )\n\t   free(host);\n\n\tif( !h )\n\t   print_p(fd,\"ERR\\n\");\t\n\n\treturn h;\n}\n\n/* Authentication (Client side) */\nint auth_client(int fd, struct vtun_host *host, int * reason)\n{\n\tchar buf[VTUN_MESG_SIZE], chal[VTUN_CHAL_SIZE];\n\tint stage, success=0 ;\n\t\n\tstage = ST_INIT;\n    *reason = D_NOREAD;\n\twhile( readn_t(fd, buf, VTUN_MESG_SIZE, vtun.timeout) > 0 ){\n        *reason = D_OTHER;\n\t   buf[sizeof(buf)-1]='\\0';\n\t   switch( stage ){\n\t\tcase ST_INIT:\n            if (!strncmp(buf, \"VTRUNKD\", 7)) {\n\t\t      stage = ST_HOST;\n\t\t      print_p(fd,\"HOST: %s\\n\",host->host);\n\t\t      continue;\n\t           }\n               *reason = D_GREET;\n\t\t   break;\t\n\n\t        case ST_HOST:\n\t\t   if( !strncmp(buf,\"OK\",2) && cs2cl(buf,chal)){\n\t\t      stage = ST_CHAL;\n\t\t\t\t\t\n\t\t      encrypt_chal(chal,host->passwd);\n\t\t      print_p(fd,\"CHAL: %s\\n\", cl2cs(chal));\n\n\t\t      continue;\n\t   \t   }\n           *reason = D_CHAL;\n\t\t   break;\t\n\t\n\t        case ST_CHAL:\n\t\t   if( !strncmp(buf,\"OK\",2) && cf2bf(buf,host) )\n\t\t      success = 1;\n           else *reason = D_PWD;\n\t\t   break;\n\t   }\n\t   break;\n\t}\n\n\treturn success;\n}\n"
  },
  {
    "path": "auth.h",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * auth.h,v 1.1.1.2.6.1 2006/11/16 04:02:36 mtbishop Exp\n */ \n\n#define VTUN_CHAL_SIZE\t 16\t\n\n#define ST_INIT  0\n#define ST_HOST  1\n#define ST_CHAL  2\n\nstruct vtun_host * auth_server(int fd, int * reason);\nint auth_client(int fd, struct vtun_host *host, int * reason);\n\n"
  },
  {
    "path": "cfg_file.l",
    "content": "%{\n/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * cfg_file.l,v 1.1.1.2.2.1.2.2 2006/11/16 04:02:39 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <string.h>\n\n#include \"vtun.h\"\n\n#include \"cfg_file.tab.h\"\n#include \"cfg_kwords.h\"\n\n/* static buffer for strings */\nchar str_buf[255];\n\nint find_keyword(struct kword *kw, char *str);\n\n#define ECHO {;}\n#define YY_DECL int yylex(void)\n\n/* Push and pop parser state */\nstatic int stack[16];\nstatic int ptr = 0;\n\n#define PUSH_STATE()\t\t\t\t\t\t\t  \\\n\t do {\t\t\t\t\t\t  \t\t  \\\n\t   if( ptr == 16 ){\t\t\t\t\t\t  \\\n\t      yyerror(\"To many pushes to parser's state stack\"); \t  \\\n\t      return K_ERROR; \t\t\t\t\t\t  \\\n\t   }\t\t\t\t\t\t\t\t  \\\n\t   stack[ptr++] = YY_START;\t\t\t\t\t  \\\n         } while(0)\n\n#define POP_STATE()\t \t\t\t\t\t\t  \\\n\t do {\t\t\t\t\t\t  \t\t  \\\n\t   if( !ptr ){\t\t\t\t\t\t\t  \\\n\t      yyerror(\"To many pops from parser's state stack\"); \t  \\\n\t      return K_ERROR; \t\t\t\t\t\t  \\\n\t   }\t\t\t\t\t\t\t\t  \\\n\t   BEGIN(stack[--ptr]);\t\t\t\t\t\t  \\\n         } while(0)\n\nint cfg_error(const char *ftm, ...);\n\nint yyerror(char *str);\n%}\n\nnum\t\t[0-9]+\ndnum\t\t{num}:{num}\nword\t\t[A-Za-z0-9\\-\\_+=\\!\\$\\#\\%\\&\\*\\^\\@@\\\\\\~\\.]+\nwordnm\t\t{word}:{num}\nkword\t\t[A-Za-z0-9\\_\\-]+\t\ncomment\t\t\\#.*\\n\nfname\t\t[A-Za-z0-9\\_\\.\\-]+\t\npath\t\t(\\/{fname})+\nstring\t\t\\\".*\\\"\n\n%x OPTION PARAM  \n\n%%\n<*>[ \\t]\t;   /* Skip spaces and tabs (All stages) */\n\n<*>\\n\t\t{ lineno++; } /* (All stages) */\n\n<INITIAL,OPTION>{comment}\t{ lineno++; } /* Skip comments */\n\n{kword}\t\t{\n\t\t  int kw = find_keyword(cfg_keyword,yytext);\n\t\t  if( kw != -1 )\t\n\t\t     return kw;\n\n\t\t  /* Keyword not found, means host definition. */\n\t\t  yylval.str = yytext;\n\t\t  return K_HOST;\n\t\t}\n\n{word}\t\t{\n\t\t  yylval.str = yytext;\n\t\t  return K_ERROR;\n\t\t}\n\n<*>\\{\t\t{ \n\t\t  PUSH_STATE();\n\t\t  BEGIN(OPTION); \n\t\t  return *yytext;\n\t\t}\t\t\n<*>\\}\t\t{\n\t\t  POP_STATE();\n\t\t  return *yytext;\n\t\t}\n\n<OPTION>{word}\t{\n\t\t  int kw = find_keyword(cfg_keyword,yytext);\n\t\t  if( kw != -1 ){\t\n\t\t     /* Option found, switch to PARAM stage */\n\t\t     PUSH_STATE();\n\t\t     BEGIN(PARAM);\n\t\t     return kw;\n\t\t  }\n\t\t  yylval.str = yytext;\n\t\t  return K_ERROR;\n\t\t}\n\n<PARAM>{string}\t{\n\t\t  if(yyleng > sizeof(str_buf)-1){\n\t\t     yyerror(\"string to long\");\n\t\t     return 0;\n\t\t  }\n\t\t  strncpy(str_buf, yytext+1, yyleng-2);\n\t\t  str_buf[yyleng-2] = '\\0';\n\n\t\t  yylval.str = str_buf;\n\t\t\t\t\t  \n\t\t  return STRING;\n\t\t}\n\n<PARAM>{dnum}   {\n\t          char *ptr = strchr(yytext,':') + 1;\n\t\t \n\t\t  yylval.dnum.num1 = atoi(yytext);\n\t\t  yylval.dnum.num2 = atoi(ptr);\n\t\t  return DNUM;\n\t\t}\n\n<PARAM>{num}\t{\n\t\t  yylval.num = atoi(yytext);\n\t\t  return NUM;\n\t\t}\n\n<PARAM>{word}\t{\n\t\t  int kw = find_keyword(cfg_param,yytext);\n\t\t  if( kw != -1 ){\t\n\t\t     /* Special parameter found (yes,no,etc) */\n\t\t     yylval.num = kw;\n\t\t     return NUM;\n\t\t  }\n\t\t  yylval.str = yytext;\n\t\t  return WORD;\n\t\t}\n\n<PARAM>{wordnm} {\n\t          char *ptr = strchr(yytext,':'); *ptr='\\0'; \n\t\t  yylval.dnum.num1 = find_keyword(cfg_param,yytext);\n\t\t  yylval.dnum.num2 = atoi(++ptr);\n\t\t  return DNUM;\n\t\t}\n\n<PARAM>{path}\t{\n\t\t  yylval.str = yytext;\n\t\t  return PATH;\n\t\t}\n\n<PARAM>\\;\t{ \n\t\t  POP_STATE();\n\t\t}\n\n<*>.\t\t{ /* Garbage (All stages) */\n\t\t  cfg_error(\"Invalid character \\'%s\\'\", yytext); \n\t\t}\n%%\n\nint yywrap(void) \n{\n    return 1;\n}\n\nint find_keyword(struct kword *kw, char *str)\n{\n    while( kw->str ){\n\tif( !strncmp(str,kw->str,20) )\n\t   return kw->type;\n\tkw++;\n    }\n    return -1;\n}\n"
  },
  {
    "path": "cfg_file.y",
    "content": "%{\n/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * cfg_file.y,v 1.1.1.2.2.13.2.4 2006/11/16 04:02:42 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <stdarg.h>\n\n#include <syslog.h>\n\n#include \"compat.h\"\n#include \"vtun.h\"\n#include \"lib.h\"\n#include \"log.h\"\n\nint lineno = 1;\n\nstruct vtun_host *parse_host;\nextern struct vtun_host default_host;\n\nllist  *parse_cmds;\nstruct vtun_cmd parse_cmd;\n\nllist host_list;\n\nint  cfg_error(const char *fmt, ...);\nint  add_cmd(llist *cmds, char *prog, char *args, int flags);\nvoid *cp_cmd(void *d, void *u);\nint  free_cmd(void *d, void *u);\n\nvoid copy_addr(struct vtun_host *to, struct vtun_host *from);\nint  free_host(void *d, void *u);\nvoid free_addr(struct vtun_host *h);\nvoid free_host_list(void);\n\nint  parse_syslog(char *facility);\n\nint yyparse(void);\nint yylex(void);\t\nint yyerror(char *s); \n\n#define YYERROR_VERBOSE 1\n\n%}\n\n%union {\n   char *str;\n   int  num;\n   struct { int num1; int num2; } dnum;\n}\n%expect 20\n\n%token K_OPTIONS K_DEFAULT K_PORT K_BINDADDR K_PERSIST K_TIMEOUT\n%token K_PASSWD K_PROG K_PPP K_SPEED K_IFCFG K_FWALL K_ROUTE K_DEVICE \n%token K_MULTI K_SRCADDR K_IFACE K_ADDR\n%token K_TYPE K_PROT K_COMPRESS K_ENCRYPT K_KALIVE K_STAT\n%token K_UP K_DOWN K_SYSLOG K_IPROUTE\n%token K_TICK_SECS K_RXMIT_CNT_DROP_PERIOD K_MAX_WEIGHT_NORM K_WEIGHT_SCALE K_WEIGHT_SMOOTH_DIV K_WEIGHT_START_STICKINESS K_WEIGHT_SAW_STEP_UP_DIV K_WEIGHT_SAW_STEP_UP_MIN_STEP K_WEIGHT_SAW_STEP_DN_DIV K_PEN_USEC_IMMUNE\nK_WEIGHT_MSEC_DELAY K_MAX_WINDOW K_MAX_LATENCY K_MAX_LATENCY_DROP K_MAX_ALLOWED_BUF_LEN K_MAX_REORDER K_MAX_IDLE_TIMEOUT K_FRAME_COUNT_SEND_LWS K_PING_INTERVAL K_TUN_TXQUEUE_LEN K_MAX_TUNNELS_NUM K_TCP_CONN_AMOUNT K_START_WEIGHT K_RT_MARK\n%token <str> K_HOST K_ERROR\n%token <str> WORD PATH STRING\n%token <num> NUM \n%token <dnum> DNUM\n\n%%\nconfig: \n  | config statement \n  ;\n\nstatement: '\\n'\n  | K_OPTIONS   '{' options '}' \n\n  | K_DEFAULT   { \n\t\t  parse_host = &default_host; \n                }        \n    '{' host_options '}' \n\n  | K_HOST      { \n\t\t  if( !(parse_host = malloc(sizeof(struct vtun_host))) ){\n\t\t     yyerror(\"No memory for the host\");\n\t\t     YYABORT;\n\t\t  }\n\n\t\t  /* Fill new host struct with default values.\n\t\t   * MUST dup strings to be able to reread config.\n\t\t   */\n\t  \t  memcpy(parse_host, &default_host, sizeof(struct vtun_host));\n\t\t  parse_host->host = strdup($1);\n\t\t  parse_host->passwd = NULL;\n\n\t\t  /* Copy local address */\n\t\t  copy_addr(parse_host, &default_host);\n\n\t\t  llist_copy(&default_host.up,&parse_host->up,cp_cmd,NULL);\n\t\t  llist_copy(&default_host.down,&parse_host->down,cp_cmd,NULL);\n\n\t\t}    \n    '{' host_options '}'\n\t\t{\n\t\t  /* Check if session definition is complete */ \n\t\t  if (!parse_host->passwd) {\n\t\t  \tcfg_error(\"Ignored incomplete session definition '%s'\", parse_host->host);\n\t\t\tfree_host(parse_host, NULL);\t\t\t\n\t\t\tfree(parse_host);\n\t\t  } else {\n\t\t  \t/* Add host to the list */\n\t\t  \tllist_add(&host_list, (void *)parse_host);\n\t\t  }\n\t\t}\n\n  | K_ERROR\t{\n\t\t  cfg_error(\"Invalid clause '%s'\",$1);\n\t\t  YYABORT;\n\t\t}\n  ;\n\noptions:\n    option\n  | options option\n  ;\n\n/* Don't override command line options */\noption:  '\\n'\n  | K_PORT NUM \t\t{ \n\t\t\t  if(vtun.bind_addr.port == -1)\n\t\t\t     vtun.bind_addr.port = $2;\n\t\t\t} \n\n  | K_BINDADDR '{' bindaddr_option '}'\n\n  | K_IFACE STRING\t{ \n\t\t\t  if(vtun.svr_addr == -1)\n\t\t\t    vtun.svr_addr = strdup($2);\n\t\t\t} \n\n  | K_TYPE NUM \t\t{ \n\t\t\t  if(vtun.svr_type == -1)\n\t\t\t     vtun.svr_type = $2;\n\t\t\t} \n\n  | K_TIMEOUT NUM \t{  \n\t\t\t  if(vtun.timeout == -1)\n\t\t\t     vtun.timeout = $2; \t\n\t\t\t}\n\n  | K_PPP   PATH\t{\n\t\t\t  free(vtun.ppp);\n\t\t\t  vtun.ppp = strdup($2);\n\t\t\t}\n\n  | K_IFCFG PATH\t{\n\t\t\t  free(vtun.ifcfg);\n\t\t\t  vtun.ifcfg = strdup($2);\n\t\t\t}\n\n  | K_ROUTE PATH \t{   \n\t\t\t  free(vtun.route);  \n\t\t\t  vtun.route = strdup($2); \t\n\t\t\t}\t\t\n\n  | K_FWALL PATH \t{   \n\t\t\t  free(vtun.fwall);  \n\t\t\t  vtun.fwall = strdup($2); \t\n\t\t\t}\n\n  | K_IPROUTE PATH \t{   \n\t\t\t  free(vtun.iproute);  \n\t\t\t  vtun.iproute = strdup($2); \t\n\t\t\t}\n\n  | K_SYSLOG  syslog_opt\n\n  | K_ERROR\t\t{\n\t\t\t  cfg_error(\"Unknown option '%s'\",$1);\n\t\t\t  YYABORT;\n\t\t\t}\n\n | K_MAX_TUNNELS_NUM NUM \t{  \n\t\t\t  if(vtun.MAX_TUNNELS_NUM == -1)\n\t\t\t     vtun.MAX_TUNNELS_NUM = $2; \t\n\t\t\t}\n\n\n\n\n ;\n\nbindaddr_option: \n  K_ADDR WORD\t\t{\n\t\t\t  vtun.bind_addr.name = strdup($2);\n\t\t\t  vtun.bind_addr.type = VTUN_ADDR_NAME;\n\t\t\t}\n\n  | K_IFACE WORD\t{\n\t\t\t  vtun.bind_addr.name = strdup($2);\n\t\t\t  vtun.bind_addr.type = VTUN_ADDR_IFACE;\n\t\t\t}\n\n  | K_IFACE STRING\t{\n\t\t\t  vtun.bind_addr.name = strdup($2);\n\t\t\t  vtun.bind_addr.type = VTUN_ADDR_IFACE;\n\t\t\t}\n\n  | K_ERROR\t\t{\n\t\t\t  cfg_error(\"Unknown option '%s'\",$1);\n\t\t\t  YYABORT;\n\t\t\t}\n  ;\n\nsyslog_opt:\n  NUM \t\t\t{\n                          vtun.syslog = $1;\n  \t\t\t}\n\n  | WORD \t        {\n                          if (parse_syslog($1)) {\n                            cfg_error(\"Unknown syslog facility '%s'\", $1);\n                            YYABORT;\n                          }\n                        }\n\n  | K_ERROR \t\t{\n   \t\t\t  cfg_error(\"Unknown syslog option '%s'\",$1);\n  \t\t\t  YYABORT;\n\t\t\t}\n  ;\n\nhost_options:\n    host_option\n  | host_options host_option\n  ;\n\n/* Host options. Must free strings first, because they \n * could be strduped from default_host */\nhost_option: '\\n'\n  | K_PASSWD WORD \t{\n\t\t\t  free(parse_host->passwd);\n\t\t\t  parse_host->passwd = strdup($2);\n\t\t\t}\n\n  | K_DEVICE WORD \t{\n\t\t\t  free(parse_host->dev);\n\t\t\t  parse_host->dev = strdup($2);\n\t\t\t}\t\n\n  | K_MULTI NUM\t\t{ \n\t\t\t  parse_host->multi = $2;\n\t\t\t}\n\n  | K_TIMEOUT NUM\t{ \n\t\t\t  parse_host->timeout = $2;\n\t\t\t}\n  | K_TICK_SECS NUM \t{  \n\t\t\t     parse_host->TICK_SECS = $2; \t\n\t\t\t}\n  | K_RXMIT_CNT_DROP_PERIOD NUM \t{  \n\t\t\t     parse_host->RXMIT_CNT_DROP_PERIOD = $2; \t\n\t\t\t}\n  | K_MAX_WEIGHT_NORM NUM \t{  \n\t\t\t     parse_host->MAX_WEIGHT_NORM = $2; \t\n\t\t\t}\n  | K_WEIGHT_SCALE NUM \t{  \n\t\t\t     parse_host->WEIGHT_SCALE = $2; \t\n\t\t\t}\n  | K_WEIGHT_SMOOTH_DIV NUM \t{  \n\t\t\t     parse_host->WEIGHT_SMOOTH_DIV = $2; \t\n\t\t\t}\n\n\n | K_WEIGHT_START_STICKINESS NUM \t{  \n\t\t\t     parse_host->WEIGHT_START_STICKINESS = $2; \t\n\t\t\t}\n\n\n | K_WEIGHT_SAW_STEP_UP_DIV NUM \t{  \n\t\t\t     parse_host->WEIGHT_SAW_STEP_UP_DIV = $2; \t\n\t\t\t}\n\n | K_WEIGHT_SAW_STEP_UP_MIN_STEP NUM \t{  \n\t\t\t     parse_host->WEIGHT_SAW_STEP_UP_MIN_STEP = $2; \t\n\t\t\t}\n\n | K_WEIGHT_SAW_STEP_DN_DIV NUM \t{  \n\t\t\t     parse_host->WEIGHT_SAW_STEP_DN_DIV = $2; \t\n\t\t\t}\n\n\n | K_WEIGHT_MSEC_DELAY NUM \t{  \n\t\t\t     parse_host->WEIGHT_MSEC_DELAY = $2; \t\n\t\t\t}\n\n\n | K_MAX_WINDOW NUM \t{  \n\t\t\t     parse_host->MAX_WINDOW = $2; \t\n\t\t\t}\n\t\t\t\n | K_PEN_USEC_IMMUNE NUM \t{  \n\t\t\t    \n\t\t\t}\n\n | K_MAX_LATENCY NUM \t{  \n\t\t\t     parse_host->MAX_LATENCY = $2; \t\n\t\t\t}\n\n\n | K_MAX_LATENCY_DROP NUM \t{  \n\t\t\t     parse_host->MAX_LATENCY_DROP = $2; \t\n\t\t\t}\n\n\n | K_MAX_ALLOWED_BUF_LEN NUM \t{  \n\t\t\t     parse_host->MAX_ALLOWED_BUF_LEN = $2; \t\n\t\t\t}\n\n\n | K_MAX_REORDER NUM \t{  \n\t\t\t     parse_host->MAX_REORDER = $2; \t\n\t\t\t}\n\n\n | K_MAX_IDLE_TIMEOUT NUM \t{  \n\t\t\t     parse_host->MAX_IDLE_TIMEOUT = $2; \t\n\t\t\t}\n\n\n | K_FRAME_COUNT_SEND_LWS NUM \t{  \n\t\t\t     parse_host->FRAME_COUNT_SEND_LWS = $2; \t\n\t\t\t}\n\n\n | K_PING_INTERVAL NUM \t{  \n\t\t\t     parse_host->PING_INTERVAL = $2; \t\n\t\t\t}\n\n\n | K_TUN_TXQUEUE_LEN NUM \t{  \n\t\t\t     parse_host->TUN_TXQUEUE_LEN = $2; \t\n\t\t\t}\n\n\n | K_TCP_CONN_AMOUNT NUM\t{  \n\t\t\t     parse_host->TCP_CONN_AMOUNT = $2; \t\n\t\t\t}\n\n | K_START_WEIGHT NUM\t{  \n\t\t\t     parse_host->START_WEIGHT = $2; \t\n\t\t\t}\n\n | K_RT_MARK NUM\t{  \n\t\t\t     parse_host->RT_MARK = $2; \t\n\t\t\t}\n\n\n\n\n\n\n  | K_SPEED NUM \t{ \n\t\t\t  if( $2 ){ \n\t\t\t     parse_host->spd_in = parse_host->spd_out = $2;\n\t\t\t     parse_host->flags |= VTUN_SHAPE;\n\t\t\t  } else \n\t\t\t     parse_host->flags &= ~VTUN_SHAPE;\n\t\t\t}\n\n  | K_SPEED DNUM \t{ \n\t\t\t  if( yylval.dnum.num1 || yylval.dnum.num2 ){ \n\t\t\t     parse_host->spd_out = yylval.dnum.num1;\n\t\t             parse_host->spd_in = yylval.dnum.num2; \t\n\t\t\t     parse_host->flags |= VTUN_SHAPE;\n\t\t\t  } else \n\t\t\t     parse_host->flags &= ~VTUN_SHAPE;\n\t\t\t}\n\n  | K_COMPRESS \t\t{\n\t\t\t  parse_host->flags &= ~(VTUN_ZLIB | VTUN_LZO); \n\t\t\t}\n\t\t\tcompress\n\n  | K_ENCRYPT NUM \t{  \n\t\t\t  if( $2 ){\n\t\t\t     parse_host->flags |= VTUN_ENCRYPT;\n\t\t\t     parse_host->cipher = $2;\n\t\t\t  } else\n\t\t\t     parse_host->flags &= ~VTUN_ENCRYPT;\n\t\t\t}\n\n  | K_KALIVE \t\t{\n\t\t\t  parse_host->flags &= ~VTUN_KEEP_ALIVE; \n\t\t\t}\n\t\t\tkeepalive\t\n\n  | K_STAT NUM\t\t{\n\t\t\t  if( $2 )\n\t\t\t     parse_host->flags |= VTUN_STAT;\n\t\t\t  else\n\t\t\t     parse_host->flags &= ~VTUN_STAT;\n\t\t\t}\n\n  | K_PERSIST NUM \t{ \n\t      \t\t  parse_host->persist = $2;\n\n\t\t\t  if(vtun.persist == -1) \n\t\t\t     vtun.persist = $2; \t\n\t\t\t}\n\n  | K_TYPE NUM \t\t{  \n\t\t\t  parse_host->flags &= ~VTUN_TYPE_MASK;\n\t\t\t  parse_host->flags |= $2;\n\t\t\t}\t\n\n  | K_PROT NUM \t\t{  \n\t\t\t  parse_host->flags &= ~VTUN_PROT_MASK;\n\t\t\t  parse_host->flags |= $2;\n\t\t\t}\n\n  | K_SRCADDR \t\t'{' srcaddr_options '}'\n\n  | K_UP \t        { \n\t\t\t  parse_cmds = &parse_host->up; \n   \t\t\t  llist_free(parse_cmds, free_cmd, NULL);   \n\t\t\t} '{' command_options '}' \n\n  | K_DOWN \t        { \n\t\t\t  parse_cmds = &parse_host->down; \n   \t\t\t  llist_free(parse_cmds, free_cmd, NULL);   \n\t\t\t} '{' command_options '}' \n\n  | K_ERROR\t\t{\n\t\t\t  cfg_error(\"Unknown option '%s'\",$1);\n\t\t\t  YYABORT;\n\t\t\t} \n  ;\n\ncompress:  \n  NUM\t \t\t{ \n\t\t\t  if( $1 ){  \n      \t\t\t     parse_host->flags |= VTUN_ZLIB; \n\t\t\t     parse_host->zlevel = $1;\n\t\t\t  }\n\t\t\t}\n\n  | DNUM\t\t{\n\t\t\t  parse_host->flags |= yylval.dnum.num1;\n\t\t          parse_host->zlevel = yylval.dnum.num2;\n  \t\t\t}\n\n  | K_ERROR\t\t{\n\t\t\t  cfg_error(\"Unknown compression '%s'\",$1);\n\t\t\t  YYABORT;\n\t\t\t} \n  ;\n\nkeepalive:  \n  NUM\t \t\t{ \n\t\t\t  if( $1 )\n\t\t\t     parse_host->flags |= VTUN_KEEP_ALIVE;\n\t\t\t}\n\n  | DNUM\t\t{\n\t\t\t  if( yylval.dnum.num1 ){\n\t\t\t     parse_host->flags |= VTUN_KEEP_ALIVE;\n\t\t\t     parse_host->ka_interval = yylval.dnum.num1;\n\t\t             parse_host->ka_failure  = yylval.dnum.num2;\n\t\t\t  }\n  \t\t\t}\n\n  | K_ERROR\t\t{\n\t\t\t  cfg_error(\"Unknown keepalive option '%s'\",$1);\n\t\t\t  YYABORT;\n\t\t\t} \n  ;\n\nsrcaddr_options: /* empty */\n  | srcaddr_option\n  | srcaddr_options srcaddr_option\n  ;\n\nsrcaddr_option:  \n  K_ADDR WORD\t\t{\n\t\t\t  free_addr(parse_host);\n\t\t\t  parse_host->src_addr.name = strdup($2);\n\t\t\t  parse_host->src_addr.type = VTUN_ADDR_NAME;\n\t\t\t}\n\n  | K_IFACE WORD\t{\n\t\t\t  free_addr(parse_host);\n\t\t\t  parse_host->src_addr.name = strdup($2);\n\t\t\t  parse_host->src_addr.type = VTUN_ADDR_IFACE;\n\t\t\t}\n\n  | K_IFACE STRING\t{\n\t\t\t  free_addr(parse_host);\n\t\t\t  parse_host->src_addr.name = strdup($2);\n\t\t\t  parse_host->src_addr.type = VTUN_ADDR_IFACE;\n\t\t\t}\n\n  | K_PORT NUM \t\t{\n\t\t\t  parse_host->src_addr.port = $2;\n\t\t\t}\n\n  | K_ERROR\t\t{\n\t\t\t  cfg_error(\"Unknown option '%s'\",$1);\n\t\t\t  YYABORT;\n\t\t\t} \n  ;\n\ncommand_options: /* empty */\n  | command_option\n  | command_options command_option\n  ;\n\ncommand_option: '\\n' \n  | K_PROG\t\t{\n\t\t\t  memset(&parse_cmd, 0, sizeof(struct vtun_cmd));\n\t\t\t} \n \tprog_options    {\n\t\t\t  add_cmd(parse_cmds, parse_cmd.prog, \n\t\t\t\t  parse_cmd.args, parse_cmd.flags);\n\t\t\t}\n\n  | K_PPP STRING \t{   \n\t\t\t  add_cmd(parse_cmds, strdup(vtun.ppp), strdup($2), \n\t\t\t\t\tVTUN_CMD_DELAY);\n\t\t\t}\t\t\n\n  | K_IFCFG STRING \t{   \n\t\t\t  add_cmd(parse_cmds, strdup(vtun.ifcfg),strdup($2),\n\t\t\t\t\tVTUN_CMD_WAIT);\n\t\t\t}\n\n  | K_ROUTE STRING \t{   \n\t\t\t  add_cmd(parse_cmds, strdup(vtun.route),strdup($2),\n\t\t\t\t\tVTUN_CMD_WAIT);\n\t\t\t}\n\n  | K_FWALL STRING \t{   \n\t\t\t  add_cmd(parse_cmds, strdup(vtun.fwall),strdup($2),\n\t\t\t\t\tVTUN_CMD_WAIT);\n\t\t\t}\n\n  | K_IPROUTE STRING \t{   \n\t\t\t  add_cmd(parse_cmds, strdup(vtun.iproute),strdup($2),\n\t\t\t\t\tVTUN_CMD_WAIT);\n\t\t\t}\n\n  | K_ERROR\t\t{\n\t\t\t  cfg_error(\"Unknown cmd '%s'\",$1);\n\t\t\t  YYABORT;\n\t\t\t} \n  ;\n\nprog_options:\n    prog_option\n  | prog_options prog_option\n  ;\n\nprog_option:\n  PATH  \t\t{\n\t\t\t  parse_cmd.prog = strdup($1);\n\t\t\t}\n\n  | STRING \t\t{\n\t\t\t  parse_cmd.args = strdup($1);\n\t\t\t}\n\n  | NUM\t\t   \t{\n\t\t\t  parse_cmd.flags = $1;\n\t\t\t}\n  ;\n%%\n\nint yyerror(char *s) \n{\n   vlog(LOG_ERR, \"%s line %d\\n\", s, lineno);\n   return 0;\n}\n\nint cfg_error(const char *fmt, ...)\n{\n   char buf[255];\n   va_list ap;\n\n   /* print the argument string */\n   va_start(ap, fmt);\n   vsnprintf(buf,sizeof(buf),fmt,ap);\n   va_end(ap);\n\n   yyerror(buf);\n   return 0;\n}\n\nint add_cmd(llist *cmds, char *prog, char *args, int flags)\n{\n   struct vtun_cmd *cmd;\n   if( !(cmd = malloc(sizeof(struct vtun_cmd))) ){\n      yyerror(\"No memory for the command\");\n      return -1;\n   }\n   memset(cmd, 0, sizeof(struct vtun_cmd)); \t\t   \t\t\t\n\n   cmd->prog = prog;\n   cmd->args = args;\n   cmd->flags = flags;\n   llist_add(cmds, cmd);\n\n   return 0;\n}\t\t\n\nvoid *cp_cmd(void *d, void *u)\n{\n   struct vtun_cmd *cmd = d, *cmd_copy; \n\n   if( !(cmd_copy = malloc(sizeof(struct vtun_cmd))) ){\n      yyerror(\"No memory to copy the command\");\n      return NULL;\n   }\n \n   cmd_copy->prog = strdup(cmd->prog);\n   cmd_copy->args = strdup(cmd->args);\n   cmd_copy->flags = cmd->flags;\n   return cmd_copy;\n}\n\nint free_cmd(void *d, void *u)\n{\n   struct vtun_cmd *cmd = d; \n   free(cmd->prog);\n   free(cmd->args);\n   free(cmd);\n   return 0;\n}\n\nvoid copy_addr(struct vtun_host *to, struct vtun_host *from)\n{  \n   if( from->src_addr.type ){\n      to->src_addr.type = from->src_addr.type;\n      to->src_addr.name = strdup(from->src_addr.name);\n   }\n   to->src_addr.port = from->src_addr.port;\n}\n\nvoid free_addr(struct vtun_host *h)\n{  \n   if( h->src_addr.type ){\n      h->src_addr.type = 0;\n      free(h->src_addr.name);\n   }\n}\n\nint free_host(void *d, void *u)\n{\n   struct vtun_host *h = d;\n\n   if (u && !strcmp(h->host, u))\n      return 1;\n\n   free(h->host);   \n   free(h->passwd);   \n   \n   llist_free(&h->up, free_cmd, NULL);   \n   llist_free(&h->down, free_cmd, NULL);\n\n   free_addr(h);\n\n   /* releases only host struct instances which were\n    * allocated in the case of K_HOST except default_host */\n   if( h->passwd )\n      free(h);\n \n   return 0;   \n}\n\n/* Find host in the hosts list.\n * NOTE: This function can be called only once since it deallocates hosts list.\n */ \ninline struct vtun_host* find_host(char *host)\n{\n   return (struct vtun_host *)llist_free(&host_list, free_host, host);\n}\n\ninline void free_host_list(void)\n{\n   llist_free(&host_list, free_host, NULL);\n}\n\nstatic struct {\n   char *c_name;\n   int  c_val;\n} syslog_names[] = {\n    { \"auth\",   LOG_AUTH },\n    { \"cron\",   LOG_CRON },\n    { \"daemon\", LOG_DAEMON },\n    { \"kern\",   LOG_KERN },\n    { \"lpr\",    LOG_LPR },\n    { \"mail\",   LOG_MAIL },\n    { \"news\",   LOG_NEWS },\n    { \"syslog\", LOG_SYSLOG },\n    { \"user\",   LOG_USER },\n    { \"uucp\",   LOG_UUCP },\n    { \"local0\", LOG_LOCAL0 },\n    { \"local1\", LOG_LOCAL1 },\n    { \"local2\", LOG_LOCAL2 },\n    { \"local3\", LOG_LOCAL3 },\n    { \"local4\", LOG_LOCAL4 },\n    { \"local5\", LOG_LOCAL5 },\n    { \"local6\", LOG_LOCAL6 },\n    { \"local7\", LOG_LOCAL7 },\n    { NULL, -1 }\n};\n\nint parse_syslog(char *facility)\n{\n   int i;\n\n   for (i=0; syslog_names[i].c_name;i++) {\n      if (!strcmp(syslog_names[i].c_name, facility)) {\n         vtun.syslog = syslog_names[i].c_val;\n         return(0);\n      }\n   }\n}\n\n/* \n * Read config file. \n */ \nint read_config(char *file) \n{\n   static int cfg_loaded = 0;\n   extern FILE *yyin;\n\n   if( cfg_loaded ){\n      free_host_list();\n      vlog(LOG_INFO,\"Reloading configuration file\");\n   }\t \n   cfg_loaded = 1;\n\n   llist_init(&host_list);\n\n   if( !(yyin = fopen(file,\"r\")) ){\n      vlog(LOG_ERR,\"Can not open %s\", file);\n      return -1;      \n   }\n\n   yyparse();\n\n   free_host(&default_host, NULL);\n\n   fclose(yyin);\n  \n   return !llist_empty(&host_list);     \n}\n"
  },
  {
    "path": "cfg_kwords.h",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * cfg_kwords.h,v 1.1.1.1.2.3.2.8 2006/11/16 04:02:45 mtbishop Exp\n */ \n\nextern int lineno;\n\nstruct kword {\n   char *str;\n   int  type;\n}; \n\nstruct kword cfg_keyword[] = {\n   { \"options\",  K_OPTIONS }, \n   { \"default\",  K_DEFAULT },\n   { \"up\",\t K_UP },\n   { \"down\",\t K_DOWN },\n   { \"port\",     K_PORT }, \n   { \"srcaddr\",  K_SRCADDR }, \n   { \"addr\",  \t K_ADDR }, \n   { \"iface\",  \t K_IFACE }, \n   { \"bindaddr\", K_BINDADDR },\n   { \"persist\",\t K_PERSIST }, \n   { \"multi\",\t K_MULTI }, \n   { \"iface\",    K_IFACE }, \n   { \"timeout\",\t K_TIMEOUT }, \n   { \"passwd\",   K_PASSWD }, \n   { \"password\", K_PASSWD }, \n   { \"program\",  K_PROG }, \n   { \"speed\",    K_SPEED }, \n   { \"compress\", K_COMPRESS }, \n   { \"encrypt\",  K_ENCRYPT }, \n   { \"type\",\t K_TYPE }, \n   { \"proto\",\t K_PROT }, \n   { \"device\",\t K_DEVICE }, \n   { \"ppp\",\t K_PPP },\n   { \"ifconfig\", K_IFCFG },\n   { \"ifcfg\", \t K_IFCFG },\n   { \"firewall\", K_FWALL }, \n   { \"route\", \t K_ROUTE }, \n   { \"ip\", \t K_IPROUTE }, \n   { \"keepalive\",K_KALIVE }, \n   { \"stat\",\t K_STAT }, \n   { \"syslog\",   K_SYSLOG },\n\n\n   { \"tick_secs\",   K_TICK_SECS },\n   { \"rxmit_cnt_drop_period\",   K_RXMIT_CNT_DROP_PERIOD },\n   { \"max_weight_norm\",   K_MAX_WEIGHT_NORM },\n   { \"weight_scale\",   K_WEIGHT_SCALE },\n   { \"weight_smooth_div\",   K_WEIGHT_SMOOTH_DIV },\n   { \"weight_start_stickiness\",   K_WEIGHT_START_STICKINESS },\n   { \"weight_saw_step_up_div\",   K_WEIGHT_SAW_STEP_UP_DIV },\n   { \"weight_saw_step_up_min_step\",   K_WEIGHT_SAW_STEP_UP_MIN_STEP },\n   { \"weight_saw_step_dn_div\",   K_WEIGHT_SAW_STEP_DN_DIV },\n   { \"weight_msec_delay\",   K_WEIGHT_MSEC_DELAY },\n   { \"weight_usec_delay\",   K_WEIGHT_MSEC_DELAY },\n   { \"max_window\",   K_MAX_WINDOW },\n   { \"pen_usec_immune\",   K_PEN_USEC_IMMUNE},\n   { \"max_latency\",   K_MAX_LATENCY },\n   { \"max_latency_drop\",   K_MAX_LATENCY_DROP },\n   { \"max_allowed_buf_len\",   K_MAX_ALLOWED_BUF_LEN },\n   { \"max_reorder\",   K_MAX_REORDER },\n   { \"max_idle_timeout\",   K_MAX_IDLE_TIMEOUT },\n   { \"frame_count_send_lws\",   K_FRAME_COUNT_SEND_LWS },\n   { \"ping_interval\",   K_PING_INTERVAL },\n   { \"tun_txqueue_len\",   K_TUN_TXQUEUE_LEN },\n   { \"max_tunnels_num\",   K_MAX_TUNNELS_NUM },\n   { \"tcp_conn_amount\",   K_TCP_CONN_AMOUNT },\n   { \"start_weight\", K_START_WEIGHT },\n   { \"rt_mark\", K_RT_MARK },\n\n\n   { NULL , 0 }\n};\n\nstruct kword cfg_param[] = {\n   { \"yes\",      1 }, \n   { \"no\",       0 },\n   { \"allow\",\t 1 },\n   { \"deny\",\t 0 },\n   { \"enable\",\t 1 },\n   { \"disable\",\t 0 },\n   { \"tty\",      VTUN_TTY }, \n   { \"pipe\",\t VTUN_PIPE }, \n   { \"ether\",\t VTUN_ETHER }, \n   { \"tun\",\t VTUN_TUN }, \n   { \"tcp\",      VTUN_TCP }, \n   { \"udp\",      VTUN_UDP }, \n   { \"lzo\",      VTUN_LZO }, \n   { \"zlib\",     VTUN_ZLIB }, \n   { \"wait\",\t 1 },\n   { \"killold\",\t VTUN_MULTI_KILL },\n   { \"inetd\",\t VTUN_INETD },\n   { \"stand\",\t VTUN_STAND_ALONE },\n   { \"keep\",     VTUN_PERSIST_KEEPIF },\n   { \"blowfish128ecb\", VTUN_ENC_BF128ECB },\n   { \"blowfish128cbc\", VTUN_ENC_BF128CBC },\n   { \"blowfish128cfb\", VTUN_ENC_BF128CFB },\n   { \"blowfish128ofb\", VTUN_ENC_BF128OFB },\n   { \"blowfish256ecb\", VTUN_ENC_BF256ECB },\n   { \"blowfish256cbc\", VTUN_ENC_BF256CBC },\n   { \"blowfish256cfb\", VTUN_ENC_BF256CFB },\n   { \"blowfish256ofb\", VTUN_ENC_BF256OFB },\n   { \"aes128ecb\",      VTUN_ENC_AES128ECB },\n   { \"aes128cbc\",      VTUN_ENC_AES128CBC },\n   { \"aes128cfb\",      VTUN_ENC_AES128CFB },\n   { \"aes128ofb\",      VTUN_ENC_AES128OFB },\n   { \"aes256ecb\",      VTUN_ENC_AES256ECB },\n   { \"aes256cbc\",      VTUN_ENC_AES256CBC },\n   { \"aes256cfb\",      VTUN_ENC_AES256CFB },\n   { \"aes256ofb\",      VTUN_ENC_AES256OFB },\n   { NULL , 0 }\n};\n"
  },
  {
    "path": "client.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * client.c,v 1.5.2.8.2.1 2006/11/16 04:02:48 mtbishop Exp\n */ \n\n#include \"config.h\"\n#include \"vtun_socks.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <signal.h>\n#include <fcntl.h>\n#include <syslog.h>\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\n#ifdef HAVE_ARPA_INET_H\n#include <arpa/inet.h>\n#endif\n\n#include <sys/types.h>   /* basic system data types */\n#include <sys/socket.h>  /* basic socket definitions */\n#include <sys/time.h>    /* timeval{} for select() */\n#include <time.h>        /* timespec{} for pselect() */\n#include <netinet/in.h>  /* sockaddr_in{} and other Internet defns */\n#include <arpa/inet.h>   /* inet(3) functions */\n#include <errno.h>\n#include <fcntl.h>       /* for nonblocking */\n#include <netdb.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>    /* for S_xxx file mode constants */\n#include <sys/uio.h>     /* for iovec{} and readv/writev */\n#include <unistd.h>\n#include <sys/wait.h>\n#include <sys/un.h>      /* for Unix domain sockets */\n\n\n#include \"vtun.h\"\n#include \"lib.h\"\n#include \"log.h\"\n#include \"llist.h\"\n#include \"auth.h\"\n#include \"compat.h\"\n#include \"netlib.h\"\n\nstatic volatile sig_atomic_t client_term;\nstatic void sig_term(int sig)\n{\n    vlog(LOG_INFO, \"Terminated\");\n    client_term = VTUN_SIG_TERM;\n}\n/*\nint cshit3(struct conn_info * sci, int fx) {\n     int cnt = 0, cnt2=0;\n     int nnl = sci->resend_buf.frames.rel_head;\n     int nnf = sci->resend_buf.free_frames.rel_head;\n     \n     while(nnl > -1) {\n          cnt++;\n          nnl = sci->resend_buf.frames_buf[nnl].rel_next;\n     }\n     \n     while(nnf > -1) {\n          cnt++;\n          nnf = sci->resend_buf.frames_buf[nnf].rel_next;\n     }\n     vlog(LOG_INFO, \"%d count l: %d f: %d\", fx, cnt, cnt2);\n     return 0;\n}\n*/\n\nvoid client(struct vtun_host *host)\n{\n    struct sockaddr_in my_addr, svr_addr;\n    struct sigaction sa;\n    int s, opt, reconnect, sss, len;\n    int shm_new = 0;\n    struct sockaddr_un remote;\n\n    vlog_close();\n    vlog_open(host->host, LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);\n\n#ifdef CLIENTONLY\n    vlog(LOG_INFO, \"vtrunkd client only ver %s %s started\", VTUN_VER, BUILD_DATE);\n#else\n    vlog(LOG_INFO, \"vtrunkd client ver %s %s started\", VTUN_VER, BUILD_DATE);\n#endif\n    memset(&sa, 0, sizeof(sa));\n    sa.sa_handler = SIG_IGN;\n    sa.sa_flags = SA_NOCLDWAIT;\n    sigaction(SIGHUP, &sa, NULL);\n    sigaction(SIGQUIT, &sa, NULL);\n    sigaction(SIGPIPE, &sa, NULL);\n    sigaction(SIGCHLD, &sa, NULL);\n\n    memset(&sa, 0, sizeof(sa));\n    sa.sa_handler = sig_term;\n    sigaction(SIGTERM, &sa, NULL);\n    // sigaction(SIGINT, &sa, NULL);\n\n\n    // now init everything...\n    int shmid;\n    int reason = 0; // connection denial reason\n    key_t key;\n    struct conn_info *shm_conn_info;\n    struct timeval cur_time;\n    /*\n    * We'll name our shared memory segment\n    * \"5678\".\n    */\n    key = vtun.shm_key;\n\n\n    /*\n    * First, try to open shm\n    */\n\n    if ((shmid = shmget(key, sizeof(struct conn_info), 0666)) < 0) {\n        /*\n        * Create the segment.\n        */\n        vlog(LOG_INFO, \"client: init new shm...\");\n        if ((shmid = shmget(key, sizeof(struct conn_info), IPC_CREAT | 0666)) < 0) {\n            vlog(LOG_ERR, \"shmget 2 size %d\", sizeof(struct conn_info));\n            exit(1);\n        }\n        shm_new = 1;\n    } else {\n        vlog(LOG_INFO, \"client: reusing shm...\");\n        shm_new = 0;\n    }\n    /*\n    * Now we attach the segment to our data space.\n    */\n    if ((shm_conn_info = shmat(shmid, NULL, 0)) == (struct conn_info *) - 1) {\n        vlog(LOG_ERR, \"shmat 2\");\n        exit(1);\n    }\n    //cshit3(&shm_conn_info[0], 36);\n    // now try to connect to socket if shm_new ==0\n    if (!shm_new) {\n        if ((sss = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {\n            vlog(LOG_ERR, \"socket 44\");\n            exit(1);\n        }\n        remote.sun_family = AF_UNIX;\n        sprintf(remote.sun_path, \"/tmp/vtrunkd_%s.socket\", shm_conn_info[0].devname);\n        len = strlen(remote.sun_path) + sizeof(remote.sun_family);\n        if ( (shm_conn_info->rdy) && (connect(sss, (struct sockaddr *)&remote, len) == -1)) {\n            vlog(LOG_INFO, \"SHM ready but socket not open! Assuming we're only process running;\");\n            shm_new = 1; // could not connect; assume we're new!\n        } else {\n            vlog(LOG_INFO, \"Socket connected OK seems all OK\");\n        }\n        close(sss);\n    }\n    if (shm_new) {\n        vlog(LOG_INFO, \"client doing memset\");\n        memset(shm_conn_info, 0, sizeof(struct conn_info));\n    }\n    //cshit3(&shm_conn_info[0], 37);\n\n    client_term = 0; reconnect = 0;\n    while ( (!client_term) || (client_term == VTUN_SIG_HUP) ) {\n        if ( reconnect && (client_term != VTUN_SIG_HUP) ) {\n            if ( vtun.persist || host->persist ) {\n                /* Persist mode. Sleep and reconnect. */\n                sleep(5);\n            } else {\n                /* Exit */\n                break;\n            }\n        } else {\n            reconnect = 1;\n        }\n\n        set_title(\"%s init initializing\", host->host);\n\n        /* Set server address */\n        if ( server_addr(&svr_addr, host) < 0 )\n            continue;\n\n        /* Set local address */\n        if ( local_addr(&my_addr, host, 0) < 0 )\n            continue;\n\n        /* We have to create socket again every time\n         * we want to connect, since STREAM sockets\n         * can be successfully connected only once.\n         */\n        if ( (s = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {\n            vlog(LOG_ERR, \"Can't create socket. %s(%d)\",\n                        strerror(errno), errno);\n            continue;\n        }\n        //cshit3(&shm_conn_info[0], 38);\n\n        /* Required when client is forced to bind to specific port */\n        opt = 1;\n        setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));\n\n//        #ifndef W_O_SO_MARK\n        if (host->RT_MARK != -1) {\n            if (setsockopt(s, SOL_SOCKET, SO_MARK, &host->RT_MARK, sizeof(host->RT_MARK))) {\n                vlog(LOG_ERR, \"client socket rt mark error %s(%d)\",\n                            strerror(errno), errno);\n                break;\n            }\n        }\n//        #endif\n\n\n        if ( bind(s, (struct sockaddr *)&my_addr, sizeof(my_addr)) ) {\n            vlog(LOG_ERR, \"Can't bind socket. %s(%d)\",\n                        strerror(errno), errno);\n            continue;\n        }\n\n        /*\n         * Clear speed and flags which will be supplied by server.\n         */\n        host->spd_in = host->spd_out = 0;\n        host->flags &= VTUN_CLNT_MASK;\n\n        io_init();\n\n        set_title(\"%s connecting to %s\", host->host, vtun.svr_name);\n        vlog(LOG_INFO, \"Connecting to %s\", vtun.svr_name);\n\n        if ( connect_t(s, (struct sockaddr *) &svr_addr, host->timeout) ) {\n            vlog(LOG_ERR, \"Connect to %s failed. %s(%d)\", vtun.svr_name,\n                        strerror(errno), errno);\n        } else {\n            if ( auth_client(s, host, &reason) ) {\n                vlog(LOG_ERR, \"Session %s[%s] opened (build %s)\", host->host, vtun.svr_name, BUILD_DATE);\n\n\n\n                host->rmt_fd = s;\n                //cshit3(&shm_conn_info[0], 39);\n\n                /* Start the tunnel */\n                client_term = tunnel(host, 0, NULL);\n                gettimeofday(&cur_time, NULL);\n                shm_conn_info->alive = cur_time.tv_sec; // show we are alive and trying to reconnect still.. (or fd_server will quit)\n\n                vlog(LOG_ERR, \"Session %s[%s] closed\", host->host, vtun.svr_name);\n            } else {\n                vlog(LOG_ERR, \"Connection denied by %s, reason: %d\", vtun.svr_name, reason);\n            }\n        }\n        close(s);\n        free_sopt(&host->sopt);\n    }\n\n    vlog(LOG_INFO, \"Exit\");\n    return;\n}\n"
  },
  {
    "path": "compat.h",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * compat.h,v 1.1.1.2.6.1 2006/11/16 04:02:51 mtbishop Exp\n */ \n#ifndef _VTUN_COMPAT_H\n#define _VTUN_COMPAT_H\n\n#ifndef LOG_PERROR\n#define LOG_PERROR 0\n#endif\n\n#ifndef SA_NOCLDWAIT\n#define SA_NOCLDWAIT 0\n#endif\n\n#endif /* _VTUN_COMPAT_H */\n"
  },
  {
    "path": "config.guess",
    "content": "#! /bin/sh\n# Attempt to guess a canonical system name.\n#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001\n#   Free Software Foundation, Inc.\n\ntimestamp='2001-11-08'\n\n# This file is free software; you can redistribute it and/or modify it\n# under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n# General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n#\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that program.\n\n# Originally written by Per Bothner <bothner@cygnus.com>.\n# Please send patches to <config-patches@gnu.org>.  Submit a context\n# diff and a properly formatted ChangeLog entry.\n#\n# This script attempts to guess a canonical system name similar to\n# config.sub.  If it succeeds, it prints the system name on stdout, and\n# exits with 0.  Otherwise, it exits with 1.\n#\n# The plan is that this can be called by configure scripts if you\n# don't specify an explicit build system type.\n\nme=`echo \"$0\" | sed -e 's,.*/,,'`\n\nusage=\"\\\nUsage: $0 [OPTION]\n\nOutput the configuration name of the system \\`$me' is run on.\n\nOperation modes:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.guess ($timestamp)\n\nOriginally written by Per Bothner.\nCopyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001\nFree Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit 0 ;;\n    --version | -v )\n       echo \"$version\" ; exit 0 ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit 0 ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\" >&2\n       exit 1 ;;\n    * )\n       break ;;\n  esac\ndone\n\nif test $# != 0; then\n  echo \"$me: too many arguments$help\" >&2\n  exit 1\nfi\n\n\ndummy=dummy-$$\ntrap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15\n\n# CC_FOR_BUILD -- compiler used by this script.\n# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still\n# use `HOST_CC' if defined, but it is deprecated.\n\nset_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in\n ,,)    echo \"int dummy(){}\" > $dummy.c ;\n\tfor c in cc gcc c89 ; do\n\t  ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;\n\t  if test $? = 0 ; then\n\t     CC_FOR_BUILD=\"$c\"; break ;\n\t  fi ;\n\tdone ;\n\trm -f $dummy.c $dummy.o $dummy.rel ;\n\tif test x\"$CC_FOR_BUILD\" = x ; then\n\t  CC_FOR_BUILD=no_compiler_found ;\n\tfi\n\t;;\n ,,*)   CC_FOR_BUILD=$CC ;;\n ,*,*)  CC_FOR_BUILD=$HOST_CC ;;\nesac'\n\n# This is needed to find uname on a Pyramid OSx when run in the BSD universe.\n# (ghazi@noc.rutgers.edu 1994-08-24)\nif (test -f /.attbin/uname) >/dev/null 2>&1 ; then\n\tPATH=$PATH:/.attbin ; export PATH\nfi\n\nUNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown\nUNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown\nUNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown\nUNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown\n\n# Note: order is significant - the case branches are not exclusive.\n\ncase \"${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}\" in\n    *:NetBSD:*:*)\n\t# NetBSD (nbsd) targets should (where applicable) match one or\n\t# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,\n\t# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently\n\t# switched to ELF, *-*-netbsd* would select the old\n\t# object file format.  This provides both forward\n\t# compatibility and a consistent mechanism for selecting the\n\t# object file format.\n\t# Determine the machine/vendor (is the vendor relevant).\n\tcase \"${UNAME_MACHINE}\" in\n\t    amiga) machine=m68k-unknown ;;\n\t    arm32) machine=arm-unknown ;;\n\t    atari*) machine=m68k-atari ;;\n\t    sun3*) machine=m68k-sun ;;\n\t    mac68k) machine=m68k-apple ;;\n\t    macppc) machine=powerpc-apple ;;\n\t    hp3[0-9][05]) machine=m68k-hp ;;\n\t    ibmrt|romp-ibm) machine=romp-ibm ;;\n\t    sparc*) machine=`uname -p`-unknown ;;\n\t    *) machine=${UNAME_MACHINE}-unknown ;;\n\tesac\n\t# The Operating System including object format, if it has switched\n\t# to ELF recently, or will in the future.\n\tcase \"${UNAME_MACHINE}\" in\n\t    i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)\n\t\teval $set_cc_for_build\n\t\tif echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \\\n\t\t\t| grep __ELF__ >/dev/null\n\t\tthen\n\t\t    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).\n\t\t    # Return netbsd for either.  FIX?\n\t\t    os=netbsd\n\t\telse\n\t\t    os=netbsdelf\n\t\tfi\n\t\t;;\n\t    *)\n\t        os=netbsd\n\t\t;;\n\tesac\n\t# The OS release\n\trelease=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\\./'`\n\t# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:\n\t# contains redundant information, the shorter form:\n\t# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.\n\techo \"${machine}-${os}${release}\"\n\texit 0 ;;\n    amiga:OpenBSD:*:*)\n\techo m68k-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    arc:OpenBSD:*:*)\n\techo mipsel-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    hp300:OpenBSD:*:*)\n\techo m68k-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    mac68k:OpenBSD:*:*)\n\techo m68k-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    macppc:OpenBSD:*:*)\n\techo powerpc-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    mvme68k:OpenBSD:*:*)\n\techo m68k-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    mvme88k:OpenBSD:*:*)\n\techo m88k-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    mvmeppc:OpenBSD:*:*)\n\techo powerpc-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    pmax:OpenBSD:*:*)\n\techo mipsel-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    sgi:OpenBSD:*:*)\n\techo mipseb-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    sun3:OpenBSD:*:*)\n\techo m68k-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    wgrisc:OpenBSD:*:*)\n\techo mipsel-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    *:OpenBSD:*:*)\n\techo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}\n\texit 0 ;;\n    alpha:OSF1:*:*)\n\tif test $UNAME_RELEASE = \"V4.0\"; then\n\t\tUNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`\n\tfi\n\t# A Vn.n version is a released version.\n\t# A Tn.n version is a released field test version.\n\t# A Xn.n version is an unreleased experimental baselevel.\n\t# 1.2 uses \"1.2\" for uname -r.\n\tcat <<EOF >$dummy.s\n\t.data\n\\$Lformat:\n\t.byte 37,100,45,37,120,10,0\t# \"%d-%x\\n\"\n\n\t.text\n\t.globl main\n\t.align 4\n\t.ent main\nmain:\n\t.frame \\$30,16,\\$26,0\n\tldgp \\$29,0(\\$27)\n\t.prologue 1\n\t.long 0x47e03d80 # implver \\$0\n\tlda \\$2,-1\n\t.long 0x47e20c21 # amask \\$2,\\$1\n\tlda \\$16,\\$Lformat\n\tmov \\$0,\\$17\n\tnot \\$1,\\$18\n\tjsr \\$26,printf\n\tldgp \\$29,0(\\$26)\n\tmov 0,\\$16\n\tjsr \\$26,exit\n\t.end main\nEOF\n\teval $set_cc_for_build\n\t$CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null\n\tif test \"$?\" = 0 ; then\n\t\tcase `./$dummy` in\n\t\t\t0-0)\n\t\t\t\tUNAME_MACHINE=\"alpha\"\n\t\t\t\t;;\n\t\t\t1-0)\n\t\t\t\tUNAME_MACHINE=\"alphaev5\"\n\t\t\t\t;;\n\t\t\t1-1)\n\t\t\t\tUNAME_MACHINE=\"alphaev56\"\n\t\t\t\t;;\n\t\t\t1-101)\n\t\t\t\tUNAME_MACHINE=\"alphapca56\"\n\t\t\t\t;;\n\t\t\t2-303)\n\t\t\t\tUNAME_MACHINE=\"alphaev6\"\n\t\t\t\t;;\n\t\t\t2-307)\n\t\t\t\tUNAME_MACHINE=\"alphaev67\"\n\t\t\t\t;;\n\t\t\t2-1307)\n\t\t\t\tUNAME_MACHINE=\"alphaev68\"\n\t\t\t\t;;\n\t\tesac\n\tfi\n\trm -f $dummy.s $dummy\n\techo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`\n\texit 0 ;;\n    Alpha\\ *:Windows_NT*:*)\n\t# How do we know it's Interix rather than the generic POSIX subsystem?\n\t# Should we change UNAME_MACHINE based on the output of uname instead\n\t# of the specific Alpha model?\n\techo alpha-pc-interix\n\texit 0 ;;\n    21064:Windows_NT:50:3)\n\techo alpha-dec-winnt3.5\n\texit 0 ;;\n    Amiga*:UNIX_System_V:4.0:*)\n\techo m68k-unknown-sysv4\n\texit 0;;\n    *:[Aa]miga[Oo][Ss]:*:*)\n\techo ${UNAME_MACHINE}-unknown-amigaos\n\texit 0 ;;\n    *:OS/390:*:*)\n\techo i370-ibm-openedition\n\texit 0 ;;\n    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)\n\techo arm-acorn-riscix${UNAME_RELEASE}\n\texit 0;;\n    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)\n\techo hppa1.1-hitachi-hiuxmpp\n\texit 0;;\n    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)\n\t# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.\n\tif test \"`(/bin/universe) 2>/dev/null`\" = att ; then\n\t\techo pyramid-pyramid-sysv3\n\telse\n\t\techo pyramid-pyramid-bsd\n\tfi\n\texit 0 ;;\n    NILE*:*:*:dcosx)\n\techo pyramid-pyramid-svr4\n\texit 0 ;;\n    sun4H:SunOS:5.*:*)\n\techo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit 0 ;;\n    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)\n\techo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit 0 ;;\n    i86pc:SunOS:5.*:*)\n\techo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit 0 ;;\n    sun4*:SunOS:6*:*)\n\t# According to config.sub, this is the proper way to canonicalize\n\t# SunOS6.  Hard to guess exactly what SunOS6 will be like, but\n\t# it's likely to be more like Solaris than SunOS4.\n\techo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit 0 ;;\n    sun4*:SunOS:*:*)\n\tcase \"`/usr/bin/arch -k`\" in\n\t    Series*|S4*)\n\t\tUNAME_RELEASE=`uname -v`\n\t\t;;\n\tesac\n\t# Japanese Language versions have a version number like `4.1.3-JL'.\n\techo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`\n\texit 0 ;;\n    sun3*:SunOS:*:*)\n\techo m68k-sun-sunos${UNAME_RELEASE}\n\texit 0 ;;\n    sun*:*:4.2BSD:*)\n\tUNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`\n\ttest \"x${UNAME_RELEASE}\" = \"x\" && UNAME_RELEASE=3\n\tcase \"`/bin/arch`\" in\n\t    sun3)\n\t\techo m68k-sun-sunos${UNAME_RELEASE}\n\t\t;;\n\t    sun4)\n\t\techo sparc-sun-sunos${UNAME_RELEASE}\n\t\t;;\n\tesac\n\texit 0 ;;\n    aushp:SunOS:*:*)\n\techo sparc-auspex-sunos${UNAME_RELEASE}\n\texit 0 ;;\n    # The situation for MiNT is a little confusing.  The machine name\n    # can be virtually everything (everything which is not\n    # \"atarist\" or \"atariste\" at least should have a processor\n    # > m68000).  The system name ranges from \"MiNT\" over \"FreeMiNT\"\n    # to the lowercase version \"mint\" (or \"freemint\").  Finally\n    # the system name \"TOS\" denotes a system which is actually not\n    # MiNT.  But MiNT is downward compatible to TOS, so this should\n    # be no problem.\n    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)\n        echo m68k-atari-mint${UNAME_RELEASE}\n\texit 0 ;;\n    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)\n\techo m68k-atari-mint${UNAME_RELEASE}\n        exit 0 ;;\n    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)\n        echo m68k-atari-mint${UNAME_RELEASE}\n\texit 0 ;;\n    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)\n        echo m68k-milan-mint${UNAME_RELEASE}\n        exit 0 ;;\n    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)\n        echo m68k-hades-mint${UNAME_RELEASE}\n        exit 0 ;;\n    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)\n        echo m68k-unknown-mint${UNAME_RELEASE}\n        exit 0 ;;\n    powerpc:machten:*:*)\n\techo powerpc-apple-machten${UNAME_RELEASE}\n\texit 0 ;;\n    RISC*:Mach:*:*)\n\techo mips-dec-mach_bsd4.3\n\texit 0 ;;\n    RISC*:ULTRIX:*:*)\n\techo mips-dec-ultrix${UNAME_RELEASE}\n\texit 0 ;;\n    VAX*:ULTRIX*:*:*)\n\techo vax-dec-ultrix${UNAME_RELEASE}\n\texit 0 ;;\n    2020:CLIX:*:* | 2430:CLIX:*:*)\n\techo clipper-intergraph-clix${UNAME_RELEASE}\n\texit 0 ;;\n    mips:*:*:UMIPS | mips:*:*:RISCos)\n\teval $set_cc_for_build\n\tsed 's/^\t//' << EOF >$dummy.c\n#ifdef __cplusplus\n#include <stdio.h>  /* for printf() prototype */\n\tint main (int argc, char *argv[]) {\n#else\n\tint main (argc, argv) int argc; char *argv[]; {\n#endif\n\t#if defined (host_mips) && defined (MIPSEB)\n\t#if defined (SYSTYPE_SYSV)\n\t  printf (\"mips-mips-riscos%ssysv\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_SVR4)\n\t  printf (\"mips-mips-riscos%ssvr4\\n\", argv[1]); exit (0);\n\t#endif\n\t#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)\n\t  printf (\"mips-mips-riscos%sbsd\\n\", argv[1]); exit (0);\n\t#endif\n\t#endif\n\t  exit (-1);\n\t}\nEOF\n\t$CC_FOR_BUILD $dummy.c -o $dummy \\\n\t  && ./$dummy `echo \"${UNAME_RELEASE}\" | sed -n 's/\\([0-9]*\\).*/\\1/p'` \\\n\t  && rm -f $dummy.c $dummy && exit 0\n\trm -f $dummy.c $dummy\n\techo mips-mips-riscos${UNAME_RELEASE}\n\texit 0 ;;\n    Motorola:PowerMAX_OS:*:*)\n\techo powerpc-motorola-powermax\n\texit 0 ;;\n    Night_Hawk:Power_UNIX:*:*)\n\techo powerpc-harris-powerunix\n\texit 0 ;;\n    m88k:CX/UX:7*:*)\n\techo m88k-harris-cxux7\n\texit 0 ;;\n    m88k:*:4*:R4*)\n\techo m88k-motorola-sysv4\n\texit 0 ;;\n    m88k:*:3*:R3*)\n\techo m88k-motorola-sysv3\n\texit 0 ;;\n    AViiON:dgux:*:*)\n        # DG/UX returns AViiON for all architectures\n        UNAME_PROCESSOR=`/usr/bin/uname -p`\n\tif [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]\n\tthen\n\t    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \\\n\t       [ ${TARGET_BINARY_INTERFACE}x = x ]\n\t    then\n\t\techo m88k-dg-dgux${UNAME_RELEASE}\n\t    else\n\t\techo m88k-dg-dguxbcs${UNAME_RELEASE}\n\t    fi\n\telse\n\t    echo i586-dg-dgux${UNAME_RELEASE}\n\tfi\n \texit 0 ;;\n    M88*:DolphinOS:*:*)\t# DolphinOS (SVR3)\n\techo m88k-dolphin-sysv3\n\texit 0 ;;\n    M88*:*:R3*:*)\n\t# Delta 88k system running SVR3\n\techo m88k-motorola-sysv3\n\texit 0 ;;\n    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)\n\techo m88k-tektronix-sysv3\n\texit 0 ;;\n    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)\n\techo m68k-tektronix-bsd\n\texit 0 ;;\n    *:IRIX*:*:*)\n\techo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`\n\texit 0 ;;\n    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.\n\techo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id\n\texit 0 ;;              # Note that: echo \"'`uname -s`'\" gives 'AIX '\n    i*86:AIX:*:*)\n\techo i386-ibm-aix\n\texit 0 ;;\n    ia64:AIX:*:*)\n\tif [ -x /usr/bin/oslevel ] ; then\n\t\tIBM_REV=`/usr/bin/oslevel`\n\telse\n\t\tIBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}\n\tfi\n\techo ${UNAME_MACHINE}-ibm-aix${IBM_REV}\n\texit 0 ;;\n    *:AIX:2:3)\n\tif grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\teval $set_cc_for_build\n\t\tsed 's/^\t\t//' << EOF >$dummy.c\n\t\t#include <sys/systemcfg.h>\n\n\t\tmain()\n\t\t\t{\n\t\t\tif (!__power_pc())\n\t\t\t\texit(1);\n\t\t\tputs(\"powerpc-ibm-aix3.2.5\");\n\t\t\texit(0);\n\t\t\t}\nEOF\n\t\t$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0\n\t\trm -f $dummy.c $dummy\n\t\techo rs6000-ibm-aix3.2.5\n\telif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then\n\t\techo rs6000-ibm-aix3.2.4\n\telse\n\t\techo rs6000-ibm-aix3.2\n\tfi\n\texit 0 ;;\n    *:AIX:*:[45])\n\tIBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`\n\tif /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then\n\t\tIBM_ARCH=rs6000\n\telse\n\t\tIBM_ARCH=powerpc\n\tfi\n\tif [ -x /usr/bin/oslevel ] ; then\n\t\tIBM_REV=`/usr/bin/oslevel`\n\telse\n\t\tIBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}\n\tfi\n\techo ${IBM_ARCH}-ibm-aix${IBM_REV}\n\texit 0 ;;\n    *:AIX:*:*)\n\techo rs6000-ibm-aix\n\texit 0 ;;\n    ibmrt:4.4BSD:*|romp-ibm:BSD:*)\n\techo romp-ibm-bsd4.4\n\texit 0 ;;\n    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and\n\techo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to\n\texit 0 ;;                           # report: romp-ibm BSD 4.3\n    *:BOSX:*:*)\n\techo rs6000-bull-bosx\n\texit 0 ;;\n    DPX/2?00:B.O.S.:*:*)\n\techo m68k-bull-sysv3\n\texit 0 ;;\n    9000/[34]??:4.3bsd:1.*:*)\n\techo m68k-hp-bsd\n\texit 0 ;;\n    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)\n\techo m68k-hp-bsd4.4\n\texit 0 ;;\n    9000/[34678]??:HP-UX:*:*)\n\tHPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`\n\tcase \"${UNAME_MACHINE}\" in\n\t    9000/31? )            HP_ARCH=m68000 ;;\n\t    9000/[34]?? )         HP_ARCH=m68k ;;\n\t    9000/[678][0-9][0-9])\n\t\tif [ -x /usr/bin/getconf ]; then\n\t\t    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`\n                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`\n                    case \"${sc_cpu_version}\" in\n                      523) HP_ARCH=\"hppa1.0\" ;; # CPU_PA_RISC1_0\n                      528) HP_ARCH=\"hppa1.1\" ;; # CPU_PA_RISC1_1\n                      532)                      # CPU_PA_RISC2_0\n                        case \"${sc_kernel_bits}\" in\n                          32) HP_ARCH=\"hppa2.0n\" ;;\n                          64) HP_ARCH=\"hppa2.0w\" ;;\n\t\t\t  '') HP_ARCH=\"hppa2.0\" ;;   # HP-UX 10.20\n                        esac ;;\n                    esac\n\t\tfi\n\t\tif [ \"${HP_ARCH}\" = \"\" ]; then\n\t\t    eval $set_cc_for_build\n\t\t    sed 's/^              //' << EOF >$dummy.c\n\n              #define _HPUX_SOURCE\n              #include <stdlib.h>\n              #include <unistd.h>\n\n              int main ()\n              {\n              #if defined(_SC_KERNEL_BITS)\n                  long bits = sysconf(_SC_KERNEL_BITS);\n              #endif\n                  long cpu  = sysconf (_SC_CPU_VERSION);\n\n                  switch (cpu)\n              \t{\n              \tcase CPU_PA_RISC1_0: puts (\"hppa1.0\"); break;\n              \tcase CPU_PA_RISC1_1: puts (\"hppa1.1\"); break;\n              \tcase CPU_PA_RISC2_0:\n              #if defined(_SC_KERNEL_BITS)\n              \t    switch (bits)\n              \t\t{\n              \t\tcase 64: puts (\"hppa2.0w\"); break;\n              \t\tcase 32: puts (\"hppa2.0n\"); break;\n              \t\tdefault: puts (\"hppa2.0\"); break;\n              \t\t} break;\n              #else  /* !defined(_SC_KERNEL_BITS) */\n              \t    puts (\"hppa2.0\"); break;\n              #endif\n              \tdefault: puts (\"hppa1.0\"); break;\n              \t}\n                  exit (0);\n              }\nEOF\n\t\t    (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy`\n\t\t    if test -z \"$HP_ARCH\"; then HP_ARCH=hppa; fi\n\t\t    rm -f $dummy.c $dummy\n\t\tfi ;;\n\tesac\n\techo ${HP_ARCH}-hp-hpux${HPUX_REV}\n\texit 0 ;;\n    ia64:HP-UX:*:*)\n\tHPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`\n\techo ia64-hp-hpux${HPUX_REV}\n\texit 0 ;;\n    3050*:HI-UX:*:*)\n\teval $set_cc_for_build\n\tsed 's/^\t//' << EOF >$dummy.c\n\t#include <unistd.h>\n\tint\n\tmain ()\n\t{\n\t  long cpu = sysconf (_SC_CPU_VERSION);\n\t  /* The order matters, because CPU_IS_HP_MC68K erroneously returns\n\t     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct\n\t     results, however.  */\n\t  if (CPU_IS_PA_RISC (cpu))\n\t    {\n\t      switch (cpu)\n\t\t{\n\t\t  case CPU_PA_RISC1_0: puts (\"hppa1.0-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC1_1: puts (\"hppa1.1-hitachi-hiuxwe2\"); break;\n\t\t  case CPU_PA_RISC2_0: puts (\"hppa2.0-hitachi-hiuxwe2\"); break;\n\t\t  default: puts (\"hppa-hitachi-hiuxwe2\"); break;\n\t\t}\n\t    }\n\t  else if (CPU_IS_HP_MC68K (cpu))\n\t    puts (\"m68k-hitachi-hiuxwe2\");\n\t  else puts (\"unknown-hitachi-hiuxwe2\");\n\t  exit (0);\n\t}\nEOF\n\t$CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0\n\trm -f $dummy.c $dummy\n\techo unknown-hitachi-hiuxwe2\n\texit 0 ;;\n    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )\n\techo hppa1.1-hp-bsd\n\texit 0 ;;\n    9000/8??:4.3bsd:*:*)\n\techo hppa1.0-hp-bsd\n\texit 0 ;;\n    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)\n\techo hppa1.0-hp-mpeix\n\texit 0 ;;\n    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )\n\techo hppa1.1-hp-osf\n\texit 0 ;;\n    hp8??:OSF1:*:*)\n\techo hppa1.0-hp-osf\n\texit 0 ;;\n    i*86:OSF1:*:*)\n\tif [ -x /usr/sbin/sysversion ] ; then\n\t    echo ${UNAME_MACHINE}-unknown-osf1mk\n\telse\n\t    echo ${UNAME_MACHINE}-unknown-osf1\n\tfi\n\texit 0 ;;\n    parisc*:Lites*:*:*)\n\techo hppa1.1-hp-lites\n\texit 0 ;;\n    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)\n\techo c1-convex-bsd\n        exit 0 ;;\n    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)\n\tif getsysinfo -f scalar_acc\n\tthen echo c32-convex-bsd\n\telse echo c2-convex-bsd\n\tfi\n        exit 0 ;;\n    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)\n\techo c34-convex-bsd\n        exit 0 ;;\n    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)\n\techo c38-convex-bsd\n        exit 0 ;;\n    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)\n\techo c4-convex-bsd\n        exit 0 ;;\n    CRAY*X-MP:*:*:*)\n\techo xmp-cray-unicos\n        exit 0 ;;\n    CRAY*Y-MP:*:*:*)\n\techo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit 0 ;;\n    CRAY*[A-Z]90:*:*:*)\n\techo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \\\n\t| sed -e 's/CRAY.*\\([A-Z]90\\)/\\1/' \\\n\t      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \\\n\t      -e 's/\\.[^.]*$/.X/'\n\texit 0 ;;\n    CRAY*TS:*:*:*)\n\techo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit 0 ;;\n    CRAY*T3D:*:*:*)\n\techo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit 0 ;;\n    CRAY*T3E:*:*:*)\n\techo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit 0 ;;\n    CRAY*SV1:*:*:*)\n\techo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\\.[^.]*$/.X/'\n\texit 0 ;;\n    CRAY-2:*:*:*)\n\techo cray2-cray-unicos\n        exit 0 ;;\n    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)\n\tFUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`\n        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\\///'`\n        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`\n        echo \"${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}\"\n        exit 0 ;;\n    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\\ Embedded/OS:*:*)\n\techo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}\n\texit 0 ;;\n    sparc*:BSD/OS:*:*)\n\techo sparc-unknown-bsdi${UNAME_RELEASE}\n\texit 0 ;;\n    *:BSD/OS:*:*)\n\techo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}\n\texit 0 ;;\n    *:FreeBSD:*:*)\n\techo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`\n\texit 0 ;;\n    i*:CYGWIN*:*)\n\techo ${UNAME_MACHINE}-pc-cygwin\n\texit 0 ;;\n    i*:MINGW*:*)\n\techo ${UNAME_MACHINE}-pc-mingw32\n\texit 0 ;;\n    i*:PW*:*)\n\techo ${UNAME_MACHINE}-pc-pw32\n\texit 0 ;;\n    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)\n\t# How do we know it's Interix rather than the generic POSIX subsystem?\n\t# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we\n\t# UNAME_MACHINE based on the output of uname instead of i386?\n\techo i386-pc-interix\n\texit 0 ;;\n    i*:UWIN*:*)\n\techo ${UNAME_MACHINE}-pc-uwin\n\texit 0 ;;\n    p*:CYGWIN*:*)\n\techo powerpcle-unknown-cygwin\n\texit 0 ;;\n    prep*:SunOS:5.*:*)\n\techo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`\n\texit 0 ;;\n    *:GNU:*:*)\n\techo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`\n\texit 0 ;;\n    i*86:Minix:*:*)\n\techo ${UNAME_MACHINE}-pc-minix\n\texit 0 ;;\n    arm*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-gnu\n\texit 0 ;;\n    ia64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux\n\texit 0 ;;\n    m68*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-gnu\n\texit 0 ;;\n    mips:Linux:*:*)\n\tcase `sed -n '/^byte/s/^.*: \\(.*\\) endian/\\1/p' < /proc/cpuinfo` in\n\t  big)    echo mips-unknown-linux-gnu && exit 0 ;;\n\t  little) echo mipsel-unknown-linux-gnu && exit 0 ;;\n\tesac\n\t;;\n    ppc:Linux:*:*)\n\techo powerpc-unknown-linux-gnu\n\texit 0 ;;\n    ppc64:Linux:*:*)\n\techo powerpc64-unknown-linux-gnu\n\texit 0 ;;\n    alpha:Linux:*:*)\n\tcase `sed -n '/^cpu model/s/^.*: \\(.*\\)/\\1/p' < /proc/cpuinfo` in\n\t  EV5)   UNAME_MACHINE=alphaev5 ;;\n\t  EV56)  UNAME_MACHINE=alphaev56 ;;\n\t  PCA56) UNAME_MACHINE=alphapca56 ;;\n\t  PCA57) UNAME_MACHINE=alphapca56 ;;\n\t  EV6)   UNAME_MACHINE=alphaev6 ;;\n\t  EV67)  UNAME_MACHINE=alphaev67 ;;\n\t  EV68*) UNAME_MACHINE=alphaev68 ;;\n        esac\n\tobjdump --private-headers /bin/sh | grep ld.so.1 >/dev/null\n\tif test \"$?\" = 0 ; then LIBC=\"libc1\" ; else LIBC=\"\" ; fi\n\techo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}\n\texit 0 ;;\n    parisc:Linux:*:* | hppa:Linux:*:*)\n\t# Look for CPU level\n\tcase `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in\n\t  PA7*) echo hppa1.1-unknown-linux-gnu ;;\n\t  PA8*) echo hppa2.0-unknown-linux-gnu ;;\n\t  *)    echo hppa-unknown-linux-gnu ;;\n\tesac\n\texit 0 ;;\n    parisc64:Linux:*:* | hppa64:Linux:*:*)\n\techo hppa64-unknown-linux-gnu\n\texit 0 ;;\n    s390:Linux:*:* | s390x:Linux:*:*)\n\techo ${UNAME_MACHINE}-ibm-linux\n\texit 0 ;;\n    sh*:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-gnu\n\texit 0 ;;\n    sparc:Linux:*:* | sparc64:Linux:*:*)\n\techo ${UNAME_MACHINE}-unknown-linux-gnu\n\texit 0 ;;\n    x86_64:Linux:*:*)\n\techo x86_64-unknown-linux-gnu\n\texit 0 ;;\n    i*86:Linux:*:*)\n\t# The BFD linker knows what the default object file format is, so\n\t# first see if it will tell us. cd to the root directory to prevent\n\t# problems with other programs or directories called `ld' in the path.\n\tld_supported_targets=`cd /; ld --help 2>&1 \\\n\t\t\t | sed -ne '/supported targets:/!d\n\t\t\t\t    s/[ \t][ \t]*/ /g\n\t\t\t\t    s/.*supported targets: *//\n\t\t\t\t    s/ .*//\n\t\t\t\t    p'`\n        case \"$ld_supported_targets\" in\n\t  elf32-i386)\n\t\tTENTATIVE=\"${UNAME_MACHINE}-pc-linux-gnu\"\n\t\t;;\n\t  a.out-i386-linux)\n\t\techo \"${UNAME_MACHINE}-pc-linux-gnuaout\"\n\t\texit 0 ;;\t\t\n\t  coff-i386)\n\t\techo \"${UNAME_MACHINE}-pc-linux-gnucoff\"\n\t\texit 0 ;;\n\t  \"\")\n\t\t# Either a pre-BFD a.out linker (linux-gnuoldld) or\n\t\t# one that does not give us useful --help.\n\t\techo \"${UNAME_MACHINE}-pc-linux-gnuoldld\"\n\t\texit 0 ;;\n\tesac\n\t# Determine whether the default compiler is a.out or elf\n\teval $set_cc_for_build\n\tcat >$dummy.c <<EOF\n#include <features.h>\n#ifdef __cplusplus\n#include <stdio.h>  /* for printf() prototype */\n\tint main (int argc, char *argv[]) {\n#else\n\tint main (argc, argv) int argc; char *argv[]; {\n#endif\n#ifdef __ELF__\n# ifdef __GLIBC__\n#  if __GLIBC__ >= 2\n    printf (\"%s-pc-linux-gnu\\n\", argv[1]);\n#  else\n    printf (\"%s-pc-linux-gnulibc1\\n\", argv[1]);\n#  endif\n# else\n   printf (\"%s-pc-linux-gnulibc1\\n\", argv[1]);\n# endif\n#else\n  printf (\"%s-pc-linux-gnuaout\\n\", argv[1]);\n#endif\n  return 0;\n}\nEOF\n\t$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy \"${UNAME_MACHINE}\" && rm -f $dummy.c $dummy && exit 0\n\trm -f $dummy.c $dummy\n\ttest x\"${TENTATIVE}\" != x && echo \"${TENTATIVE}\" && exit 0\n\t;;\n    i*86:DYNIX/ptx:4*:*)\n\t# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.\n\t# earlier versions are messed up and put the nodename in both\n\t# sysname and nodename.\n\techo i386-sequent-sysv4\n\texit 0 ;;\n    i*86:UNIX_SV:4.2MP:2.*)\n        # Unixware is an offshoot of SVR4, but it has its own version\n        # number series starting with 2...\n        # I am not positive that other SVR4 systems won't match this,\n\t# I just have to hope.  -- rms.\n        # Use sysv4.2uw... so that sysv4* matches it.\n\techo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}\n\texit 0 ;;\n    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)\n\tUNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\\/MP$//'`\n\tif grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then\n\t\techo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}\n\telse\n\t\techo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}\n\tfi\n\texit 0 ;;\n    i*86:*:5:[78]*)\n\tcase `/bin/uname -X | grep \"^Machine\"` in\n\t    *486*)\t     UNAME_MACHINE=i486 ;;\n\t    *Pentium)\t     UNAME_MACHINE=i586 ;;\n\t    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;\n\tesac\n\techo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}\n\texit 0 ;;\n    i*86:*:3.2:*)\n\tif test -f /usr/options/cb.name; then\n\t\tUNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`\n\t\techo ${UNAME_MACHINE}-pc-isc$UNAME_REL\n\telif /bin/uname -X 2>/dev/null >/dev/null ; then\n\t\tUNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`\n\t\t(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486\n\t\t(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i586\n\t\t(/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\t(/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \\\n\t\t\t&& UNAME_MACHINE=i686\n\t\techo ${UNAME_MACHINE}-pc-sco$UNAME_REL\n\telse\n\t\techo ${UNAME_MACHINE}-pc-sysv32\n\tfi\n\texit 0 ;;\n    i*86:*DOS:*:*)\n\techo ${UNAME_MACHINE}-pc-msdosdjgpp\n\texit 0 ;;\n    pc:*:*:*)\n\t# Left here for compatibility:\n        # uname -m prints for DJGPP always 'pc', but it prints nothing about\n        # the processor, so we play safe by assuming i386.\n\techo i386-pc-msdosdjgpp\n        exit 0 ;;\n    Intel:Mach:3*:*)\n\techo i386-pc-mach3\n\texit 0 ;;\n    paragon:*:*:*)\n\techo i860-intel-osf1\n\texit 0 ;;\n    i860:*:4.*:*) # i860-SVR4\n\tif grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then\n\t  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4\n\telse # Add other i860-SVR4 vendors below as they are discovered.\n\t  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4\n\tfi\n\texit 0 ;;\n    mini*:CTIX:SYS*5:*)\n\t# \"miniframe\"\n\techo m68010-convergent-sysv\n\texit 0 ;;\n    M68*:*:R3V[567]*:*)\n\ttest -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;\n    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0)\n\tOS_REL=''\n\ttest -r /etc/.relid \\\n\t&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \\([0-9][0-9]\\).*/\\1/p' < /etc/.relid`\n\t/bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n\t  && echo i486-ncr-sysv4.3${OS_REL} && exit 0\n\t/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \\\n\t  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;\n    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)\n        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \\\n          && echo i486-ncr-sysv4 && exit 0 ;;\n    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)\n\techo m68k-unknown-lynxos${UNAME_RELEASE}\n\texit 0 ;;\n    mc68030:UNIX_System_V:4.*:*)\n\techo m68k-atari-sysv4\n\texit 0 ;;\n    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)\n\techo i386-unknown-lynxos${UNAME_RELEASE}\n\texit 0 ;;\n    TSUNAMI:LynxOS:2.*:*)\n\techo sparc-unknown-lynxos${UNAME_RELEASE}\n\texit 0 ;;\n    rs6000:LynxOS:2.*:*)\n\techo rs6000-unknown-lynxos${UNAME_RELEASE}\n\texit 0 ;;\n    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)\n\techo powerpc-unknown-lynxos${UNAME_RELEASE}\n\texit 0 ;;\n    SM[BE]S:UNIX_SV:*:*)\n\techo mips-dde-sysv${UNAME_RELEASE}\n\texit 0 ;;\n    RM*:ReliantUNIX-*:*:*)\n\techo mips-sni-sysv4\n\texit 0 ;;\n    RM*:SINIX-*:*:*)\n\techo mips-sni-sysv4\n\texit 0 ;;\n    *:SINIX-*:*:*)\n\tif uname -p 2>/dev/null >/dev/null ; then\n\t\tUNAME_MACHINE=`(uname -p) 2>/dev/null`\n\t\techo ${UNAME_MACHINE}-sni-sysv4\n\telse\n\t\techo ns32k-sni-sysv\n\tfi\n\texit 0 ;;\n    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort\n                      # says <Richard.M.Bartel@ccMail.Census.GOV>\n        echo i586-unisys-sysv4\n        exit 0 ;;\n    *:UNIX_System_V:4*:FTX*)\n\t# From Gerald Hewes <hewes@openmarket.com>.\n\t# How about differentiating between stratus architectures? -djm\n\techo hppa1.1-stratus-sysv4\n\texit 0 ;;\n    *:*:*:FTX*)\n\t# From seanf@swdc.stratus.com.\n\techo i860-stratus-sysv4\n\texit 0 ;;\n    *:VOS:*:*)\n\t# From Paul.Green@stratus.com.\n\techo hppa1.1-stratus-vos\n\texit 0 ;;\n    mc68*:A/UX:*:*)\n\techo m68k-apple-aux${UNAME_RELEASE}\n\texit 0 ;;\n    news*:NEWS-OS:6*:*)\n\techo mips-sony-newsos6\n\texit 0 ;;\n    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)\n\tif [ -d /usr/nec ]; then\n\t        echo mips-nec-sysv${UNAME_RELEASE}\n\telse\n\t        echo mips-unknown-sysv${UNAME_RELEASE}\n\tfi\n        exit 0 ;;\n    BeBox:BeOS:*:*)\t# BeOS running on hardware made by Be, PPC only.\n\techo powerpc-be-beos\n\texit 0 ;;\n    BeMac:BeOS:*:*)\t# BeOS running on Mac or Mac clone, PPC only.\n\techo powerpc-apple-beos\n\texit 0 ;;\n    BePC:BeOS:*:*)\t# BeOS running on Intel PC compatible.\n\techo i586-pc-beos\n\texit 0 ;;\n    SX-4:SUPER-UX:*:*)\n\techo sx4-nec-superux${UNAME_RELEASE}\n\texit 0 ;;\n    SX-5:SUPER-UX:*:*)\n\techo sx5-nec-superux${UNAME_RELEASE}\n\texit 0 ;;\n    Power*:Rhapsody:*:*)\n\techo powerpc-apple-rhapsody${UNAME_RELEASE}\n\texit 0 ;;\n    *:Rhapsody:*:*)\n\techo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}\n\texit 0 ;;\n    *:Darwin:*:*)\n\techo `uname -p`-apple-darwin${UNAME_RELEASE}\n\texit 0 ;;\n    *:procnto*:*:* | *:QNX:[0123456789]*:*)\n\tif test \"${UNAME_MACHINE}\" = \"x86pc\"; then\n\t\tUNAME_MACHINE=pc\n\tfi\n\techo `uname -p`-${UNAME_MACHINE}-nto-qnx\n\texit 0 ;;\n    *:QNX:*:4*)\n\techo i386-pc-qnx\n\texit 0 ;;\n    NSR-[KW]:NONSTOP_KERNEL:*:*)\n\techo nsr-tandem-nsk${UNAME_RELEASE}\n\texit 0 ;;\n    *:NonStop-UX:*:*)\n\techo mips-compaq-nonstopux\n\texit 0 ;;\n    BS2000:POSIX*:*:*)\n\techo bs2000-siemens-sysv\n\texit 0 ;;\n    DS/*:UNIX_System_V:*:*)\n\techo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}\n\texit 0 ;;\n    *:Plan9:*:*)\n\t# \"uname -m\" is not consistent, so use $cputype instead. 386\n\t# is converted to i386 for consistency with other x86\n\t# operating systems.\n\tif test \"$cputype\" = \"386\"; then\n\t    UNAME_MACHINE=i386\n\telse\n\t    UNAME_MACHINE=\"$cputype\"\n\tfi\n\techo ${UNAME_MACHINE}-unknown-plan9\n\texit 0 ;;\n    i*86:OS/2:*:*)\n\t# If we were able to find `uname', then EMX Unix compatibility\n\t# is probably installed.\n\techo ${UNAME_MACHINE}-pc-os2-emx\n\texit 0 ;;\n    *:TOPS-10:*:*)\n\techo pdp10-unknown-tops10\n\texit 0 ;;\n    *:TENEX:*:*)\n\techo pdp10-unknown-tenex\n\texit 0 ;;\n    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)\n\techo pdp10-dec-tops20\n\texit 0 ;;\n    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)\n\techo pdp10-xkl-tops20\n\texit 0 ;;\n    *:TOPS-20:*:*)\n\techo pdp10-unknown-tops20\n\texit 0 ;;\n    *:ITS:*:*)\n\techo pdp10-unknown-its\n\texit 0 ;;\n    i*86:XTS-300:*:STOP)\n\techo ${UNAME_MACHINE}-unknown-stop\n\texit 0 ;;\n    i*86:atheos:*:*)\n\techo ${UNAME_MACHINE}-unknown-atheos\n\texit 0 ;;\nesac\n\n#echo '(No uname command or uname output not recognized.)' 1>&2\n#echo \"${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}\" 1>&2\n\neval $set_cc_for_build\ncat >$dummy.c <<EOF\n#ifdef _SEQUENT_\n# include <sys/types.h>\n# include <sys/utsname.h>\n#endif\nmain ()\n{\n#if defined (sony)\n#if defined (MIPSEB)\n  /* BFD wants \"bsd\" instead of \"newsos\".  Perhaps BFD should be changed,\n     I don't know....  */\n  printf (\"mips-sony-bsd\\n\"); exit (0);\n#else\n#include <sys/param.h>\n  printf (\"m68k-sony-newsos%s\\n\",\n#ifdef NEWSOS4\n          \"4\"\n#else\n\t  \"\"\n#endif\n         ); exit (0);\n#endif\n#endif\n\n#if defined (__arm) && defined (__acorn) && defined (__unix)\n  printf (\"arm-acorn-riscix\"); exit (0);\n#endif\n\n#if defined (hp300) && !defined (hpux)\n  printf (\"m68k-hp-bsd\\n\"); exit (0);\n#endif\n\n#if defined (NeXT)\n#if !defined (__ARCHITECTURE__)\n#define __ARCHITECTURE__ \"m68k\"\n#endif\n  int version;\n  version=`(hostinfo | sed -n 's/.*NeXT Mach \\([0-9]*\\).*/\\1/p') 2>/dev/null`;\n  if (version < 4)\n    printf (\"%s-next-nextstep%d\\n\", __ARCHITECTURE__, version);\n  else\n    printf (\"%s-next-openstep%d\\n\", __ARCHITECTURE__, version);\n  exit (0);\n#endif\n\n#if defined (MULTIMAX) || defined (n16)\n#if defined (UMAXV)\n  printf (\"ns32k-encore-sysv\\n\"); exit (0);\n#else\n#if defined (CMU)\n  printf (\"ns32k-encore-mach\\n\"); exit (0);\n#else\n  printf (\"ns32k-encore-bsd\\n\"); exit (0);\n#endif\n#endif\n#endif\n\n#if defined (__386BSD__)\n  printf (\"i386-pc-bsd\\n\"); exit (0);\n#endif\n\n#if defined (sequent)\n#if defined (i386)\n  printf (\"i386-sequent-dynix\\n\"); exit (0);\n#endif\n#if defined (ns32000)\n  printf (\"ns32k-sequent-dynix\\n\"); exit (0);\n#endif\n#endif\n\n#if defined (_SEQUENT_)\n    struct utsname un;\n\n    uname(&un);\n\n    if (strncmp(un.version, \"V2\", 2) == 0) {\n\tprintf (\"i386-sequent-ptx2\\n\"); exit (0);\n    }\n    if (strncmp(un.version, \"V1\", 2) == 0) { /* XXX is V1 correct? */\n\tprintf (\"i386-sequent-ptx1\\n\"); exit (0);\n    }\n    printf (\"i386-sequent-ptx\\n\"); exit (0);\n\n#endif\n\n#if defined (vax)\n# if !defined (ultrix)\n#  include <sys/param.h>\n#  if defined (BSD)\n#   if BSD == 43\n      printf (\"vax-dec-bsd4.3\\n\"); exit (0);\n#   else\n#    if BSD == 199006\n      printf (\"vax-dec-bsd4.3reno\\n\"); exit (0);\n#    else\n      printf (\"vax-dec-bsd\\n\"); exit (0);\n#    endif\n#   endif\n#  else\n    printf (\"vax-dec-bsd\\n\"); exit (0);\n#  endif\n# else\n    printf (\"vax-dec-ultrix\\n\"); exit (0);\n# endif\n#endif\n\n#if defined (alliant) && defined (i860)\n  printf (\"i860-alliant-bsd\\n\"); exit (0);\n#endif\n\n  exit (1);\n}\nEOF\n\n$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0\nrm -f $dummy.c $dummy\n\n# Apollos put the system type in the environment.\n\ntest -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }\n\n# Convex versions that predate uname can use getsysinfo(1)\n\nif [ -x /usr/convex/getsysinfo ]\nthen\n    case `getsysinfo -f cpu_type` in\n    c1*)\n\techo c1-convex-bsd\n\texit 0 ;;\n    c2*)\n\tif getsysinfo -f scalar_acc\n\tthen echo c32-convex-bsd\n\telse echo c2-convex-bsd\n\tfi\n\texit 0 ;;\n    c34*)\n\techo c34-convex-bsd\n\texit 0 ;;\n    c38*)\n\techo c38-convex-bsd\n\texit 0 ;;\n    c4*)\n\techo c4-convex-bsd\n\texit 0 ;;\n    esac\nfi\n\ncat >&2 <<EOF\n$0: unable to guess system type\n\nThis script, last modified $timestamp, has failed to recognize\nthe operating system you are using. It is advised that you\ndownload the most up to date version of the config scripts from\n\n    ftp://ftp.gnu.org/pub/gnu/config/\n\nIf the version you run ($0) is already up to date, please\nsend the following data and any information you think might be\npertinent to <config-patches@gnu.org> in order to provide the needed\ninformation to handle your system.\n\nconfig.guess timestamp = $timestamp\n\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`\n\nhostinfo               = `(hostinfo) 2>/dev/null`\n/bin/universe          = `(/bin/universe) 2>/dev/null`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`\n/bin/arch              = `(/bin/arch) 2>/dev/null`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`\n\nUNAME_MACHINE = ${UNAME_MACHINE}\nUNAME_RELEASE = ${UNAME_RELEASE}\nUNAME_SYSTEM  = ${UNAME_SYSTEM}\nUNAME_VERSION = ${UNAME_VERSION}\nEOF\n\nexit 1\n\n# Local variables:\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "config.h.in",
    "content": "/* config.h.in.  Generated automatically from configure.in by autoheader.  */\n\n/* Define to empty if the keyword does not work.  */\n#undef const\n\n/* Define as __inline if that's what the C compiler calls it.  */\n#undef inline\n\n/* Define if you have the ANSI C header files.  */\n#undef STDC_HEADERS\n\n/* Define if you have the gettimeofday function.  */\n#undef HAVE_GETTIMEOFDAY\n\n/* Define if you have the <arpa/inet.h> header file.  */\n#undef HAVE_ARPA_INET_H\n\n/* Define if you have the <fcntl.h> header file.  */\n#undef HAVE_FCNTL_H\n\n/* Define if you have the <netinet/in.h> header file.  */\n#undef HAVE_NETINET_IN_H\n\n/* Define if you have the <netinet/ip.h> header file.  */\n#undef HAVE_NETINET_IP_H\n\n/* Define if you have the <netinet/tcp.h> header file.  */\n#undef HAVE_NETINET_TCP_H\n\n/* Define if you have the <netinet/in_systm.h> header file.  */\n#undef HAVE_NETINET_IN_SYSTM_H\n\n/* Define if you have the <netdb.h> header file.  */\n#undef HAVE_NETDB_H\n\n/* Define if you have the <sched.h> header file.  */\n#undef HAVE_SCHED_H\n\n/* Define if you have the <sys/resource.h> header file.  */\n#undef HAVE_SYS_RESOURCE_H\n\n/* Define if you have the <sys/time.h> header file.  */\n#undef HAVE_SYS_TIME_H\n\n/* Define if you have the <sys/sockio.h> header file.  */\n#undef HAVE_SYS_SOCKIO_H\n\n/* Define if you have the <linux/if_tun.h> header file.  */\n#undef HAVE_LINUX_IF_TUN_H\n\n/* Define if you have setproctitle. */\n#undef HAVE_SETPROC_TITLE\n\n#undef HAVE_LIBUTIL_H\n\n/* Define if you have ZLIB */\n#undef HAVE_ZLIB\n\n/* Define if you have LZO */\n#undef HAVE_LZO\n\n/* Define if you have OpenSSL */\n#undef HAVE_SSL\n\n#undef HAVE_SSL_BLOWFISH\n\n#undef HAVE_SSL_AES\n\n#undef HAVE_SSL_EVP\n\n#undef HAVE_SHAPER\n\n/* Release version and date */\n#undef VTUN_VER\n"
  },
  {
    "path": "config.sub",
    "content": "#! /bin/sh\n# Configuration validation subroutine script.\n#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001\n#   Free Software Foundation, Inc.\n\ntimestamp='2001-11-08'\n\n# This file is (in principle) common to ALL GNU software.\n# The presence of a machine in this file suggests that SOME GNU software\n# can handle that machine.  It does not imply ALL GNU software can.\n#\n# This file is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with this program; if not, write to the Free Software\n# Foundation, Inc., 59 Temple Place - Suite 330,\n# Boston, MA 02111-1307, USA.\n\n# As a special exception to the GNU General Public License, if you\n# distribute this file as part of a program that contains a\n# configuration script generated by Autoconf, you may include it under\n# the same distribution terms that you use for the rest of that program.\n\n# Please send patches to <config-patches@gnu.org>.  Submit a context\n# diff and a properly formatted ChangeLog entry.\n#\n# Configuration subroutine to validate and canonicalize a configuration type.\n# Supply the specified configuration type as an argument.\n# If it is invalid, we print an error message on stderr and exit with code 1.\n# Otherwise, we print the canonical config type on stdout and succeed.\n\n# This file is supposed to be the same for all GNU packages\n# and recognize all the CPU types, system types and aliases\n# that are meaningful with *any* GNU software.\n# Each package is responsible for reporting which valid configurations\n# it does not support.  The user should be able to distinguish\n# a failure to support a valid configuration from a meaningless\n# configuration.\n\n# The goal of this file is to map all the various variations of a given\n# machine specification into a single specification in the form:\n#\tCPU_TYPE-MANUFACTURER-OPERATING_SYSTEM\n# or in some cases, the newer four-part form:\n#\tCPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM\n# It is wrong to echo any other type of specification.\n\nme=`echo \"$0\" | sed -e 's,.*/,,'`\n\nusage=\"\\\nUsage: $0 [OPTION] CPU-MFR-OPSYS\n       $0 [OPTION] ALIAS\n\nCanonicalize a configuration name.\n\nOperation modes:\n  -h, --help         print this help, then exit\n  -t, --time-stamp   print date of last modification, then exit\n  -v, --version      print version number, then exit\n\nReport bugs and patches to <config-patches@gnu.org>.\"\n\nversion=\"\\\nGNU config.sub ($timestamp)\n\nCopyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001\nFree Software Foundation, Inc.\n\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\"\n\nhelp=\"\nTry \\`$me --help' for more information.\"\n\n# Parse command line\nwhile test $# -gt 0 ; do\n  case $1 in\n    --time-stamp | --time* | -t )\n       echo \"$timestamp\" ; exit 0 ;;\n    --version | -v )\n       echo \"$version\" ; exit 0 ;;\n    --help | --h* | -h )\n       echo \"$usage\"; exit 0 ;;\n    -- )     # Stop option processing\n       shift; break ;;\n    - )\t# Use stdin as input.\n       break ;;\n    -* )\n       echo \"$me: invalid option $1$help\"\n       exit 1 ;;\n\n    *local*)\n       # First pass through any local machine types.\n       echo $1\n       exit 0;;\n\n    * )\n       break ;;\n  esac\ndone\n\ncase $# in\n 0) echo \"$me: missing argument$help\" >&2\n    exit 1;;\n 1) ;;\n *) echo \"$me: too many arguments$help\" >&2\n    exit 1;;\nesac\n\n# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).\n# Here we must recognize all the valid KERNEL-OS combinations.\nmaybe_os=`echo $1 | sed 's/^\\(.*\\)-\\([^-]*-[^-]*\\)$/\\2/'`\ncase $maybe_os in\n  nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)\n    os=-$maybe_os\n    basic_machine=`echo $1 | sed 's/^\\(.*\\)-\\([^-]*-[^-]*\\)$/\\1/'`\n    ;;\n  *)\n    basic_machine=`echo $1 | sed 's/-[^-]*$//'`\n    if [ $basic_machine != $1 ]\n    then os=`echo $1 | sed 's/.*-/-/'`\n    else os=; fi\n    ;;\nesac\n\n### Let's recognize common machines as not being operating systems so\n### that things like config.sub decstation-3100 work.  We also\n### recognize some manufacturers as not being operating systems, so we\n### can provide default operating systems below.\ncase $os in\n\t-sun*os*)\n\t\t# Prevent following clause from handling this invalid input.\n\t\t;;\n\t-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \\\n\t-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \\\n\t-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \\\n\t-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\\\n\t-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \\\n\t-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \\\n\t-apple | -axis)\n\t\tos=\n\t\tbasic_machine=$1\n\t\t;;\n\t-sim | -cisco | -oki | -wec | -winbond)\n\t\tos=\n\t\tbasic_machine=$1\n\t\t;;\n\t-scout)\n\t\t;;\n\t-wrs)\n\t\tos=-vxworks\n\t\tbasic_machine=$1\n\t\t;;\n\t-chorusos*)\n\t\tos=-chorusos\n\t\tbasic_machine=$1\n\t\t;;\n \t-chorusrdb)\n \t\tos=-chorusrdb\n\t\tbasic_machine=$1\n \t\t;;\n\t-hiux*)\n\t\tos=-hiuxwe2\n\t\t;;\n\t-sco5)\n\t\tos=-sco3.2v5\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco4)\n\t\tos=-sco3.2v4\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco3.2.[4-9]*)\n\t\tos=`echo $os | sed -e 's/sco3.2./sco3.2v/'`\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco3.2v[4-9]*)\n\t\t# Don't forget version if it is 3.2v4 or newer.\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-sco*)\n\t\tos=-sco3.2v2\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-udk*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-isc)\n\t\tos=-isc2.2\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-clix*)\n\t\tbasic_machine=clipper-intergraph\n\t\t;;\n\t-isc*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`\n\t\t;;\n\t-lynx*)\n\t\tos=-lynxos\n\t\t;;\n\t-ptx*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`\n\t\t;;\n\t-windowsnt*)\n\t\tos=`echo $os | sed -e 's/windowsnt/winnt/'`\n\t\t;;\n\t-psos*)\n\t\tos=-psos\n\t\t;;\n\t-mint | -mint[0-9]*)\n\t\tbasic_machine=m68k-atari\n\t\tos=-mint\n\t\t;;\nesac\n\n# Decode aliases for certain CPU-COMPANY combinations.\ncase $basic_machine in\n\t# Recognize the basic CPU types without company name.\n\t# Some are omitted here because they have special meanings below.\n\t1750a | 580 \\\n\t| a29k \\\n\t| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \\\n\t| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \\\n\t| c4x | clipper \\\n\t| d10v | d30v | dsp16xx \\\n\t| fr30 \\\n\t| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \\\n\t| i370 | i860 | i960 | ia64 \\\n\t| m32r | m68000 | m68k | m88k | mcore \\\n\t| mips16 | mips64 | mips64el | mips64orion | mips64orionel \\\n\t| mips64vr4100 | mips64vr4100el | mips64vr4300 \\\n\t| mips64vr4300el | mips64vr5000 | mips64vr5000el \\\n\t| mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \\\n\t| mipsisa32 \\\n\t| mn10200 | mn10300 \\\n\t| ns16k | ns32k \\\n\t| openrisc \\\n\t| pdp10 | pdp11 | pj | pjl \\\n\t| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \\\n\t| pyramid \\\n\t| sh | sh[34] | sh[34]eb | shbe | shle \\\n\t| sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \\\n\t| strongarm \\\n\t| tahoe | thumb | tic80 | tron \\\n\t| v850 \\\n\t| we32k \\\n\t| x86 | xscale | xstormy16 \\\n\t| z8k)\n\t\tbasic_machine=$basic_machine-unknown\n\t\t;;\n\tm6811 | m68hc11 | m6812 | m68hc12)\n\t\t# Motorola 68HC11/12.\n\t\tbasic_machine=$basic_machine-unknown\n\t\tos=-none\n\t\t;;\n\tm88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)\n\t\t;;\n\n\t# We use `pc' rather than `unknown'\n\t# because (1) that's what they normally are, and\n\t# (2) the word \"unknown\" tends to confuse beginning users.\n\ti*86 | x86_64)\n\t  basic_machine=$basic_machine-pc\n\t  ;;\n\t# Object if more than one company name word.\n\t*-*-*)\n\t\techo Invalid configuration \\`$1\\': machine \\`$basic_machine\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\n\t# Recognize the basic CPU types with company name.\n\t580-* \\\n\t| a29k-* \\\n\t| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \\\n\t| alphapca5[67]-* | arc-* \\\n\t| arm-*  | armbe-* | armle-* | armv*-* \\\n\t| avr-* \\\n\t| bs2000-* \\\n\t| c[123]* | c30-* | [cjt]90-* | c54x-* \\\n\t| clipper-* | cray2-* | cydra-* \\\n\t| d10v-* | d30v-* \\\n\t| elxsi-* \\\n\t| f30[01]-* | f700-* | fr30-* | fx80-* \\\n\t| h8300-* | h8500-* \\\n\t| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \\\n\t| i*86-* | i860-* | i960-* | ia64-* \\\n\t| m32r-* \\\n\t| m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \\\n\t| m88110-* | m88k-* | mcore-* \\\n\t| mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \\\n\t| mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \\\n\t| mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \\\n\t| mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \\\n\t| none-* | np1-* | ns16k-* | ns32k-* \\\n\t| orion-* \\\n\t| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \\\n\t| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \\\n\t| pyramid-* \\\n\t| romp-* | rs6000-* \\\n\t| sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \\\n\t| sparc-* | sparc64-* | sparc86x-* | sparclite-* \\\n\t| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* \\\n\t| t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \\\n\t| v850-* | vax-* \\\n\t| we32k-* \\\n\t| x86-* | x86_64-* | xmp-* | xps100-* | xscale-* | xstormy16-* \\\n\t| ymp-* \\\n\t| z8k-*)\n\t\t;;\n\t# Recognize the various machine names and aliases which stand\n\t# for a CPU type and a company and sometimes even an OS.\n\t386bsd)\n\t\tbasic_machine=i386-unknown\n\t\tos=-bsd\n\t\t;;\n\t3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)\n\t\tbasic_machine=m68000-att\n\t\t;;\n\t3b*)\n\t\tbasic_machine=we32k-att\n\t\t;;\n\ta29khif)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tadobe68k)\n\t\tbasic_machine=m68010-adobe\n\t\tos=-scout\n\t\t;;\n\talliant | fx80)\n\t\tbasic_machine=fx80-alliant\n\t\t;;\n\taltos | altos3068)\n\t\tbasic_machine=m68k-altos\n\t\t;;\n\tam29k)\n\t\tbasic_machine=a29k-none\n\t\tos=-bsd\n\t\t;;\n\tamdahl)\n\t\tbasic_machine=580-amdahl\n\t\tos=-sysv\n\t\t;;\n\tamiga | amiga-*)\n\t\tbasic_machine=m68k-unknown\n\t\t;;\n\tamigaos | amigados)\n\t\tbasic_machine=m68k-unknown\n\t\tos=-amigaos\n\t\t;;\n\tamigaunix | amix)\n\t\tbasic_machine=m68k-unknown\n\t\tos=-sysv4\n\t\t;;\n\tapollo68)\n\t\tbasic_machine=m68k-apollo\n\t\tos=-sysv\n\t\t;;\n\tapollo68bsd)\n\t\tbasic_machine=m68k-apollo\n\t\tos=-bsd\n\t\t;;\n\taux)\n\t\tbasic_machine=m68k-apple\n\t\tos=-aux\n\t\t;;\n\tbalance)\n\t\tbasic_machine=ns32k-sequent\n\t\tos=-dynix\n\t\t;;\n\tconvex-c1)\n\t\tbasic_machine=c1-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c2)\n\t\tbasic_machine=c2-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c32)\n\t\tbasic_machine=c32-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c34)\n\t\tbasic_machine=c34-convex\n\t\tos=-bsd\n\t\t;;\n\tconvex-c38)\n\t\tbasic_machine=c38-convex\n\t\tos=-bsd\n\t\t;;\n\tcray | ymp)\n\t\tbasic_machine=ymp-cray\n\t\tos=-unicos\n\t\t;;\n\tcray2)\n\t\tbasic_machine=cray2-cray\n\t\tos=-unicos\n\t\t;;\n\t[cjt]90)\n\t\tbasic_machine=${basic_machine}-cray\n\t\tos=-unicos\n\t\t;;\n\tcrds | unos)\n\t\tbasic_machine=m68k-crds\n\t\t;;\n\tcris | cris-* | etrax*)\n\t\tbasic_machine=cris-axis\n\t\t;;\n\tda30 | da30-*)\n\t\tbasic_machine=m68k-da30\n\t\t;;\n\tdecstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)\n\t\tbasic_machine=mips-dec\n\t\t;;\n\tdelta | 3300 | motorola-3300 | motorola-delta \\\n\t      | 3300-motorola | delta-motorola)\n\t\tbasic_machine=m68k-motorola\n\t\t;;\n\tdelta88)\n\t\tbasic_machine=m88k-motorola\n\t\tos=-sysv3\n\t\t;;\n\tdpx20 | dpx20-*)\n\t\tbasic_machine=rs6000-bull\n\t\tos=-bosx\n\t\t;;\n\tdpx2* | dpx2*-bull)\n\t\tbasic_machine=m68k-bull\n\t\tos=-sysv3\n\t\t;;\n\tebmon29k)\n\t\tbasic_machine=a29k-amd\n\t\tos=-ebmon\n\t\t;;\n\telxsi)\n\t\tbasic_machine=elxsi-elxsi\n\t\tos=-bsd\n\t\t;;\n\tencore | umax | mmax)\n\t\tbasic_machine=ns32k-encore\n\t\t;;\n\tes1800 | OSE68k | ose68k | ose | OSE)\n\t\tbasic_machine=m68k-ericsson\n\t\tos=-ose\n\t\t;;\n\tfx2800)\n\t\tbasic_machine=i860-alliant\n\t\t;;\n\tgenix)\n\t\tbasic_machine=ns32k-ns\n\t\t;;\n\tgmicro)\n\t\tbasic_machine=tron-gmicro\n\t\tos=-sysv\n\t\t;;\n\tgo32)\n\t\tbasic_machine=i386-pc\n\t\tos=-go32\n\t\t;;\n\th3050r* | hiux*)\n\t\tbasic_machine=hppa1.1-hitachi\n\t\tos=-hiuxwe2\n\t\t;;\n\th8300hms)\n\t\tbasic_machine=h8300-hitachi\n\t\tos=-hms\n\t\t;;\n\th8300xray)\n\t\tbasic_machine=h8300-hitachi\n\t\tos=-xray\n\t\t;;\n\th8500hms)\n\t\tbasic_machine=h8500-hitachi\n\t\tos=-hms\n\t\t;;\n\tharris)\n\t\tbasic_machine=m88k-harris\n\t\tos=-sysv3\n\t\t;;\n\thp300-*)\n\t\tbasic_machine=m68k-hp\n\t\t;;\n\thp300bsd)\n\t\tbasic_machine=m68k-hp\n\t\tos=-bsd\n\t\t;;\n\thp300hpux)\n\t\tbasic_machine=m68k-hp\n\t\tos=-hpux\n\t\t;;\n\thp3k9[0-9][0-9] | hp9[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thp9k2[0-9][0-9] | hp9k31[0-9])\n\t\tbasic_machine=m68000-hp\n\t\t;;\n\thp9k3[2-9][0-9])\n\t\tbasic_machine=m68k-hp\n\t\t;;\n\thp9k6[0-9][0-9] | hp6[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thp9k7[0-79][0-9] | hp7[0-79][0-9])\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k78[0-9] | hp78[0-9])\n\t\t# FIXME: really hppa2.0-hp\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)\n\t\t# FIXME: really hppa2.0-hp\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[0-9][13679] | hp8[0-9][13679])\n\t\tbasic_machine=hppa1.1-hp\n\t\t;;\n\thp9k8[0-9][0-9] | hp8[0-9][0-9])\n\t\tbasic_machine=hppa1.0-hp\n\t\t;;\n\thppa-next)\n\t\tos=-nextstep3\n\t\t;;\n\thppaosf)\n\t\tbasic_machine=hppa1.1-hp\n\t\tos=-osf\n\t\t;;\n\thppro)\n\t\tbasic_machine=hppa1.1-hp\n\t\tos=-proelf\n\t\t;;\n\ti370-ibm* | ibm*)\n\t\tbasic_machine=i370-ibm\n\t\t;;\n# I'm not sure what \"Sysv32\" means.  Should this be sysv3.2?\n\ti*86v32)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv32\n\t\t;;\n\ti*86v4*)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv4\n\t\t;;\n\ti*86v)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-sysv\n\t\t;;\n\ti*86sol2)\n\t\tbasic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`\n\t\tos=-solaris2\n\t\t;;\n\ti386mach)\n\t\tbasic_machine=i386-mach\n\t\tos=-mach\n\t\t;;\n\ti386-vsta | vsta)\n\t\tbasic_machine=i386-unknown\n\t\tos=-vsta\n\t\t;;\n\tiris | iris4d)\n\t\tbasic_machine=mips-sgi\n\t\tcase $os in\n\t\t    -irix*)\n\t\t\t;;\n\t\t    *)\n\t\t\tos=-irix4\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tisi68 | isi)\n\t\tbasic_machine=m68k-isi\n\t\tos=-sysv\n\t\t;;\n\tm88k-omron*)\n\t\tbasic_machine=m88k-omron\n\t\t;;\n\tmagnum | m3230)\n\t\tbasic_machine=mips-mips\n\t\tos=-sysv\n\t\t;;\n\tmerlin)\n\t\tbasic_machine=ns32k-utek\n\t\tos=-sysv\n\t\t;;\n\tmingw32)\n\t\tbasic_machine=i386-pc\n\t\tos=-mingw32\n\t\t;;\n\tminiframe)\n\t\tbasic_machine=m68000-convergent\n\t\t;;\n\t*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)\n\t\tbasic_machine=m68k-atari\n\t\tos=-mint\n\t\t;;\n\tmipsel*-linux*)\n\t\tbasic_machine=mipsel-unknown\n\t\tos=-linux-gnu\n\t\t;;\n\tmips*-linux*)\n\t\tbasic_machine=mips-unknown\n\t\tos=-linux-gnu\n\t\t;;\n\tmips3*-*)\n\t\tbasic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`\n\t\t;;\n\tmips3*)\n\t\tbasic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown\n\t\t;;\n\tmmix*)\n\t\tbasic_machine=mmix-knuth\n\t\tos=-mmixware\n\t\t;;\n\tmonitor)\n\t\tbasic_machine=m68k-rom68k\n\t\tos=-coff\n\t\t;;\n\tmsdos)\n\t\tbasic_machine=i386-pc\n\t\tos=-msdos\n\t\t;;\n\tmvs)\n\t\tbasic_machine=i370-ibm\n\t\tos=-mvs\n\t\t;;\n\tncr3000)\n\t\tbasic_machine=i486-ncr\n\t\tos=-sysv4\n\t\t;;\n\tnetbsd386)\n\t\tbasic_machine=i386-unknown\n\t\tos=-netbsd\n\t\t;;\n\tnetwinder)\n\t\tbasic_machine=armv4l-rebel\n\t\tos=-linux\n\t\t;;\n\tnews | news700 | news800 | news900)\n\t\tbasic_machine=m68k-sony\n\t\tos=-newsos\n\t\t;;\n\tnews1000)\n\t\tbasic_machine=m68030-sony\n\t\tos=-newsos\n\t\t;;\n\tnews-3600 | risc-news)\n\t\tbasic_machine=mips-sony\n\t\tos=-newsos\n\t\t;;\n\tnecv70)\n\t\tbasic_machine=v70-nec\n\t\tos=-sysv\n\t\t;;\n\tnext | m*-next )\n\t\tbasic_machine=m68k-next\n\t\tcase $os in\n\t\t    -nextstep* )\n\t\t\t;;\n\t\t    -ns2*)\n\t\t      os=-nextstep2\n\t\t\t;;\n\t\t    *)\n\t\t      os=-nextstep3\n\t\t\t;;\n\t\tesac\n\t\t;;\n\tnh3000)\n\t\tbasic_machine=m68k-harris\n\t\tos=-cxux\n\t\t;;\n\tnh[45]000)\n\t\tbasic_machine=m88k-harris\n\t\tos=-cxux\n\t\t;;\n\tnindy960)\n\t\tbasic_machine=i960-intel\n\t\tos=-nindy\n\t\t;;\n\tmon960)\n\t\tbasic_machine=i960-intel\n\t\tos=-mon960\n\t\t;;\n\tnonstopux)\n\t\tbasic_machine=mips-compaq\n\t\tos=-nonstopux\n\t\t;;\n\tnp1)\n\t\tbasic_machine=np1-gould\n\t\t;;\n\tnsr-tandem)\n\t\tbasic_machine=nsr-tandem\n\t\t;;\n\top50n-* | op60c-*)\n\t\tbasic_machine=hppa1.1-oki\n\t\tos=-proelf\n\t\t;;\n\tOSE68000 | ose68000)\n\t\tbasic_machine=m68000-ericsson\n\t\tos=-ose\n\t\t;;\n\tos68k)\n\t\tbasic_machine=m68k-none\n\t\tos=-os68k\n\t\t;;\n\tpa-hitachi)\n\t\tbasic_machine=hppa1.1-hitachi\n\t\tos=-hiuxwe2\n\t\t;;\n\tparagon)\n\t\tbasic_machine=i860-intel\n\t\tos=-osf\n\t\t;;\n\tpbd)\n\t\tbasic_machine=sparc-tti\n\t\t;;\n\tpbb)\n\t\tbasic_machine=m68k-tti\n\t\t;;\n        pc532 | pc532-*)\n\t\tbasic_machine=ns32k-pc532\n\t\t;;\n\tpentium | p5 | k5 | k6 | nexgen | viac3)\n\t\tbasic_machine=i586-pc\n\t\t;;\n\tpentiumpro | p6 | 6x86 | athlon)\n\t\tbasic_machine=i686-pc\n\t\t;;\n\tpentiumii | pentium2)\n\t\tbasic_machine=i686-pc\n\t\t;;\n\tpentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)\n\t\tbasic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentiumpro-* | p6-* | 6x86-* | athlon-*)\n\t\tbasic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpentiumii-* | pentium2-*)\n\t\tbasic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tpn)\n\t\tbasic_machine=pn-gould\n\t\t;;\n\tpower)\tbasic_machine=power-ibm\n\t\t;;\n\tppc)\tbasic_machine=powerpc-unknown\n\t        ;;\n\tppc-*)\tbasic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppcle | powerpclittle | ppc-le | powerpc-little)\n\t\tbasic_machine=powerpcle-unknown\n\t        ;;\n\tppcle-* | powerpclittle-*)\n\t\tbasic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppc64)\tbasic_machine=powerpc64-unknown\n\t        ;;\n\tppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tppc64le | powerpc64little | ppc64-le | powerpc64-little)\n\t\tbasic_machine=powerpc64le-unknown\n\t        ;;\n\tppc64le-* | powerpc64little-*)\n\t\tbasic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`\n\t\t;;\n\tps2)\n\t\tbasic_machine=i386-ibm\n\t\t;;\n\tpw32)\n\t\tbasic_machine=i586-unknown\n\t\tos=-pw32\n\t\t;;\n\trom68k)\n\t\tbasic_machine=m68k-rom68k\n\t\tos=-coff\n\t\t;;\n\trm[46]00)\n\t\tbasic_machine=mips-siemens\n\t\t;;\n\trtpc | rtpc-*)\n\t\tbasic_machine=romp-ibm\n\t\t;;\n\ts390 | s390-*)\n\t\tbasic_machine=s390-ibm\n\t\t;;\n\ts390x | s390x-*)\n\t\tbasic_machine=s390x-ibm\n\t\t;;\n\tsa29200)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tsequent)\n\t\tbasic_machine=i386-sequent\n\t\t;;\n\tsh)\n\t\tbasic_machine=sh-hitachi\n\t\tos=-hms\n\t\t;;\n\tsparclite-wrs | simso-wrs)\n\t\tbasic_machine=sparclite-wrs\n\t\tos=-vxworks\n\t\t;;\n\tsps7)\n\t\tbasic_machine=m68k-bull\n\t\tos=-sysv2\n\t\t;;\n\tspur)\n\t\tbasic_machine=spur-unknown\n\t\t;;\n\tst2000)\n\t\tbasic_machine=m68k-tandem\n\t\t;;\n\tstratus)\n\t\tbasic_machine=i860-stratus\n\t\tos=-sysv4\n\t\t;;\n\tsun2)\n\t\tbasic_machine=m68000-sun\n\t\t;;\n\tsun2os3)\n\t\tbasic_machine=m68000-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun2os4)\n\t\tbasic_machine=m68000-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun3os3)\n\t\tbasic_machine=m68k-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun3os4)\n\t\tbasic_machine=m68k-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun4os3)\n\t\tbasic_machine=sparc-sun\n\t\tos=-sunos3\n\t\t;;\n\tsun4os4)\n\t\tbasic_machine=sparc-sun\n\t\tos=-sunos4\n\t\t;;\n\tsun4sol2)\n\t\tbasic_machine=sparc-sun\n\t\tos=-solaris2\n\t\t;;\n\tsun3 | sun3-*)\n\t\tbasic_machine=m68k-sun\n\t\t;;\n\tsun4)\n\t\tbasic_machine=sparc-sun\n\t\t;;\n\tsun386 | sun386i | roadrunner)\n\t\tbasic_machine=i386-sun\n\t\t;;\n\tsv1)\n\t\tbasic_machine=sv1-cray\n\t\tos=-unicos\n\t\t;;\n\tsymmetry)\n\t\tbasic_machine=i386-sequent\n\t\tos=-dynix\n\t\t;;\n\tt3e)\n\t\tbasic_machine=t3e-cray\n\t\tos=-unicos\n\t\t;;\n\ttic54x | c54x*)\n\t\tbasic_machine=tic54x-unknown\n\t\tos=-coff\n\t\t;;\n\ttx39)\n\t\tbasic_machine=mipstx39-unknown\n\t\t;;\n\ttx39el)\n\t\tbasic_machine=mipstx39el-unknown\n\t\t;;\n\ttower | tower-32)\n\t\tbasic_machine=m68k-ncr\n\t\t;;\n\tudi29k)\n\t\tbasic_machine=a29k-amd\n\t\tos=-udi\n\t\t;;\n\tultra3)\n\t\tbasic_machine=a29k-nyu\n\t\tos=-sym1\n\t\t;;\n\tv810 | necv810)\n\t\tbasic_machine=v810-nec\n\t\tos=-none\n\t\t;;\n\tvaxv)\n\t\tbasic_machine=vax-dec\n\t\tos=-sysv\n\t\t;;\n\tvms)\n\t\tbasic_machine=vax-dec\n\t\tos=-vms\n\t\t;;\n\tvpp*|vx|vx-*)\n               basic_machine=f301-fujitsu\n               ;;\n\tvxworks960)\n\t\tbasic_machine=i960-wrs\n\t\tos=-vxworks\n\t\t;;\n\tvxworks68)\n\t\tbasic_machine=m68k-wrs\n\t\tos=-vxworks\n\t\t;;\n\tvxworks29k)\n\t\tbasic_machine=a29k-wrs\n\t\tos=-vxworks\n\t\t;;\n\tw65*)\n\t\tbasic_machine=w65-wdc\n\t\tos=-none\n\t\t;;\n\tw89k-*)\n\t\tbasic_machine=hppa1.1-winbond\n\t\tos=-proelf\n\t\t;;\n\twindows32)\n\t\tbasic_machine=i386-pc\n\t\tos=-windows32-msvcrt\n\t\t;;\n\txmp)\n\t\tbasic_machine=xmp-cray\n\t\tos=-unicos\n\t\t;;\n        xps | xps100)\n\t\tbasic_machine=xps100-honeywell\n\t\t;;\n\tz8k-*-coff)\n\t\tbasic_machine=z8k-unknown\n\t\tos=-sim\n\t\t;;\n\tnone)\n\t\tbasic_machine=none-none\n\t\tos=-none\n\t\t;;\n\n# Here we handle the default manufacturer of certain CPU types.  It is in\n# some cases the only manufacturer, in others, it is the most popular.\n\tw89k)\n\t\tbasic_machine=hppa1.1-winbond\n\t\t;;\n\top50n)\n\t\tbasic_machine=hppa1.1-oki\n\t\t;;\n\top60c)\n\t\tbasic_machine=hppa1.1-oki\n\t\t;;\n\tmips)\n\t\tif [ x$os = x-linux-gnu ]; then\n\t\t\tbasic_machine=mips-unknown\n\t\telse\n\t\t\tbasic_machine=mips-mips\n\t\tfi\n\t\t;;\n\tromp)\n\t\tbasic_machine=romp-ibm\n\t\t;;\n\trs6000)\n\t\tbasic_machine=rs6000-ibm\n\t\t;;\n\tvax)\n\t\tbasic_machine=vax-dec\n\t\t;;\n\tpdp10)\n\t\t# there are many clones, so DEC is not a safe bet\n\t\tbasic_machine=pdp10-unknown\n\t\t;;\n\tpdp11)\n\t\tbasic_machine=pdp11-dec\n\t\t;;\n\twe32k)\n\t\tbasic_machine=we32k-att\n\t\t;;\n\tsh3 | sh4 | sh3eb | sh4eb)\n\t\tbasic_machine=sh-unknown\n\t\t;;\n\tsparc | sparcv9 | sparcv9b)\n\t\tbasic_machine=sparc-sun\n\t\t;;\n        cydra)\n\t\tbasic_machine=cydra-cydrome\n\t\t;;\n\torion)\n\t\tbasic_machine=orion-highlevel\n\t\t;;\n\torion105)\n\t\tbasic_machine=clipper-highlevel\n\t\t;;\n\tmac | mpw | mac-mpw)\n\t\tbasic_machine=m68k-apple\n\t\t;;\n\tpmac | pmac-mpw)\n\t\tbasic_machine=powerpc-apple\n\t\t;;\n\tc4x*)\n\t\tbasic_machine=c4x-none\n\t\tos=-coff\n\t\t;;\n\t*-unknown)\n\t\t# Make sure to match an already-canonicalized machine name.\n\t\t;;\n\t*)\n\t\techo Invalid configuration \\`$1\\': machine \\`$basic_machine\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\nesac\n\n# Here we canonicalize certain aliases for manufacturers.\ncase $basic_machine in\n\t*-digital*)\n\t\tbasic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`\n\t\t;;\n\t*-commodore*)\n\t\tbasic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`\n\t\t;;\n\t*)\n\t\t;;\nesac\n\n# Decode manufacturer-specific aliases for certain operating systems.\n\nif [ x\"$os\" != x\"\" ]\nthen\ncase $os in\n        # First match some system type aliases\n        # that might get confused with valid system types.\n\t# -solaris* is a basic system type, with this one exception.\n\t-solaris1 | -solaris1.*)\n\t\tos=`echo $os | sed -e 's|solaris1|sunos4|'`\n\t\t;;\n\t-solaris)\n\t\tos=-solaris2\n\t\t;;\n\t-svr4*)\n\t\tos=-sysv4\n\t\t;;\n\t-unixware*)\n\t\tos=-sysv4.2uw\n\t\t;;\n\t-gnu/linux*)\n\t\tos=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`\n\t\t;;\n\t# First accept the basic system types.\n\t# The portable systems comes first.\n\t# Each alternative MUST END IN A *, to match a version number.\n\t# -sysv* is not here because it comes later, after sysvr4.\n\t-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \\\n\t      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\\\n\t      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \\\n\t      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \\\n\t      | -aos* \\\n\t      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \\\n\t      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \\\n\t      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \\\n\t      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \\\n\t      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \\\n\t      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \\\n\t      | -chorusos* | -chorusrdb* \\\n\t      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \\\n\t      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \\\n\t      | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \\\n\t      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \\\n\t      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \\\n\t      | -os2* | -vos* | -palmos* | -uclinux*)\n\t# Remember, each alternative MUST END IN *, to match a version number.\n\t\t;;\n\t-qnx*)\n\t\tcase $basic_machine in\n\t\t    x86-* | i*86-*)\n\t\t\t;;\n\t\t    *)\n\t\t\tos=-nto$os\n\t\t\t;;\n\t\tesac\n\t\t;;\n\t-nto*)\n\t\tos=-nto-qnx\n\t\t;;\n\t-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \\\n\t      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \\\n\t      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)\n\t\t;;\n\t-mac*)\n\t\tos=`echo $os | sed -e 's|mac|macos|'`\n\t\t;;\n\t-linux*)\n\t\tos=`echo $os | sed -e 's|linux|linux-gnu|'`\n\t\t;;\n\t-sunos5*)\n\t\tos=`echo $os | sed -e 's|sunos5|solaris2|'`\n\t\t;;\n\t-sunos6*)\n\t\tos=`echo $os | sed -e 's|sunos6|solaris3|'`\n\t\t;;\n\t-opened*)\n\t\tos=-openedition\n\t\t;;\n\t-wince*)\n\t\tos=-wince\n\t\t;;\n\t-osfrose*)\n\t\tos=-osfrose\n\t\t;;\n\t-osf*)\n\t\tos=-osf\n\t\t;;\n\t-utek*)\n\t\tos=-bsd\n\t\t;;\n\t-dynix*)\n\t\tos=-bsd\n\t\t;;\n\t-acis*)\n\t\tos=-aos\n\t\t;;\n\t-386bsd)\n\t\tos=-bsd\n\t\t;;\n\t-ctix* | -uts*)\n\t\tos=-sysv\n\t\t;;\n\t-ns2 )\n\t        os=-nextstep2\n\t\t;;\n\t-nsk*)\n\t\tos=-nsk\n\t\t;;\n\t# Preserve the version number of sinix5.\n\t-sinix5.*)\n\t\tos=`echo $os | sed -e 's|sinix|sysv|'`\n\t\t;;\n\t-sinix*)\n\t\tos=-sysv4\n\t\t;;\n\t-triton*)\n\t\tos=-sysv3\n\t\t;;\n\t-oss*)\n\t\tos=-sysv3\n\t\t;;\n\t-svr4)\n\t\tos=-sysv4\n\t\t;;\n\t-svr3)\n\t\tos=-sysv3\n\t\t;;\n\t-sysvr4)\n\t\tos=-sysv4\n\t\t;;\n\t# This must come after -sysvr4.\n\t-sysv*)\n\t\t;;\n\t-ose*)\n\t\tos=-ose\n\t\t;;\n\t-es1800*)\n\t\tos=-ose\n\t\t;;\n\t-xenix)\n\t\tos=-xenix\n\t\t;;\n        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)\n\t        os=-mint\n\t\t;;\n\t-none)\n\t\t;;\n\t*)\n\t\t# Get rid of the `-' at the beginning of $os.\n\t\tos=`echo $os | sed 's/[^-]*-//'`\n\t\techo Invalid configuration \\`$1\\': system \\`$os\\' not recognized 1>&2\n\t\texit 1\n\t\t;;\nesac\nelse\n\n# Here we handle the default operating systems that come with various machines.\n# The value should be what the vendor currently ships out the door with their\n# machine or put another way, the most popular os provided with the machine.\n\n# Note that if you're going to try to match \"-MANUFACTURER\" here (say,\n# \"-sun\"), then you have to tell the case statement up towards the top\n# that MANUFACTURER isn't an operating system.  Otherwise, code above\n# will signal an error saying that MANUFACTURER isn't an operating\n# system, and we'll never get to this point.\n\ncase $basic_machine in\n\t*-acorn)\n\t\tos=-riscix1.2\n\t\t;;\n\tarm*-rebel)\n\t\tos=-linux\n\t\t;;\n\tarm*-semi)\n\t\tos=-aout\n\t\t;;\n\tpdp10-*)\n\t\tos=-tops20\n\t\t;;\n        pdp11-*)\n\t\tos=-none\n\t\t;;\n\t*-dec | vax-*)\n\t\tos=-ultrix4.2\n\t\t;;\n\tm68*-apollo)\n\t\tos=-domain\n\t\t;;\n\ti386-sun)\n\t\tos=-sunos4.0.2\n\t\t;;\n\tm68000-sun)\n\t\tos=-sunos3\n\t\t# This also exists in the configure program, but was not the\n\t\t# default.\n\t\t# os=-sunos4\n\t\t;;\n\tm68*-cisco)\n\t\tos=-aout\n\t\t;;\n\tmips*-cisco)\n\t\tos=-elf\n\t\t;;\n\tmips*-*)\n\t\tos=-elf\n\t\t;;\n\t*-tti)\t# must be before sparc entry or we get the wrong os.\n\t\tos=-sysv3\n\t\t;;\n\tsparc-* | *-sun)\n\t\tos=-sunos4.1.1\n\t\t;;\n\t*-be)\n\t\tos=-beos\n\t\t;;\n\t*-ibm)\n\t\tos=-aix\n\t\t;;\n\t*-wec)\n\t\tos=-proelf\n\t\t;;\n\t*-winbond)\n\t\tos=-proelf\n\t\t;;\n\t*-oki)\n\t\tos=-proelf\n\t\t;;\n\t*-hp)\n\t\tos=-hpux\n\t\t;;\n\t*-hitachi)\n\t\tos=-hiux\n\t\t;;\n\ti860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)\n\t\tos=-sysv\n\t\t;;\n\t*-cbm)\n\t\tos=-amigaos\n\t\t;;\n\t*-dg)\n\t\tos=-dgux\n\t\t;;\n\t*-dolphin)\n\t\tos=-sysv3\n\t\t;;\n\tm68k-ccur)\n\t\tos=-rtu\n\t\t;;\n\tm88k-omron*)\n\t\tos=-luna\n\t\t;;\n\t*-next )\n\t\tos=-nextstep\n\t\t;;\n\t*-sequent)\n\t\tos=-ptx\n\t\t;;\n\t*-crds)\n\t\tos=-unos\n\t\t;;\n\t*-ns)\n\t\tos=-genix\n\t\t;;\n\ti370-*)\n\t\tos=-mvs\n\t\t;;\n\t*-next)\n\t\tos=-nextstep3\n\t\t;;\n        *-gould)\n\t\tos=-sysv\n\t\t;;\n        *-highlevel)\n\t\tos=-bsd\n\t\t;;\n\t*-encore)\n\t\tos=-bsd\n\t\t;;\n        *-sgi)\n\t\tos=-irix\n\t\t;;\n        *-siemens)\n\t\tos=-sysv4\n\t\t;;\n\t*-masscomp)\n\t\tos=-rtu\n\t\t;;\n\tf30[01]-fujitsu | f700-fujitsu)\n\t\tos=-uxpv\n\t\t;;\n\t*-rom68k)\n\t\tos=-coff\n\t\t;;\n\t*-*bug)\n\t\tos=-coff\n\t\t;;\n\t*-apple)\n\t\tos=-macos\n\t\t;;\n\t*-atari*)\n\t\tos=-mint\n\t\t;;\n\t*)\n\t\tos=-none\n\t\t;;\nesac\nfi\n\n# Here we handle the case where we know the os, and the CPU type, but not the\n# manufacturer.  We pick the logical manufacturer.\nvendor=unknown\ncase $basic_machine in\n\t*-unknown)\n\t\tcase $os in\n\t\t\t-riscix*)\n\t\t\t\tvendor=acorn\n\t\t\t\t;;\n\t\t\t-sunos*)\n\t\t\t\tvendor=sun\n\t\t\t\t;;\n\t\t\t-aix*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-beos*)\n\t\t\t\tvendor=be\n\t\t\t\t;;\n\t\t\t-hpux*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t-mpeix*)\n\t\t\t\tvendor=hp\n\t\t\t\t;;\n\t\t\t-hiux*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t-unos*)\n\t\t\t\tvendor=crds\n\t\t\t\t;;\n\t\t\t-dgux*)\n\t\t\t\tvendor=dg\n\t\t\t\t;;\n\t\t\t-luna*)\n\t\t\t\tvendor=omron\n\t\t\t\t;;\n\t\t\t-genix*)\n\t\t\t\tvendor=ns\n\t\t\t\t;;\n\t\t\t-mvs* | -opened*)\n\t\t\t\tvendor=ibm\n\t\t\t\t;;\n\t\t\t-ptx*)\n\t\t\t\tvendor=sequent\n\t\t\t\t;;\n\t\t\t-vxsim* | -vxworks*)\n\t\t\t\tvendor=wrs\n\t\t\t\t;;\n\t\t\t-aux*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t-hms*)\n\t\t\t\tvendor=hitachi\n\t\t\t\t;;\n\t\t\t-mpw* | -macos*)\n\t\t\t\tvendor=apple\n\t\t\t\t;;\n\t\t\t-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)\n\t\t\t\tvendor=atari\n\t\t\t\t;;\n\t\t\t-vos*)\n\t\t\t\tvendor=stratus\n\t\t\t\t;;\n\t\tesac\n\t\tbasic_machine=`echo $basic_machine | sed \"s/unknown/$vendor/\"`\n\t\t;;\nesac\n\necho $basic_machine$os\nexit 0\n\n# Local variables:\n# eval: (add-hook 'write-file-hooks 'time-stamp)\n# time-stamp-start: \"timestamp='\"\n# time-stamp-format: \"%:y-%02m-%02d\"\n# time-stamp-end: \"'\"\n# End:\n"
  },
  {
    "path": "configure",
    "content": "#! /bin/sh\n# Guess values for system-dependent variables and create Makefiles.\n# Generated by GNU Autoconf 2.69.\n#\n#\n# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.\n#\n#\n# This configure script is free software; the Free Software Foundation\n# gives unlimited permission to copy, distribute and modify it.\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test -n \"${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse\n  case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\n\nas_nl='\n'\nexport as_nl\n# Printing a long string crashes Solaris 7 /usr/bin/printf.\nas_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo\n# Prefer a ksh shell builtin over an external printf program on Solaris,\n# but without wasting forks for bash or zsh.\nif test -z \"$BASH_VERSION$ZSH_VERSION\" \\\n    && (test \"X`print -r -- $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='print -r --'\n  as_echo_n='print -rn --'\nelif (test \"X`printf %s $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='printf %s\\n'\n  as_echo_n='printf %s'\nelse\n  if test \"X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`\" = \"X-n $as_echo\"; then\n    as_echo_body='eval /usr/ucb/echo -n \"$1$as_nl\"'\n    as_echo_n='/usr/ucb/echo -n'\n  else\n    as_echo_body='eval expr \"X$1\" : \"X\\\\(.*\\\\)\"'\n    as_echo_n_body='eval\n      arg=$1;\n      case $arg in #(\n      *\"$as_nl\"*)\n\texpr \"X$arg\" : \"X\\\\(.*\\\\)$as_nl\";\n\targ=`expr \"X$arg\" : \".*$as_nl\\\\(.*\\\\)\"`;;\n      esac;\n      expr \"X$arg\" : \"X\\\\(.*\\\\)\" | tr -d \"$as_nl\"\n    '\n    export as_echo_n_body\n    as_echo_n='sh -c $as_echo_n_body as_echo'\n  fi\n  export as_echo_body\n  as_echo='sh -c $as_echo_body as_echo'\nfi\n\n# The user is always right.\nif test \"${PATH_SEPARATOR+set}\" != set; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# IFS\n# We need space, tab and new line, in precisely that order.  Quoting is\n# there to prevent editors from complaining about space-tab.\n# (If _AS_PATH_WALK were called with IFS unset, it would disable word\n# splitting by setting IFS to empty value.)\nIFS=\" \"\"\t$as_nl\"\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    test -r \"$as_dir/$0\" && as_myself=$as_dir/$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as `sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  $as_echo \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n# Unset variables that we do not need and which cause bugs (e.g. in\n# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the \"|| exit 1\"\n# suppresses any \"Segmentation fault\" message there.  '((' could\n# trigger a bug in pdksh 5.2.14.\nfor as_var in BASH_ENV ENV MAIL MAILPATH\ndo eval test x\\${$as_var+set} = xset \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# NLS nuisances.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# CDPATH.\n(unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\n# Use a proper internal environment variable to ensure we don't fall\n  # into an infinite loop, continuously re-executing ourselves.\n  if test x\"${_as_can_reexec}\" != xno && test \"x$CONFIG_SHELL\" != x; then\n    _as_can_reexec=no; export _as_can_reexec;\n    # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\nexec $CONFIG_SHELL $as_opts \"$as_myself\" ${1+\"$@\"}\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed `exec'.\n$as_echo \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nas_fn_exit 255\n  fi\n  # We don't want this to propagate to other subprocesses.\n          { _as_can_reexec=; unset _as_can_reexec;}\nif test \"x$CONFIG_SHELL\" = x; then\n  as_bourne_compatible=\"if test -n \\\"\\${ZSH_VERSION+set}\\\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on \\${1+\\\"\\$@\\\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '\\${1+\\\"\\$@\\\"}'='\\\"\\$@\\\"'\n  setopt NO_GLOB_SUBST\nelse\n  case \\`(set -o) 2>/dev/null\\` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\"\n  as_required=\"as_fn_return () { (exit \\$1); }\nas_fn_success () { as_fn_return 0; }\nas_fn_failure () { as_fn_return 1; }\nas_fn_ret_success () { return 0; }\nas_fn_ret_failure () { return 1; }\n\nexitcode=0\nas_fn_success || { exitcode=1; echo as_fn_success failed.; }\nas_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }\nas_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }\nas_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }\nif ( set x; as_fn_ret_success y && test x = \\\"\\$1\\\" ); then :\n\nelse\n  exitcode=1; echo positional parameters were not saved.\nfi\ntest x\\$exitcode = x0 || exit 1\ntest -x / || exit 1\"\n  as_suggested=\"  as_lineno_1=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_1a=\\$LINENO\n  as_lineno_2=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_2a=\\$LINENO\n  eval 'test \\\"x\\$as_lineno_1'\\$as_run'\\\" != \\\"x\\$as_lineno_2'\\$as_run'\\\" &&\n  test \\\"x\\`expr \\$as_lineno_1'\\$as_run' + 1\\`\\\" = \\\"x\\$as_lineno_2'\\$as_run'\\\"' || exit 1\ntest \\$(( 1 + 1 )) = 2 || exit 1\"\n  if (eval \"$as_required\") 2>/dev/null; then :\n  as_have_required=yes\nelse\n  as_have_required=no\nfi\n  if test x$as_have_required = xyes && (eval \"$as_suggested\") 2>/dev/null; then :\n\nelse\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nas_found=false\nfor as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n  as_found=:\n  case $as_dir in #(\n\t /*)\n\t   for as_base in sh bash ksh sh5; do\n\t     # Try only shells that exist, to save several forks.\n\t     as_shell=$as_dir/$as_base\n\t     if { test -f \"$as_shell\" || test -f \"$as_shell.exe\"; } &&\n\t\t    { $as_echo \"$as_bourne_compatible\"\"$as_required\" | as_run=a \"$as_shell\"; } 2>/dev/null; then :\n  CONFIG_SHELL=$as_shell as_have_required=yes\n\t\t   if { $as_echo \"$as_bourne_compatible\"\"$as_suggested\" | as_run=a \"$as_shell\"; } 2>/dev/null; then :\n  break 2\nfi\nfi\n\t   done;;\n       esac\n  as_found=false\ndone\n$as_found || { if { test -f \"$SHELL\" || test -f \"$SHELL.exe\"; } &&\n\t      { $as_echo \"$as_bourne_compatible\"\"$as_required\" | as_run=a \"$SHELL\"; } 2>/dev/null; then :\n  CONFIG_SHELL=$SHELL as_have_required=yes\nfi; }\nIFS=$as_save_IFS\n\n\n      if test \"x$CONFIG_SHELL\" != x; then :\n  export CONFIG_SHELL\n             # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\nexec $CONFIG_SHELL $as_opts \"$as_myself\" ${1+\"$@\"}\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed `exec'.\n$as_echo \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nexit 255\nfi\n\n    if test x$as_have_required = xno; then :\n  $as_echo \"$0: This script requires a shell more modern than all\"\n  $as_echo \"$0: the shells that I found on your system.\"\n  if test x${ZSH_VERSION+set} = xset ; then\n    $as_echo \"$0: In particular, zsh $ZSH_VERSION has bugs and should\"\n    $as_echo \"$0: be upgraded to zsh 4.3.4 or later.\"\n  else\n    $as_echo \"$0: Please tell bug-autoconf@gnu.org about your system,\n$0: including any error possibly output before this\n$0: message. Then install a modern shell, or manually run\n$0: the script under such a shell if you do have one.\"\n  fi\n  exit 1\nfi\nfi\nfi\nSHELL=${CONFIG_SHELL-/bin/sh}\nexport SHELL\n# Unset more variables known to interfere with behavior of common tools.\nCLICOLOR_FORCE= GREP_OPTIONS=\nunset CLICOLOR_FORCE GREP_OPTIONS\n\n## --------------------- ##\n## M4sh Shell Functions. ##\n## --------------------- ##\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`$as_echo \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null; then :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse\n  as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  }\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null; then :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse\n  as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  }\nfi # as_fn_arith\n\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    $as_echo \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  $as_echo \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\n\n  as_lineno_1=$LINENO as_lineno_1a=$LINENO\n  as_lineno_2=$LINENO as_lineno_2a=$LINENO\n  eval 'test \"x$as_lineno_1'$as_run'\" != \"x$as_lineno_2'$as_run'\" &&\n  test \"x`expr $as_lineno_1'$as_run' + 1`\" = \"x$as_lineno_2'$as_run'\"' || {\n  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)\n  sed -n '\n    p\n    /[$]LINENO/=\n  ' <$as_myself |\n    sed '\n      s/[$]LINENO.*/&-/\n      t lineno\n      b\n      :lineno\n      N\n      :loop\n      s/[$]LINENO\\([^'$as_cr_alnum'_].*\\n\\)\\(.*\\)/\\2\\1\\2/\n      t loop\n      s/-\\n.*//\n    ' >$as_me.lineno &&\n  chmod +x \"$as_me.lineno\" ||\n    { $as_echo \"$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell\" >&2; as_fn_exit 1; }\n\n  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have\n  # already done that, so ensure we don't try to do so again and fall\n  # in an infinite loop.  This has already happened in practice.\n  _as_can_reexec=no; export _as_can_reexec\n  # Don't try to exec as it changes $[0], causing all sort of problems\n  # (the dirname of $[0] is not the place where we might find the\n  # original and so on.  Autoconf is especially sensitive to this).\n  . \"./$as_me.lineno\"\n  # Exit status is that of the last command.\n  exit\n}\n\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.\n    # In both cases, we have to default to `cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_tr_cpp=\"eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'\"\n\n# Sed expression to map a string onto a valid variable name.\nas_tr_sh=\"eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'\"\n\n\ntest -n \"$DJDIR\" || exec 7<&0 </dev/null\nexec 6>&1\n\n# Name of the host.\n# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,\n# so uname gets run too.\nac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`\n\n#\n# Initializations.\n#\nac_default_prefix=/usr/local\nac_clean_files=\nac_config_libobj_dir=.\nLIBOBJS=\ncross_compiling=no\nsubdirs=\nMFLAGS=\nMAKEFLAGS=\n\n# Identity of this package.\nPACKAGE_NAME=\nPACKAGE_TARNAME=\nPACKAGE_VERSION=\nPACKAGE_STRING=\nPACKAGE_BUGREPORT=\nPACKAGE_URL=\n\nac_unique_file=\"lib.c\"\n# Factoring default headers for most tests.\nac_includes_default=\"\\\n#include <stdio.h>\n#ifdef HAVE_SYS_TYPES_H\n# include <sys/types.h>\n#endif\n#ifdef HAVE_SYS_STAT_H\n# include <sys/stat.h>\n#endif\n#ifdef STDC_HEADERS\n# include <stdlib.h>\n# include <stddef.h>\n#else\n# ifdef HAVE_STDLIB_H\n#  include <stdlib.h>\n# endif\n#endif\n#ifdef HAVE_STRING_H\n# if !defined STDC_HEADERS && defined HAVE_MEMORY_H\n#  include <memory.h>\n# endif\n# include <string.h>\n#endif\n#ifdef HAVE_STRINGS_H\n# include <strings.h>\n#endif\n#ifdef HAVE_INTTYPES_H\n# include <inttypes.h>\n#endif\n#ifdef HAVE_STDINT_H\n# include <stdint.h>\n#endif\n#ifdef HAVE_UNISTD_H\n# include <unistd.h>\n#endif\"\n\nac_subst_vars='LTLIBOBJS\nLIBOBJS\nEGREP\nGREP\nCPP\nINSTALL_DATA\nINSTALL_SCRIPT\nINSTALL_PROGRAM\nLEXLIB\nOBJEXT\nEXEEXT\nac_ct_CC\nCPPFLAGS\nLDFLAGS\nCFLAGS\nCC\nLEX_OUTPUT_ROOT\nLEX\nYFLAGS\nYACC\ntarget_os\ntarget_vendor\ntarget_cpu\ntarget\nhost_os\nhost_vendor\nhost_cpu\nhost\nbuild_os\nbuild_vendor\nbuild_cpu\nbuild\ntarget_alias\nhost_alias\nbuild_alias\nLIBS\nECHO_T\nECHO_N\nECHO_C\nDEFS\nmandir\nlocaledir\nlibdir\npsdir\npdfdir\ndvidir\nhtmldir\ninfodir\ndocdir\noldincludedir\nincludedir\nlocalstatedir\nsharedstatedir\nsysconfdir\ndatadir\ndatarootdir\nlibexecdir\nsbindir\nbindir\nprogram_transform_name\nprefix\nexec_prefix\nPACKAGE_URL\nPACKAGE_BUGREPORT\nPACKAGE_STRING\nPACKAGE_VERSION\nPACKAGE_TARNAME\nPACKAGE_NAME\nPATH_SEPARATOR\nSHELL'\nac_subst_files=''\nac_user_opts='\nenable_option_checking\nenable_o3\nenable_sum_send\nenable_mark\nenable_syslog\nenable_low_mem\nenable_json\nenable_debugg\nenable_self_testing\nenable_client_only\nwith_ssl_headers\nwith_ssl_lib\nwith_lzo_headers\nwith_lzo_lib\nwith_blowfish_headers\nwith_socks_lib\n'\n      ac_precious_vars='build_alias\nhost_alias\ntarget_alias\nYACC\nYFLAGS\nCC\nCFLAGS\nLDFLAGS\nLIBS\nCPPFLAGS\nCPP'\n\n\n# Initialize some variables set by options.\nac_init_help=\nac_init_version=false\nac_unrecognized_opts=\nac_unrecognized_sep=\n# The variables have the same names as the options, with\n# dashes changed to underlines.\ncache_file=/dev/null\nexec_prefix=NONE\nno_create=\nno_recursion=\nprefix=NONE\nprogram_prefix=NONE\nprogram_suffix=NONE\nprogram_transform_name=s,x,x,\nsilent=\nsite=\nsrcdir=\nverbose=\nx_includes=NONE\nx_libraries=NONE\n\n# Installation directory options.\n# These are left unexpanded so users can \"make install exec_prefix=/foo\"\n# and all the variables that are supposed to be based on exec_prefix\n# by default will actually change.\n# Use braces instead of parens because sh, perl, etc. also accept them.\n# (The list follows the same order as the GNU Coding Standards.)\nbindir='${exec_prefix}/bin'\nsbindir='${exec_prefix}/sbin'\nlibexecdir='${exec_prefix}/libexec'\ndatarootdir='${prefix}/share'\ndatadir='${datarootdir}'\nsysconfdir='${prefix}/etc'\nsharedstatedir='${prefix}/com'\nlocalstatedir='${prefix}/var'\nincludedir='${prefix}/include'\noldincludedir='/usr/include'\ndocdir='${datarootdir}/doc/${PACKAGE}'\ninfodir='${datarootdir}/info'\nhtmldir='${docdir}'\ndvidir='${docdir}'\npdfdir='${docdir}'\npsdir='${docdir}'\nlibdir='${exec_prefix}/lib'\nlocaledir='${datarootdir}/locale'\nmandir='${datarootdir}/man'\n\nac_prev=\nac_dashdash=\nfor ac_option\ndo\n  # If the previous option needs an argument, assign it.\n  if test -n \"$ac_prev\"; then\n    eval $ac_prev=\\$ac_option\n    ac_prev=\n    continue\n  fi\n\n  case $ac_option in\n  *=?*) ac_optarg=`expr \"X$ac_option\" : '[^=]*=\\(.*\\)'` ;;\n  *=)   ac_optarg= ;;\n  *)    ac_optarg=yes ;;\n  esac\n\n  # Accept the important Cygnus configure options, so we can diagnose typos.\n\n  case $ac_dashdash$ac_option in\n  --)\n    ac_dashdash=yes ;;\n\n  -bindir | --bindir | --bindi | --bind | --bin | --bi)\n    ac_prev=bindir ;;\n  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)\n    bindir=$ac_optarg ;;\n\n  -build | --build | --buil | --bui | --bu)\n    ac_prev=build_alias ;;\n  -build=* | --build=* | --buil=* | --bui=* | --bu=*)\n    build_alias=$ac_optarg ;;\n\n  -cache-file | --cache-file | --cache-fil | --cache-fi \\\n  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)\n    ac_prev=cache_file ;;\n  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \\\n  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)\n    cache_file=$ac_optarg ;;\n\n  --config-cache | -C)\n    cache_file=config.cache ;;\n\n  -datadir | --datadir | --datadi | --datad)\n    ac_prev=datadir ;;\n  -datadir=* | --datadir=* | --datadi=* | --datad=*)\n    datadir=$ac_optarg ;;\n\n  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \\\n  | --dataroo | --dataro | --datar)\n    ac_prev=datarootdir ;;\n  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \\\n  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)\n    datarootdir=$ac_optarg ;;\n\n  -disable-* | --disable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*disable-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=no ;;\n\n  -docdir | --docdir | --docdi | --doc | --do)\n    ac_prev=docdir ;;\n  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)\n    docdir=$ac_optarg ;;\n\n  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)\n    ac_prev=dvidir ;;\n  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)\n    dvidir=$ac_optarg ;;\n\n  -enable-* | --enable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*enable-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=\\$ac_optarg ;;\n\n  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \\\n  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \\\n  | --exec | --exe | --ex)\n    ac_prev=exec_prefix ;;\n  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \\\n  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \\\n  | --exec=* | --exe=* | --ex=*)\n    exec_prefix=$ac_optarg ;;\n\n  -gas | --gas | --ga | --g)\n    # Obsolete; use --with-gas.\n    with_gas=yes ;;\n\n  -help | --help | --hel | --he | -h)\n    ac_init_help=long ;;\n  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)\n    ac_init_help=recursive ;;\n  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)\n    ac_init_help=short ;;\n\n  -host | --host | --hos | --ho)\n    ac_prev=host_alias ;;\n  -host=* | --host=* | --hos=* | --ho=*)\n    host_alias=$ac_optarg ;;\n\n  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)\n    ac_prev=htmldir ;;\n  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \\\n  | --ht=*)\n    htmldir=$ac_optarg ;;\n\n  -includedir | --includedir | --includedi | --included | --include \\\n  | --includ | --inclu | --incl | --inc)\n    ac_prev=includedir ;;\n  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \\\n  | --includ=* | --inclu=* | --incl=* | --inc=*)\n    includedir=$ac_optarg ;;\n\n  -infodir | --infodir | --infodi | --infod | --info | --inf)\n    ac_prev=infodir ;;\n  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)\n    infodir=$ac_optarg ;;\n\n  -libdir | --libdir | --libdi | --libd)\n    ac_prev=libdir ;;\n  -libdir=* | --libdir=* | --libdi=* | --libd=*)\n    libdir=$ac_optarg ;;\n\n  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \\\n  | --libexe | --libex | --libe)\n    ac_prev=libexecdir ;;\n  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \\\n  | --libexe=* | --libex=* | --libe=*)\n    libexecdir=$ac_optarg ;;\n\n  -localedir | --localedir | --localedi | --localed | --locale)\n    ac_prev=localedir ;;\n  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)\n    localedir=$ac_optarg ;;\n\n  -localstatedir | --localstatedir | --localstatedi | --localstated \\\n  | --localstate | --localstat | --localsta | --localst | --locals)\n    ac_prev=localstatedir ;;\n  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \\\n  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)\n    localstatedir=$ac_optarg ;;\n\n  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)\n    ac_prev=mandir ;;\n  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)\n    mandir=$ac_optarg ;;\n\n  -nfp | --nfp | --nf)\n    # Obsolete; use --without-fp.\n    with_fp=no ;;\n\n  -no-create | --no-create | --no-creat | --no-crea | --no-cre \\\n  | --no-cr | --no-c | -n)\n    no_create=yes ;;\n\n  -no-recursion | --no-recursion | --no-recursio | --no-recursi \\\n  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)\n    no_recursion=yes ;;\n\n  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \\\n  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \\\n  | --oldin | --oldi | --old | --ol | --o)\n    ac_prev=oldincludedir ;;\n  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \\\n  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \\\n  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)\n    oldincludedir=$ac_optarg ;;\n\n  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)\n    ac_prev=prefix ;;\n  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)\n    prefix=$ac_optarg ;;\n\n  -program-prefix | --program-prefix | --program-prefi | --program-pref \\\n  | --program-pre | --program-pr | --program-p)\n    ac_prev=program_prefix ;;\n  -program-prefix=* | --program-prefix=* | --program-prefi=* \\\n  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)\n    program_prefix=$ac_optarg ;;\n\n  -program-suffix | --program-suffix | --program-suffi | --program-suff \\\n  | --program-suf | --program-su | --program-s)\n    ac_prev=program_suffix ;;\n  -program-suffix=* | --program-suffix=* | --program-suffi=* \\\n  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)\n    program_suffix=$ac_optarg ;;\n\n  -program-transform-name | --program-transform-name \\\n  | --program-transform-nam | --program-transform-na \\\n  | --program-transform-n | --program-transform- \\\n  | --program-transform | --program-transfor \\\n  | --program-transfo | --program-transf \\\n  | --program-trans | --program-tran \\\n  | --progr-tra | --program-tr | --program-t)\n    ac_prev=program_transform_name ;;\n  -program-transform-name=* | --program-transform-name=* \\\n  | --program-transform-nam=* | --program-transform-na=* \\\n  | --program-transform-n=* | --program-transform-=* \\\n  | --program-transform=* | --program-transfor=* \\\n  | --program-transfo=* | --program-transf=* \\\n  | --program-trans=* | --program-tran=* \\\n  | --progr-tra=* | --program-tr=* | --program-t=*)\n    program_transform_name=$ac_optarg ;;\n\n  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)\n    ac_prev=pdfdir ;;\n  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)\n    pdfdir=$ac_optarg ;;\n\n  -psdir | --psdir | --psdi | --psd | --ps)\n    ac_prev=psdir ;;\n  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)\n    psdir=$ac_optarg ;;\n\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil)\n    silent=yes ;;\n\n  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)\n    ac_prev=sbindir ;;\n  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \\\n  | --sbi=* | --sb=*)\n    sbindir=$ac_optarg ;;\n\n  -sharedstatedir | --sharedstatedir | --sharedstatedi \\\n  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \\\n  | --sharedst | --shareds | --shared | --share | --shar \\\n  | --sha | --sh)\n    ac_prev=sharedstatedir ;;\n  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \\\n  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \\\n  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \\\n  | --sha=* | --sh=*)\n    sharedstatedir=$ac_optarg ;;\n\n  -site | --site | --sit)\n    ac_prev=site ;;\n  -site=* | --site=* | --sit=*)\n    site=$ac_optarg ;;\n\n  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)\n    ac_prev=srcdir ;;\n  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)\n    srcdir=$ac_optarg ;;\n\n  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \\\n  | --syscon | --sysco | --sysc | --sys | --sy)\n    ac_prev=sysconfdir ;;\n  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \\\n  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)\n    sysconfdir=$ac_optarg ;;\n\n  -target | --target | --targe | --targ | --tar | --ta | --t)\n    ac_prev=target_alias ;;\n  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)\n    target_alias=$ac_optarg ;;\n\n  -v | -verbose | --verbose | --verbos | --verbo | --verb)\n    verbose=yes ;;\n\n  -version | --version | --versio | --versi | --vers | -V)\n    ac_init_version=: ;;\n\n  -with-* | --with-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*with-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=\\$ac_optarg ;;\n\n  -without-* | --without-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*without-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: $ac_useropt\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`$as_echo \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=no ;;\n\n  --x)\n    # Obsolete; use --with-x.\n    with_x=yes ;;\n\n  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \\\n  | --x-incl | --x-inc | --x-in | --x-i)\n    ac_prev=x_includes ;;\n  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \\\n  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)\n    x_includes=$ac_optarg ;;\n\n  -x-libraries | --x-libraries | --x-librarie | --x-librari \\\n  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)\n    ac_prev=x_libraries ;;\n  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \\\n  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)\n    x_libraries=$ac_optarg ;;\n\n  -*) as_fn_error $? \"unrecognized option: \\`$ac_option'\nTry \\`$0 --help' for more information\"\n    ;;\n\n  *=*)\n    ac_envvar=`expr \"x$ac_option\" : 'x\\([^=]*\\)='`\n    # Reject names that are not valid shell variable names.\n    case $ac_envvar in #(\n      '' | [0-9]* | *[!_$as_cr_alnum]* )\n      as_fn_error $? \"invalid variable name: \\`$ac_envvar'\" ;;\n    esac\n    eval $ac_envvar=\\$ac_optarg\n    export $ac_envvar ;;\n\n  *)\n    # FIXME: should be removed in autoconf 3.0.\n    $as_echo \"$as_me: WARNING: you should use --build, --host, --target\" >&2\n    expr \"x$ac_option\" : \".*[^-._$as_cr_alnum]\" >/dev/null &&\n      $as_echo \"$as_me: WARNING: invalid host type: $ac_option\" >&2\n    : \"${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}\"\n    ;;\n\n  esac\ndone\n\nif test -n \"$ac_prev\"; then\n  ac_option=--`echo $ac_prev | sed 's/_/-/g'`\n  as_fn_error $? \"missing argument to $ac_option\"\nfi\n\nif test -n \"$ac_unrecognized_opts\"; then\n  case $enable_option_checking in\n    no) ;;\n    fatal) as_fn_error $? \"unrecognized options: $ac_unrecognized_opts\" ;;\n    *)     $as_echo \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2 ;;\n  esac\nfi\n\n# Check all directory arguments for consistency.\nfor ac_var in\texec_prefix prefix bindir sbindir libexecdir datarootdir \\\n\t\tdatadir sysconfdir sharedstatedir localstatedir includedir \\\n\t\toldincludedir docdir infodir htmldir dvidir pdfdir psdir \\\n\t\tlibdir localedir mandir\ndo\n  eval ac_val=\\$$ac_var\n  # Remove trailing slashes.\n  case $ac_val in\n    */ )\n      ac_val=`expr \"X$ac_val\" : 'X\\(.*[^/]\\)' \\| \"X$ac_val\" : 'X\\(.*\\)'`\n      eval $ac_var=\\$ac_val;;\n  esac\n  # Be sure to have absolute directory names.\n  case $ac_val in\n    [\\\\/$]* | ?:[\\\\/]* )  continue;;\n    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;\n  esac\n  as_fn_error $? \"expected an absolute directory name for --$ac_var: $ac_val\"\ndone\n\n# There might be people who depend on the old broken behavior: `$host'\n# used to hold the argument of --host etc.\n# FIXME: To remove some day.\nbuild=$build_alias\nhost=$host_alias\ntarget=$target_alias\n\n# FIXME: To remove some day.\nif test \"x$host_alias\" != x; then\n  if test \"x$build_alias\" = x; then\n    cross_compiling=maybe\n  elif test \"x$build_alias\" != \"x$host_alias\"; then\n    cross_compiling=yes\n  fi\nfi\n\nac_tool_prefix=\ntest -n \"$host_alias\" && ac_tool_prefix=$host_alias-\n\ntest \"$silent\" = yes && exec 6>/dev/null\n\n\nac_pwd=`pwd` && test -n \"$ac_pwd\" &&\nac_ls_di=`ls -di .` &&\nac_pwd_ls_di=`cd \"$ac_pwd\" && ls -di .` ||\n  as_fn_error $? \"working directory cannot be determined\"\ntest \"X$ac_ls_di\" = \"X$ac_pwd_ls_di\" ||\n  as_fn_error $? \"pwd does not report name of working directory\"\n\n\n# Find the source files, if location was not specified.\nif test -z \"$srcdir\"; then\n  ac_srcdir_defaulted=yes\n  # Try the directory containing this script, then the parent directory.\n  ac_confdir=`$as_dirname -- \"$as_myself\" ||\n$as_expr X\"$as_myself\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_myself\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_myself\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  srcdir=$ac_confdir\n  if test ! -r \"$srcdir/$ac_unique_file\"; then\n    srcdir=..\n  fi\nelse\n  ac_srcdir_defaulted=no\nfi\nif test ! -r \"$srcdir/$ac_unique_file\"; then\n  test \"$ac_srcdir_defaulted\" = yes && srcdir=\"$ac_confdir or ..\"\n  as_fn_error $? \"cannot find sources ($ac_unique_file) in $srcdir\"\nfi\nac_msg=\"sources are in $srcdir, but \\`cd $srcdir' does not work\"\nac_abs_confdir=`(\n\tcd \"$srcdir\" && test -r \"./$ac_unique_file\" || as_fn_error $? \"$ac_msg\"\n\tpwd)`\n# When building in place, set srcdir=.\nif test \"$ac_abs_confdir\" = \"$ac_pwd\"; then\n  srcdir=.\nfi\n# Remove unnecessary trailing slashes from srcdir.\n# Double slashes in file names in object file debugging info\n# mess up M-x gdb in Emacs.\ncase $srcdir in\n*/) srcdir=`expr \"X$srcdir\" : 'X\\(.*[^/]\\)' \\| \"X$srcdir\" : 'X\\(.*\\)'`;;\nesac\nfor ac_var in $ac_precious_vars; do\n  eval ac_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_env_${ac_var}_value=\\$${ac_var}\n  eval ac_cv_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_cv_env_${ac_var}_value=\\$${ac_var}\ndone\n\n#\n# Report the --help message.\n#\nif test \"$ac_init_help\" = \"long\"; then\n  # Omit some internal or obsolete options to make the list less imposing.\n  # This message is too long to be a string in the A/UX 3.1 sh.\n  cat <<_ACEOF\n\\`configure' configures this package to adapt to many kinds of systems.\n\nUsage: $0 [OPTION]... [VAR=VALUE]...\n\nTo assign environment variables (e.g., CC, CFLAGS...), specify them as\nVAR=VALUE.  See below for descriptions of some of the useful variables.\n\nDefaults for the options are specified in brackets.\n\nConfiguration:\n  -h, --help              display this help and exit\n      --help=short        display options specific to this package\n      --help=recursive    display the short help of all the included packages\n  -V, --version           display version information and exit\n  -q, --quiet, --silent   do not print \\`checking ...' messages\n      --cache-file=FILE   cache test results in FILE [disabled]\n  -C, --config-cache      alias for \\`--cache-file=config.cache'\n  -n, --no-create         do not create output files\n      --srcdir=DIR        find the sources in DIR [configure dir or \\`..']\n\nInstallation directories:\n  --prefix=PREFIX         install architecture-independent files in PREFIX\n                          [$ac_default_prefix]\n  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX\n                          [PREFIX]\n\nBy default, \\`make install' will install all the files in\n\\`$ac_default_prefix/bin', \\`$ac_default_prefix/lib' etc.  You can specify\nan installation prefix other than \\`$ac_default_prefix' using \\`--prefix',\nfor instance \\`--prefix=\\$HOME'.\n\nFor better control, use the options below.\n\nFine tuning of the installation directories:\n  --bindir=DIR            user executables [EPREFIX/bin]\n  --sbindir=DIR           system admin executables [EPREFIX/sbin]\n  --libexecdir=DIR        program executables [EPREFIX/libexec]\n  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]\n  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]\n  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]\n  --libdir=DIR            object code libraries [EPREFIX/lib]\n  --includedir=DIR        C header files [PREFIX/include]\n  --oldincludedir=DIR     C header files for non-gcc [/usr/include]\n  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]\n  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]\n  --infodir=DIR           info documentation [DATAROOTDIR/info]\n  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]\n  --mandir=DIR            man documentation [DATAROOTDIR/man]\n  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]\n  --htmldir=DIR           html documentation [DOCDIR]\n  --dvidir=DIR            dvi documentation [DOCDIR]\n  --pdfdir=DIR            pdf documentation [DOCDIR]\n  --psdir=DIR             ps documentation [DOCDIR]\n_ACEOF\n\n  cat <<\\_ACEOF\n\nSystem types:\n  --build=BUILD     configure for building on BUILD [guessed]\n  --host=HOST       cross-compile to build programs to run on HOST [BUILD]\n  --target=TARGET   configure for building compilers for TARGET [HOST]\n_ACEOF\nfi\n\nif test -n \"$ac_init_help\"; then\n\n  cat <<\\_ACEOF\n\nOptional Features:\n  --disable-option-checking  ignore unrecognized --enable/--with options\n  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)\n  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]\n--disable-o3     \t   Compile without -O3 optimization\n--enable-sum-send      Enable redundancy code sending\n--disable-mark     \t   Disable SO_MARK support on socket. Only available in Linux >=2.6.25\n--disable-syslog          Disable syslog output\n--enable-low-mem         Compile for low ram device\n--enable-json              JSON logging\n--enable-debugg     \t   Compile with verbose logging for debug\n--enable-self-testing         Compile with self-testing support\n--enable-client-only     \t   Client only version\n\nOptional Packages:\n  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]\n  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)\n--with-ssl-headers=DIR  Crypto Include files location\n--with-ssl-lib=DIR      Crypto Library location\n--with-lzo-headers=DIR     LZO Include files location\n--with-lzo-lib=DIR         LZO Library location\n--with-blowfish-headers=DIR     Blowfish Include files location\n--with-socks-lib=DIR         SOCKS Library location\n\nSome influential environment variables:\n  YACC        The `Yet Another Compiler Compiler' implementation to use.\n              Defaults to the first program found out of: `bison -y', `byacc',\n              `yacc'.\n  YFLAGS      The list of arguments that will be passed by default to $YACC.\n              This script will default YFLAGS to the empty string to avoid a\n              default value of `-d' given by some make applications.\n  CC          C compiler command\n  CFLAGS      C compiler flags\n  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a\n              nonstandard directory <lib dir>\n  LIBS        libraries to pass to the linker, e.g. -l<library>\n  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if\n              you have headers in a nonstandard directory <include dir>\n  CPP         C preprocessor\n\nUse these variables to override the choices made by `configure' or to help\nit to find libraries and programs with nonstandard names/locations.\n\nReport bugs to the package provider.\n_ACEOF\nac_status=$?\nfi\n\nif test \"$ac_init_help\" = \"recursive\"; then\n  # If there are subdirs, report their specific --help.\n  for ac_dir in : $ac_subdirs_all; do test \"x$ac_dir\" = x: && continue\n    test -d \"$ac_dir\" ||\n      { cd \"$srcdir\" && ac_pwd=`pwd` && srcdir=. && test -d \"$ac_dir\"; } ||\n      continue\n    ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`$as_echo \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`$as_echo \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n    cd \"$ac_dir\" || { ac_status=$?; continue; }\n    # Check for guested configure.\n    if test -f \"$ac_srcdir/configure.gnu\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure.gnu\" --help=recursive\n    elif test -f \"$ac_srcdir/configure\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure\" --help=recursive\n    else\n      $as_echo \"$as_me: WARNING: no configuration information is in $ac_dir\" >&2\n    fi || ac_status=$?\n    cd \"$ac_pwd\" || { ac_status=$?; break; }\n  done\nfi\n\ntest -n \"$ac_init_help\" && exit $ac_status\nif $ac_init_version; then\n  cat <<\\_ACEOF\nconfigure\ngenerated by GNU Autoconf 2.69\n\nCopyright (C) 2012 Free Software Foundation, Inc.\nThis configure script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\n_ACEOF\n  exit\nfi\n\n## ------------------------ ##\n## Autoconf initialization. ##\n## ------------------------ ##\n\n# ac_fn_c_try_compile LINENO\n# --------------------------\n# Try to compile conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext\n  if { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest.$ac_objext; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_compile\n\n# ac_fn_c_try_link LINENO\n# -----------------------\n# Try to link conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_link ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext conftest$ac_exeext\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest$ac_exeext && {\n\t test \"$cross_compiling\" = yes ||\n\t test -x conftest$ac_exeext\n       }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1\nfi\n  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information\n  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would\n  # interfere with the next link command; also delete a directory that is\n  # left behind by Apple's compiler.  We do this before executing the actions.\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_link\n\n# ac_fn_c_try_cpp LINENO\n# ----------------------\n# Try to preprocess conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_cpp ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_cpp conftest.$ac_ext\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_cpp conftest.$ac_ext\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } > conftest.i && {\n\t test -z \"$ac_c_preproc_warn_flag$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n    ac_retval=1\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_cpp\n\n# ac_fn_c_try_run LINENO\n# ----------------------\n# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes\n# that executables *can* be run.\nac_fn_c_try_run ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }; then :\n  ac_retval=0\nelse\n  $as_echo \"$as_me: program exited with status $ac_status\" >&5\n       $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n       ac_retval=$ac_status\nfi\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_run\n\n# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES\n# -------------------------------------------------------\n# Tests whether HEADER exists, giving a warning if it cannot be compiled using\n# the include files in INCLUDES and setting the cache variable VAR\n# accordingly.\nac_fn_c_check_header_mongrel ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  if eval \\${$3+:} false; then :\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\nelse\n  # Is the header compilable?\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking $2 usability\" >&5\n$as_echo_n \"checking $2 usability... \" >&6; }\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\n#include <$2>\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_header_compiler=yes\nelse\n  ac_header_compiler=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler\" >&5\n$as_echo \"$ac_header_compiler\" >&6; }\n\n# Is the header present?\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking $2 presence\" >&5\n$as_echo_n \"checking $2 presence... \" >&6; }\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <$2>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  ac_header_preproc=yes\nelse\n  ac_header_preproc=no\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc\" >&5\n$as_echo \"$ac_header_preproc\" >&6; }\n\n# So?  What about this header?\ncase $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((\n  yes:no: )\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!\" >&5\n$as_echo \"$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result\" >&5\n$as_echo \"$as_me: WARNING: $2: proceeding with the compiler's result\" >&2;}\n    ;;\n  no:yes:* )\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled\" >&5\n$as_echo \"$as_me: WARNING: $2: present but cannot be compiled\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?\" >&5\n$as_echo \"$as_me: WARNING: $2:     check for missing prerequisite headers?\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation\" >&5\n$as_echo \"$as_me: WARNING: $2: see the Autoconf documentation\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \\\"Present But Cannot Be Compiled\\\"\" >&5\n$as_echo \"$as_me: WARNING: $2:     section \\\"Present But Cannot Be Compiled\\\"\" >&2;}\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result\" >&5\n$as_echo \"$as_me: WARNING: $2: proceeding with the compiler's result\" >&2;}\n    ;;\nesac\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  eval \"$3=\\$ac_header_compiler\"\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_header_mongrel\n\n# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES\n# -------------------------------------------------------\n# Tests whether HEADER exists and can be compiled using the include files in\n# INCLUDES, setting the cache variable VAR accordingly.\nac_fn_c_check_header_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\n#include <$2>\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  eval \"$3=yes\"\nelse\n  eval \"$3=no\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_header_compile\n\n# ac_fn_c_check_func LINENO FUNC VAR\n# ----------------------------------\n# Tests whether FUNC exists, setting the cache variable VAR accordingly\nac_fn_c_check_func ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\n$as_echo_n \"checking for $2... \" >&6; }\nif eval \\${$3+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n/* Define $2 to an innocuous variant, in case <limits.h> declares $2.\n   For example, HP-UX 11i <limits.h> declares gettimeofday.  */\n#define $2 innocuous_$2\n\n/* System header to define __stub macros and hopefully few prototypes,\n    which can conflict with char $2 (); below.\n    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n    <limits.h> exists even on freestanding compilers.  */\n\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\n#undef $2\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar $2 ();\n/* The GNU C library defines this for functions which it implements\n    to always fail with ENOSYS.  Some functions are actually named\n    something starting with __ and the normal name is an alias.  */\n#if defined __stub_$2 || defined __stub___$2\nchoke me\n#endif\n\nint\nmain ()\n{\nreturn $2 ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  eval \"$3=yes\"\nelse\n  eval \"$3=no\"\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nfi\neval ac_res=\\$$3\n\t       { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\n$as_echo \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_func\ncat >config.log <<_ACEOF\nThis file contains any messages produced by compilers while\nrunning configure, to aid debugging if configure makes a mistake.\n\nIt was created by $as_me, which was\ngenerated by GNU Autoconf 2.69.  Invocation command line was\n\n  $ $0 $@\n\n_ACEOF\nexec 5>>config.log\n{\ncat <<_ASUNAME\n## --------- ##\n## Platform. ##\n## --------- ##\n\nhostname = `(hostname || uname -n) 2>/dev/null | sed 1q`\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`\n\n/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`\n/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`\n/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`\n/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`\n\n_ASUNAME\n\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    $as_echo \"PATH: $as_dir\"\n  done\nIFS=$as_save_IFS\n\n} >&5\n\ncat >&5 <<_ACEOF\n\n\n## ----------- ##\n## Core tests. ##\n## ----------- ##\n\n_ACEOF\n\n\n# Keep a trace of the command line.\n# Strip out --no-create and --no-recursion so they do not pile up.\n# Strip out --silent because we don't want to record it for future runs.\n# Also quote any args containing shell meta-characters.\n# Make two passes to allow for proper duplicate-argument suppression.\nac_configure_args=\nac_configure_args0=\nac_configure_args1=\nac_must_keep_next=false\nfor ac_pass in 1 2\ndo\n  for ac_arg\n  do\n    case $ac_arg in\n    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;\n    -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n    | -silent | --silent | --silen | --sile | --sil)\n      continue ;;\n    *\\'*)\n      ac_arg=`$as_echo \"$ac_arg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    esac\n    case $ac_pass in\n    1) as_fn_append ac_configure_args0 \" '$ac_arg'\" ;;\n    2)\n      as_fn_append ac_configure_args1 \" '$ac_arg'\"\n      if test $ac_must_keep_next = true; then\n\tac_must_keep_next=false # Got value, back to normal.\n      else\n\tcase $ac_arg in\n\t  *=* | --config-cache | -C | -disable-* | --disable-* \\\n\t  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \\\n\t  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \\\n\t  | -with-* | --with-* | -without-* | --without-* | --x)\n\t    case \"$ac_configure_args0 \" in\n\t      \"$ac_configure_args1\"*\" '$ac_arg' \"* ) continue ;;\n\t    esac\n\t    ;;\n\t  -* ) ac_must_keep_next=true ;;\n\tesac\n      fi\n      as_fn_append ac_configure_args \" '$ac_arg'\"\n      ;;\n    esac\n  done\ndone\n{ ac_configure_args0=; unset ac_configure_args0;}\n{ ac_configure_args1=; unset ac_configure_args1;}\n\n# When interrupted or exit'd, cleanup temporary files, and complete\n# config.log.  We remove comments because anyway the quotes in there\n# would cause problems or look ugly.\n# WARNING: Use '\\'' to represent an apostrophe within the trap.\n# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.\ntrap 'exit_status=$?\n  # Save into config.log some information that might help in debugging.\n  {\n    echo\n\n    $as_echo \"## ---------------- ##\n## Cache variables. ##\n## ---------------- ##\"\n    echo\n    # The following way of writing the cache mishandles newlines in values,\n(\n  for ac_var in `(set) 2>&1 | sed -n '\\''s/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'\\''`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\n$as_echo \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n  (set) 2>&1 |\n    case $as_nl`(ac_space='\\'' '\\''; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      sed -n \\\n\t\"s/'\\''/'\\''\\\\\\\\'\\'''\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\''\\\\2'\\''/p\"\n      ;; #(\n    *)\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n)\n    echo\n\n    $as_echo \"## ----------------- ##\n## Output variables. ##\n## ----------------- ##\"\n    echo\n    for ac_var in $ac_subst_vars\n    do\n      eval ac_val=\\$$ac_var\n      case $ac_val in\n      *\\'\\''*) ac_val=`$as_echo \"$ac_val\" | sed \"s/'\\''/'\\''\\\\\\\\\\\\\\\\'\\'''\\''/g\"`;;\n      esac\n      $as_echo \"$ac_var='\\''$ac_val'\\''\"\n    done | sort\n    echo\n\n    if test -n \"$ac_subst_files\"; then\n      $as_echo \"## ------------------- ##\n## File substitutions. ##\n## ------------------- ##\"\n      echo\n      for ac_var in $ac_subst_files\n      do\n\teval ac_val=\\$$ac_var\n\tcase $ac_val in\n\t*\\'\\''*) ac_val=`$as_echo \"$ac_val\" | sed \"s/'\\''/'\\''\\\\\\\\\\\\\\\\'\\'''\\''/g\"`;;\n\tesac\n\t$as_echo \"$ac_var='\\''$ac_val'\\''\"\n      done | sort\n      echo\n    fi\n\n    if test -s confdefs.h; then\n      $as_echo \"## ----------- ##\n## confdefs.h. ##\n## ----------- ##\"\n      echo\n      cat confdefs.h\n      echo\n    fi\n    test \"$ac_signal\" != 0 &&\n      $as_echo \"$as_me: caught signal $ac_signal\"\n    $as_echo \"$as_me: exit $exit_status\"\n  } >&5\n  rm -f core *.core core.conftest.* &&\n    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&\n    exit $exit_status\n' 0\nfor ac_signal in 1 2 13 15; do\n  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal\ndone\nac_signal=0\n\n# confdefs.h avoids OS command line length limits that DEFS can exceed.\nrm -f -r conftest* confdefs.h\n\n$as_echo \"/* confdefs.h */\" > confdefs.h\n\n# Predefined preprocessor variables.\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_NAME \"$PACKAGE_NAME\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_VERSION \"$PACKAGE_VERSION\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_STRING \"$PACKAGE_STRING\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"\n_ACEOF\n\ncat >>confdefs.h <<_ACEOF\n#define PACKAGE_URL \"$PACKAGE_URL\"\n_ACEOF\n\n\n# Let the site file select an alternate cache file if it wants to.\n# Prefer an explicitly selected file to automatically selected ones.\nac_site_file1=NONE\nac_site_file2=NONE\nif test -n \"$CONFIG_SITE\"; then\n  # We do not want a PATH search for config.site.\n  case $CONFIG_SITE in #((\n    -*)  ac_site_file1=./$CONFIG_SITE;;\n    */*) ac_site_file1=$CONFIG_SITE;;\n    *)   ac_site_file1=./$CONFIG_SITE;;\n  esac\nelif test \"x$prefix\" != xNONE; then\n  ac_site_file1=$prefix/share/config.site\n  ac_site_file2=$prefix/etc/config.site\nelse\n  ac_site_file1=$ac_default_prefix/share/config.site\n  ac_site_file2=$ac_default_prefix/etc/config.site\nfi\nfor ac_site_file in \"$ac_site_file1\" \"$ac_site_file2\"\ndo\n  test \"x$ac_site_file\" = xNONE && continue\n  if test /dev/null != \"$ac_site_file\" && test -r \"$ac_site_file\"; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file\" >&5\n$as_echo \"$as_me: loading site script $ac_site_file\" >&6;}\n    sed 's/^/| /' \"$ac_site_file\" >&5\n    . \"$ac_site_file\" \\\n      || { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"failed to load site script $ac_site_file\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n  fi\ndone\n\nif test -r \"$cache_file\"; then\n  # Some versions of bash will fail to source /dev/null (special files\n  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.\n  if test /dev/null != \"$cache_file\" && test -f \"$cache_file\"; then\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: loading cache $cache_file\" >&5\n$as_echo \"$as_me: loading cache $cache_file\" >&6;}\n    case $cache_file in\n      [\\\\/]* | ?:[\\\\/]* ) . \"$cache_file\";;\n      *)                      . \"./$cache_file\";;\n    esac\n  fi\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: creating cache $cache_file\" >&5\n$as_echo \"$as_me: creating cache $cache_file\" >&6;}\n  >$cache_file\nfi\n\n# Check that the precious variables saved in the cache have kept the same\n# value.\nac_cache_corrupted=false\nfor ac_var in $ac_precious_vars; do\n  eval ac_old_set=\\$ac_cv_env_${ac_var}_set\n  eval ac_new_set=\\$ac_env_${ac_var}_set\n  eval ac_old_val=\\$ac_cv_env_${ac_var}_value\n  eval ac_new_val=\\$ac_env_${ac_var}_value\n  case $ac_old_set,$ac_new_set in\n    set,)\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' was set to \\`$ac_old_val' in the previous run\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' was set to \\`$ac_old_val' in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,set)\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' was not set in the previous run\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' was not set in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,);;\n    *)\n      if test \"x$ac_old_val\" != \"x$ac_new_val\"; then\n\t# differences in whitespace do not lead to failure.\n\tac_old_val_w=`echo x $ac_old_val`\n\tac_new_val_w=`echo x $ac_new_val`\n\tif test \"$ac_old_val_w\" != \"$ac_new_val_w\"; then\n\t  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' has changed since the previous run:\" >&5\n$as_echo \"$as_me: error: \\`$ac_var' has changed since the previous run:\" >&2;}\n\t  ac_cache_corrupted=:\n\telse\n\t  { $as_echo \"$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \\`$ac_var' since the previous run:\" >&5\n$as_echo \"$as_me: warning: ignoring whitespace changes in \\`$ac_var' since the previous run:\" >&2;}\n\t  eval $ac_var=\\$ac_old_val\n\tfi\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}:   former value:  \\`$ac_old_val'\" >&5\n$as_echo \"$as_me:   former value:  \\`$ac_old_val'\" >&2;}\n\t{ $as_echo \"$as_me:${as_lineno-$LINENO}:   current value: \\`$ac_new_val'\" >&5\n$as_echo \"$as_me:   current value: \\`$ac_new_val'\" >&2;}\n      fi;;\n  esac\n  # Pass precious variables to config.status.\n  if test \"$ac_new_set\" = set; then\n    case $ac_new_val in\n    *\\'*) ac_arg=$ac_var=`$as_echo \"$ac_new_val\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    *) ac_arg=$ac_var=$ac_new_val ;;\n    esac\n    case \" $ac_configure_args \" in\n      *\" '$ac_arg' \"*) ;; # Avoid dups.  Use of quotes ensures accuracy.\n      *) as_fn_append ac_configure_args \" '$ac_arg'\" ;;\n    esac\n  fi\ndone\nif $ac_cache_corrupted; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build\" >&5\n$as_echo \"$as_me: error: changes in the environment can compromise the build\" >&2;}\n  as_fn_error $? \"run \\`make distclean' and/or \\`rm $cache_file' and start over\" \"$LINENO\" 5\nfi\n## -------------------- ##\n## Main body of script. ##\n## -------------------- ##\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\nac_config_headers=\"$ac_config_headers config.h\"\n\n\nCFLAGS=\"$CFLAGS -std=gnu99\"\n\n# Check whether --enable-o3 was given.\nif test \"${enable_o3+set}\" = set; then :\n  enableval=$enable_o3; O3=$enableval\nelse\n  O3=yes\n\nfi\n\n\n# Check whether --enable-sum-send was given.\nif test \"${enable_sum_send+set}\" = set; then :\n  enableval=$enable_sum_send; SUM_SEND=$enableval\nelse\n  SUM_SEND=no\n\nfi\n\n\n# Check whether --enable-mark was given.\nif test \"${enable_mark+set}\" = set; then :\n  enableval=$enable_mark; MARK=$enableval\nelse\n  MARK=yes\n\nfi\n\n\n# Check whether --enable-syslog was given.\nif test \"${enable_syslog+set}\" = set; then :\n  enableval=$enable_syslog; SYSLOG=$enableval\nelse\n  SYSLOG=yes\n\nfi\n\n\n# Check whether --enable-low-mem was given.\nif test \"${enable_low_mem+set}\" = set; then :\n  enableval=$enable_low_mem; LOW_MEM=$enableval\nelse\n  LOW_MEM=no\n\nfi\n\n\n# Check whether --enable-json was given.\nif test \"${enable_json+set}\" = set; then :\n  enableval=$enable_json; JSON=$enableval\nelse\n  JSON=no\n\nfi\n\n\n# Check whether --enable-debugg was given.\nif test \"${enable_debugg+set}\" = set; then :\n  enableval=$enable_debugg; DEBUGG=$enableval\nelse\n  DEBUGG=no\n\nfi\n\n\n# Check whether --enable-self-testing was given.\nif test \"${enable_self_testing+set}\" = set; then :\n  enableval=$enable_self_testing; SELFTESTING=$enableval\nelse\n  SELFTESTING=no\n\nfi\n\n\n# Check whether --enable-client-only was given.\nif test \"${enable_client_only+set}\" = set; then :\n  enableval=$enable_client_only; CLIENTONLY=$enableval\nelse\n  CLIENTONLY=no\n\nfi\n\n\n\n# Check whether --with-ssl-headers was given.\nif test \"${with_ssl_headers+set}\" = set; then :\n  withval=$with_ssl_headers; SSL_HDR_DIR=\"$withval\"\n   CPPFLAGS=\"$CPPFLAGS -I$withval\"\n\nfi\n\n\n# Check whether --with-ssl-lib was given.\nif test \"${with_ssl_lib+set}\" = set; then :\n  withval=$with_ssl_lib; LIBS=\"$LIBS -L$withval\"\n\nfi\n\n\n\n# Check whether --with-lzo-headers was given.\nif test \"${with_lzo_headers+set}\" = set; then :\n  withval=$with_lzo_headers; LZO_HDR_DIR=\"$withval\"\n\nfi\n\n\n# Check whether --with-lzo-lib was given.\nif test \"${with_lzo_lib+set}\" = set; then :\n  withval=$with_lzo_lib; LIBS=\"$LIBS -L$withval\"\n\nfi\n\n\n\n# Check whether --with-blowfish-headers was given.\nif test \"${with_blowfish_headers+set}\" = set; then :\n  withval=$with_blowfish_headers; BLOWFISH_HDR_DIR=\"$withval\"\n\nfi\n\n\n\n# Check whether --with-socks-lib was given.\nif test \"${with_socks_lib+set}\" = set; then :\n  withval=$with_socks_lib; LIBS=\"$LIBS -L$withval\"\n\nfi\n\n\nac_aux_dir=\nfor ac_dir in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"; do\n  if test -f \"$ac_dir/install-sh\"; then\n    ac_aux_dir=$ac_dir\n    ac_install_sh=\"$ac_aux_dir/install-sh -c\"\n    break\n  elif test -f \"$ac_dir/install.sh\"; then\n    ac_aux_dir=$ac_dir\n    ac_install_sh=\"$ac_aux_dir/install.sh -c\"\n    break\n  elif test -f \"$ac_dir/shtool\"; then\n    ac_aux_dir=$ac_dir\n    ac_install_sh=\"$ac_aux_dir/shtool install -c\"\n    break\n  fi\ndone\nif test -z \"$ac_aux_dir\"; then\n  as_fn_error $? \"cannot find install-sh, install.sh, or shtool in \\\"$srcdir\\\" \\\"$srcdir/..\\\" \\\"$srcdir/../..\\\"\" \"$LINENO\" 5\nfi\n\n# These three variables are undocumented and unsupported,\n# and are intended to be withdrawn in a future Autoconf release.\n# They can cause serious problems if a builder's source tree is in a directory\n# whose full name contains unusual characters.\nac_config_guess=\"$SHELL $ac_aux_dir/config.guess\"  # Please don't use this var.\nac_config_sub=\"$SHELL $ac_aux_dir/config.sub\"  # Please don't use this var.\nac_configure=\"$SHELL $ac_aux_dir/configure\"  # Please don't use this var.\n\n\n# Make sure we can run config.sub.\n$SHELL \"$ac_aux_dir/config.sub\" sun4 >/dev/null 2>&1 ||\n  as_fn_error $? \"cannot run $SHELL $ac_aux_dir/config.sub\" \"$LINENO\" 5\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking build system type\" >&5\n$as_echo_n \"checking build system type... \" >&6; }\nif ${ac_cv_build+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_build_alias=$build_alias\ntest \"x$ac_build_alias\" = x &&\n  ac_build_alias=`$SHELL \"$ac_aux_dir/config.guess\"`\ntest \"x$ac_build_alias\" = x &&\n  as_fn_error $? \"cannot guess build type; you must specify one\" \"$LINENO\" 5\nac_cv_build=`$SHELL \"$ac_aux_dir/config.sub\" $ac_build_alias` ||\n  as_fn_error $? \"$SHELL $ac_aux_dir/config.sub $ac_build_alias failed\" \"$LINENO\" 5\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_build\" >&5\n$as_echo \"$ac_cv_build\" >&6; }\ncase $ac_cv_build in\n*-*-*) ;;\n*) as_fn_error $? \"invalid value of canonical build\" \"$LINENO\" 5;;\nesac\nbuild=$ac_cv_build\nac_save_IFS=$IFS; IFS='-'\nset x $ac_cv_build\nshift\nbuild_cpu=$1\nbuild_vendor=$2\nshift; shift\n# Remember, the first character of IFS is used to create $*,\n# except with old shells:\nbuild_os=$*\nIFS=$ac_save_IFS\ncase $build_os in *\\ *) build_os=`echo \"$build_os\" | sed 's/ /-/g'`;; esac\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking host system type\" >&5\n$as_echo_n \"checking host system type... \" >&6; }\nif ${ac_cv_host+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test \"x$host_alias\" = x; then\n  ac_cv_host=$ac_cv_build\nelse\n  ac_cv_host=`$SHELL \"$ac_aux_dir/config.sub\" $host_alias` ||\n    as_fn_error $? \"$SHELL $ac_aux_dir/config.sub $host_alias failed\" \"$LINENO\" 5\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_host\" >&5\n$as_echo \"$ac_cv_host\" >&6; }\ncase $ac_cv_host in\n*-*-*) ;;\n*) as_fn_error $? \"invalid value of canonical host\" \"$LINENO\" 5;;\nesac\nhost=$ac_cv_host\nac_save_IFS=$IFS; IFS='-'\nset x $ac_cv_host\nshift\nhost_cpu=$1\nhost_vendor=$2\nshift; shift\n# Remember, the first character of IFS is used to create $*,\n# except with old shells:\nhost_os=$*\nIFS=$ac_save_IFS\ncase $host_os in *\\ *) host_os=`echo \"$host_os\" | sed 's/ /-/g'`;; esac\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking target system type\" >&5\n$as_echo_n \"checking target system type... \" >&6; }\nif ${ac_cv_target+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test \"x$target_alias\" = x; then\n  ac_cv_target=$ac_cv_host\nelse\n  ac_cv_target=`$SHELL \"$ac_aux_dir/config.sub\" $target_alias` ||\n    as_fn_error $? \"$SHELL $ac_aux_dir/config.sub $target_alias failed\" \"$LINENO\" 5\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_target\" >&5\n$as_echo \"$ac_cv_target\" >&6; }\ncase $ac_cv_target in\n*-*-*) ;;\n*) as_fn_error $? \"invalid value of canonical target\" \"$LINENO\" 5;;\nesac\ntarget=$ac_cv_target\nac_save_IFS=$IFS; IFS='-'\nset x $ac_cv_target\nshift\ntarget_cpu=$1\ntarget_vendor=$2\nshift; shift\n# Remember, the first character of IFS is used to create $*,\n# except with old shells:\ntarget_os=$*\nIFS=$ac_save_IFS\ncase $target_os in *\\ *) target_os=`echo \"$target_os\" | sed 's/ /-/g'`;; esac\n\n\n# The aliases save the names the user supplied, while $host etc.\n# will get canonicalized.\ntest -n \"$target_alias\" &&\n  test \"$program_prefix$program_suffix$program_transform_name\" = \\\n    NONENONEs,x,x, &&\n  program_prefix=${target_alias}-\n\n\nfor ac_prog in 'bison -y' byacc\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_YACC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$YACC\"; then\n  ac_cv_prog_YACC=\"$YACC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_YACC=\"$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nYACC=$ac_cv_prog_YACC\nif test -n \"$YACC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $YACC\" >&5\n$as_echo \"$YACC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  test -n \"$YACC\" && break\ndone\ntest -n \"$YACC\" || YACC=\"yacc\"\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}gcc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"gcc\", so it can be a program name with args.\nset dummy gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nif test -z \"$CC\"; then\n          if test -n \"$ac_tool_prefix\"; then\n    # Extract the first word of \"${ac_tool_prefix}cc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  fi\nfi\nif test -z \"$CC\"; then\n  # Extract the first word of \"cc\", so it can be a program name with args.\nset dummy cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\n  ac_prog_rejected=no\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    if test \"$as_dir/$ac_word$ac_exec_ext\" = \"/usr/ucb/cc\"; then\n       ac_prog_rejected=yes\n       continue\n     fi\n    ac_cv_prog_CC=\"cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nif test $ac_prog_rejected = yes; then\n  # We found a bogon in the path, so make sure we never use it.\n  set dummy $ac_cv_prog_CC\n  shift\n  if test $# != 0; then\n    # We chose a different compiler from the bogus one.\n    # However, it has the same basename, so the bogon will be chosen\n    # first if we set CC to just the basename; use the full file name.\n    shift\n    ac_cv_prog_CC=\"$as_dir/$ac_word${1+' '}$@\"\n  fi\nfi\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  for ac_prog in cl.exe\n  do\n    # Extract the first word of \"$ac_tool_prefix$ac_prog\", so it can be a program name with args.\nset dummy $ac_tool_prefix$ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"$ac_tool_prefix$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n    test -n \"$CC\" && break\n  done\nfi\nif test -z \"$CC\"; then\n  ac_ct_CC=$CC\n  for ac_prog in cl.exe\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  test -n \"$ac_ct_CC\" && break\ndone\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nfi\n\nfi\n\n\ntest -z \"$CC\" && { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"no acceptable C compiler found in \\$PATH\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n\n# Provide some information about the compiler.\n$as_echo \"$as_me:${as_lineno-$LINENO}: checking for C compiler version\" >&5\nset X $ac_compile\nac_compiler=$2\nfor ac_option in --version -v -V -qversion; do\n  { { ac_try=\"$ac_compiler $ac_option >&5\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compiler $ac_option >&5\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    sed '10a\\\n... rest of stderr output deleted ...\n         10q' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n  fi\n  rm -f conftest.er1 conftest.err\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\ndone\n\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files a.out a.out.dSYM a.exe b.out\"\n# Try to create an executable without -o first, disregard a.out.\n# It will help us diagnose broken compilers, and finding out an intuition\n# of exeext.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether the C compiler works\" >&5\n$as_echo_n \"checking whether the C compiler works... \" >&6; }\nac_link_default=`$as_echo \"$ac_link\" | sed 's/ -o *conftest[^ ]*//'`\n\n# The possible output files:\nac_files=\"a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*\"\n\nac_rmfiles=\nfor ac_file in $ac_files\ndo\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    * ) ac_rmfiles=\"$ac_rmfiles $ac_file\";;\n  esac\ndone\nrm -f $ac_rmfiles\n\nif { { ac_try=\"$ac_link_default\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link_default\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.\n# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'\n# in a Makefile.  We should not override ac_cv_exeext if it was cached,\n# so that the user can short-circuit this test for compilers unknown to\n# Autoconf.\nfor ac_file in $ac_files ''\ndo\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )\n\t;;\n    [ab].out )\n\t# We found the default executable, but exeext='' is most\n\t# certainly right.\n\tbreak;;\n    *.* )\n\tif test \"${ac_cv_exeext+set}\" = set && test \"$ac_cv_exeext\" != no;\n\tthen :; else\n\t   ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\tfi\n\t# We set ac_cv_exeext here because the later test for it is not\n\t# safe: cross compilers may not add the suffix if given an `-o'\n\t# argument, so we may need to know it at that point already.\n\t# Even if this section looks crufty: it has the advantage of\n\t# actually working.\n\tbreak;;\n    * )\n\tbreak;;\n  esac\ndone\ntest \"$ac_cv_exeext\" = no && ac_cv_exeext=\n\nelse\n  ac_file=''\nfi\nif test -z \"$ac_file\"; then :\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\n$as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error 77 \"C compiler cannot create executables\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\n$as_echo \"yes\" >&6; }\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name\" >&5\n$as_echo_n \"checking for C compiler default output file name... \" >&6; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_file\" >&5\n$as_echo \"$ac_file\" >&6; }\nac_exeext=$ac_cv_exeext\n\nrm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out\nac_clean_files=$ac_clean_files_save\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for suffix of executables\" >&5\n$as_echo_n \"checking for suffix of executables... \" >&6; }\nif { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  # If both `conftest.exe' and `conftest' are `present' (well, observable)\n# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will\n# work properly (i.e., refer to `conftest.exe'), while it won't with\n# `rm'.\nfor ac_file in conftest.exe conftest conftest.*; do\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    *.* ) ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\t  break;;\n    * ) break;;\n  esac\ndone\nelse\n  { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of executables: cannot compile and link\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\nrm -f conftest conftest$ac_cv_exeext\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext\" >&5\n$as_echo \"$ac_cv_exeext\" >&6; }\n\nrm -f conftest.$ac_ext\nEXEEXT=$ac_cv_exeext\nac_exeext=$EXEEXT\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdio.h>\nint\nmain ()\n{\nFILE *f = fopen (\"conftest.out\", \"w\");\n return ferror (f) || fclose (f) != 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files=\"$ac_clean_files conftest.out\"\n# Check that the compiler produces executables we can run.  If not, either\n# the compiler is broken, or we cross compile.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling\" >&5\n$as_echo_n \"checking whether we are cross compiling... \" >&6; }\nif test \"$cross_compiling\" != yes; then\n  { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\n  if { ac_try='./conftest$ac_cv_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }; then\n    cross_compiling=no\n  else\n    if test \"$cross_compiling\" = maybe; then\n\tcross_compiling=yes\n    else\n\t{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot run C compiled programs.\nIf you meant to cross compile, use \\`--host'.\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n    fi\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $cross_compiling\" >&5\n$as_echo \"$cross_compiling\" >&6; }\n\nrm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out\nac_clean_files=$ac_clean_files_save\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for suffix of object files\" >&5\n$as_echo_n \"checking for suffix of object files... \" >&6; }\nif ${ac_cv_objext+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nrm -f conftest.o conftest.obj\nif { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; then :\n  for ac_file in conftest.o conftest.obj conftest.*; do\n  test -f \"$ac_file\" || continue;\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;\n    *) ac_cv_objext=`expr \"$ac_file\" : '.*\\.\\(.*\\)'`\n       break;;\n  esac\ndone\nelse\n  $as_echo \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of object files: cannot compile\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\nrm -f conftest.$ac_cv_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext\" >&5\n$as_echo \"$ac_cv_objext\" >&6; }\nOBJEXT=$ac_cv_objext\nac_objext=$OBJEXT\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler\" >&5\n$as_echo_n \"checking whether we are using the GNU C compiler... \" >&6; }\nif ${ac_cv_c_compiler_gnu+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n#ifndef __GNUC__\n       choke me\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_compiler_gnu=yes\nelse\n  ac_compiler_gnu=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nac_cv_c_compiler_gnu=$ac_compiler_gnu\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu\" >&5\n$as_echo \"$ac_cv_c_compiler_gnu\" >&6; }\nif test $ac_compiler_gnu = yes; then\n  GCC=yes\nelse\n  GCC=\nfi\nac_test_CFLAGS=${CFLAGS+set}\nac_save_CFLAGS=$CFLAGS\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g\" >&5\n$as_echo_n \"checking whether $CC accepts -g... \" >&6; }\nif ${ac_cv_prog_cc_g+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_save_c_werror_flag=$ac_c_werror_flag\n   ac_c_werror_flag=yes\n   ac_cv_prog_cc_g=no\n   CFLAGS=\"-g\"\n   cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nelse\n  CFLAGS=\"\"\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n\nelse\n  ac_c_werror_flag=$ac_save_c_werror_flag\n\t CFLAGS=\"-g\"\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n   ac_c_werror_flag=$ac_save_c_werror_flag\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g\" >&5\n$as_echo \"$ac_cv_prog_cc_g\" >&6; }\nif test \"$ac_test_CFLAGS\" = set; then\n  CFLAGS=$ac_save_CFLAGS\nelif test $ac_cv_prog_cc_g = yes; then\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-g -O2\"\n  else\n    CFLAGS=\"-g\"\n  fi\nelse\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-O2\"\n  else\n    CFLAGS=\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89\" >&5\n$as_echo_n \"checking for $CC option to accept ISO C89... \" >&6; }\nif ${ac_cv_prog_cc_c89+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_cv_prog_cc_c89=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdarg.h>\n#include <stdio.h>\nstruct stat;\n/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */\nstruct buf { int x; };\nFILE * (*rcsopen) (struct buf *, struct stat *, int);\nstatic char *e (p, i)\n     char **p;\n     int i;\n{\n  return p[i];\n}\nstatic char *f (char * (*g) (char **, int), char **p, ...)\n{\n  char *s;\n  va_list v;\n  va_start (v,p);\n  s = g (p, va_arg (v,int));\n  va_end (v);\n  return s;\n}\n\n/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has\n   function prototypes and stuff, but not '\\xHH' hex character constants.\n   These don't provoke an error unfortunately, instead are silently treated\n   as 'x'.  The following induces an error, until -std is added to get\n   proper ANSI mode.  Curiously '\\x00'!='x' always comes out true, for an\n   array size at least.  It's necessary to write '\\x00'==0 to get something\n   that's true only with -std.  */\nint osf4_cc_array ['\\x00' == 0 ? 1 : -1];\n\n/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters\n   inside strings and character constants.  */\n#define FOO(x) 'x'\nint xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];\n\nint test (int i, double x);\nstruct s1 {int (*f) (int a);};\nstruct s2 {int (*f) (double a);};\nint pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);\nint argc;\nchar **argv;\nint\nmain ()\n{\nreturn f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \\\n\t-Ae \"-Aa -D_HPUX_SOURCE\" \"-Xc -D__EXTENSIONS__\"\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_c89=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext\n  test \"x$ac_cv_prog_cc_c89\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC\n\nfi\n# AC_CACHE_VAL\ncase \"x$ac_cv_prog_cc_c89\" in\n  x)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\n$as_echo \"none needed\" >&6; } ;;\n  xno)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\n$as_echo \"unsupported\" >&6; } ;;\n  *)\n    CC=\"$CC $ac_cv_prog_cc_c89\"\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89\" >&5\n$as_echo \"$ac_cv_prog_cc_c89\" >&6; } ;;\nesac\nif test \"x$ac_cv_prog_cc_c89\" != xno; then :\n\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\nfor ac_prog in flex lex\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_LEX+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$LEX\"; then\n  ac_cv_prog_LEX=\"$LEX\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_LEX=\"$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nLEX=$ac_cv_prog_LEX\nif test -n \"$LEX\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $LEX\" >&5\n$as_echo \"$LEX\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  test -n \"$LEX\" && break\ndone\ntest -n \"$LEX\" || LEX=\":\"\n\nif test \"x$LEX\" != \"x:\"; then\n  cat >conftest.l <<_ACEOF\n%%\na { ECHO; }\nb { REJECT; }\nc { yymore (); }\nd { yyless (1); }\ne { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument.  */\n    yyless ((input () != 0)); }\nf { unput (yytext[0]); }\n. { BEGIN INITIAL; }\n%%\n#ifdef YYTEXT_POINTER\nextern char *yytext;\n#endif\nint\nmain (void)\n{\n  return ! yylex () + ! yywrap ();\n}\n_ACEOF\n{ { ac_try=\"$LEX conftest.l\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$LEX conftest.l\") 2>&5\n  ac_status=$?\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking lex output file root\" >&5\n$as_echo_n \"checking lex output file root... \" >&6; }\nif ${ac_cv_prog_lex_root+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\nif test -f lex.yy.c; then\n  ac_cv_prog_lex_root=lex.yy\nelif test -f lexyy.c; then\n  ac_cv_prog_lex_root=lexyy\nelse\n  as_fn_error $? \"cannot find output from $LEX; giving up\" \"$LINENO\" 5\nfi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root\" >&5\n$as_echo \"$ac_cv_prog_lex_root\" >&6; }\nLEX_OUTPUT_ROOT=$ac_cv_prog_lex_root\n\nif test -z \"${LEXLIB+set}\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: checking lex library\" >&5\n$as_echo_n \"checking lex library... \" >&6; }\nif ${ac_cv_lib_lex+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n\n    ac_save_LIBS=$LIBS\n    ac_cv_lib_lex='none needed'\n    for ac_lib in '' -lfl -ll; do\n      LIBS=\"$ac_lib $ac_save_LIBS\"\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n`cat $LEX_OUTPUT_ROOT.c`\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_lib_lex=$ac_lib\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\n      test \"$ac_cv_lib_lex\" != 'none needed' && break\n    done\n    LIBS=$ac_save_LIBS\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex\" >&5\n$as_echo \"$ac_cv_lib_lex\" >&6; }\n  test \"$ac_cv_lib_lex\" != 'none needed' && LEXLIB=$ac_cv_lib_lex\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer\" >&5\n$as_echo_n \"checking whether yytext is a pointer... \" >&6; }\nif ${ac_cv_prog_lex_yytext_pointer+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  # POSIX says lex can declare yytext either as a pointer or an array; the\n# default is implementation-dependent.  Figure out which it is, since\n# not all implementations provide the %pointer and %array declarations.\nac_cv_prog_lex_yytext_pointer=no\nac_save_LIBS=$LIBS\nLIBS=\"$LEXLIB $ac_save_LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n  #define YYTEXT_POINTER 1\n`cat $LEX_OUTPUT_ROOT.c`\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_prog_lex_yytext_pointer=yes\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_save_LIBS\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer\" >&5\n$as_echo \"$ac_cv_prog_lex_yytext_pointer\" >&6; }\nif test $ac_cv_prog_lex_yytext_pointer = yes; then\n\n$as_echo \"#define YYTEXT_POINTER 1\" >>confdefs.h\n\nfi\nrm -f conftest.l $LEX_OUTPUT_ROOT.c\n\nfi\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}gcc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"gcc\", so it can be a program name with args.\nset dummy gcc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"gcc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nif test -z \"$CC\"; then\n          if test -n \"$ac_tool_prefix\"; then\n    # Extract the first word of \"${ac_tool_prefix}cc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  fi\nfi\nif test -z \"$CC\"; then\n  # Extract the first word of \"cc\", so it can be a program name with args.\nset dummy cc; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\n  ac_prog_rejected=no\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    if test \"$as_dir/$ac_word$ac_exec_ext\" = \"/usr/ucb/cc\"; then\n       ac_prog_rejected=yes\n       continue\n     fi\n    ac_cv_prog_CC=\"cc\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nif test $ac_prog_rejected = yes; then\n  # We found a bogon in the path, so make sure we never use it.\n  set dummy $ac_cv_prog_CC\n  shift\n  if test $# != 0; then\n    # We chose a different compiler from the bogus one.\n    # However, it has the same basename, so the bogon will be chosen\n    # first if we set CC to just the basename; use the full file name.\n    shift\n    ac_cv_prog_CC=\"$as_dir/$ac_word${1+' '}$@\"\n  fi\nfi\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  for ac_prog in cl.exe\n  do\n    # Extract the first word of \"$ac_tool_prefix$ac_prog\", so it can be a program name with args.\nset dummy $ac_tool_prefix$ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"$ac_tool_prefix$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\n$as_echo \"$CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n    test -n \"$CC\" && break\n  done\nfi\nif test -z \"$CC\"; then\n  ac_ct_CC=$CC\n  for ac_prog in cl.exe\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\n$as_echo_n \"checking for $ac_word... \" >&6; }\nif ${ac_cv_prog_ac_ct_CC+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir/$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"$ac_prog\"\n    $as_echo \"$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\n$as_echo \"$ac_ct_CC\" >&6; }\nelse\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\n$as_echo \"no\" >&6; }\nfi\n\n\n  test -n \"$ac_ct_CC\" && break\ndone\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\n$as_echo \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nfi\n\nfi\n\n\ntest -z \"$CC\" && { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"no acceptable C compiler found in \\$PATH\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n\n# Provide some information about the compiler.\n$as_echo \"$as_me:${as_lineno-$LINENO}: checking for C compiler version\" >&5\nset X $ac_compile\nac_compiler=$2\nfor ac_option in --version -v -V -qversion; do\n  { { ac_try=\"$ac_compiler $ac_option >&5\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\n$as_echo \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compiler $ac_option >&5\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    sed '10a\\\n... rest of stderr output deleted ...\n         10q' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n  fi\n  rm -f conftest.er1 conftest.err\n  $as_echo \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\ndone\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler\" >&5\n$as_echo_n \"checking whether we are using the GNU C compiler... \" >&6; }\nif ${ac_cv_c_compiler_gnu+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n#ifndef __GNUC__\n       choke me\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_compiler_gnu=yes\nelse\n  ac_compiler_gnu=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nac_cv_c_compiler_gnu=$ac_compiler_gnu\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu\" >&5\n$as_echo \"$ac_cv_c_compiler_gnu\" >&6; }\nif test $ac_compiler_gnu = yes; then\n  GCC=yes\nelse\n  GCC=\nfi\nac_test_CFLAGS=${CFLAGS+set}\nac_save_CFLAGS=$CFLAGS\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g\" >&5\n$as_echo_n \"checking whether $CC accepts -g... \" >&6; }\nif ${ac_cv_prog_cc_g+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_save_c_werror_flag=$ac_c_werror_flag\n   ac_c_werror_flag=yes\n   ac_cv_prog_cc_g=no\n   CFLAGS=\"-g\"\n   cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nelse\n  CFLAGS=\"\"\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n\nelse\n  ac_c_werror_flag=$ac_save_c_werror_flag\n\t CFLAGS=\"-g\"\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_g=yes\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n   ac_c_werror_flag=$ac_save_c_werror_flag\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g\" >&5\n$as_echo \"$ac_cv_prog_cc_g\" >&6; }\nif test \"$ac_test_CFLAGS\" = set; then\n  CFLAGS=$ac_save_CFLAGS\nelif test $ac_cv_prog_cc_g = yes; then\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-g -O2\"\n  else\n    CFLAGS=\"-g\"\n  fi\nelse\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-O2\"\n  else\n    CFLAGS=\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89\" >&5\n$as_echo_n \"checking for $CC option to accept ISO C89... \" >&6; }\nif ${ac_cv_prog_cc_c89+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_cv_prog_cc_c89=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdarg.h>\n#include <stdio.h>\nstruct stat;\n/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */\nstruct buf { int x; };\nFILE * (*rcsopen) (struct buf *, struct stat *, int);\nstatic char *e (p, i)\n     char **p;\n     int i;\n{\n  return p[i];\n}\nstatic char *f (char * (*g) (char **, int), char **p, ...)\n{\n  char *s;\n  va_list v;\n  va_start (v,p);\n  s = g (p, va_arg (v,int));\n  va_end (v);\n  return s;\n}\n\n/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has\n   function prototypes and stuff, but not '\\xHH' hex character constants.\n   These don't provoke an error unfortunately, instead are silently treated\n   as 'x'.  The following induces an error, until -std is added to get\n   proper ANSI mode.  Curiously '\\x00'!='x' always comes out true, for an\n   array size at least.  It's necessary to write '\\x00'==0 to get something\n   that's true only with -std.  */\nint osf4_cc_array ['\\x00' == 0 ? 1 : -1];\n\n/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters\n   inside strings and character constants.  */\n#define FOO(x) 'x'\nint xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];\n\nint test (int i, double x);\nstruct s1 {int (*f) (int a);};\nstruct s2 {int (*f) (double a);};\nint pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);\nint argc;\nchar **argv;\nint\nmain ()\n{\nreturn f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \\\n\t-Ae \"-Aa -D_HPUX_SOURCE\" \"-Xc -D__EXTENSIONS__\"\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_prog_cc_c89=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext\n  test \"x$ac_cv_prog_cc_c89\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC\n\nfi\n# AC_CACHE_VAL\ncase \"x$ac_cv_prog_cc_c89\" in\n  x)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\n$as_echo \"none needed\" >&6; } ;;\n  xno)\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\n$as_echo \"unsupported\" >&6; } ;;\n  *)\n    CC=\"$CC $ac_cv_prog_cc_c89\"\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89\" >&5\n$as_echo \"$ac_cv_prog_cc_c89\" >&6; } ;;\nesac\nif test \"x$ac_cv_prog_cc_c89\" != xno; then :\n\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n# Find a good install program.  We prefer a C program (faster),\n# so one script is as good as another.  But avoid the broken or\n# incompatible versions:\n# SysV /etc/install, /usr/sbin/install\n# SunOS /usr/etc/install\n# IRIX /sbin/install\n# AIX /bin/install\n# AmigaOS /C/install, which installs bootblocks on floppy discs\n# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag\n# AFS /usr/afsws/bin/install, which mishandles nonexistent args\n# SVR4 /usr/ucb/install, which tries to use the nonexistent group \"staff\"\n# OS/2's system install, which has a completely different semantic\n# ./install, which can be erroneously created by make from ./install.sh.\n# Reject install programs that cannot install multiple files.\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install\" >&5\n$as_echo_n \"checking for a BSD-compatible install... \" >&6; }\nif test -z \"$INSTALL\"; then\nif ${ac_cv_path_install+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    # Account for people who put trailing slashes in PATH elements.\ncase $as_dir/ in #((\n  ./ | .// | /[cC]/* | \\\n  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \\\n  ?:[\\\\/]os2[\\\\/]install[\\\\/]* | ?:[\\\\/]OS2[\\\\/]INSTALL[\\\\/]* | \\\n  /usr/ucb/* ) ;;\n  *)\n    # OSF1 and SCO ODT 3.0 have their own names for install.\n    # Don't use installbsd from OSF since it installs stuff as root\n    # by default.\n    for ac_prog in ginstall scoinst install; do\n      for ac_exec_ext in '' $ac_executable_extensions; do\n\tif as_fn_executable_p \"$as_dir/$ac_prog$ac_exec_ext\"; then\n\t  if test $ac_prog = install &&\n\t    grep dspmsg \"$as_dir/$ac_prog$ac_exec_ext\" >/dev/null 2>&1; then\n\t    # AIX install.  It has an incompatible calling convention.\n\t    :\n\t  elif test $ac_prog = install &&\n\t    grep pwplus \"$as_dir/$ac_prog$ac_exec_ext\" >/dev/null 2>&1; then\n\t    # program-specific install script used by HP pwplus--don't use.\n\t    :\n\t  else\n\t    rm -rf conftest.one conftest.two conftest.dir\n\t    echo one > conftest.one\n\t    echo two > conftest.two\n\t    mkdir conftest.dir\n\t    if \"$as_dir/$ac_prog$ac_exec_ext\" -c conftest.one conftest.two \"`pwd`/conftest.dir\" &&\n\t      test -s conftest.one && test -s conftest.two &&\n\t      test -s conftest.dir/conftest.one &&\n\t      test -s conftest.dir/conftest.two\n\t    then\n\t      ac_cv_path_install=\"$as_dir/$ac_prog$ac_exec_ext -c\"\n\t      break 3\n\t    fi\n\t  fi\n\tfi\n      done\n    done\n    ;;\nesac\n\n  done\nIFS=$as_save_IFS\n\nrm -rf conftest.one conftest.two conftest.dir\n\nfi\n  if test \"${ac_cv_path_install+set}\" = set; then\n    INSTALL=$ac_cv_path_install\n  else\n    # As a last resort, use the slow shell script.  Don't cache a\n    # value for INSTALL within a source directory, because that will\n    # break other packages using the cache if that directory is\n    # removed, or if the value is a relative name.\n    INSTALL=$ac_install_sh\n  fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $INSTALL\" >&5\n$as_echo \"$INSTALL\" >&6; }\n\n# Use test -z because SunOS4 sh mishandles braces in ${var-val}.\n# It thinks the first close brace ends the variable substitution.\ntest -z \"$INSTALL_PROGRAM\" && INSTALL_PROGRAM='${INSTALL}'\n\ntest -z \"$INSTALL_SCRIPT\" && INSTALL_SCRIPT='${INSTALL}'\n\ntest -z \"$INSTALL_DATA\" && INSTALL_DATA='${INSTALL} -m 644'\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const\" >&5\n$as_echo_n \"checking for an ANSI C-conforming const... \" >&6; }\nif ${ac_cv_c_const+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain ()\n{\n\n#ifndef __cplusplus\n  /* Ultrix mips cc rejects this sort of thing.  */\n  typedef int charset[2];\n  const charset cs = { 0, 0 };\n  /* SunOS 4.1.1 cc rejects this.  */\n  char const *const *pcpcc;\n  char **ppc;\n  /* NEC SVR4.0.2 mips cc rejects this.  */\n  struct point {int x, y;};\n  static struct point const zero = {0,0};\n  /* AIX XL C 1.02.0.0 rejects this.\n     It does not let you subtract one const X* pointer from another in\n     an arm of an if-expression whose if-part is not a constant\n     expression */\n  const char *g = \"string\";\n  pcpcc = &g + (g ? g-g : 0);\n  /* HPUX 7.0 cc rejects these. */\n  ++pcpcc;\n  ppc = (char**) pcpcc;\n  pcpcc = (char const *const *) ppc;\n  { /* SCO 3.2v4 cc rejects this sort of thing.  */\n    char tx;\n    char *t = &tx;\n    char const *s = 0 ? (char *) 0 : (char const *) 0;\n\n    *t++ = 0;\n    if (s) return 0;\n  }\n  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */\n    int x[] = {25, 17};\n    const int *foo = &x[0];\n    ++foo;\n  }\n  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */\n    typedef const int *iptr;\n    iptr p = 0;\n    ++p;\n  }\n  { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying\n       \"k.c\", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */\n    struct s { int j; const int *ap[3]; } bx;\n    struct s *b = &bx; b->j = 5;\n  }\n  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */\n    const int foo = 10;\n    if (!foo) return 0;\n  }\n  return !cs[0] && !zero.x;\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_c_const=yes\nelse\n  ac_cv_c_const=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const\" >&5\n$as_echo \"$ac_cv_c_const\" >&6; }\nif test $ac_cv_c_const = no; then\n\n$as_echo \"#define const /**/\" >>confdefs.h\n\nfi\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for inline\" >&5\n$as_echo_n \"checking for inline... \" >&6; }\nif ${ac_cv_c_inline+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_cv_c_inline=no\nfor ac_kw in inline __inline__ __inline; do\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifndef __cplusplus\ntypedef int foo_t;\nstatic $ac_kw foo_t static_foo () {return 0; }\n$ac_kw foo_t foo () {return 0; }\n#endif\n\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_c_inline=$ac_kw\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n  test \"$ac_cv_c_inline\" != no && break\ndone\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline\" >&5\n$as_echo \"$ac_cv_c_inline\" >&6; }\n\ncase $ac_cv_c_inline in\n  inline | yes) ;;\n  *)\n    case $ac_cv_c_inline in\n      no) ac_val=;;\n      *) ac_val=$ac_cv_c_inline;;\n    esac\n    cat >>confdefs.h <<_ACEOF\n#ifndef __cplusplus\n#define inline $ac_val\n#endif\n_ACEOF\n    ;;\nesac\n\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor\" >&5\n$as_echo_n \"checking how to run the C preprocessor... \" >&6; }\n# On Suns, sometimes $CPP names a directory.\nif test -n \"$CPP\" && test -d \"$CPP\"; then\n  CPP=\nfi\nif test -z \"$CPP\"; then\n  if ${ac_cv_prog_CPP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n      # Double quotes because CPP needs to be expanded\n    for CPP in \"$CC -E\" \"$CC -E -traditional-cpp\" \"/lib/cpp\"\n    do\n      ac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n  # <limits.h> exists even on freestanding compilers.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n\nelse\n  # Broken: fails on valid input.\ncontinue\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  # Broken: success on invalid input.\ncontinue\nelse\n  # Passes both tests.\nac_preproc_ok=:\nbreak\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\ndone\n# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.i conftest.err conftest.$ac_ext\nif $ac_preproc_ok; then :\n  break\nfi\n\n    done\n    ac_cv_prog_CPP=$CPP\n\nfi\n  CPP=$ac_cv_prog_CPP\nelse\n  ac_cv_prog_CPP=$CPP\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $CPP\" >&5\n$as_echo \"$CPP\" >&6; }\nac_preproc_ok=false\nfor ac_c_preproc_warn_flag in '' yes\ndo\n  # Use a header file that comes with gcc, so configuring glibc\n  # with a fresh cross-compiler works.\n  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since\n  # <limits.h> exists even on freestanding compilers.\n  # On the NeXT, cc -E runs the code through the compiler's parser,\n  # not just through cpp. \"Syntax error\" is here to catch this case.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#ifdef __STDC__\n# include <limits.h>\n#else\n# include <assert.h>\n#endif\n\t\t     Syntax error\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n\nelse\n  # Broken: fails on valid input.\ncontinue\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\n  # OK, works on sane cases.  Now check whether nonexistent headers\n  # can be detected and how.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ac_nonexistent.h>\n_ACEOF\nif ac_fn_c_try_cpp \"$LINENO\"; then :\n  # Broken: success on invalid input.\ncontinue\nelse\n  # Passes both tests.\nac_preproc_ok=:\nbreak\nfi\nrm -f conftest.err conftest.i conftest.$ac_ext\n\ndone\n# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.\nrm -f conftest.i conftest.err conftest.$ac_ext\nif $ac_preproc_ok; then :\n\nelse\n  { { $as_echo \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\n$as_echo \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"C preprocessor \\\"$CPP\\\" fails sanity check\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e\" >&5\n$as_echo_n \"checking for grep that handles long lines and -e... \" >&6; }\nif ${ac_cv_path_GREP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if test -z \"$GREP\"; then\n  ac_path_GREP_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_prog in grep ggrep; do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_GREP=\"$as_dir/$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_GREP\" || continue\n# Check for GNU ac_path_GREP and select it if it is found.\n  # Check for GNU $ac_path_GREP\ncase `\"$ac_path_GREP\" --version 2>&1` in\n*GNU*)\n  ac_cv_path_GREP=\"$ac_path_GREP\" ac_path_GREP_found=:;;\n*)\n  ac_count=0\n  $as_echo_n 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    $as_echo 'GREP' >> \"conftest.nl\"\n    \"$ac_path_GREP\" -e 'GREP$' -e '-(cannot match)-' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_GREP_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_GREP=\"$ac_path_GREP\"\n      ac_path_GREP_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_GREP_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_GREP\"; then\n    as_fn_error $? \"no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_GREP=$GREP\nfi\n\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP\" >&5\n$as_echo \"$ac_cv_path_GREP\" >&6; }\n GREP=\"$ac_cv_path_GREP\"\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for egrep\" >&5\n$as_echo_n \"checking for egrep... \" >&6; }\nif ${ac_cv_path_EGREP+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1\n   then ac_cv_path_EGREP=\"$GREP -E\"\n   else\n     if test -z \"$EGREP\"; then\n  ac_path_EGREP_found=false\n  # Loop through the user's path and test for each of PROGNAME-LIST\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    for ac_prog in egrep; do\n    for ac_exec_ext in '' $ac_executable_extensions; do\n      ac_path_EGREP=\"$as_dir/$ac_prog$ac_exec_ext\"\n      as_fn_executable_p \"$ac_path_EGREP\" || continue\n# Check for GNU ac_path_EGREP and select it if it is found.\n  # Check for GNU $ac_path_EGREP\ncase `\"$ac_path_EGREP\" --version 2>&1` in\n*GNU*)\n  ac_cv_path_EGREP=\"$ac_path_EGREP\" ac_path_EGREP_found=:;;\n*)\n  ac_count=0\n  $as_echo_n 0123456789 >\"conftest.in\"\n  while :\n  do\n    cat \"conftest.in\" \"conftest.in\" >\"conftest.tmp\"\n    mv \"conftest.tmp\" \"conftest.in\"\n    cp \"conftest.in\" \"conftest.nl\"\n    $as_echo 'EGREP' >> \"conftest.nl\"\n    \"$ac_path_EGREP\" 'EGREP$' < \"conftest.nl\" >\"conftest.out\" 2>/dev/null || break\n    diff \"conftest.out\" \"conftest.nl\" >/dev/null 2>&1 || break\n    as_fn_arith $ac_count + 1 && ac_count=$as_val\n    if test $ac_count -gt ${ac_path_EGREP_max-0}; then\n      # Best one so far, save it but keep looking for a better one\n      ac_cv_path_EGREP=\"$ac_path_EGREP\"\n      ac_path_EGREP_max=$ac_count\n    fi\n    # 10*(2^10) chars as input seems more than enough\n    test $ac_count -gt 10 && break\n  done\n  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;\nesac\n\n      $ac_path_EGREP_found && break 3\n    done\n  done\n  done\nIFS=$as_save_IFS\n  if test -z \"$ac_cv_path_EGREP\"; then\n    as_fn_error $? \"no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin\" \"$LINENO\" 5\n  fi\nelse\n  ac_cv_path_EGREP=$EGREP\nfi\n\n   fi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP\" >&5\n$as_echo \"$ac_cv_path_EGREP\" >&6; }\n EGREP=\"$ac_cv_path_EGREP\"\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for ANSI C header files\" >&5\n$as_echo_n \"checking for ANSI C header files... \" >&6; }\nif ${ac_cv_header_stdc+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\n#include <stdarg.h>\n#include <string.h>\n#include <float.h>\n\nint\nmain ()\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"; then :\n  ac_cv_header_stdc=yes\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.$ac_ext\n\nif test $ac_cv_header_stdc = yes; then\n  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <string.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"memchr\" >/dev/null 2>&1; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f conftest*\n\nfi\n\nif test $ac_cv_header_stdc = yes; then\n  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdlib.h>\n\n_ACEOF\nif (eval \"$ac_cpp conftest.$ac_ext\") 2>&5 |\n  $EGREP \"free\" >/dev/null 2>&1; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f conftest*\n\nfi\n\nif test $ac_cv_header_stdc = yes; then\n  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.\n  if test \"$cross_compiling\" = yes; then :\n  :\nelse\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <ctype.h>\n#include <stdlib.h>\n#if ((' ' & 0x0FF) == 0x020)\n# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')\n# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))\n#else\n# define ISLOWER(c) \\\n\t\t   (('a' <= (c) && (c) <= 'i') \\\n\t\t     || ('j' <= (c) && (c) <= 'r') \\\n\t\t     || ('s' <= (c) && (c) <= 'z'))\n# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))\n#endif\n\n#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))\nint\nmain ()\n{\n  int i;\n  for (i = 0; i < 256; i++)\n    if (XOR (islower (i), ISLOWER (i))\n\t|| toupper (i) != TOUPPER (i))\n      return 2;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_run \"$LINENO\"; then :\n\nelse\n  ac_cv_header_stdc=no\nfi\nrm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \\\n  conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\n\nfi\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc\" >&5\n$as_echo \"$ac_cv_header_stdc\" >&6; }\nif test $ac_cv_header_stdc = yes; then\n\n$as_echo \"#define STDC_HEADERS 1\" >>confdefs.h\n\nfi\n\n# On IRIX 5.3, sys/types and inttypes.h are conflicting.\nfor ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \\\n\t\t  inttypes.h stdint.h unistd.h\ndo :\n  as_ac_Header=`$as_echo \"ac_cv_header_$ac_header\" | $as_tr_sh`\nac_fn_c_check_header_compile \"$LINENO\" \"$ac_header\" \"$as_ac_Header\" \"$ac_includes_default\n\"\nif eval test \\\"x\\$\"$as_ac_Header\"\\\" = x\"yes\"; then :\n  cat >>confdefs.h <<_ACEOF\n#define `$as_echo \"HAVE_$ac_header\" | $as_tr_cpp` 1\n_ACEOF\n\nfi\n\ndone\n\n\nfor ac_header in sys/resource.h netdb.h sched.h resolv.h arpa/inet.h\ndo :\n  as_ac_Header=`$as_echo \"ac_cv_header_$ac_header\" | $as_tr_sh`\nac_fn_c_check_header_mongrel \"$LINENO\" \"$ac_header\" \"$as_ac_Header\" \"$ac_includes_default\"\nif eval test \\\"x\\$\"$as_ac_Header\"\\\" = x\"yes\"; then :\n  cat >>confdefs.h <<_ACEOF\n#define `$as_echo \"HAVE_$ac_header\" | $as_tr_cpp` 1\n_ACEOF\n\nfi\n\ndone\n\nfor ac_header in netinet/ip.h netinet/in.h netinet/tcp.h netinet/in_systm.h\ndo :\n  as_ac_Header=`$as_echo \"ac_cv_header_$ac_header\" | $as_tr_sh`\nac_fn_c_check_header_mongrel \"$LINENO\" \"$ac_header\" \"$as_ac_Header\" \"$ac_includes_default\"\nif eval test \\\"x\\$\"$as_ac_Header\"\\\" = x\"yes\"; then :\n  cat >>confdefs.h <<_ACEOF\n#define `$as_echo \"HAVE_$ac_header\" | $as_tr_cpp` 1\n_ACEOF\n\nfi\n\ndone\n\nfor ac_header in libutil.h sys/sockio.h\ndo :\n  as_ac_Header=`$as_echo \"ac_cv_header_$ac_header\" | $as_tr_sh`\nac_fn_c_check_header_mongrel \"$LINENO\" \"$ac_header\" \"$as_ac_Header\" \"$ac_includes_default\"\nif eval test \\\"x\\$\"$as_ac_Header\"\\\" = x\"yes\"; then :\n  cat >>confdefs.h <<_ACEOF\n#define `$as_echo \"HAVE_$ac_header\" | $as_tr_cpp` 1\n_ACEOF\n\nfi\n\ndone\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for library containing socket\" >&5\n$as_echo_n \"checking for library containing socket... \" >&6; }\nif ${ac_cv_search_socket+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_func_search_save_LIBS=$LIBS\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar socket ();\nint\nmain ()\n{\nreturn socket ();\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_lib in '' socket; do\n  if test -z \"$ac_lib\"; then\n    ac_res=\"none required\"\n  else\n    ac_res=-l$ac_lib\n    LIBS=\"-l$ac_lib  $ac_func_search_save_LIBS\"\n  fi\n  if ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_search_socket=$ac_res\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext\n  if ${ac_cv_search_socket+:} false; then :\n  break\nfi\ndone\nif ${ac_cv_search_socket+:} false; then :\n\nelse\n  ac_cv_search_socket=no\nfi\nrm conftest.$ac_ext\nLIBS=$ac_func_search_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket\" >&5\n$as_echo \"$ac_cv_search_socket\" >&6; }\nac_res=$ac_cv_search_socket\nif test \"$ac_res\" != no; then :\n  test \"$ac_res\" = \"none required\" || LIBS=\"$ac_res $LIBS\"\n\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for library containing inet_ntoa\" >&5\n$as_echo_n \"checking for library containing inet_ntoa... \" >&6; }\nif ${ac_cv_search_inet_ntoa+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_func_search_save_LIBS=$LIBS\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar inet_ntoa ();\nint\nmain ()\n{\nreturn inet_ntoa ();\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_lib in '' nsl; do\n  if test -z \"$ac_lib\"; then\n    ac_res=\"none required\"\n  else\n    ac_res=-l$ac_lib\n    LIBS=\"-l$ac_lib  $ac_func_search_save_LIBS\"\n  fi\n  if ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_search_inet_ntoa=$ac_res\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext\n  if ${ac_cv_search_inet_ntoa+:} false; then :\n  break\nfi\ndone\nif ${ac_cv_search_inet_ntoa+:} false; then :\n\nelse\n  ac_cv_search_inet_ntoa=no\nfi\nrm conftest.$ac_ext\nLIBS=$ac_func_search_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_ntoa\" >&5\n$as_echo \"$ac_cv_search_inet_ntoa\" >&6; }\nac_res=$ac_cv_search_inet_ntoa\nif test \"$ac_res\" != no; then :\n  test \"$ac_res\" = \"none required\" || LIBS=\"$ac_res $LIBS\"\n\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create\" >&5\n$as_echo_n \"checking for library containing pthread_create... \" >&6; }\nif ${ac_cv_search_pthread_create+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_func_search_save_LIBS=$LIBS\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar pthread_create ();\nint\nmain ()\n{\nreturn pthread_create ();\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_lib in '' pthread; do\n  if test -z \"$ac_lib\"; then\n    ac_res=\"none required\"\n  else\n    ac_res=-l$ac_lib\n    LIBS=\"-l$ac_lib  $ac_func_search_save_LIBS\"\n  fi\n  if ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_search_pthread_create=$ac_res\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext\n  if ${ac_cv_search_pthread_create+:} false; then :\n  break\nfi\ndone\nif ${ac_cv_search_pthread_create+:} false; then :\n\nelse\n  ac_cv_search_pthread_create=no\nfi\nrm conftest.$ac_ext\nLIBS=$ac_func_search_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create\" >&5\n$as_echo \"$ac_cv_search_pthread_create\" >&6; }\nac_res=$ac_cv_search_pthread_create\nif test \"$ac_res\" != no; then :\n  test \"$ac_res\" = \"none required\" || LIBS=\"$ac_res $LIBS\"\n\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname\" >&5\n$as_echo_n \"checking for library containing gethostbyname... \" >&6; }\nif ${ac_cv_search_gethostbyname+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_func_search_save_LIBS=$LIBS\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar gethostbyname ();\nint\nmain ()\n{\nreturn gethostbyname ();\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_lib in '' resolv nsl; do\n  if test -z \"$ac_lib\"; then\n    ac_res=\"none required\"\n  else\n    ac_res=-l$ac_lib\n    LIBS=\"-l$ac_lib  $ac_func_search_save_LIBS\"\n  fi\n  if ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_search_gethostbyname=$ac_res\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext\n  if ${ac_cv_search_gethostbyname+:} false; then :\n  break\nfi\ndone\nif ${ac_cv_search_gethostbyname+:} false; then :\n\nelse\n  ac_cv_search_gethostbyname=no\nfi\nrm conftest.$ac_ext\nLIBS=$ac_func_search_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname\" >&5\n$as_echo \"$ac_cv_search_gethostbyname\" >&6; }\nac_res=$ac_cv_search_gethostbyname\nif test \"$ac_res\" != no; then :\n  test \"$ac_res\" = \"none required\" || LIBS=\"$ac_res $LIBS\"\n\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for library containing nanosleep\" >&5\n$as_echo_n \"checking for library containing nanosleep... \" >&6; }\nif ${ac_cv_search_nanosleep+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_func_search_save_LIBS=$LIBS\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar nanosleep ();\nint\nmain ()\n{\nreturn nanosleep ();\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_lib in '' rt posix4; do\n  if test -z \"$ac_lib\"; then\n    ac_res=\"none required\"\n  else\n    ac_res=-l$ac_lib\n    LIBS=\"-l$ac_lib  $ac_func_search_save_LIBS\"\n  fi\n  if ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_search_nanosleep=$ac_res\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext\n  if ${ac_cv_search_nanosleep+:} false; then :\n  break\nfi\ndone\nif ${ac_cv_search_nanosleep+:} false; then :\n\nelse\n  ac_cv_search_nanosleep=no\nfi\nrm conftest.$ac_ext\nLIBS=$ac_func_search_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_nanosleep\" >&5\n$as_echo \"$ac_cv_search_nanosleep\" >&6; }\nac_res=$ac_cv_search_nanosleep\nif test \"$ac_res\" != no; then :\n  test \"$ac_res\" = \"none required\" || LIBS=\"$ac_res $LIBS\"\n\nfi\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: checking for library containing setproctitle\" >&5\n$as_echo_n \"checking for library containing setproctitle... \" >&6; }\nif ${ac_cv_search_setproctitle+:} false; then :\n  $as_echo_n \"(cached) \" >&6\nelse\n  ac_func_search_save_LIBS=$LIBS\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\n#ifdef __cplusplus\nextern \"C\"\n#endif\nchar setproctitle ();\nint\nmain ()\n{\nreturn setproctitle ();\n  ;\n  return 0;\n}\n_ACEOF\nfor ac_lib in '' util bsd; do\n  if test -z \"$ac_lib\"; then\n    ac_res=\"none required\"\n  else\n    ac_res=-l$ac_lib\n    LIBS=\"-l$ac_lib  $ac_func_search_save_LIBS\"\n  fi\n  if ac_fn_c_try_link \"$LINENO\"; then :\n  ac_cv_search_setproctitle=$ac_res\nfi\nrm -f core conftest.err conftest.$ac_objext \\\n    conftest$ac_exeext\n  if ${ac_cv_search_setproctitle+:} false; then :\n  break\nfi\ndone\nif ${ac_cv_search_setproctitle+:} false; then :\n\nelse\n  ac_cv_search_setproctitle=no\nfi\nrm conftest.$ac_ext\nLIBS=$ac_func_search_save_LIBS\nfi\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_setproctitle\" >&5\n$as_echo \"$ac_cv_search_setproctitle\" >&6; }\nac_res=$ac_cv_search_setproctitle\nif test \"$ac_res\" != no; then :\n  test \"$ac_res\" = \"none required\" || LIBS=\"$ac_res $LIBS\"\n  $as_echo \"#define HAVE_SETPROC_TITLE 1\" >>confdefs.h\n\nfi\n\n\nif test \"$MARK\" = \"no\"; then\n\t  CFLAGS=\"$CFLAGS -DW_O_SO_MARK=1\"\nfi\n\nif test \"$SYSLOG\" = \"yes\"; then\n          CFLAGS=\"$CFLAGS -DSYSLOG=1\"\nfi\n\nif test \"$SUM_SEND\" = \"yes\"; then\n          CFLAGS=\"$CFLAGS\"\nfi\n\nif test \"$DEBUGG\" = \"yes\"; then\n\t  CFLAGS=\"$CFLAGS -DDEBUGG=1\"\nfi\n\nif test \"$SELFTESTING\" = \"yes\"; then\n          CFLAGS=\"$CFLAGS -DTESTING=1\"\nfi\n\nif test \"$LOW_MEM\" = \"yes\"; then\n          CFLAGS=\"$CFLAGS -DLOW_MEM=1\"\nfi\n\nif test \"$JSON\" = \"yes\"; then\n          CFLAGS=\"$CFLAGS -DJSON=1\"\nfi\n\nif test \"$O3\" = \"yes\"; then\n\t  CFLAGS=\"$CFLAGS -O3\"\nfi\n\nif test \"$CLIENTONLY\" = \"yes\"; then\n\t  CFLAGS=\"$CFLAGS -DCLIENTONLY=1\"\nfi\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: \" >&5\n$as_echo \"\" >&6; }\n\nfor ac_func in getpt grantpt unlockpt ptsname\ndo :\n  as_ac_var=`$as_echo \"ac_cv_func_$ac_func\" | $as_tr_sh`\nac_fn_c_check_func \"$LINENO\" \"$ac_func\" \"$as_ac_var\"\nif eval test \\\"x\\$\"$as_ac_var\"\\\" = x\"yes\"; then :\n  cat >>confdefs.h <<_ACEOF\n#define `$as_echo \"HAVE_$ac_func\" | $as_tr_cpp` 1\n_ACEOF\n\nfi\ndone\n\n\nOS_REL=`uname -r | tr -d 'A-Za-z\\-\\_\\.'`\ncase $host_os in\n\t*linux*)\n\t     OS_DIR=\"linux\"\n\t     for ac_header in linux/if_tun.h\ndo :\n  ac_fn_c_check_header_mongrel \"$LINENO\" \"linux/if_tun.h\" \"ac_cv_header_linux_if_tun_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_linux_if_tun_h\" = xyes; then :\n  cat >>confdefs.h <<_ACEOF\n#define HAVE_LINUX_IF_TUN_H 1\n_ACEOF\n\nfi\n\ndone\n\n\t     ;;\n\t*solaris*)\n\t     OS_DIR=\"svr4\"\n\t     ;;\n\t*freebsd*)\n\t     if test \"$OS_REL\" -ge \"40\"; then\n\t        OS_DIR=\"freebsd\"\n\t     fi\n\t     ;;\n\t*openbsd*)\n\t     if test \"$OS_REL\" -ge \"25\"; then\n\t        OS_DIR=\"openbsd\"\n\t     fi\n\t     ;;\nesac\n\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: result: creating driver and protocol links ... \" >&5\n$as_echo \"creating driver and protocol links ... \" >&6; }\n\n    if test \"$OS_DIR\" != \"\"; then\n\n    for i in `cat vtun.drivers`; do\n      if test -f $OS_DIR/$i -a ! -f $i; then\n         { $as_echo \"$as_me:${as_lineno-$LINENO}: result: linking $OS_DIR/$i  to  $i\" >&5\n$as_echo \"linking $OS_DIR/$i  to  $i\" >&6; }\n         ln -f -s $OS_DIR/$i $i\n      fi\n    done\n\n    fi\n\n    for i in `cat vtun.drivers`; do\n      if test -f generic/$i -a ! -f $i; then\n         { $as_echo \"$as_me:${as_lineno-$LINENO}: result: linking generic/$i  to  $i\" >&5\n$as_echo \"linking generic/$i  to  $i\" >&6; }\n         ln -f -s generic/$i $i\n      fi\n    done\n\n\n\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: result: \" >&5\n$as_echo \"\" >&6; }\n\n\nREL=\"0.1b\"\n\n\ncat >>confdefs.h <<_ACEOF\n#define VTUN_VER \"$REL `date '+%m/%d/%Y'`\"\n_ACEOF\n\n\nac_config_files=\"$ac_config_files Makefile\"\n\ncat >confcache <<\\_ACEOF\n# This file is a shell script that caches the results of configure\n# tests run on this system so they can be shared between configure\n# scripts and configure runs, see configure's option --config-cache.\n# It is not useful on other systems.  If it contains results you don't\n# want to keep, you may remove or edit it.\n#\n# config.status only pays attention to the cache file if you give it\n# the --recheck option to rerun configure.\n#\n# `ac_cv_env_foo' variables (set or unset) will be overridden when\n# loading this file, other *unset* `ac_cv_foo' will be assigned the\n# following values.\n\n_ACEOF\n\n# The following way of writing the cache mishandles newlines in values,\n# but we know of no workaround that is simple, portable, and efficient.\n# So, we kill variables containing newlines.\n# Ultrix sh set writes to stderr and can't be redirected directly,\n# and sets the high bit in the cache file unless we assign to the vars.\n(\n  for ac_var in `(set) 2>&1 | sed -n 's/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\n$as_echo \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n\n  (set) 2>&1 |\n    case $as_nl`(ac_space=' '; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      # `set' does not quote correctly, so add quotes: double-quote\n      # substitution turns \\\\\\\\ into \\\\, and sed turns \\\\ into \\.\n      sed -n \\\n\t\"s/'/'\\\\\\\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\\\2'/p\"\n      ;; #(\n    *)\n      # `set' quotes correctly as required by POSIX, so do not add quotes.\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n) |\n  sed '\n     /^ac_cv_env_/b end\n     t clear\n     :clear\n     s/^\\([^=]*\\)=\\(.*[{}].*\\)$/test \"${\\1+set}\" = set || &/\n     t end\n     s/^\\([^=]*\\)=\\(.*\\)$/\\1=${\\1=\\2}/\n     :end' >>confcache\nif diff \"$cache_file\" confcache >/dev/null 2>&1; then :; else\n  if test -w \"$cache_file\"; then\n    if test \"x$cache_file\" != \"x/dev/null\"; then\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: updating cache $cache_file\" >&5\n$as_echo \"$as_me: updating cache $cache_file\" >&6;}\n      if test ! -f \"$cache_file\" || test -h \"$cache_file\"; then\n\tcat confcache >\"$cache_file\"\n      else\n        case $cache_file in #(\n        */* | ?:*)\n\t  mv -f confcache \"$cache_file\"$$ &&\n\t  mv -f \"$cache_file\"$$ \"$cache_file\" ;; #(\n        *)\n\t  mv -f confcache \"$cache_file\" ;;\n\tesac\n      fi\n    fi\n  else\n    { $as_echo \"$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file\" >&5\n$as_echo \"$as_me: not updating unwritable cache $cache_file\" >&6;}\n  fi\nfi\nrm -f confcache\n\ntest \"x$prefix\" = xNONE && prefix=$ac_default_prefix\n# Let make expand exec_prefix.\ntest \"x$exec_prefix\" = xNONE && exec_prefix='${prefix}'\n\nDEFS=-DHAVE_CONFIG_H\n\nac_libobjs=\nac_ltlibobjs=\nU=\nfor ac_i in : $LIBOBJS; do test \"x$ac_i\" = x: && continue\n  # 1. Remove the extension, and $U if already installed.\n  ac_script='s/\\$U\\././;s/\\.o$//;s/\\.obj$//'\n  ac_i=`$as_echo \"$ac_i\" | sed \"$ac_script\"`\n  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR\n  #    will be set to the directory where LIBOBJS objects are built.\n  as_fn_append ac_libobjs \" \\${LIBOBJDIR}$ac_i\\$U.$ac_objext\"\n  as_fn_append ac_ltlibobjs \" \\${LIBOBJDIR}$ac_i\"'$U.lo'\ndone\nLIBOBJS=$ac_libobjs\n\nLTLIBOBJS=$ac_ltlibobjs\n\n\n\n: \"${CONFIG_STATUS=./config.status}\"\nac_write_fail=0\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files $CONFIG_STATUS\"\n{ $as_echo \"$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS\" >&5\n$as_echo \"$as_me: creating $CONFIG_STATUS\" >&6;}\nas_write_fail=0\ncat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1\n#! $SHELL\n# Generated by $as_me.\n# Run this file to recreate the current configuration.\n# Compiler output produced by configure, useful for debugging\n# configure, is in config.log if it exists.\n\ndebug=false\nac_cs_recheck=false\nac_cs_silent=false\n\nSHELL=\\${CONFIG_SHELL-$SHELL}\nexport SHELL\n_ASEOF\ncat >>$CONFIG_STATUS <<\\_ASEOF || as_write_fail=1\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nif test -n \"${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse\n  case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\n\nas_nl='\n'\nexport as_nl\n# Printing a long string crashes Solaris 7 /usr/bin/printf.\nas_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo\nas_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo\n# Prefer a ksh shell builtin over an external printf program on Solaris,\n# but without wasting forks for bash or zsh.\nif test -z \"$BASH_VERSION$ZSH_VERSION\" \\\n    && (test \"X`print -r -- $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='print -r --'\n  as_echo_n='print -rn --'\nelif (test \"X`printf %s $as_echo`\" = \"X$as_echo\") 2>/dev/null; then\n  as_echo='printf %s\\n'\n  as_echo_n='printf %s'\nelse\n  if test \"X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`\" = \"X-n $as_echo\"; then\n    as_echo_body='eval /usr/ucb/echo -n \"$1$as_nl\"'\n    as_echo_n='/usr/ucb/echo -n'\n  else\n    as_echo_body='eval expr \"X$1\" : \"X\\\\(.*\\\\)\"'\n    as_echo_n_body='eval\n      arg=$1;\n      case $arg in #(\n      *\"$as_nl\"*)\n\texpr \"X$arg\" : \"X\\\\(.*\\\\)$as_nl\";\n\targ=`expr \"X$arg\" : \".*$as_nl\\\\(.*\\\\)\"`;;\n      esac;\n      expr \"X$arg\" : \"X\\\\(.*\\\\)\" | tr -d \"$as_nl\"\n    '\n    export as_echo_n_body\n    as_echo_n='sh -c $as_echo_n_body as_echo'\n  fi\n  export as_echo_body\n  as_echo='sh -c $as_echo_body as_echo'\nfi\n\n# The user is always right.\nif test \"${PATH_SEPARATOR+set}\" != set; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# IFS\n# We need space, tab and new line, in precisely that order.  Quoting is\n# there to prevent editors from complaining about space-tab.\n# (If _AS_PATH_WALK were called with IFS unset, it would disable word\n# splitting by setting IFS to empty value.)\nIFS=\" \"\"\t$as_nl\"\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  test -z \"$as_dir\" && as_dir=.\n    test -r \"$as_dir/$0\" && as_myself=$as_dir/$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as `sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  $as_echo \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n# Unset variables that we do not need and which cause bugs (e.g. in\n# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the \"|| exit 1\"\n# suppresses any \"Segmentation fault\" message there.  '((' could\n# trigger a bug in pdksh 5.2.14.\nfor as_var in BASH_ENV ENV MAIL MAILPATH\ndo eval test x\\${$as_var+set} = xset \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# NLS nuisances.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# CDPATH.\n(unset CDPATH) >/dev/null 2>&1 && unset CDPATH\n\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    $as_echo \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  $as_echo \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null; then :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse\n  as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  }\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null; then :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse\n  as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  }\nfi # as_fn_arith\n\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.\n    # In both cases, we have to default to `cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`$as_echo \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_tr_cpp=\"eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'\"\n\n# Sed expression to map a string onto a valid variable name.\nas_tr_sh=\"eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'\"\n\n\nexec 6>&1\n## ----------------------------------- ##\n## Main body of $CONFIG_STATUS script. ##\n## ----------------------------------- ##\n_ASEOF\ntest $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# Save the log message, to keep $0 and so on meaningful, and to\n# report actual input values of CONFIG_FILES etc. instead of their\n# values after options handling.\nac_log=\"\nThis file was extended by $as_me, which was\ngenerated by GNU Autoconf 2.69.  Invocation command line was\n\n  CONFIG_FILES    = $CONFIG_FILES\n  CONFIG_HEADERS  = $CONFIG_HEADERS\n  CONFIG_LINKS    = $CONFIG_LINKS\n  CONFIG_COMMANDS = $CONFIG_COMMANDS\n  $ $0 $@\n\non `(hostname || uname -n) 2>/dev/null | sed 1q`\n\"\n\n_ACEOF\n\ncase $ac_config_files in *\"\n\"*) set x $ac_config_files; shift; ac_config_files=$*;;\nesac\n\ncase $ac_config_headers in *\"\n\"*) set x $ac_config_headers; shift; ac_config_headers=$*;;\nesac\n\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n# Files that config.status was made for.\nconfig_files=\"$ac_config_files\"\nconfig_headers=\"$ac_config_headers\"\n\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nac_cs_usage=\"\\\n\\`$as_me' instantiates files and other configuration actions\nfrom templates according to the current configuration.  Unless the files\nand actions are specified as TAGs, all are instantiated by default.\n\nUsage: $0 [OPTION]... [TAG]...\n\n  -h, --help       print this help, then exit\n  -V, --version    print version number and configuration settings, then exit\n      --config     print configuration, then exit\n  -q, --quiet, --silent\n                   do not print progress messages\n  -d, --debug      don't remove temporary files\n      --recheck    update $as_me by reconfiguring in the same conditions\n      --file=FILE[:TEMPLATE]\n                   instantiate the configuration file FILE\n      --header=FILE[:TEMPLATE]\n                   instantiate the configuration header FILE\n\nConfiguration files:\n$config_files\n\nConfiguration headers:\n$config_headers\n\nReport bugs to the package provider.\"\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nac_cs_config=\"`$as_echo \"$ac_configure_args\" | sed 's/^ //; s/[\\\\\"\"\\`\\$]/\\\\\\\\&/g'`\"\nac_cs_version=\"\\\\\nconfig.status\nconfigured by $0, generated by GNU Autoconf 2.69,\n  with options \\\\\"\\$ac_cs_config\\\\\"\n\nCopyright (C) 2012 Free Software Foundation, Inc.\nThis config.status script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\"\n\nac_pwd='$ac_pwd'\nsrcdir='$srcdir'\nINSTALL='$INSTALL'\ntest -n \"\\$AWK\" || AWK=awk\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# The default lists apply if the user does not specify any file.\nac_need_defaults=:\nwhile test $# != 0\ndo\n  case $1 in\n  --*=?*)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=`expr \"X$1\" : 'X[^=]*=\\(.*\\)'`\n    ac_shift=:\n    ;;\n  --*=)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=\n    ac_shift=:\n    ;;\n  *)\n    ac_option=$1\n    ac_optarg=$2\n    ac_shift=shift\n    ;;\n  esac\n\n  case $ac_option in\n  # Handling of the options.\n  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)\n    ac_cs_recheck=: ;;\n  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )\n    $as_echo \"$ac_cs_version\"; exit ;;\n  --config | --confi | --conf | --con | --co | --c )\n    $as_echo \"$ac_cs_config\"; exit ;;\n  --debug | --debu | --deb | --de | --d | -d )\n    debug=: ;;\n  --file | --fil | --fi | --f )\n    $ac_shift\n    case $ac_optarg in\n    *\\'*) ac_optarg=`$as_echo \"$ac_optarg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    '') as_fn_error $? \"missing file argument\" ;;\n    esac\n    as_fn_append CONFIG_FILES \" '$ac_optarg'\"\n    ac_need_defaults=false;;\n  --header | --heade | --head | --hea )\n    $ac_shift\n    case $ac_optarg in\n    *\\'*) ac_optarg=`$as_echo \"$ac_optarg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    esac\n    as_fn_append CONFIG_HEADERS \" '$ac_optarg'\"\n    ac_need_defaults=false;;\n  --he | --h)\n    # Conflict between --help and --header\n    as_fn_error $? \"ambiguous option: \\`$1'\nTry \\`$0 --help' for more information.\";;\n  --help | --hel | -h )\n    $as_echo \"$ac_cs_usage\"; exit ;;\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil | --si | --s)\n    ac_cs_silent=: ;;\n\n  # This is an error.\n  -*) as_fn_error $? \"unrecognized option: \\`$1'\nTry \\`$0 --help' for more information.\" ;;\n\n  *) as_fn_append ac_config_targets \" $1\"\n     ac_need_defaults=false ;;\n\n  esac\n  shift\ndone\n\nac_configure_extra_args=\n\nif $ac_cs_silent; then\n  exec 6>/dev/null\n  ac_configure_extra_args=\"$ac_configure_extra_args --silent\"\nfi\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nif \\$ac_cs_recheck; then\n  set X $SHELL '$0' $ac_configure_args \\$ac_configure_extra_args --no-create --no-recursion\n  shift\n  \\$as_echo \"running CONFIG_SHELL=$SHELL \\$*\" >&6\n  CONFIG_SHELL='$SHELL'\n  export CONFIG_SHELL\n  exec \"\\$@\"\nfi\n\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nexec 5>>config.log\n{\n  echo\n  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX\n## Running $as_me. ##\n_ASBOX\n  $as_echo \"$ac_log\"\n} >&5\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n\n# Handling of arguments.\nfor ac_config_target in $ac_config_targets\ndo\n  case $ac_config_target in\n    \"config.h\") CONFIG_HEADERS=\"$CONFIG_HEADERS config.h\" ;;\n    \"Makefile\") CONFIG_FILES=\"$CONFIG_FILES Makefile\" ;;\n\n  *) as_fn_error $? \"invalid argument: \\`$ac_config_target'\" \"$LINENO\" 5;;\n  esac\ndone\n\n\n# If the user did not use the arguments to specify the items to instantiate,\n# then the envvar interface is used.  Set only those that are not.\n# We use the long form for the default assignment because of an extremely\n# bizarre bug on SunOS 4.1.3.\nif $ac_need_defaults; then\n  test \"${CONFIG_FILES+set}\" = set || CONFIG_FILES=$config_files\n  test \"${CONFIG_HEADERS+set}\" = set || CONFIG_HEADERS=$config_headers\nfi\n\n# Have a temporary directory for convenience.  Make it in the build tree\n# simply because there is no reason against having it here, and in addition,\n# creating and moving files from /tmp can sometimes cause problems.\n# Hook for its removal unless debugging.\n# Note that there is a small window in which the directory will not be cleaned:\n# after its creation but before its name has been assigned to `$tmp'.\n$debug ||\n{\n  tmp= ac_tmp=\n  trap 'exit_status=$?\n  : \"${ac_tmp:=$tmp}\"\n  { test ! -d \"$ac_tmp\" || rm -fr \"$ac_tmp\"; } && exit $exit_status\n' 0\n  trap 'as_fn_exit 1' 1 2 13 15\n}\n# Create a (secure) tmp directory for tmp files.\n\n{\n  tmp=`(umask 077 && mktemp -d \"./confXXXXXX\") 2>/dev/null` &&\n  test -d \"$tmp\"\n}  ||\n{\n  tmp=./conf$$-$RANDOM\n  (umask 077 && mkdir \"$tmp\")\n} || as_fn_error $? \"cannot create a temporary directory in .\" \"$LINENO\" 5\nac_tmp=$tmp\n\n# Set up the scripts for CONFIG_FILES section.\n# No need to generate them if there are no CONFIG_FILES.\n# This happens for instance with `./config.status config.h'.\nif test -n \"$CONFIG_FILES\"; then\n\n\nac_cr=`echo X | tr X '\\015'`\n# On cygwin, bash can eat \\r inside `` if the user requested igncr.\n# But we know of no other shell where ac_cr would be empty at this\n# point, so we can use a bashism as a fallback.\nif test \"x$ac_cr\" = x; then\n  eval ac_cr=\\$\\'\\\\r\\'\nfi\nac_cs_awk_cr=`$AWK 'BEGIN { print \"a\\rb\" }' </dev/null 2>/dev/null`\nif test \"$ac_cs_awk_cr\" = \"a${ac_cr}b\"; then\n  ac_cs_awk_cr='\\\\r'\nelse\n  ac_cs_awk_cr=$ac_cr\nfi\n\necho 'BEGIN {' >\"$ac_tmp/subs1.awk\" &&\n_ACEOF\n\n\n{\n  echo \"cat >conf$$subs.awk <<_ACEOF\" &&\n  echo \"$ac_subst_vars\" | sed 's/.*/&!$&$ac_delim/' &&\n  echo \"_ACEOF\"\n} >conf$$subs.sh ||\n  as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\nac_delim_num=`echo \"$ac_subst_vars\" | grep -c '^'`\nac_delim='%!_!# '\nfor ac_last_try in false false false false false :; do\n  . ./conf$$subs.sh ||\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n\n  ac_delim_n=`sed -n \"s/.*$ac_delim\\$/X/p\" conf$$subs.awk | grep -c X`\n  if test $ac_delim_n = $ac_delim_num; then\n    break\n  elif $ac_last_try; then\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n  else\n    ac_delim=\"$ac_delim!$ac_delim _$ac_delim!! \"\n  fi\ndone\nrm -f conf$$subs.sh\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\ncat >>\"\\$ac_tmp/subs1.awk\" <<\\\\_ACAWK &&\n_ACEOF\nsed -n '\nh\ns/^/S[\"/; s/!.*/\"]=/\np\ng\ns/^[^!]*!//\n:repl\nt repl\ns/'\"$ac_delim\"'$//\nt delim\n:nl\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\\\\n\"\\\\/\np\nn\nb repl\n:more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt nl\n:delim\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"/\np\nb\n:more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt delim\n' <conf$$subs.awk | sed '\n/^[^\"\"]/{\n  N\n  s/\\n//\n}\n' >>$CONFIG_STATUS || ac_write_fail=1\nrm -f conf$$subs.awk\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n_ACAWK\ncat >>\"\\$ac_tmp/subs1.awk\" <<_ACAWK &&\n  for (key in S) S_is_set[key] = 1\n  FS = \"\u0007\"\n\n}\n{\n  line = $ 0\n  nfields = split(line, field, \"@\")\n  substed = 0\n  len = length(field[1])\n  for (i = 2; i < nfields; i++) {\n    key = field[i]\n    keylen = length(key)\n    if (S_is_set[key]) {\n      value = S[key]\n      line = substr(line, 1, len) \"\" value \"\" substr(line, len + keylen + 3)\n      len += length(value) + length(field[++i])\n      substed = 1\n    } else\n      len += 1 + keylen\n  }\n\n  print line\n}\n\n_ACAWK\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nif sed \"s/$ac_cr//\" < /dev/null > /dev/null 2>&1; then\n  sed \"s/$ac_cr\\$//; s/$ac_cr/$ac_cs_awk_cr/g\"\nelse\n  cat\nfi < \"$ac_tmp/subs1.awk\" > \"$ac_tmp/subs.awk\" \\\n  || as_fn_error $? \"could not setup config files machinery\" \"$LINENO\" 5\n_ACEOF\n\n# VPATH may cause trouble with some makes, so we remove sole $(srcdir),\n# ${srcdir} and @srcdir@ entries from VPATH if srcdir is \".\", strip leading and\n# trailing colons and then remove the whole line if VPATH becomes empty\n# (actually we leave an empty line to preserve line numbers).\nif test \"x$srcdir\" = x.; then\n  ac_vpsub='/^[\t ]*VPATH[\t ]*=[\t ]*/{\nh\ns///\ns/^/:/\ns/[\t ]*$/:/\ns/:\\$(srcdir):/:/g\ns/:\\${srcdir}:/:/g\ns/:@srcdir@:/:/g\ns/^:*//\ns/:*$//\nx\ns/\\(=[\t ]*\\).*/\\1/\nG\ns/\\n//\ns/^[^=]*=[\t ]*$//\n}'\nfi\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nfi # test -n \"$CONFIG_FILES\"\n\n# Set up the scripts for CONFIG_HEADERS section.\n# No need to generate them if there are no CONFIG_HEADERS.\n# This happens for instance with `./config.status Makefile'.\nif test -n \"$CONFIG_HEADERS\"; then\ncat >\"$ac_tmp/defines.awk\" <<\\_ACAWK ||\nBEGIN {\n_ACEOF\n\n# Transform confdefs.h into an awk script `defines.awk', embedded as\n# here-document in config.status, that substitutes the proper values into\n# config.h.in to produce config.h.\n\n# Create a delimiter string that does not exist in confdefs.h, to ease\n# handling of long lines.\nac_delim='%!_!# '\nfor ac_last_try in false false :; do\n  ac_tt=`sed -n \"/$ac_delim/p\" confdefs.h`\n  if test -z \"$ac_tt\"; then\n    break\n  elif $ac_last_try; then\n    as_fn_error $? \"could not make $CONFIG_HEADERS\" \"$LINENO\" 5\n  else\n    ac_delim=\"$ac_delim!$ac_delim _$ac_delim!! \"\n  fi\ndone\n\n# For the awk script, D is an array of macro values keyed by name,\n# likewise P contains macro parameters if any.  Preserve backslash\n# newline sequences.\n\nac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*\nsed -n '\ns/.\\{148\\}/&'\"$ac_delim\"'/g\nt rset\n:rset\ns/^[\t ]*#[\t ]*define[\t ][\t ]*/ /\nt def\nd\n:def\ns/\\\\$//\nt bsnl\ns/[\"\\\\]/\\\\&/g\ns/^ \\('\"$ac_word_re\"'\\)\\(([^()]*)\\)[\t ]*\\(.*\\)/P[\"\\1\"]=\"\\2\"\\\nD[\"\\1\"]=\" \\3\"/p\ns/^ \\('\"$ac_word_re\"'\\)[\t ]*\\(.*\\)/D[\"\\1\"]=\" \\2\"/p\nd\n:bsnl\ns/[\"\\\\]/\\\\&/g\ns/^ \\('\"$ac_word_re\"'\\)\\(([^()]*)\\)[\t ]*\\(.*\\)/P[\"\\1\"]=\"\\2\"\\\nD[\"\\1\"]=\" \\3\\\\\\\\\\\\n\"\\\\/p\nt cont\ns/^ \\('\"$ac_word_re\"'\\)[\t ]*\\(.*\\)/D[\"\\1\"]=\" \\2\\\\\\\\\\\\n\"\\\\/p\nt cont\nd\n:cont\nn\ns/.\\{148\\}/&'\"$ac_delim\"'/g\nt clear\n:clear\ns/\\\\$//\nt bsnlc\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"/p\nd\n:bsnlc\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\\\\\\\\\\\\n\"\\\\/p\nb cont\n' <confdefs.h | sed '\ns/'\"$ac_delim\"'/\"\\\\\\\n\"/g' >>$CONFIG_STATUS || ac_write_fail=1\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n  for (key in D) D_is_set[key] = 1\n  FS = \"\u0007\"\n}\n/^[\\t ]*#[\\t ]*(define|undef)[\\t ]+$ac_word_re([\\t (]|\\$)/ {\n  line = \\$ 0\n  split(line, arg, \" \")\n  if (arg[1] == \"#\") {\n    defundef = arg[2]\n    mac1 = arg[3]\n  } else {\n    defundef = substr(arg[1], 2)\n    mac1 = arg[2]\n  }\n  split(mac1, mac2, \"(\") #)\n  macro = mac2[1]\n  prefix = substr(line, 1, index(line, defundef) - 1)\n  if (D_is_set[macro]) {\n    # Preserve the white space surrounding the \"#\".\n    print prefix \"define\", macro P[macro] D[macro]\n    next\n  } else {\n    # Replace #undef with comments.  This is necessary, for example,\n    # in the case of _POSIX_SOURCE, which is predefined and required\n    # on some systems where configure will not decide to define it.\n    if (defundef == \"undef\") {\n      print \"/*\", prefix defundef, macro, \"*/\"\n      next\n    }\n  }\n}\n{ print }\n_ACAWK\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n  as_fn_error $? \"could not setup config headers machinery\" \"$LINENO\" 5\nfi # test -n \"$CONFIG_HEADERS\"\n\n\neval set X \"  :F $CONFIG_FILES  :H $CONFIG_HEADERS    \"\nshift\nfor ac_tag\ndo\n  case $ac_tag in\n  :[FHLC]) ac_mode=$ac_tag; continue;;\n  esac\n  case $ac_mode$ac_tag in\n  :[FHL]*:*);;\n  :L* | :C*:*) as_fn_error $? \"invalid tag \\`$ac_tag'\" \"$LINENO\" 5;;\n  :[FH]-) ac_tag=-:-;;\n  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;\n  esac\n  ac_save_IFS=$IFS\n  IFS=:\n  set x $ac_tag\n  IFS=$ac_save_IFS\n  shift\n  ac_file=$1\n  shift\n\n  case $ac_mode in\n  :L) ac_source=$1;;\n  :[FH])\n    ac_file_inputs=\n    for ac_f\n    do\n      case $ac_f in\n      -) ac_f=\"$ac_tmp/stdin\";;\n      *) # Look for the file first in the build tree, then in the source tree\n\t # (if the path is not absolute).  The absolute path cannot be DOS-style,\n\t # because $ac_f cannot contain `:'.\n\t test -f \"$ac_f\" ||\n\t   case $ac_f in\n\t   [\\\\/$]*) false;;\n\t   *) test -f \"$srcdir/$ac_f\" && ac_f=\"$srcdir/$ac_f\";;\n\t   esac ||\n\t   as_fn_error 1 \"cannot find input file: \\`$ac_f'\" \"$LINENO\" 5;;\n      esac\n      case $ac_f in *\\'*) ac_f=`$as_echo \"$ac_f\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; esac\n      as_fn_append ac_file_inputs \" '$ac_f'\"\n    done\n\n    # Let's still pretend it is `configure' which instantiates (i.e., don't\n    # use $as_me), people would be surprised to read:\n    #    /* config.h.  Generated by config.status.  */\n    configure_input='Generated from '`\n\t  $as_echo \"$*\" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'\n\t`' by configure.'\n    if test x\"$ac_file\" != x-; then\n      configure_input=\"$ac_file.  $configure_input\"\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: creating $ac_file\" >&5\n$as_echo \"$as_me: creating $ac_file\" >&6;}\n    fi\n    # Neutralize special characters interpreted by sed in replacement strings.\n    case $configure_input in #(\n    *\\&* | *\\|* | *\\\\* )\n       ac_sed_conf_input=`$as_echo \"$configure_input\" |\n       sed 's/[\\\\\\\\&|]/\\\\\\\\&/g'`;; #(\n    *) ac_sed_conf_input=$configure_input;;\n    esac\n\n    case $ac_tag in\n    *:-:* | *:-) cat >\"$ac_tmp/stdin\" \\\n      || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5 ;;\n    esac\n    ;;\n  esac\n\n  ac_dir=`$as_dirname -- \"$ac_file\" ||\n$as_expr X\"$ac_file\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)$' \\| \\\n\t X\"$ac_file\" : 'X\\(/\\)' \\| . 2>/dev/null ||\n$as_echo X\"$ac_file\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  as_dir=\"$ac_dir\"; as_fn_mkdir_p\n  ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`$as_echo \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`$as_echo \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n\n  case $ac_mode in\n  :F)\n  #\n  # CONFIG_FILE\n  #\n\n  case $INSTALL in\n  [\\\\/$]* | ?:[\\\\/]* ) ac_INSTALL=$INSTALL ;;\n  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;\n  esac\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# If the template does not know about datarootdir, expand it.\n# FIXME: This hack should be removed a few years after 2.60.\nac_datarootdir_hack=; ac_datarootdir_seen=\nac_sed_dataroot='\n/datarootdir/ {\n  p\n  q\n}\n/@datadir@/p\n/@docdir@/p\n/@infodir@/p\n/@localedir@/p\n/@mandir@/p'\ncase `eval \"sed -n \\\"\\$ac_sed_dataroot\\\" $ac_file_inputs\"` in\n*datarootdir*) ac_datarootdir_seen=yes;;\n*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&5\n$as_echo \"$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&2;}\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n  ac_datarootdir_hack='\n  s&@datadir@&$datadir&g\n  s&@docdir@&$docdir&g\n  s&@infodir@&$infodir&g\n  s&@localedir@&$localedir&g\n  s&@mandir@&$mandir&g\n  s&\\\\\\${datarootdir}&$datarootdir&g' ;;\nesac\n_ACEOF\n\n# Neutralize VPATH when `$srcdir' = `.'.\n# Shell code in configure.ac might set extrasub.\n# FIXME: do we really want to maintain this feature?\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nac_sed_extra=\"$ac_vpsub\n$extrasub\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n:t\n/@[a-zA-Z_][a-zA-Z_0-9]*@/!b\ns|@configure_input@|$ac_sed_conf_input|;t t\ns&@top_builddir@&$ac_top_builddir_sub&;t t\ns&@top_build_prefix@&$ac_top_build_prefix&;t t\ns&@srcdir@&$ac_srcdir&;t t\ns&@abs_srcdir@&$ac_abs_srcdir&;t t\ns&@top_srcdir@&$ac_top_srcdir&;t t\ns&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t\ns&@builddir@&$ac_builddir&;t t\ns&@abs_builddir@&$ac_abs_builddir&;t t\ns&@abs_top_builddir@&$ac_abs_top_builddir&;t t\ns&@INSTALL@&$ac_INSTALL&;t t\n$ac_datarootdir_hack\n\"\neval sed \\\"\\$ac_sed_extra\\\" \"$ac_file_inputs\" | $AWK -f \"$ac_tmp/subs.awk\" \\\n  >$ac_tmp/out || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n\ntest -z \"$ac_datarootdir_hack$ac_datarootdir_seen\" &&\n  { ac_out=`sed -n '/\\${datarootdir}/p' \"$ac_tmp/out\"`; test -n \"$ac_out\"; } &&\n  { ac_out=`sed -n '/^[\t ]*datarootdir[\t ]*:*=/p' \\\n      \"$ac_tmp/out\"`; test -z \"$ac_out\"; } &&\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \\`datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&5\n$as_echo \"$as_me: WARNING: $ac_file contains a reference to the variable \\`datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&2;}\n\n  rm -f \"$ac_tmp/stdin\"\n  case $ac_file in\n  -) cat \"$ac_tmp/out\" && rm -f \"$ac_tmp/out\";;\n  *) rm -f \"$ac_file\" && mv \"$ac_tmp/out\" \"$ac_file\";;\n  esac \\\n  || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n ;;\n  :H)\n  #\n  # CONFIG_HEADER\n  #\n  if test x\"$ac_file\" != x-; then\n    {\n      $as_echo \"/* $configure_input  */\" \\\n      && eval '$AWK -f \"$ac_tmp/defines.awk\"' \"$ac_file_inputs\"\n    } >\"$ac_tmp/config.h\" \\\n      || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n    if diff \"$ac_file\" \"$ac_tmp/config.h\" >/dev/null 2>&1; then\n      { $as_echo \"$as_me:${as_lineno-$LINENO}: $ac_file is unchanged\" >&5\n$as_echo \"$as_me: $ac_file is unchanged\" >&6;}\n    else\n      rm -f \"$ac_file\"\n      mv \"$ac_tmp/config.h\" \"$ac_file\" \\\n\t|| as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n    fi\n  else\n    $as_echo \"/* $configure_input  */\" \\\n      && eval '$AWK -f \"$ac_tmp/defines.awk\"' \"$ac_file_inputs\" \\\n      || as_fn_error $? \"could not create -\" \"$LINENO\" 5\n  fi\n ;;\n\n\n  esac\n\ndone # for ac_tag\n\n\nas_fn_exit 0\n_ACEOF\nac_clean_files=$ac_clean_files_save\n\ntest $ac_write_fail = 0 ||\n  as_fn_error $? \"write failure creating $CONFIG_STATUS\" \"$LINENO\" 5\n\n\n# configure is writing to config.log, and then calls config.status.\n# config.status does its own redirection, appending to config.log.\n# Unfortunately, on DOS this fails, as config.log is still kept open\n# by configure, so config.status won't be able to write to it; its\n# output is simply discarded.  So we exec the FD to /dev/null,\n# effectively closing config.log, so it can be properly (re)opened and\n# appended to by config.status.  When coming back to configure, we\n# need to make the FD available again.\nif test \"$no_create\" != yes; then\n  ac_cs_success=:\n  ac_config_status_args=\n  test \"$silent\" = yes &&\n    ac_config_status_args=\"$ac_config_status_args --quiet\"\n  exec 5>/dev/null\n  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false\n  exec 5>>config.log\n  # Use ||, not &&, to avoid exiting from the if with $? = 1, which\n  # would make configure fail if this is the last instruction.\n  $ac_cs_success || as_fn_exit 1\nfi\nif test -n \"$ac_unrecognized_opts\" && test \"$enable_option_checking\" != no; then\n  { $as_echo \"$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts\" >&5\n$as_echo \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2;}\nfi\n\n"
  },
  {
    "path": "configure.in",
    "content": "dnl\ndnl vtrunkd - Virtual Tunnel Trunking over TCP/IP network.\ndnl Copyright (C) 2011-2016  Vrayo Systems Ltd. team\ndnl derived from\ndnl VTun - Virtual Tunnel over TCP/IP network.\ndnl Copyright (C) 1998-2006  Maxim Krasnyansky <max_mk@yahoo.com>\ndnl License: GPL v.3 or higher\ndnl configure.in,v 1.10.2.12.2.6 2006/12/11 01:47:45 mtbishop Exp\ndnl\ndnl Process this file with autoconf to produce a configure script.\ndnl\n\nAC_INIT(lib.c)\nAC_CONFIG_HEADER(config.h)\n\nCFLAGS=\"$CFLAGS -std=gnu99\"\n\ndnl no O3 support\nAC_ARG_ENABLE(o3,\n   --disable-o3     \t   Compile without -O3 optimization,\n   O3=$enableval,\n   O3=yes\n)\n\nAC_ARG_ENABLE(sum-send,\n   --enable-sum-send      Enable redundancy code sending,\n   SUM_SEND=$enableval,\n   SUM_SEND=no\n)\n\nAC_ARG_ENABLE(mark,\n   --disable-mark     \t   Disable SO_MARK support on socket. Only available in Linux >=2.6.25,\n   MARK=$enableval,\n   MARK=yes\n)\n\nAC_ARG_ENABLE(syslog,\n   --disable-syslog          Disable syslog output,\n   SYSLOG=$enableval,\n   SYSLOG=yes\n)\n\ndnl enable low memory opt\nAC_ARG_ENABLE(low-mem,\n   --enable-low-mem         Compile for low ram device,\n   LOW_MEM=$enableval,\n   LOW_MEM=no\n)\n\nAC_ARG_ENABLE(json,\n   --enable-json              JSON logging,\n   JSON=$enableval,\n   JSON=no\n)\n\ndnl enable verbose debug\nAC_ARG_ENABLE(debugg,\n   --enable-debugg     \t   Compile with verbose logging for debug,\n   DEBUGG=$enableval,\n   DEBUGG=no\n)\n\nAC_ARG_ENABLE(self-testing,\n   --enable-self-testing         Compile with self-testing support,\n   SELFTESTING=$enableval,\n   SELFTESTING=no\n)\n\nAC_ARG_ENABLE(client-only,\n   --enable-client-only     \t   Client only version,\n   CLIENTONLY=$enableval,\n   CLIENTONLY=no\n)\n\nAC_ARG_WITH(ssl-headers,\n   --with-ssl-headers=DIR  Crypto Include files location,\n   SSL_HDR_DIR=\"$withval\"\n   CPPFLAGS=\"$CPPFLAGS -I$withval\" \n)\nAC_ARG_WITH(ssl-lib,\n   --with-ssl-lib=DIR      Crypto Library location,\n   LIBS=\"$LIBS -L$withval\" \n)\n\nAC_ARG_WITH(lzo-headers,\n   --with-lzo-headers=DIR     LZO Include files location,\n   LZO_HDR_DIR=\"$withval\"\n)\nAC_ARG_WITH(lzo-lib,\n   --with-lzo-lib=DIR         LZO Library location,\n   LIBS=\"$LIBS -L$withval\" \n)\n\nAC_ARG_WITH(blowfish-headers,\n   --with-blowfish-headers=DIR     Blowfish Include files location,\n   BLOWFISH_HDR_DIR=\"$withval\"\n)\n\nAC_ARG_WITH(socks-lib,\n   --with-socks-lib=DIR         SOCKS Library location,\n   LIBS=\"$LIBS -L$withval\" \n)\n\ndnl Guess host type.\nAC_CANONICAL_HOST\nAC_CANONICAL_SYSTEM\n\ndnl Check for programs.\nAC_PROG_YACC\nAC_PROG_LEX\nAC_PROG_CC\nAC_PROG_INSTALL\n\ndnl Checks for typedefs, structures, and compiler characteristics.\nAC_C_CONST\nAC_C_INLINE\n\ndnl Check for header files.\nAC_HEADER_STDC\nAC_CHECK_HEADERS(sys/resource.h netdb.h sched.h resolv.h arpa/inet.h)\nAC_CHECK_HEADERS(netinet/ip.h netinet/in.h netinet/tcp.h netinet/in_systm.h)\nAC_CHECK_HEADERS(libutil.h sys/sockio.h)\n\ndnl Check for libsocket\nAC_SEARCH_LIBS(socket, socket)\n\ndnl Check for libnsl\nAC_SEARCH_LIBS(inet_ntoa, nsl)\n\ndnl Check for pthread\nAC_SEARCH_LIBS(pthread_create, pthread)\n\ndnl Check for libresolv\nAC_SEARCH_LIBS(gethostbyname, resolv nsl)\n\ndnl Check for librt\nAC_SEARCH_LIBS(nanosleep, rt posix4)\n\ndnl Check for setproctitle in libutil\nAC_SEARCH_LIBS(setproctitle, util bsd, AC_DEFINE(HAVE_SETPROC_TITLE) )\n\nif test \"$MARK\" = \"no\"; then\n\t  CFLAGS=\"$CFLAGS -DW_O_SO_MARK=1\"\nfi\n\nif test \"$SYSLOG\" = \"yes\"; then\n          CFLAGS=\"$CFLAGS -DSYSLOG=1\"\nfi\n\nif test \"$SUM_SEND\" = \"yes\"; then\n          CFLAGS=\"$CFLAGS -DSUM_SEND=1\"\nfi\n\nif test \"$DEBUGG\" = \"yes\"; then\n\t  CFLAGS=\"$CFLAGS -DDEBUGG=1\"\nfi\n\nif test \"$SELFTESTING\" = \"yes\"; then\n          CFLAGS=\"$CFLAGS -DTESTING=1\"\nfi\n\nif test \"$LOW_MEM\" = \"yes\"; then\n          CFLAGS=\"$CFLAGS -DLOW_MEM=1\"\nfi\n\nif test \"$JSON\" = \"yes\"; then\n          CFLAGS=\"$CFLAGS -DJSON=1\"\nfi\n\nif test \"$O3\" = \"yes\"; then\n\t  CFLAGS=\"$CFLAGS -O3\"\nfi\n\nif test \"$CLIENTONLY\" = \"yes\"; then\n\t  CFLAGS=\"$CFLAGS -DCLIENTONLY=1\"\nfi\n\nAC_MSG_RESULT()\n\nAC_CHECK_FUNCS([getpt grantpt unlockpt ptsname])\n\nOS_REL=`uname -r | tr -d '[A-Za-z\\-\\_\\.]'`\ncase $host_os in\n\t*linux*)\n\t     OS_DIR=\"linux\"\n\t     AC_CHECK_HEADERS(linux/if_tun.h)\n\t     ;;\n\t*solaris*)\n\t     OS_DIR=\"svr4\"\n\t     ;;\n\t*freebsd*)\n\t     if test \"$OS_REL\" -ge \"40\"; then \n\t        OS_DIR=\"freebsd\"\n\t     fi\n\t     ;;\n\t*openbsd*)\n\t     if test \"$OS_REL\" -ge \"25\"; then \n\t        OS_DIR=\"openbsd\"\n\t     fi\n\t     ;;\nesac\t     \nAC_LINK_DRV(`cat vtun.drivers`, $OS_DIR)\n\nAC_MSG_RESULT()\n\ndnl Build release name\nchangequote(<,>)\ndnl REL=`echo 'BRANCH-3_X' | tr -d '$: \\-' | sed 's/^[A-Za-z]*//' | sed 's/\\_/\\./'`\nREL=\"0.1b\"\nchangequote([,])\n\nAC_DEFINE_UNQUOTED(VTUN_VER, \"$REL `date '+%m/%d/%Y'`\")\n\nAC_OUTPUT(Makefile)\n"
  },
  {
    "path": "const.h",
    "content": "\n#ifndef _CONST_H\n#define _CONST_H\n\n// max aggregated VPN-links compiled-in (+ some extras for racing)\n#define MAX_TCP_PHYSICAL_CHANNELS 7\n#define AGAG_AG_THRESH 30 // how many agag to consider AG mode\n#define DROP_TIME_IMMUNE 2500000 // useconds of drop immune\n#define MAX_HSQS_EAT 20 // percent of channel send_q allowed to be eaten in SELECT_SLEEP_USEC\n#define MAX_HSQS_PUSH 20 // the same for push MSBL to network\n#define MSBL_LIMIT 1000\n#define MSBL_RESERV 10\n#define PBL_SMOOTH_NUMERATOR 5\n#define PBL_SMOOTH_DENOMINATOR 6\n#define EFF_LEN_AVG_N 7\n#define EFF_LEN_AVG_D 8\n#define AVG_LEN_IN_ACK_THRESH 100 /** treat incoming traffic as ACK-only if average incoming packet length is lower than this */\n#define LOSSED_BACKLOG_SIZE 250\n#define UNRECOVERABLE_LOSS LOSSED_BACKLOG_SIZE-1 /** amount of packets that we won't even try to retransmit */\n#define WBUF_HASH_SIZE 256\n#define MAX_WBUF_HASH_DEPTH 6\n#define RSR_TOP 2990000 // now infinity...\n#define MIN_PPS 10 // minimal packets per second for the system\n#define TOKENS_MAXWAIT 40 // amount of tokens to wait for drop max. (this limits jitter)\n#define MAX_PACKET_WAIT {5,0} // 5 seconds max possible total lag before unconditional drop\n\n// general const\n\n#define SESSION_NAME_SIZE 50\n// maximum compiled-in buffers for tcp channels per link\n#define MAX_TCP_LOGICAL_CHANNELS 7//100 // int\n#define SPEED_AVG_ARR 15 // for speed_algo.h structs\n#define PLP_BUF_SIZE 20 // size of buffer used for old values of PBL for PLP calc\n/* Max lenght of device name */\n#define VTUN_DEV_LEN  20 \n// should be --> MAX_ALLOWED_BUF_LEN*TCP_CONN_AMOUNT to exclude outages\n#define FRAME_BUF_SIZE 2200 // int WARNING: see P_MAX_ALLOWED_BUF_LEN\n\n// to avoid drops absolutely, this should be able to hold up to MAX_LATENCY_DROP*(TCP_CONN_AMOUT+1)*speed packets!\n#ifdef LOW_MEM\n    #define RESEND_BUF_SIZE 600 // int\n    #define JS_MAX 1000 // data for logs, * 3 times is allocated\n#else\n    #define RESEND_BUF_SIZE 3000 // int\n    #define JS_MAX 20000 // 100kb string len of JSON logs * 3 size is used!\n#endif\n#define FAST_RESEND_BUF_SIZE 21 // (MAX_TCP_PHYSICAL_CHANNELS*3)\n#define FLUSHED_PACKET_ARRAY_SIZE 1000 // size of hashed seq_num array to check for flushed packets\n#define CHECK_SZ 256 // size of bit check field\n#define LOSS_ARRAY 80\n#define W_STREAMS_AMT 1000\n#endif"
  },
  {
    "path": "debian/changelog",
    "content": "vtrunkd (0.1-1) unstable; urgency=low\n\n  * Initial release (Closes: #205)\n\n -- David Parunakian <dp@dp.io>  Sat, 16 Jan 2016 00:07:40 +0300\n"
  },
  {
    "path": "debian/compat",
    "content": "9\n"
  },
  {
    "path": "debian/control",
    "content": "Source: vtrunkd\nSection: net\nPriority: optional\nMaintainer: David Parunakian <dp@dp.io>\nBuild-Depends: debhelper (>= 9), autotools-dev, bison, flex, build-essential, liblzo2-dev,\n zlib1g-dev, libssl-dev\nStandards-Version: 3.9.5\nHomepage: http://vrayo.com\n\nPackage: vtrunkd\nArchitecture: amd64\nDepends: ${shlibs:Depends}, ${misc:Depends}, udev [linux-any] | makedev [linux-any], python-pip, python-all-dev, libffi-dev\nDescription: Wireless channel trunking daemon\n The first software inverse multiplexing solution for connected automotive,\n live streaming, bonded internet and more.\n"
  },
  {
    "path": "debian/copyright",
    "content": "Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: vtrunkd\nSource: <http://vrayo.com>\n\nFiles: *\nCopyright: Copyright (C) 2011-2016 Vrayo Systems Ltd. team\n           1998-2003 Maxim Krasnyansky <max_mk@yahoo.com>\n\nLicense: \n\n   This package is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n   .\n   This package is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n   .\n   You should have received a copy of the GNU General Public License\n   along with this package; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA\n   .\n   In addition, as a special exception, the copyright holders give permission\n   to link the code of portions of this program with the OpenSSL library under\n   certain conditions as described in each individual source file, and\n   distribute linked combinations including the two.\n   .\n   You must obey the GNU General Public License in all respects for all of the\n   code used other than OpenSSL. If you modify file(s) with this exception, you\n   may extend this exception to your version of the file(s), but you are not\n   obligated to do so. If you do not wish to do so, delete this exception\n   statement from your version. If you delete this exception statement from all\n   source files in the program, then also delete it here.\n   .\nOn Debian systems, the complete text of the GNU General\nPublic License can be found in `/usr/share/common-licenses/GPL'.\n\nThe Debian packaging is © 2006-2008, Martín Ferrari <martin.ferrari@gmail.com>\nand is licensed under the GPL, see above.\n\nFiles: debian/*\nCopyright: 2016 David Parunakian <dp@dp.io>\nLicense: GPL-2+\n This package is free software; you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation; either version 2 of the License, or\n (at your option) any later version.\n .\n This package is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n .\n You should have received a copy of the GNU General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>\n .\n On Debian systems, the complete text of the GNU General\n Public License version 2 can be found in \"/usr/share/common-licenses/GPL-2\".\n"
  },
  {
    "path": "debian/docs",
    "content": "Credits\nFAQ\nREADME\nREADME.Setup\n"
  },
  {
    "path": "debian/logrotate",
    "content": "/var/log/vtrunkd/*.dump {\n  rotate 54\n  daily\n  compress\n  copytruncate\n  missingok\n}\n"
  },
  {
    "path": "debian/postinst",
    "content": "#!/bin/sh\n# postinst script for vtrunkd\n#\n# see: dh_installdeb(1)\n\nset -e\n\ncase \"$1\" in\n    configure)\n\n\tpip install cffi==1.0.0 snakemq==1.2\n\n    service vtrunkd-helper start\n\t\n    ;;\n\n    abort-upgrade|abort-remove|abort-deconfigure)\n    ;;\n\n    *)\n        echo \"postinst called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "debian/postrm",
    "content": "#!/bin/sh\n# postrm script for vtrunkd\n#\n# see: dh_installdeb(1)\n\nset -e\n\ncase \"$1\" in\n    purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)\n\n\trm -rf /var/run/vtrunkd\n\trm -rf /usr/lib/python2.7/dist-packages/vtrunkd_helper\n\n    ;;\n\n    *)\n        echo \"postrm called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "debian/prerm",
    "content": "#!/bin/bash -e\n# postrm script for vtrunkd\n#\n# see: dh_installdeb(1)\n\nset -e\n\ncase ${1} in\n\n    remove|upgrade|deconfigure)\n\t\n\tservice vtrunkd-helper stop || true\n\t\n    ;;\n\n    failed-upgrade)\n\n    ;;\n\n    *)\n\n        echo \"prerm no reconoce el argumento '\"${1}\"'\" >&2\n        exit 1\n    ;;\n\nesac\n\n#DEBHELPER#\n\nexit 0"
  },
  {
    "path": "debian/rules",
    "content": "#!/usr/bin/make -f\n# See debhelper(7) (uncomment to enable)\n# output every command that modifies files on the build system.\n#DH_VERBOSE = 1\n\n# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*\nDPKG_EXPORT_BUILDFLAGS = 1\ninclude /usr/share/dpkg/default.mk\n\n# see FEATURE AREAS in dpkg-buildflags(1)\n#export DEB_BUILD_MAINT_OPTIONS = hardening=+all\n\n# see ENVIRONMENT in dpkg-buildflags(1)\n# package maintainers to append CFLAGS\n#export DEB_CFLAGS_MAINT_APPEND  = -Wall -pedantic\n# package maintainers to append LDFLAGS\n#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed\n\n\n# main packaging script based on dh7 syntax\n%:\n\tdh $@  --with autotools-dev\n\n# debmake generated override targets\n# This is example for Cmake (See http://bugs.debian.org/641051 )\n#override_dh_auto_configure:\n#\tdh_auto_configure -- \\\n#\t-DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)\n\noverride_dh_installdocs:\n\n\n"
  },
  {
    "path": "debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "debian/vtrunkd2.substvars",
    "content": "shlibs:Depends=libc6 (>= 2.15)\nmisc:Depends=\n"
  },
  {
    "path": "defines.h",
    "content": "/*\n * defines.h\n *\n *  Created on: 03.09.2014\n *      Author: Vrayo Systems Ltd. team\n */\n\n#ifndef DEFINES_H_\n#define DEFINES_H_\n\n#define SEQ_START_VAL 10\n\n\n#endif /* DEFINES_H_ */\n"
  },
  {
    "path": "driver.h",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * driver.h,v 1.1.1.1.2.1.2.1 2006/11/16 04:02:57 mtbishop Exp\n */ \n#ifndef _DRIVER_H\n#define _DRIVER_H\n\n/* Definitions for device and protocol drivers \n * Interface will be completely rewritten in \n * version 3.0\n */\n\nextern int (*dev_write)(int fd, char *buf, int len);\nextern int (*dev_read)(int fd, char *buf, int len);\n\nextern int (*proto_write)(int fd, char *buf, int len);\nextern int (*proto_read)(int fd, char *buf);\n\nint tun_open(char *dev);\nint tun_close(int fd, char *dev);\nint tun_write(int fd, char *buf, int len);\nint tun_read(int fd, char *buf, int len);\n\nint tap_open(char *dev);\nint tap_close(int fd, char *dev);\nint tap_write(int fd, char *buf, int len);\nint tap_read(int fd, char *buf, int len);\n\nint pty_open(char *dev);\nint pty_write(int fd, char *buf, int len);\nint pty_read(int fd, char *buf, int len);\n\nint pipe_open(int *fd);\nint pipe_write(int fd, char *buf, int len);\nint pipe_read(int fd, char *buf, int len);\n\nint tcp_write(int fd, char *buf, int len);\nint tcp_read(int fd, char *buf);\n\nint udp_write(int fd, char *buf, int len);\nint udp_read(int fd, char *buf);\n\n#endif\n"
  },
  {
    "path": "frame_llist.c",
    "content": "\n/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * llist.c,v 1.1.1.2.6.1 2006/11/16 04:03:29 mtbishop Exp\n */ \n\n#include <stdlib.h>\n#include <string.h>\n#include \"frame_llist.h\"\n\n/* Function to work with the Linked Lists */\n\n\n\nvoid frame_llist_init(struct frame_llist *l) {\n    l->rel_head = l->rel_tail = -1;\n    l->length = 0;\n    l->stub_total = 0;\n} \n\nvoid frame_llist_fill(struct frame_llist *l, struct frame_seq flist[], int len)\n{\n    int i;\n    l->rel_head = 0;\n    l->length = 0;\n    for (i = 0; i < (len - 1); i++) {\n        flist[i].rel_next = i + 1;\n    }\n    flist[len - 1].rel_next = -1;\n    l->rel_tail = len - 1;\n    l->length = len;\n} \n\n\nint frame_llist_empty(struct frame_llist *l)\n{\n\treturn l->rel_tail == -1;\n}\n\n\nint frame_llist_pull(struct frame_llist *lfree, struct frame_seq flist[], int *f)\n{\n\tif(lfree->rel_head == -1) { // no more chunks available\n\t\treturn -1; \n\t}\n    lfree->length--;\n\t*f = lfree->rel_head;\n\tlfree->rel_head = flist[lfree->rel_head].rel_next;\n    if (lfree->rel_head == -1)\n        lfree->rel_tail = -1;\n    flist[(*f)].rel_next = -1; // make sure to set it!\n    return 0;\n}\n\nvoid frame_llist_append(struct frame_llist *l, int f, struct frame_seq buf[]) {\n    if(l->rel_tail > -1) {\n          buf[l->rel_tail].rel_next = f;\n          l->rel_tail = f;\n    } else {\n          l->rel_tail = l->rel_head = f;\n    }\n    buf[f].rel_next = -1;\n    l->length++;\n}\n\n\nvoid frame_llist_prepend(struct frame_llist *l, int f, struct frame_seq buf[]) {\n    if(l->rel_head > -1) {\n          buf[f].rel_next = l->rel_head;\n          l->rel_head = f;\n    } else {\n          l->rel_tail = l->rel_head = f;\n          buf[f].rel_next = -1;\n    }\n    l->length++;\n}\n\n\n/* free a frame into free list */\nint frame_llist_free(struct frame_llist *l, struct frame_llist *lfree, struct frame_seq flist[], int f)\n{\t\n\tint i = l->rel_head, n, prev=-1;\n\tint icbt = 0;\n\tif(i<0) return i;\n\n\twhile( i > -1 ){\n\t   n = flist[i].rel_next; \t\n\t   if( f == i ) {\n\t\tif(f == l->rel_head) {\n\t\t\tl->rel_head = n;\n\t\t} else {\n\t\t\tflist[prev].rel_next = n;\n\t\t}\n\t\tif(lfree->rel_head == -1)\n\t\t\tlfree->rel_head = lfree->rel_tail = f;\n\t\telse\n\t\t\tflist[lfree->rel_tail].rel_next = f;\n\t\tlfree->rel_tail = f;\n\t\tflist[f].rel_next = -1;\n\t\tbreak;\n\t   }\n\t   prev = i;\n\t   i = n;\n\t   if( (icbt++) > 2000) break; // TODO: logging???\n\t}\n\treturn 0;\n} \n\n"
  },
  {
    "path": "frame_llist.h",
    "content": "\n/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Andrew Gryaznov <realgrandrew@gmail.com>\n   This file is dual-licensed to be compatible with \n   Vrayo Systems vtrunkd_helper, part of Vrayo Internet Combiner package\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * llist.h,v 1.1.1.2.6.1 2006/11/16 04:03:32 mtbishop Exp\n */ \n\n#ifndef _VTUN_FRAME_LLIST_H\n#define _VTUN_FRAME_LLIST_H\n\n#include <sys/time.h>\n#include <stdint.h>\n#include \"const.h\"\n\n#define VTUN_FRAME_SIZE2 1536 // 3*512\n\nstruct frame_seq {\n    char out[VTUN_FRAME_SIZE2];\n    int len;\n    unsigned long seq_num;\n    unsigned long local_seq_num[MAX_TCP_PHYSICAL_CHANNELS];\n    int rel_next; // relative pointer [TODO: make it short or even char!]\n    int sender_pid; // okay as short?\n    int chan_num;\n    int physical_channel_num;\n    struct timeval time_stamp;\n    struct timeval flush_time;\n    int current_rtt;\n    uint32_t marker;\n    int stub_counter; // amount of stub packets before this one to skip\n    unsigned int shash; // stream hash (max W_STREAMS_AMT)\n    int unconditional_write_flag;\n};\n\nstruct frame_llist{\n\tint rel_head;\n\tint rel_tail;\n    int length;\n    int stub_total; // not controlled by standard methods; total stub packets in buffer \n};\n\nvoid frame_llist_fill(struct frame_llist *l, struct frame_seq flist[], int len);\nvoid frame_llist_init(struct frame_llist *l);\nint frame_llist_empty(struct frame_llist *l);\nint frame_llist_free(struct frame_llist *l, struct frame_llist *lfree, struct frame_seq flist[], int f);\nint frame_llist_pull(struct frame_llist *lfree, struct frame_seq flist[], int *f);\nvoid frame_llist_append(struct frame_llist *l, int f, struct frame_seq buf[]);\nvoid frame_llist_prepend(struct frame_llist *l, int f, struct frame_seq buf[]);\n\n\n#endif /* _VTUN_FRAME_LLIST_H */\n"
  },
  {
    "path": "generic/pipe_dev.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * pipe_dev.c,v 1.1.1.1.2.1.2.1 2006/11/16 04:04:26 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <syslog.h>\n#include <sys/socket.h>\n\n#include \"vtun.h\"\n#include \"lib.h\"\n\n/* \n * Create pipe. Return open fd. \n */  \nint pipe_open(int *fd)\n{\n    return socketpair(AF_UNIX, SOCK_STREAM, 0, fd);\n}\n\n/* Write frames to pipe */\nint pipe_write(int fd, char *buf, int len)\n{\n    return write_n(fd, buf, len);\n}\n\n/* Read frames from pipe */\nint pipe_read(int fd, char *buf, int len)\n{\n    return read(fd, buf, len);\n}\n"
  },
  {
    "path": "generic/pty_dev.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * pty_dev.c,v 1.1.1.1.2.3.2.1 2006/11/16 04:04:29 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <syslog.h>\n\n#include \"vtun.h\"\n#include \"lib.h\"\n\n/* \n * Allocate pseudo tty, returns master side fd. \n * Stores slave name in the first arg(must be large enough).\n */  \nint pty_open(char *sl_name)\n{\n    int  mr_fd;\n#if defined (HAVE_GETPT) && defined (HAVE_GRANTPT) && defined (HAVE_UNLOCKPT) && defined (HAVE_PTSNAME)\n    char *ptyname;\n\n    if((mr_fd=getpt()) < 0)\n \treturn -1;\n    if(grantpt(mr_fd) != 0)\n\treturn -1;\n    if(unlockpt(mr_fd) != 0)\n\treturn -1;\n    if ((ptyname = (char*)ptsname(mr_fd)) == NULL)\n\treturn -1;\n    strcpy(sl_name, ptyname);\n    return mr_fd;\n\n#else\n\n    char ptyname[] = \"/dev/ptyXY\";\n    char ch[] = \"pqrstuvwxyz\";\n    char digit[] = \"0123456789abcdefghijklmnopqrstuv\";\n    int  l, m;\n\n    /* This algorithm should work for almost all standard Unices */\t\n    for(l=0; ch[l]; l++ ) {\n        for(m=0; digit[m]; m++ ) {\n\t \tptyname[8] = ch[l];\n\t\tptyname[9] = digit[m];\n\t\t/* Open the master */\n\t\tif( (mr_fd=open(ptyname, O_RDWR)) < 0 )\n\t \t   continue;\n\t\t/* Check the slave */\n\t\tptyname[5] = 't';\n\t\tif( (access(ptyname, R_OK | W_OK)) < 0 ){\n\t\t   close(mr_fd);\n\t\t   ptyname[5] = 'p';\n\t\t   continue;\n\t\t}\n\t\tstrcpy(sl_name,ptyname);\n\t\treturn mr_fd;\n\t    }\n\t}\n\treturn -1;\n#endif\n}\n\n/* Write frames to PTY device */\nint pty_write(int fd, char *buf, int len)\n{\n    return write_n(fd, buf, len);\n}\n\n/* Read frames from PTY device */\nint pty_read(int fd, char *buf, int len)\n{\n    return read(fd, buf, len);\n}\n"
  },
  {
    "path": "generic/tap_dev.c",
    "content": "/*  \n    VTun - Virtual Tunnel over TCP/IP network.\n\n    Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n    VTun has been derived from VPPP package by Maxim Krasnyansky. \n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n */\n\n/*\n * tap_dev.c,v 1.2.2.1.2.1 2006/11/16 04:04:32 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <syslog.h>\n\n#include \"vtun.h\"\n#include \"lib.h\"\n\n/* \n * Allocate Ether TAP device, returns opened fd. \n * Stores dev name in the first arg(must be large enough).\n */ \nint tap_open(char *dev)\n{\n    char tapname[14];\n    int i, fd;\n\n    if( *dev ) {\n       sprintf(tapname, \"/dev/%s\", dev);\n       return open(tapname, O_RDWR);\n    }\n\n    for(i=0; i < 255; i++) {\n       sprintf(tapname, \"/dev/tap%d\", i);\n       /* Open device */\n       if( (fd=open(tapname, O_RDWR)) > 0 ) {\n          sprintf(dev, \"tap%d\",i);\n          return fd;\n       }\n    }\n    return -1;\n}\n\nint tap_close(int fd, char *dev)\n{\n    return close(fd);\n}\n\n/* Write frames to TAP device */\nint tap_write(int fd, char *buf, int len)\n{\n    return write(fd, buf, len);\n}\n\n/* Read frames from TAP device */\nint tap_read(int fd, char *buf, int len)\n{\n    return read(fd, buf, len);\n}\n"
  },
  {
    "path": "generic/tcp_proto.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team,\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * tcp_proto.c,v 1.4.2.3.2.1 2006/11/16 04:04:35 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdint.h>\n#include <string.h>\n#include <sys/time.h>\n#include <sys/wait.h>\n#include <syslog.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/uio.h>\n#include <errno.h>\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\n#ifdef HAVE_NETINET_IN_SYSTM_H\n#include <netinet/in_systm.h>\n#endif\n\n#ifdef HAVE_NETINET_IP_H\n#include <netinet/ip.h>\n#endif\n\n#ifdef HAVE_NETINET_TCP_H\n#include <netinet/tcp.h>\n#endif\n\n#include \"vtun.h\"\n#include \"lib.h\"\n#include \"log.h\"\n\nint tcp_write(int fd, char *buf, int len)\n{\n     char *ptr;\n     int bad_frame = len & ~VTUN_FSIZE_MASK;\n#ifdef BAD_LOCAL_SEQ_LOG_TCP\n     if (bad_frame == 0) {\n         vlog(LOG_INFO, \"tcp local_seqnum %lu regular packet\", ntohl(*((uint32_t *) (&buf[len - 3 * sizeof(uint32_t) - sizeof(uint16_t)]))));\n     } else if(bad_frame == VTUN_BAD_FRAME) {\n         int flag_var = 0;\n         memcpy(&flag_var, buf + sizeof(uint32_t), sizeof(uint16_t));\n         if (ntohs(flag_var) == FRAME_REDUNDANCY_CODE) {\n             vlog(LOG_INFO, \"tcp local_seqnum %lu sum packet\", ntohl(*((uint32_t *) (&buf[len - 4 * sizeof(uint32_t)]))));\n         }\n     } else  {\n         vlog(LOG_INFO, \"tcp local_seqnum other\");\n     }\n#endif\n     ptr = buf - sizeof(uint16_t);\n\n     *((uint16_t *)ptr) = htons(len);\n     len  = (len & VTUN_FSIZE_MASK) + sizeof(uint16_t);\n\n     return write_n(fd, ptr, len);\n}\n\nint tcp_read(int fd, char *buf)\n{\n     uint16_t len, flen;\n     int rlen;\n\n     /* Rad frame size */\n     if( (rlen = read_n(fd, (char *)&len, sizeof(uint16_t)) ) <= 0) {\n#ifdef DEBUGG\n        vlog(LOG_ERR, \"Null-size or -1 frame length received len %d\", rlen); // TODO: remove! OK on client connect error\n#endif\n          return rlen;\n     }\n\n     len = ntohs(len);\n     flen = len & VTUN_FSIZE_MASK;\n\n     if( flen > VTUN_FRAME_SIZE + VTUN_FRAME_OVERHEAD ){\n     \t/* Oversized frame, drop it. */ \n        while( flen ){\n\t   len = min(flen, VTUN_FRAME_SIZE);\n           if( (rlen = read_n(fd, buf, len)) <= 0 )\n\t      break;\n           flen -= rlen;\n        }\n        vlog(LOG_ERR, \"Oversized frame received %hd\", flen); // TODO: remove!\n\treturn VTUN_BAD_FRAME;\n     }\t\n\n     if( len & ~VTUN_FSIZE_MASK ){\n\t/* Return flags */\n        read_n(fd, buf, flen);\n\treturn len;\n     }\n\n     /* Read frame */\n     return read_n(fd, buf, flen);\n}\n"
  },
  {
    "path": "generic/tun_dev.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * tun_dev.c,v 1.2.2.1.2.1 2006/11/16 04:04:40 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <syslog.h>\n\n#include \"vtun.h\"\n#include \"lib.h\"\n\n/* \n * Allocate TUN device, returns opened fd. \n * Stores dev name in the first arg(must be large enough).\n */  \nint tun_open(char *dev)\n{\n    char tunname[14];\n    int i, fd;\n\n    if( *dev ) {\n       sprintf(tunname, \"/dev/%s\", dev);\n       return open(tunname, O_RDWR);\n    }\n\n    for(i=0; i < 255; i++){\n       sprintf(tunname, \"/dev/tun%d\", i);\n       /* Open device */\n       if( (fd=open(tunname, O_RDWR)) > 0 ){\n          sprintf(dev, \"tun%d\", i);\n          return fd;\n       }\n    }\n    return -1;\n}\n\nint tun_close(int fd, char *dev)\n{\n    return close(fd);\n}\n\n/* Read/write frames from TUN device */\nint tun_write(int fd, char *buf, int len)\n{\n    return write(fd, buf, len);\n}\n\nint tun_read(int fd, char *buf, int len)\n{\n    return read(fd, buf, len);\n}\n"
  },
  {
    "path": "generic/udp_proto.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * udp_proto.c,v 1.5.2.3.2.1 2006/11/16 04:04:43 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <stdarg.h>\n#include <sys/time.h>\n#include <sys/wait.h>\n#include <syslog.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/uio.h>\n#include <errno.h>\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\n#ifdef HAVE_NETINET_IN_SYSTM_H\n#include <netinet/in_systm.h>\n#endif\n\n#ifdef HAVE_NETINET_IP_H\n#include <netinet/ip.h>\n#endif\n\n#ifdef HAVE_NETINET_TCP_H\n#include <netinet/udp.h>\n#endif\n\n#include \"vtun.h\"\n#include \"lib.h\"\n\n//#define BAD_LOCAL_SEQ_LOG 1\n\nuint32_t previous_local_seq_num = 0;\n\n/* Functions to read/write UDP frames. */\nint udp_write(int fd, char *buf, int len)\n{\n     register char *ptr;\n     register int wlen;\n    int bad_frame = len & ~VTUN_FSIZE_MASK;\n#ifdef BAD_LOCAL_SEQ_LOG\n    if (bad_frame == 0) {\n        uint32_t local_seq_num = ntohl(*((uint32_t *) (&buf[len - 3 * sizeof(uint32_t) - sizeof(uint16_t)])));\n        if ((previous_local_seq_num) && ((previous_local_seq_num + 1) != local_seq_num)) {\n            vtun_syslog(LOG_INFO, \"udp local_seqnum %lu prev %lu regular packet\", local_seq_num, previous_local_seq_num);\n        }\n        if (local_seq_num)\n            previous_local_seq_num = local_seq_num;\n    } else if (bad_frame == VTUN_BAD_FRAME) {\n        int flag_var = 0;\n        memcpy(&flag_var, buf + sizeof(uint32_t), sizeof(uint16_t));\n        flag_var = ntohs(flag_var);\n        if (flag_var == FRAME_REDUNDANCY_CODE) {\n            uint32_t local_seq_num = ntohl(*((uint32_t *) (&buf[len - 4 * sizeof(uint32_t)])));\n            if ((previous_local_seq_num) && ((previous_local_seq_num + 1) != local_seq_num)) {\n                vtun_syslog(LOG_INFO, \"udp local_seqnum %lu prev %lu sum packet\", local_seq_num, previous_local_seq_num);\n            }\n            if (local_seq_num)\n                previous_local_seq_num = local_seq_num;\n        }\n        if (flag_var == FRAME_CHANNEL_INFO) {\n            uint32_t local_seq_num = ntohl(*((uint32_t *) (&buf[4 * sizeof(uint16_t) + sizeof(uint32_t)])));\n            if ((previous_local_seq_num) && ((previous_local_seq_num + 1) != local_seq_num)) {\n                vtun_syslog(LOG_INFO, \"udp local_seqnum %lu prev %lu FCI\", local_seq_num, previous_local_seq_num);\n            }\n            if (local_seq_num)\n                previous_local_seq_num = local_seq_num;\n        }\n    } else {\n//        vtun_syslog(LOG_INFO, \"udp local_seqnum other\");\n    }\n#endif\n\n     ptr = buf - sizeof(uint16_t);\n\n     *((uint16_t *)ptr) = htons(len);\n     len  = (len & VTUN_FSIZE_MASK) + sizeof(uint16_t);\n\n     while( 1 ){\n\tif( (wlen = write(fd, ptr, len)) < 0 ){ \n\t   if( errno == EAGAIN || errno == EINTR )\n\t      continue;\n\t   if( errno == ENOBUFS )\n\t      return 0;\n\t}\n\t/* Even if we wrote only part of the frame\n         * we can't use second write since it will produce \n         * another UDP frame */  \n        return wlen;\n     }\n}\n\nint udp_read(int fd, char *buf)\n{\n     uint16_t hdr, flen;\n     struct iovec iv[2];\n     register int rlen;\n\n     /* Read frame */\n     iv[0].iov_len  = sizeof(uint16_t);\n     iv[0].iov_base = (char *) &hdr;\n     iv[1].iov_len  = VTUN_FRAME_SIZE + VTUN_FRAME_OVERHEAD;\n     iv[1].iov_base = buf;\n\n     while( 1 ){\n        if( (rlen = readv(fd, iv, 2)) < 0 ){ \n\t   if( errno == EAGAIN || errno == EINTR )\n\t      continue;\n\t   else\n     \t      return rlen;\n\t}\n        hdr = ntohs(hdr);\n        flen = hdr & VTUN_FSIZE_MASK;\n\n        if( rlen < 2 || (rlen-2) != flen )\n\t   return VTUN_BAD_FRAME;\n\n\treturn hdr;\n     }\n}\t\t\n"
  },
  {
    "path": "install-sh",
    "content": "#! /bin/sh\n#\n# install - install a program, script, or datafile\n# This comes from X11R5.\n#\n# Calling this script install-sh is preferred over install.sh, to prevent\n# `make' implicit rules from creating a file called install from it\n# when there is no Makefile.\n#\n# This script is compatible with the BSD install script, but was written\n# from scratch.\n#\n\n\n# set DOITPROG to echo to test this script\n\n# Don't use :- since 4.3BSD and earlier shells don't like it.\ndoit=\"${DOITPROG-}\"\n\n\n# put in absolute paths if you don't have them in your path; or use env. vars.\n\nmvprog=\"${MVPROG-mv}\"\ncpprog=\"${CPPROG-cp}\"\nchmodprog=\"${CHMODPROG-chmod}\"\nchownprog=\"${CHOWNPROG-chown}\"\nchgrpprog=\"${CHGRPPROG-chgrp}\"\nstripprog=\"${STRIPPROG-strip}\"\nrmprog=\"${RMPROG-rm}\"\nmkdirprog=\"${MKDIRPROG-mkdir}\"\n\ntranformbasename=\"\"\ntransform_arg=\"\"\ninstcmd=\"$mvprog\"\nchmodcmd=\"$chmodprog 0755\"\nchowncmd=\"\"\nchgrpcmd=\"\"\nstripcmd=\"\"\nrmcmd=\"$rmprog -f\"\nmvcmd=\"$mvprog\"\nsrc=\"\"\ndst=\"\"\ndir_arg=\"\"\n\nwhile [ x\"$1\" != x ]; do\n    case $1 in\n\t-c) instcmd=\"$cpprog\"\n\t    shift\n\t    continue;;\n\n\t-d) dir_arg=true\n\t    shift\n\t    continue;;\n\n\t-m) chmodcmd=\"$chmodprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-o) chowncmd=\"$chownprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-g) chgrpcmd=\"$chgrpprog $2\"\n\t    shift\n\t    shift\n\t    continue;;\n\n\t-s) stripcmd=\"$stripprog\"\n\t    shift\n\t    continue;;\n\n\t-t=*) transformarg=`echo $1 | sed 's/-t=//'`\n\t    shift\n\t    continue;;\n\n\t-b=*) transformbasename=`echo $1 | sed 's/-b=//'`\n\t    shift\n\t    continue;;\n\n\t*)  if [ x\"$src\" = x ]\n\t    then\n\t\tsrc=$1\n\t    else\n\t\t# this colon is to work around a 386BSD /bin/sh bug\n\t\t:\n\t\tdst=$1\n\t    fi\n\t    shift\n\t    continue;;\n    esac\ndone\n\nif [ x\"$src\" = x ]\nthen\n\techo \"install:\tno input file specified\"\n\texit 1\nelse\n\ttrue\nfi\n\nif [ x\"$dir_arg\" != x ]; then\n\tdst=$src\n\tsrc=\"\"\n\t\n\tif [ -d $dst ]; then\n\t\tinstcmd=:\n\telse\n\t\tinstcmd=mkdir\n\tfi\nelse\n\n# Waiting for this to be detected by the \"$instcmd $src $dsttmp\" command\n# might cause directories to be created, which would be especially bad \n# if $src (and thus $dsttmp) contains '*'.\n\n\tif [ -f $src -o -d $src ]\n\tthen\n\t\ttrue\n\telse\n\t\techo \"install:  $src does not exist\"\n\t\texit 1\n\tfi\n\t\n\tif [ x\"$dst\" = x ]\n\tthen\n\t\techo \"install:\tno destination specified\"\n\t\texit 1\n\telse\n\t\ttrue\n\tfi\n\n# If destination is a directory, append the input filename; if your system\n# does not like double slashes in filenames, you may need to add some logic\n\n\tif [ -d $dst ]\n\tthen\n\t\tdst=\"$dst\"/`basename $src`\n\telse\n\t\ttrue\n\tfi\nfi\n\n## this sed command emulates the dirname command\ndstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`\n\n# Make sure that the destination directory exists.\n#  this part is taken from Noah Friedman's mkinstalldirs script\n\n# Skip lots of stat calls in the usual case.\nif [ ! -d \"$dstdir\" ]; then\ndefaultIFS='\t\n'\nIFS=\"${IFS-${defaultIFS}}\"\n\noIFS=\"${IFS}\"\n# Some sh's can't handle IFS=/ for some reason.\nIFS='%'\nset - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`\nIFS=\"${oIFS}\"\n\npathcomp=''\n\nwhile [ $# -ne 0 ] ; do\n\tpathcomp=\"${pathcomp}${1}\"\n\tshift\n\n\tif [ ! -d \"${pathcomp}\" ] ;\n        then\n\t\t$mkdirprog \"${pathcomp}\"\n\telse\n\t\ttrue\n\tfi\n\n\tpathcomp=\"${pathcomp}/\"\ndone\nfi\n\nif [ x\"$dir_arg\" != x ]\nthen\n\t$doit $instcmd $dst &&\n\n\tif [ x\"$chowncmd\" != x ]; then $doit $chowncmd $dst; else true ; fi &&\n\tif [ x\"$chgrpcmd\" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&\n\tif [ x\"$stripcmd\" != x ]; then $doit $stripcmd $dst; else true ; fi &&\n\tif [ x\"$chmodcmd\" != x ]; then $doit $chmodcmd $dst; else true ; fi\nelse\n\n# If we're going to rename the final executable, determine the name now.\n\n\tif [ x\"$transformarg\" = x ] \n\tthen\n\t\tdstfile=`basename $dst`\n\telse\n\t\tdstfile=`basename $dst $transformbasename | \n\t\t\tsed $transformarg`$transformbasename\n\tfi\n\n# don't allow the sed command to completely eliminate the filename\n\n\tif [ x\"$dstfile\" = x ] \n\tthen\n\t\tdstfile=`basename $dst`\n\telse\n\t\ttrue\n\tfi\n\n# Make a temp file name in the proper directory.\n\n\tdsttmp=$dstdir/#inst.$$#\n\n# Move or copy the file name to the temp name\n\n\t$doit $instcmd $src $dsttmp &&\n\n\ttrap \"rm -f ${dsttmp}\" 0 &&\n\n# and set any options; do chmod last to preserve setuid bits\n\n# If any of these fail, we abort the whole thing.  If we want to\n# ignore errors from any of these, just make sure not to ignore\n# errors from the above \"$doit $instcmd $src $dsttmp\" command.\n\n\tif [ x\"$chowncmd\" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&\n\tif [ x\"$chgrpcmd\" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&\n\tif [ x\"$stripcmd\" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&\n\tif [ x\"$chmodcmd\" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&\n\n# Now rename the file to the real destination.\n\n\t$doit $rmcmd -f $dstdir/$dstfile &&\n\t$doit $mvcmd $dsttmp $dstdir/$dstfile \n\nfi &&\n\n\nexit 0\n"
  },
  {
    "path": "lfd_encrypt.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n   Encryption module uses software developed by the OpenSSL Project\n   for use in the OpenSSL Toolkit. (http://www.openssl.org/)       \n   Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.\n */\n\n/*\n * This lfd_encrypt module uses MD5 to create 128 bits encryption\n * keys and BlowFish for actual data encryption.\n * It is based on code written by Chris Todd<christ@insynq.com> with\n * several improvements and modifications by me.\n */\n\n/*\n * The current lfd_encrypt module is based on code attributed above and \n * uses new code written by Dale Fountain <dpf-vtun@fountainbay.com> to \n * allow multiple ciphers, modes, and key sizes. Feb 2004.\n */\n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <syslog.h>\n#include <strings.h>\n#include <string.h>\n#include <time.h>\n\n#include \"vtun.h\"\n#include \"linkfd.h\"\n#include \"lib.h\"\n#include \"log.h\"\n\n#ifdef HAVE_SSL\n\n/* OpenSSL includes */\n#include <openssl/evp.h>\n#include <openssl/md5.h>\n#include <openssl/blowfish.h>\n#include <openssl/rand.h>\n\n/*\n * #define LFD_ENCRYPT_DEBUG\n */\n\n#define ENC_BUF_SIZE VTUN_FRAME_SIZE + 128 \n#define ENC_KEY_SIZE 16\n\nBF_KEY key;\nchar * enc_buf;\nchar * dec_buf;\n\n#define CIPHER_INIT\t\t0\n#define CIPHER_CODE\t\t1\t\n#define CIPHER_SEQUENCE \t2\n#define CIPHER_REQ_INIT \t3\n\nstruct vtun_host *phost;\n\nextern int send_a_packet;\n\n/* out of sync packet threshold before forcing a re-init */ \n#define MAX_GIBBERISH\t10\n#define MIN_GIBBERISH   1\n#define MAX_GIBBERISH_TIME   2\nint gibberish;\ntime_t gib_time_start;\n\nint cipher_enc_state;\nint cipher_dec_state;\nint cipher;\nint blocksize;\nint keysize;\nint enc_init_first_time;\nint dec_init_first_time;\nunsigned long sequence_num;\nchar * pkey;\nchar * iv_buf;\n\nEVP_CIPHER_CTX ctx_enc;\t/* encrypt */\nEVP_CIPHER_CTX ctx_dec;\t/* decrypt */\n\nEVP_CIPHER_CTX ctx_enc_ecb;\t/* sideband ecb encrypt */\nEVP_CIPHER_CTX ctx_dec_ecb;\t/* sideband ecb decrypt */\n\nint prep_key(char **key, int size, struct vtun_host *host)\n{\n   int tmplen, halflen;\n   char *hashkey;\n\n   if ( !(hashkey = malloc(size)) )\n   {\n      vlog(LOG_ERR,\"Can't allocate buffer for key hash\");\n      return -1;\n   }\n   memset(hashkey,0,size);\n\n   if (size == 32)\n   {\n      tmplen = strlen(host->passwd);\n      if (tmplen != 0) halflen = tmplen>>1;\n      else halflen = 0;\n      MD5(host->passwd, halflen, hashkey);\n      MD5((host->passwd)+halflen, tmplen-halflen, hashkey+16);\n   }\n   else if (size == 16)\n   {\n      MD5(host->passwd,strlen(host->passwd), hashkey);\n   }\n   else\n   {\n      /* don't know what to do */\n      free(hashkey);\n      *key = NULL;\n      return -1;\n   }\n   *key = hashkey;\n   return 0;\n}\n\nvoid free_key (char *key)\n{\n   free(key);\n}\n\nint alloc_encrypt(struct vtun_host *host)\n{\n   int sb_init = 0;\n   int var_key = 0;\n   const EVP_CIPHER *cipher_type;\n   char tmpstr[64];\n   char cipher_name[32];\n   EVP_CIPHER_CTX *pctx_enc;\n   EVP_CIPHER_CTX *pctx_dec;\n\n   enc_init_first_time = 1;   \n   dec_init_first_time = 1;   \n\n   if( !(enc_buf = lfd_alloc(ENC_BUF_SIZE)) ){\n      vlog(LOG_ERR,\"Can't allocate buffer for encryptor\");\n      return -1;\n   }\n   if( !(dec_buf = lfd_alloc(ENC_BUF_SIZE)) ){\n      vlog(LOG_ERR,\"Can't allocate buffer for decryptor\");\n      return -1;\n   }\n\n   RAND_bytes((char *)&sequence_num, 4);\n   gibberish = 0;\n   gib_time_start = 0;\n   phost = host;\n   cipher = host->cipher;\n   switch(cipher)\n   {\n      case VTUN_ENC_AES256OFB:\n      case VTUN_ENC_AES256CFB:\n      case VTUN_ENC_AES256CBC:\n         blocksize = 16;\n         keysize = 32;\n         sb_init = 1;\n         cipher_type = EVP_aes_256_ecb();\n         pctx_enc = &ctx_enc_ecb;\n         pctx_dec = &ctx_dec_ecb;\n      break;\n      \n      case VTUN_ENC_AES256ECB:\n         blocksize = 16;\n         keysize = 32;\n         pctx_enc = &ctx_enc;\n         pctx_dec = &ctx_dec;\n         cipher_type = EVP_aes_256_ecb();\n         strcpy(cipher_name,\"AES-256-ECB\");\n      break;      \n      case VTUN_ENC_AES128OFB:\n      case VTUN_ENC_AES128CFB:\n      case VTUN_ENC_AES128CBC:\n         blocksize = 16;\n         keysize = 16;\n         sb_init=1;\n         cipher_type = EVP_aes_128_ecb();\n         pctx_enc = &ctx_enc_ecb;\n         pctx_dec = &ctx_dec_ecb;\n      break;\n      case VTUN_ENC_AES128ECB:\n         blocksize = 16;\n         keysize = 16;\n         pctx_enc = &ctx_enc;\n         pctx_dec = &ctx_dec;\n         cipher_type = EVP_aes_128_ecb();\n         strcpy(cipher_name,\"AES-128-ECB\");\n      break;\n\n      case VTUN_ENC_BF256OFB:\n      case VTUN_ENC_BF256CFB:\n      case VTUN_ENC_BF256CBC:\n         blocksize = 8;\n         keysize = 32;\n         var_key = 1;\n         sb_init = 1;\n         cipher_type = EVP_bf_ecb();\n         pctx_enc = &ctx_enc_ecb;\n         pctx_dec = &ctx_dec_ecb;\n      break;\n\n      case VTUN_ENC_BF256ECB:\n         blocksize = 8;\n         keysize = 32;\n         var_key = 1;\n         pctx_enc = &ctx_enc;\n         pctx_dec = &ctx_dec;\n         cipher_type = EVP_bf_ecb();\n         strcpy(cipher_name,\"Blowfish-256-ECB\");\n      break;\n\n      case VTUN_ENC_BF128OFB:\n      case VTUN_ENC_BF128CFB:\n      case VTUN_ENC_BF128CBC:\n         blocksize = 8;\n         keysize = 16;\n         var_key = 1;\n         sb_init = 1;\n         cipher_type = EVP_bf_ecb();\n         pctx_enc = &ctx_enc_ecb;\n         pctx_dec = &ctx_dec_ecb;\n      break;\n      case VTUN_ENC_BF128ECB: /* blowfish 128 ecb is the default */\n      default:\n         blocksize = 8;\n         keysize = 16;\n         var_key = 1;\n         pctx_enc = &ctx_enc;\n         pctx_dec = &ctx_dec;\n         cipher_type = EVP_bf_ecb();\n         strcpy(cipher_name,\"Blowfish-128-ECB\");\n      break;\n   } /* switch(host->cipher) */\n\n   if (prep_key(&pkey, keysize, host) != 0) return -1;\n   EVP_CIPHER_CTX_init(pctx_enc);\n   EVP_CIPHER_CTX_init(pctx_dec);\n   EVP_EncryptInit_ex(pctx_enc, cipher_type, NULL, NULL, NULL);\n   EVP_DecryptInit_ex(pctx_dec, cipher_type, NULL, NULL, NULL);\n   if (var_key)\n   {\n      EVP_CIPHER_CTX_set_key_length(pctx_enc, keysize);\n      EVP_CIPHER_CTX_set_key_length(pctx_dec, keysize);\n   }\n   EVP_EncryptInit_ex(pctx_enc, NULL, NULL, pkey, NULL);\n   EVP_DecryptInit_ex(pctx_dec, NULL, NULL, pkey, NULL);\n   EVP_CIPHER_CTX_set_padding(pctx_enc, 0);\n   EVP_CIPHER_CTX_set_padding(pctx_dec, 0);\n   if (sb_init)\n   {\n      cipher_enc_state=CIPHER_INIT;\n      cipher_dec_state=CIPHER_INIT;\n   }\n   else\n   {\n      cipher_enc_state=CIPHER_CODE;\n      cipher_dec_state=CIPHER_CODE;\n      sprintf(tmpstr,\"%s encryption initialized\", cipher_name);\n      vlog(LOG_INFO, tmpstr);\n   }\n   return 0;\n}\n\nint free_encrypt()\n{\n   free_key(pkey); pkey = NULL;\n\n   lfd_free(enc_buf); enc_buf = NULL;\n   lfd_free(dec_buf); dec_buf = NULL;\n\n   EVP_CIPHER_CTX_cleanup(&ctx_enc);\n   EVP_CIPHER_CTX_cleanup(&ctx_dec);\n   EVP_CIPHER_CTX_cleanup(&ctx_enc_ecb);\n   EVP_CIPHER_CTX_cleanup(&ctx_dec_ecb);\n\n   return 0;\n}\n\nint encrypt_buf(int len, char *in, char **out)\n{ \n   register int pad, p, msg_len;\n   int outlen;\n   char *in_ptr, *out_ptr = enc_buf;\n\n   msg_len = send_msg(len, in, out);\n   in = *out;\n   in_ptr = in+msg_len;\n   memcpy(out_ptr,in,msg_len);\n   out_ptr += msg_len;\n   \n   send_ib_mesg(&len, &in_ptr);\n   if (!len) return 0;\n   /* ( len % blocksize ) */\n   p = (len & (blocksize-1)); pad = blocksize - p;\n   \n   memset(in_ptr+len, pad, pad);\n   outlen=len+pad;\n   if (pad == blocksize)\n      RAND_bytes(in_ptr+len, blocksize-1);\n   EVP_EncryptUpdate(&ctx_enc, out_ptr, &outlen, in_ptr, len+pad);\n   *out = enc_buf;\n\n   sequence_num++;\n\n   return outlen+msg_len;\n}\n\nint decrypt_buf(int len, char *in, char **out)\n{\n   register int pad;\n   char *tmp_ptr, *in_ptr, *out_ptr = dec_buf;\n   int outlen;\n\n   len = recv_msg(len, in, out);\n   in = *out;\n   in_ptr = in;\n\n   outlen=len;\n   if (!len) return 0;\n   EVP_DecryptUpdate(&ctx_dec, out_ptr, &outlen, in_ptr, len);\n   recv_ib_mesg(&outlen, &out_ptr);\n   if (!outlen) return 0;\n   tmp_ptr = out_ptr + outlen; tmp_ptr--;\n   pad = *tmp_ptr;\n   if (pad < 1 || pad > blocksize) {\n      vlog(LOG_INFO, \"decrypt_buf: bad pad length\");\n      return 0;\n   }\n   *out = out_ptr;\n   return outlen - pad;\n}\n\nint cipher_enc_init(char * iv)\n{\n   int var_key = 0;\n   const EVP_CIPHER *cipher_type;\n   char tmpstr[64];\n   char cipher_name[32];\n\n   switch(cipher)\n   {\n      case VTUN_ENC_AES256OFB:\n         cipher_type = EVP_aes_256_ofb();\n         strcpy(cipher_name, \"AES-256-OFB\");\n      break;\n\n      case VTUN_ENC_AES256CFB:\n         cipher_type = EVP_aes_256_cfb();\n         strcpy(cipher_name, \"AES-256-CFB\");\n      break;\n\n      case VTUN_ENC_AES256CBC:\n         cipher_type = EVP_aes_256_cbc();\n         strcpy(cipher_name, \"AES-256-CBC\");\n      break;\n\n      case VTUN_ENC_AES128OFB:\n         cipher_type = EVP_aes_128_ofb();\n         strcpy(cipher_name, \"AES-128-OFB\");\n      break;\n      case VTUN_ENC_AES128CFB:\n         cipher_type = EVP_aes_128_cfb();\n         strcpy(cipher_name, \"AES-128-CFB\");\n      break;\n      case VTUN_ENC_AES128CBC:\n         cipher_type = EVP_aes_128_cbc();\n         strcpy(cipher_name, \"AES-128-CBC\");\n      break;\n\n      case VTUN_ENC_BF256OFB:\n         var_key = 1;\n         cipher_type = EVP_bf_ofb();\n         strcpy(cipher_name, \"Blowfish-256-OFB\");\n      break;\n      case VTUN_ENC_BF256CFB:\n         var_key = 1;\n         cipher_type = EVP_bf_cfb();\n         strcpy(cipher_name, \"Blowfish-256-CFB\");\n      break;\n\n      case VTUN_ENC_BF256CBC:\n         var_key = 1;\n         cipher_type = EVP_bf_cbc();\n         strcpy(cipher_name, \"Blowfish-256-CBC\");\n      break;\n\n      case VTUN_ENC_BF128OFB:\n         var_key = 1;\n         cipher_type = EVP_bf_ofb();\n         strcpy(cipher_name, \"Blowfish-128-OFB\");\n      break;\n      case VTUN_ENC_BF128CFB:\n         var_key = 1;\n         cipher_type = EVP_bf_cfb();\n         strcpy(cipher_name, \"Blowfish-128-CFB\");\n      break;\n      case VTUN_ENC_BF128CBC:\n         var_key = 1;\n         cipher_type = EVP_bf_cbc();\n         strcpy(cipher_name, \"Blowfish-128-CBC\");\n      break;\n      default:\n      /* if we're here, something weird's going on */\n         return -1;\n      break;\n   } /* switch(cipher) */\n\n   EVP_CIPHER_CTX_init(&ctx_enc);\n   EVP_EncryptInit_ex(&ctx_enc, cipher_type, NULL, NULL, NULL);\n   if (var_key)\n      EVP_CIPHER_CTX_set_key_length(&ctx_enc, keysize);\n   EVP_EncryptInit_ex(&ctx_enc, NULL, NULL, pkey, NULL);\n   EVP_EncryptInit_ex(&ctx_enc, NULL, NULL, NULL, iv);\n   EVP_CIPHER_CTX_set_padding(&ctx_enc, 0);\n   if (enc_init_first_time)\n   {\n      sprintf(tmpstr,\"%s encryption initialized\", cipher_name);\n      vlog(LOG_INFO, tmpstr);\n      enc_init_first_time = 0;\n   }\n   return 0;\n}\n\nint cipher_dec_init(char * iv)\n{\n   int var_key = 0;\n   const EVP_CIPHER *cipher_type;\n   char tmpstr[64];\n   char cipher_name[32];\n\n   switch(cipher)\n   {\n      case VTUN_ENC_AES256OFB:\n         cipher_type = EVP_aes_256_ofb();\n         strcpy(cipher_name, \"AES-256-OFB\");\n      break;\n\n      case VTUN_ENC_AES256CFB:\n         cipher_type = EVP_aes_256_cfb();\n         strcpy(cipher_name, \"AES-256-CFB\");\n      break;\n\n      case VTUN_ENC_AES256CBC:\n         cipher_type = EVP_aes_256_cbc();\n         strcpy(cipher_name, \"AES-256-CBC\");\n      break;\n\n      case VTUN_ENC_AES128OFB:\n         cipher_type = EVP_aes_128_ofb();\n         strcpy(cipher_name, \"AES-128-OFB\");\n      break;\n      case VTUN_ENC_AES128CFB:\n         cipher_type = EVP_aes_128_cfb();\n         strcpy(cipher_name, \"AES-128-CFB\");\n      break;\n      case VTUN_ENC_AES128CBC:\n         cipher_type = EVP_aes_128_cbc();\n         strcpy(cipher_name, \"AES-128-CBC\");\n      break;\n\n      case VTUN_ENC_BF256OFB:\n         var_key = 1;\n         cipher_type = EVP_bf_ofb();\n         strcpy(cipher_name, \"Blowfish-256-OFB\");\n      break;\n      case VTUN_ENC_BF256CFB:\n         var_key = 1;\n         cipher_type = EVP_bf_cfb();\n         strcpy(cipher_name, \"Blowfish-256-CFB\");\n      break;\n      case VTUN_ENC_BF256CBC:\n         var_key = 1;\n         cipher_type = EVP_bf_cbc();\n         strcpy(cipher_name, \"Blowfish-256-CBC\");\n      break;\n\n      case VTUN_ENC_BF128OFB:\n         var_key = 1;\n         cipher_type = EVP_bf_ofb();\n         strcpy(cipher_name, \"Blowfish-128-OFB\");\n      break;\n      case VTUN_ENC_BF128CFB:\n         var_key = 1;\n         cipher_type = EVP_bf_cfb();\n         strcpy(cipher_name, \"Blowfish-128-CFB\");\n      break;\n      case VTUN_ENC_BF128CBC:\n         var_key = 1;\n         cipher_type = EVP_bf_cbc();\n         strcpy(cipher_name, \"Blowfish-128-CBC\");\n      break;\n      default:\n      /* if we're here, something weird's going on */\n         return -1;\n      break;\n   } /* switch(cipher) */\n\n   EVP_CIPHER_CTX_init(&ctx_dec);\n   EVP_DecryptInit_ex(&ctx_dec, cipher_type, NULL, NULL, NULL);\n   if (var_key)\n      EVP_CIPHER_CTX_set_key_length(&ctx_dec, keysize);\n   EVP_DecryptInit_ex(&ctx_dec, NULL, NULL, pkey, NULL);\n   EVP_DecryptInit_ex(&ctx_dec, NULL, NULL, NULL, iv);\n   EVP_CIPHER_CTX_set_padding(&ctx_dec, 0);\n   if (dec_init_first_time)\n   {\n      sprintf(tmpstr,\"%s decryption initialized\", cipher_name);\n      vlog(LOG_INFO, tmpstr);\n      dec_init_first_time = 0;\n   }\n   return 0;\n}\n\nint send_msg(int len, char *in, char **out)\n{\n   char * iv; char * in_ptr;\n   int outlen;\n\n   switch(cipher_enc_state)\n   {\n      case CIPHER_INIT:\n         in_ptr = in - blocksize*2;\n         iv = malloc(blocksize);\n         RAND_bytes(iv, blocksize);\n         strncpy(in_ptr,\"ivec\",4);\n         in_ptr += 4;\n         memcpy(in_ptr,iv,blocksize);\n         in_ptr += blocksize;\n         cipher_enc_init(iv);\n\n         memset(iv,0,blocksize); free(iv); iv = NULL;\n         RAND_bytes(in_ptr, in - in_ptr);\n\n         in_ptr = in - blocksize*2;\n         outlen = blocksize*2;\n         EVP_EncryptUpdate(&ctx_enc_ecb, in_ptr, \n            &outlen, in_ptr, blocksize*2);\n         *out = in_ptr;\n         len = outlen;\n         cipher_enc_state = CIPHER_SEQUENCE;\n      break;\n\n      case CIPHER_CODE:\n      default:\n         *out = in;\n         len = 0;\n      break;\n   }\n   return len;\n}\n\nint recv_msg(int len, char *in, char **out)\n{\n   char * iv; char * in_ptr;\n   int outlen;\n\n   switch(cipher_dec_state)\n   {\n      case CIPHER_INIT:\n         in_ptr = in;\n         iv = malloc(blocksize);\n         outlen = blocksize*2;\n         EVP_DecryptUpdate(&ctx_dec_ecb, in_ptr, &outlen, in_ptr, blocksize*2);\n         \n         if ( !strncmp(in_ptr, \"ivec\", 4) )\n         {\n            memcpy(iv, in_ptr+4, blocksize);\n            cipher_dec_init(iv);\n\n            *out = in_ptr + blocksize*2;\n            len -= blocksize*2;\n            cipher_dec_state = CIPHER_SEQUENCE;\n            gibberish = 0;\n            gib_time_start = 0;\n         } \n         else \n         {\n            len = 0;\n            *out = in;\n            gibberish++;\n            if (gibberish == 1) gib_time_start = time(NULL);\n\n            if (gibberish == MIN_GIBBERISH)\n            {\n               cipher_enc_state = CIPHER_REQ_INIT;\n               send_a_packet = 1;\n#ifdef LFD_ENCRYPT_DEBUG\n               vlog(LOG_INFO, \n                  \"Min. gibberish threshold reached\");\n#endif\n            }\n            if (gibberish >= MAX_GIBBERISH || \n                difftime(time(NULL), gib_time_start) >= MAX_GIBBERISH_TIME)\n            {\n               gibberish = 0;\n               gib_time_start = 0;\n               send_a_packet = 1;\n\n#ifdef LFD_ENCRYPT_DEBUG\n               vlog(LOG_INFO, \n                  \"Max. gibberish threshold reached\");\n#endif\n               if (cipher_enc_state != CIPHER_INIT)\n               {\n                  cipher_enc_state = CIPHER_INIT;\n                  EVP_CIPHER_CTX_cleanup(&ctx_enc);\n#ifdef LFD_ENCRYPT_DEBUG\n                  vlog(LOG_INFO, \n                     \"Forcing local encryptor re-init\");\n#endif\n               }\n            }\n         }\n         memset(iv,0,blocksize); free(iv); iv = NULL;\n         memset(in_ptr,0,blocksize*2);         \n      break;\n\n      case CIPHER_CODE:\n      default:\n         *out = in;\n      break;\n   }\n   return len;\n}\n\n/* Send In-Band Message */\nint send_ib_mesg(int *len, char **in)\n{\n   char *in_ptr = *in;\n\n   /* To simplify matters, I assume that blocksize\n         will not be less than 8 bytes */\n   if (cipher_enc_state == CIPHER_SEQUENCE)\n   {\n      in_ptr -= blocksize;\n      memset(in_ptr,0,blocksize);\n      strncpy(in_ptr,\"seq#\",4);\n      in_ptr+=4;\n      *((unsigned long *)in_ptr) = htonl(sequence_num);\n      in_ptr-=4;\n\n      *in = in_ptr;\n      *len += blocksize;\n   }\n   else if (cipher_enc_state == CIPHER_REQ_INIT)\n   {\n      in_ptr -= blocksize;\n      memset(in_ptr,0,blocksize);\n      strncpy(in_ptr,\"rsyn\",4);\n      in_ptr+=4;\n      *((unsigned long *)in_ptr) = htonl(sequence_num);\n      in_ptr-=4;\n\n      *in = in_ptr;\n      *len += blocksize;\n#ifdef LFD_ENCRYPT_DEBUG\n      vlog(LOG_INFO, \"Requesting remote encryptor re-init\");      \n#endif\n      cipher_enc_state = CIPHER_SEQUENCE;\n      send_a_packet = 1; \n   }\n   return 0;\n}\n\n/* Receive In-Band Message */\nint recv_ib_mesg(int *len, char **in)\n{\n   char *in_ptr = *in;\n\n   if (cipher_dec_state == CIPHER_SEQUENCE)\n   {\n      /* To simplify matters, I assume that blocksize\n         will not be less than 8 bytes */\n      if ( !strncmp(in_ptr, \"seq#\", 4) )\n      {\n         *in += blocksize;\n         *len -= blocksize;\n      }\n      else if ( !strncmp(in_ptr, \"rsyn\", 4) )\n      {\n         *in += blocksize;\n         *len -= blocksize;\n\n         if (cipher_enc_state != CIPHER_INIT)\n         {\n            cipher_enc_state = CIPHER_INIT;\n            EVP_CIPHER_CTX_cleanup(&ctx_enc);\n         }\n#ifdef LFD_ENCRYPT_DEBUG\n         vlog(LOG_INFO, \"Remote requests encryptor re-init\");\n#endif\n      }\n      else\n      {\n         *len = 0;\n\n         if (cipher_dec_state != CIPHER_INIT &&\n             cipher_enc_state != CIPHER_REQ_INIT &&\n             cipher_enc_state != CIPHER_INIT)\n         {\n            EVP_CIPHER_CTX_cleanup (&ctx_dec);\n            cipher_dec_state = CIPHER_INIT;\n            cipher_enc_state = CIPHER_REQ_INIT;\n         }\n#ifdef LFD_ENCRYPT_DEBUG\n         vlog(LOG_INFO, \"Local decryptor out of sync\");\n#endif\n      }\n   }\n   return 0;\n}\n/* \n * Module structure.\n */\nstruct lfd_mod lfd_encrypt = {\n     \"Encryptor\",\n     alloc_encrypt,\n     encrypt_buf,\n     NULL,\n     decrypt_buf,\n     NULL,\n     free_encrypt,\n     NULL,\n     NULL\n};\n\n#else  /* HAVE_SSL */\n\nint no_encrypt(struct vtun_host *host)\n{\n     vlog(LOG_INFO, \"Encryption is not supported\");\n     return -1;\n}\n\nstruct lfd_mod lfd_encrypt = {\n     \"Encryptor\",\n     no_encrypt, NULL, NULL, NULL, NULL, NULL, NULL, NULL\n};\n\n#endif /* HAVE_SSL */\n"
  },
  {
    "path": "lfd_lzo.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * lfd_lzo.c,v 1.1.1.2.2.7.2.1 2006/11/16 04:03:00 mtbishop Exp\n */ \n\n/* LZO compression module */\n\n#include \"config.h\"\n\n#include <stdio.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <syslog.h>\n\n#include \"vtun.h\"\n#include \"linkfd.h\"\n#include \"lib.h\"\n#include \"log.h\"\n\n#ifdef HAVE_LZO\n\n#include \"lzo1x.h\"\n#include \"lzoutil.h\"\n\nstatic lzo_byte *zbuf;\nstatic lzo_voidp wmem;\nstatic int zbuf_size = VTUN_FRAME_SIZE * VTUN_FRAME_SIZE / 64 + 16 + 3;\n\n/* Pointer to compress function */\nint (*lzo1x_compress)(const lzo_byte *src, lzo_uint  src_len,\n\t\t   \t    lzo_byte *dst, lzo_uint *dst_len,\n\t\t   \t    lzo_voidp wrkmem);\n/* \n * Initialize compressor/decompressor.\n * Allocate the buffers.\n */  \n\nint alloc_lzo(struct vtun_host *host)\n{\n     int zlevel = host->zlevel ? host->zlevel : 1;\n     int mem;\n\n     switch( zlevel ){\n\tcase 9:\n\t   lzo1x_compress = lzo1x_999_compress;\n           mem = LZO1X_999_MEM_COMPRESS;\n           break;\n\tdefault: \t   \n \t   lzo1x_compress = lzo1x_1_15_compress;\n           mem = LZO1X_1_15_MEM_COMPRESS;\n           break;\n     }\n\n     if( lzo_init() != LZO_E_OK ){\n\tvlog(LOG_ERR,\"Can't initialize compressor\");\n\treturn 1;\n     }\t\n     if( !(zbuf = lfd_alloc(zbuf_size)) ){\n\tvlog(LOG_ERR,\"Can't allocate buffer for the compressor\");\n\treturn 1;\n     }\t\n     if( !(wmem = lzo_malloc(mem)) ){\n\tvlog(LOG_ERR,\"Can't allocate buffer for the compressor\");\n\treturn 1;\n     }\t\n\n     vlog(LOG_INFO, \"LZO compression[level %d] initialized\", zlevel);\n\n     return 0;\n}\n\n/* \n * Deinitialize compressor/decompressor.\n * Free the buffer.\n */  \n\nint free_lzo()\n{\n     lfd_free(zbuf); zbuf = NULL;\n     lzo_free(wmem); wmem = NULL;\n     return 0;\n}\n\n/* \n * This functions _MUST_ consume all incoming bytes in one pass,\n * that's why we expand buffer dynamicly.\n */  \nint comp_lzo(int len, char *in, char **out)\n{ \n     unsigned int zlen = 0;    \n     int err;\n     \n     if( (err=lzo1x_compress((void *)in,len,zbuf,&zlen,wmem)) != LZO_E_OK ){\n        vlog(LOG_ERR,\"Compress error %d\",err);\n        return -1;\n     }\n\n     *out = (void *)zbuf;\n     return zlen;\n}\n\nint decomp_lzo(int len, char *in, char **out)\n{\n     unsigned int zlen = 0;\n     int err;\n\n     if( (err=lzo1x_decompress((void *)in,len,zbuf,&zlen,wmem)) != LZO_E_OK ){\n        vlog(LOG_ERR,\"Decompress error %d\",err);\n        return -1;\n     }\n\n     *out = (void *) zbuf;\n     return zlen;\n}\n\nstruct lfd_mod lfd_lzo = {\n     \"LZO\",\n     alloc_lzo,\n     comp_lzo,\n     NULL,\n     decomp_lzo,\n     NULL,\n     free_lzo,\n     NULL,\n     NULL\n};\n\n#else  /* HAVE_LZO */\n\nint no_lzo(struct vtun_host *host)\n{\n     vlog(LOG_INFO, \"LZO compression is not supported\");\n     return -1;\n}\n\nstruct lfd_mod lfd_lzo = {\n     \"LZO\",\n     no_lzo, NULL, NULL, NULL, NULL, NULL, NULL, NULL\n};\n\n#endif /* HAVE_LZO */\n\n\n"
  },
  {
    "path": "lfd_shaper.c",
    "content": "/*\n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network.\n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky.\n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * lfd_shaper.c,v 1.1.1.2.2.4.2.1 2006/11/16 04:03:09 mtbishop Exp\n */\n\n#include \"config.h\"\n\n#include <stdio.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <sys/time.h>\n#include <syslog.h>\n\n#include \"vtun.h\"\n#include \"linkfd.h\"\n#include \"lib.h\"\n#include \"log.h\"\n\n/*\n * Shaper module.\n */\n\n#ifdef HAVE_SHAPER\n\nunsigned long bytes, max_speed;\nstruct timeval curr_time, last_time;\n\n/*\n * Initialization function.\n */\nint shaper_init(struct vtun_host *host)\n{\n    /* Calculate max speed bytes/sec */\n    max_speed = host->spd_out / 8 * 1024;\n\n    /* Compensation for delays, nanosleep and so on */\n    max_speed += 400;\n\n    bytes = 0;\n\n    vlog(LOG_INFO, \"Traffic shaping(speed %dK) initialized.\", host->spd_out);\n    return 0;\n}\n\n/* Shaper counter */\nint shaper_counter(int len, char *in, char **out)\n{\n    /* Just count incoming bytes */\n    bytes += len;\n\n    *out = in;\n    return len;\n}\n\n#ifndef timersub\n/* Some includes doesn't contain this macro */\n#define timersub(a, b, result)                          \\\n  do {                                                  \\\n    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;       \\\n    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;    \\\n    if ((result)->tv_usec < 0) {                        \\\n        --(result)->tv_sec;                             \\\n        (result)->tv_usec += 1000000;                   \\\n    }                                                   \\\n  } while (0)\n#endif\n\n/*\n * Main shaper function.\n * Compute current speed in bytes/sec and if it is\n * higher than maximal speed stop accepting input\n * until the speed become lower or equal to maximal.\n */\nint shaper_avail(void)\n{\n    static struct timeval tv;\n    register unsigned long speed;\n\n    /* Let me know if you have faster and better time source. */\n    gettimeofday(&curr_time, NULL);\n\n    timersub(&curr_time, &last_time, &tv);\n\n    /* Calculate current speed bytes/sec.\n     * (tv2ms never returns 0) */\n    speed = bytes * 1000 / tv2ms(tv);\n\n    if ( speed > max_speed ) {\n        /*\n         * Sleep about 1 microsec(actual sleep might be longer).\n         * This is actually the hack to reduce CPU usage.\n         * Without this delay we will consume 100% CPU.\n             */\n        static struct timespec ts = {0, 1000};\n        nanosleep(&ts, NULL);\n\n        /* Don't accept input */\n        return 0;\n    }\n\n    if ( curr_time.tv_sec > last_time.tv_sec ) {\n        last_time = curr_time;\n        bytes = 0;\n    }\n\n    /* Accept input */\n    return  1;\n}\n\nstruct lfd_mod lfd_shaper = {\n    \"Shaper\",\n    shaper_init,\n    shaper_counter,\n    shaper_avail,\n    NULL,\n    NULL,\n    NULL,\n    NULL,\n    NULL\n};\n\n#else  /* HAVE_SHAPER */\n\nint no_shaper(struct vtun_host *host)\n{\n    vlog(LOG_INFO, \"Traffic shaping is not supported\");\n    return -1;\n}\n\nstruct lfd_mod lfd_shaper = {\n    \"Shaper\",\n    no_shaper, NULL, NULL, NULL, NULL, NULL, NULL, NULL\n};\n\n#endif /* HAVE_SHAPER */\n"
  },
  {
    "path": "lfd_zlib.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * lfd_zlib.c,v 1.1.1.2.2.6.2.1 2006/11/16 04:03:14 mtbishop Exp\n */ \n\n/* ZLIB compression module */\n\n#include \"config.h\"\n\n#include <stdio.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <syslog.h>\n\n#include \"vtun.h\"\n#include \"linkfd.h\"\n#include \"lib.h\"\n#include \"log.h\"\n\n#ifdef HAVE_ZLIB\n\n#include <zlib.h>\n\nstatic z_stream zi, zd; \nstatic unsigned char *zbuf;\nstatic int zbuf_size = VTUN_FRAME_SIZE + 200;\n\n/* \n * Initialize compressor/decompressor.\n * Allocate the buffer.\n */  \nint zlib_alloc(struct vtun_host *host)\n{\n     int zlevel = host->zlevel ? host->zlevel : 1;\n\n     zd.zalloc = (alloc_func)0;\n     zd.zfree  = (free_func)0;\n     zd.opaque = (voidpf)0;\n     zi.zalloc = (alloc_func)0;\n     zi.zfree  = (free_func)0;\n     zi.opaque = (voidpf)0;\n    \n     if( deflateInit(&zd, zlevel ) != Z_OK ){\n\tvlog(LOG_ERR,\"Can't initialize compressor\");\n\treturn 1;\n     }\t\n     if( inflateInit(&zi) != Z_OK ){\n\tvlog(LOG_ERR,\"Can't initialize decompressor\");\n\treturn 1;\n     }\t\n     if( !(zbuf = (void *) lfd_alloc(zbuf_size)) ){\n\tvlog(LOG_ERR,\"Can't allocate buffer for the compressor\");\n\treturn 1;\n     }\n   \n     vlog(LOG_INFO,\"ZLIB compression[level %d] initialized.\", zlevel);\n     return 0;\n}\n\n/* \n * Deinitialize compressor/decompressor.\n * Free the buffer.\n */  \n\nint zlib_free()\n{\n     deflateEnd(&zd);\n     inflateEnd(&zi);\n\n     lfd_free(zbuf); zbuf = NULL;\n\n     return 0;\n}\n\nstatic int expand_zbuf(z_stream *zs, int len)\n{\n     if( !(zbuf = lfd_realloc(zbuf,zbuf_size+len)) )\n         return -1;\n     zs->next_out = zbuf + zbuf_size;\n     zs->avail_out = len;\n     zbuf_size += len;     \n\n     return 0;\n}\n\n/* \n * This functions _MUST_ consume all incoming bytes in one pass,\n * That's why we expand buffer dynamically.\n * Practice shows that buffer will not grow larger that 16K.\n */  \nint zlib_comp(int len, char *in, char **out)\n{ \n     int oavail, olen = 0;    \n     int err;\n \n     zd.next_in = (void *) in;\n     zd.avail_in = len;\n     zd.next_out = (void *) zbuf;\n     zd.avail_out = zbuf_size;\n    \n     while(1) {\n        oavail = zd.avail_out;\n        if( (err=deflate(&zd, Z_SYNC_FLUSH)) != Z_OK ){\n           vlog(LOG_ERR,\"Deflate error %d\",err);\n           return -1;\n        }\n        olen += oavail - zd.avail_out;\n        if(!zd.avail_in)\n\t   break;\n\n        if( expand_zbuf(&zd,100) ) {\n\t   vlog( LOG_ERR, \"Can't expand compression buffer\");\n           return -1;\n\t}\n     }\n     *out = (void *) zbuf;\n     return olen;\n}\n\nint zlib_decomp(int len, char *in, char **out)\n{\n     int oavail = 0, olen = 0;     \n     int err;\n\n     zi.next_in = (void *) in;\n     zi.avail_in = len;\n     zi.next_out = (void *) zbuf;\n     zi.avail_out = zbuf_size;\n\n     while(1) {\n        oavail = zi.avail_out;\n        if( (err=inflate(&zi, Z_SYNC_FLUSH)) != Z_OK ) {\n           vlog(LOG_ERR,\"Inflate error %d len %d\", err, len);\n           return -1;\n        }\n        olen += oavail - zi.avail_out;\n        if(!zi.avail_in)\n\t   break;\n        if( expand_zbuf(&zi,100) ) {\n\t   vlog( LOG_ERR, \"Can't expand compression buffer\");\n           return -1;\n\t}\n     }\n     *out = (void *) zbuf;\n     return olen;\n}\n\nstruct lfd_mod lfd_zlib = {\n     \"ZLIB\",\n     zlib_alloc,\n     zlib_comp,\n     NULL,\n     zlib_decomp,\n     NULL,\n     zlib_free,\n     NULL,\n     NULL\n};\n\n#else  /* HAVE_ZLIB */\n\nint no_zlib(struct vtun_host *host)\n{\n     vlog(LOG_INFO, \"ZLIB compression is not supported\");\n     return -1;\n}\n\nstruct lfd_mod lfd_zlib = {\n     \"ZLIB\",\n     no_zlib, NULL, NULL, NULL, NULL, NULL, NULL, NULL\n};\n\n#endif /* HAVE_ZLIB */\n"
  },
  {
    "path": "lib.c",
    "content": "/*\n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network.\n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky.\n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * lib.c,v 1.1.1.2.2.9.2.1 2006/11/16 04:03:17 mtbishop Exp\n */\n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <stdarg.h>\n#include <sys/types.h>\n#include <sys/time.h>\n#include <sys/wait.h>\n#include <errno.h>\n#include <math.h>\n#include <netinet/tcp.h>\n\n#include \"vtun.h\"\n#include \"linkfd.h\"\n#include \"lib.h\"\n#include \"log.h\"\n\nvolatile sig_atomic_t __io_canceled = 0;\n\n#ifndef HAVE_SETPROC_TITLE\n/* Functions to manipulate with program title */\n\nextern char **environ;\nchar    *title_start;   /* start of the proc title space */\nchar    *title_end;     /* end of the proc title space */\nint title_size;\n\nvoid init_title(int argc, char *argv[], char *envp[], char *name)\n{\n    int i;\n\n    /*\n     *  Move the environment so settitle can use the space at\n     *  the top of memory.\n     */\n\n    for (i = 0; envp[i]; i++);\n\n    environ = (char **) malloc(sizeof (char *) * (i + 1));\n\n    for (i = 0; envp[i]; i++)\n        environ[i] = strdup(envp[i]);\n    environ[i] = NULL;\n\n    /*\n     *  Save start and extent of argv for set_title.\n     */\n\n    title_start = argv[0];\n\n    /*\n     *  Determine how much space we can use for set_title.\n     *  Use all contiguous argv and envp pointers starting at argv[0]\n     */\n    for (i = 0; i < argc; i++)\n        if ( !i || title_end == argv[i])\n            title_end = argv[i] + strlen(argv[i]) + 1;\n\n    for (i = 0; envp[i]; i++)\n        if ( title_end == envp[i] )\n            title_end = envp[i] + strlen(envp[i]) + 1;\n\n    strcpy(title_start, name);\n    title_start += strlen(name);\n    title_size = title_end - title_start;\n}\n\nvoid set_title(const char *fmt, ...)\n{\n    char buf[255];\n    va_list ap;\n\n    memset(title_start, 0, title_size);\n\n    /* print the argument string */\n    va_start(ap, fmt);\n    vsprintf(buf, fmt, ap);\n    va_end(ap);\n\n    if ( strlen(buf) > title_size - 1)\n        buf[title_size - 1] = '\\0';\n\n    strcat(title_start, buf);\n}\n#endif  /* HAVE_SETPROC_TITLE */\n\nstruct my_ip {\n    u_int8_t    ip_vhl;     /* header length, version */\n#define IP_V(ip)    (((ip)->ip_vhl & 0xf0) >> 4)\n#define IP_HL(ip)   ((ip)->ip_vhl & 0x0f)\n    u_int8_t    ip_tos;     /* type of service */\n    u_int16_t   ip_len;     /* total length */\n    u_int16_t   ip_id;      /* identification */\n    u_int16_t   ip_off;     /* fragment offset field */\n#define IP_DF 0x4000            /* dont fragment flag */\n#define IP_MF 0x2000            /* more fragments flag */\n#define IP_OFFMASK 0x1fff       /* mask for fragmenting bits */\n    u_int8_t    ip_ttl;     /* time to live */\n    u_int8_t    ip_p;       /* protocol */\n    u_int16_t   ip_sum;     /* checksum */\n    struct  in_addr ip_src, ip_dst; /* source and dest address */\n};\n\n/*\n * Print padded messages.\n * Used by 'auth' function to force all messages\n * to be the same len.\n */\nint print_p(int fd, const char *fmt, ...)\n{\n    char buf[VTUN_MESG_SIZE];\n    va_list ap;\n\n    memset(buf, 0, sizeof(buf));\n\n    /* print the argument string */\n    va_start(ap, fmt);\n    vsnprintf(buf, sizeof(buf) - 1, fmt, ap);\n    va_end(ap);\n\n    return write_n(fd, buf, sizeof(buf));\n}\n\n/* Read N bytes with timeout */\nint readn_t(int fd, void *buf, size_t count, time_t timeout)\n{\n    fd_set fdset;\n    struct timeval tv;\n\n    tv.tv_usec = 0; tv.tv_sec = timeout;\n\n    FD_ZERO(&fdset);\n    FD_SET(fd, &fdset);\n    if ( select(fd + 1, &fdset, NULL, NULL, &tv) <= 0)\n        return -1;\n\n    return read_n(fd, buf, count);\n}\n\n/*\n * Substitutes opt in place off '%X'.\n * Returns new string.\n */\nchar * subst_opt(char *str, struct vtun_sopt *opt)\n{\n    register int slen, olen, sp, np;\n    register char *optr, *nstr, *tmp;\n    char buf[10];\n\n    if ( !str ) return NULL;\n\n    slen = strlen(str) + 1;\n    if ( !(nstr = malloc(slen)) )\n        return str;\n\n    sp = np = 0;\n    while ( str[sp] ) {\n        switch ( str[sp] ) {\n        case '%':\n            optr = NULL;\n            /* Check supported opt */\n            switch ( str[sp + 1] ) {\n            case '%':\n            case 'd':\n                optr = opt->dev;\n                break;\n            case 'A':\n                optr = opt->laddr;\n                break;\n            case 'P':\n                sprintf(buf, \"%d\", opt->lport);\n                optr = buf;\n                break;\n            case 'a':\n                optr = opt->raddr;\n                break;\n            case 'p':\n                sprintf(buf, \"%d\", opt->rport);\n                optr = buf;\n                break;\n            default:\n                sp++;\n                continue;\n            }\n            if ( optr ) {\n                /* Opt found substitute */\n                olen = strlen(optr);\n                slen = slen - 2 + olen;\n                if ( !(tmp = realloc(nstr, slen)) ) {\n                    free(nstr);\n                    return str;\n                }\n                nstr = tmp;\n                memcpy(nstr + np, optr, olen);\n                np += olen;\n            }\n            sp += 2;\n            continue;\n\n        case '\\\\':\n            nstr[np++] = str[sp++];\n            if ( !nstr[sp] )\n                continue;\n        /* fall through */\n        default:\n            nstr[np++] = str[sp++];\n            break;\n        }\n    }\n    nstr[np] = '\\0';\n    return nstr;\n}\n\n/*\n * Split arguments string.\n * ' ' - group arguments\n * Modifies original string.\n */\nvoid split_args(char *str, char **argv)\n{\n    register int i = 0;\n    int mode = 0;\n\n    while ( str && *str ) {\n        switch ( *str ) {\n        case ' ':\n            if ( mode == 1 ) {\n                *str = '\\0';\n                mode = 0;\n                i++;\n            }\n            break;\n\n        case '\\'':\n            if ( !mode ) {\n                argv[i] = str + 1;\n                mode = 2;\n            } else {\n                memmove(argv[i] + 1, argv[i], str - argv[i]);\n                argv[i]++;\n\n                if ( mode == 1 )\n                    mode = 2;\n                else\n                    mode = 1;\n            }\n            break;\n\n        case '\\\\':\n            if ( mode ) {\n                memmove(argv[i] + 1, argv[i], str - argv[i]);\n                argv[i]++;\n            }\n            if ( !*(++str) ) continue;\n        /*Fall through */\n\n        default:\n            if ( !mode ) {\n                argv[i] = str;\n                mode = 1;\n            }\n            break;\n        }\n        str++;\n    }\n    if ( mode == 1 || mode == 2)\n        i++;\n\n    argv[i] = NULL;\n}\n\nint run_cmd(void *d, void *opt)\n{\n    struct vtun_cmd *cmd = d;\n    char *argv[50], *args;\n    int pid, st;\n\n    switch ( (pid = fork()) ) {\n    case 0:\n        break;\n    case -1:\n        vlog(LOG_ERR, \"Couldn't fork()\");\n        return 0;\n    default:\n        if ( cmd->flags & VTUN_CMD_WAIT ) {\n            /* Wait for termination */\n            if ( waitpid(pid, &st, 0) > 0 && (WIFEXITED(st) && WEXITSTATUS(st)) )\n                vlog(LOG_INFO, \"Command [%s %.20s] error %d\",\n                            cmd->prog ? cmd->prog : \"sh\",\n                            cmd->args ? cmd->args : \"\",\n                            WEXITSTATUS(st) );\n        }\n        if ( cmd->flags & VTUN_CMD_DELAY ) {\n            struct timespec tm = { VTUN_DELAY_SEC, 0 };\n            /* Small delay hack to sleep after pppd start.\n             * Until I have no good solution for solving\n             * PPP + route problem  */\n            nanosleep(&tm, NULL);\n        }\n        return 0;\n    }\n\n    args = subst_opt(cmd->args, opt);\n    if ( !cmd->prog ) {\n        /* Run using shell */\n        cmd->prog = \"/bin/sh\";\n        argv[0] = \"sh\";\n        argv[1] = \"-c\";\n        argv[2] = args;\n        argv[3] = NULL;\n    } else {\n        argv[0] = cmd->prog;\n        split_args(args, argv + 1);\n    }\n    execv(cmd->prog, argv);\n\n    vlog(LOG_ERR, \"Couldn't exec program %s\", cmd->prog);\n    exit(1);\n}\n\nvoid free_sopt( struct vtun_sopt *opt )\n{\n    if ( opt->dev ) {\n        free(opt->dev);\n        opt->dev = NULL;\n    }\n\n    if ( opt->laddr ) {\n        free(opt->laddr);\n        opt->laddr = NULL;\n    }\n\n    if ( opt->raddr ) {\n        free(opt->raddr);\n        opt->raddr = NULL;\n    }\n}\n\nstatic int llsqrt(long a)\n{\n    long long prev = ~((long long)1 << 63);\n    long long x = a;\n\n    if (x > 0) {\n        while (x < prev) {\n            prev = x;\n            x = (x + (a / x)) / 2;\n        }\n    }\n\n    return (int)x;\n}\n\n/*\n * finds the standard deviation\n * =sqrt(sum)x-mean(x)^2)/n)\n */\nint std_dev(int nums[], int len)\n{\n    long sum = 0;\n    long mean = 0;\n    if (len == 0) return 0;\n    long llen = len;\n\n    int i;\n\n    for (i = 0; i < len; i++) {\n        sum += nums[i];\n    }\n    mean = sum / llen;\n    sum = 0;\n    for (i = 0; i < len; i++)\n        sum += abs(nums[i] - mean); // for stddev need to mult\n\n    //return llsqrt(sum/len);\n    return (sum / len);\n}\n\n\nuint32_t getTcpSeq(char* buf) {\n    struct my_ip *ip = (struct my_ip*) (buf);\n    if ((ip->ip_p == 6)) { //tcp ack self test\n        uint32_t seqNum;\n        memcpy(&seqNum, buf + sizeof(struct my_ip) + 4, 4);\n        seqNum = ntohl(seqNum);\n        return seqNum;\n    } else {\n        return 0; //no tcp packet\n    }\n}\n\nint isACK(char* buf, int len) {\n    struct my_ip *ip = (struct my_ip*) (buf);\n    if ((ip->ip_p == 6) && (len < 160)) { //tcp ack self test\n        uint8_t tcpOffset;\n        memcpy(&tcpOffset, buf + sizeof(struct my_ip) + 12, 1);\n        tcpOffset = (0xF0 & tcpOffset) >> 2;\n        int headerSize = sizeof(struct my_ip) + (int) tcpOffset;\n        if (headerSize == len) { //if header size == full packet size\n            return 1; //this is ACK\n        }\n    }\n    return 0;\n}\n\n"
  },
  {
    "path": "lib.h",
    "content": "/*  \n    VTun - Virtual Tunnel over TCP/IP network.\n\n    Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n    VTun has been derived from VPPP package by Maxim Krasnyansky. \n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n */\n\n/*\n * lib.h,v 1.2.2.5.2.1 2006/11/16 04:03:20 mtbishop Exp\n */ \n#ifndef _VTUN_LIB_H\n#define _VTUN_LIB_H\n\n#include \"config.h\"\n\n#include <sys/types.h>\n#include <signal.h>\n#include <errno.h>\n#include <unistd.h>\n#include <netinet/tcp.h>\n#include <netinet/in.h>\n#include <semaphore.h>\n\n#ifdef HAVE_LIBUTIL_H\n#include <libutil.h>\n#endif\n\n#ifndef HAVE_SETPROC_TITLE\n  void init_title(int argc,char *argv[],char *env[], char *name);\n  void set_title(const char *ftm, ...);\n#else\n  #define init_title( a... ) \n  #define set_title setproctitle\n#endif /* HAVE_SETPROC_TITLE */\n\n#ifndef min\n  #define min(a,b)    ( (a)<(b) ? (a):(b) )\n#endif\n\n/* convert ms(milliseconds) to timeval struct */\nstatic void ms2tv(struct timeval *result, uint64_t interval_ms) {\n    result->tv_sec = (interval_ms / 1000);\n    result->tv_usec = ((interval_ms % 1000) * 1000);\n}\n\nstatic uint64_t tv2ms(struct timeval *a) {\n    return (((uint64_t)a->tv_sec * 1000) + ((uint64_t)a->tv_usec / 1000));\n}\n\n\nint readn_t(int fd, void *buf, size_t count, time_t timeout);\nint print_p(int f, const char *ftm, ...);\n\nint  run_cmd(void *d, void *opt);\nvoid free_sopt(struct vtun_sopt *opt);\n\nint std_dev(int nums[], int len);\n\n/* IO cancelation */\nextern volatile sig_atomic_t __io_canceled;\n\nstatic inline void io_init(void)\n{\n\t__io_canceled = 0;\n}\n\nstatic inline void io_cancel(void)\n{\n\t__io_canceled = 1;\n}\n\n\n\nuint32_t getTcpSeq(char* buf);\nint isACK(char* buf, int len);\n\n\n/* Read exactly len bytes (Signal safe)*/\nstatic inline int read_n(int fd, char *buf, int len)\n{\n    int t = 0, w, ecount = 0;\n\n    while (!__io_canceled && len > 0) {\n        if ( (w = read(fd, buf, len)) < 0 ) {\n            return -1;\n        }\n        if ( !w )\n            return 0;\n        len -= w; buf += w; t += w;\n    }\n\n    return t;\n}\n\n/* Write exactly len bytes (Signal safe)*/\nstatic inline int write_n(int fd, char *buf, int len)\n{\n    int t = 0, w, state = 1;\n    setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));\n    while (!__io_canceled && len > 0) {\n        if ( (w = write(fd, buf, len)) < 0 ) {\n            return -1;\n        }\n        if ( !w )\n            return 0;\n        len -= w; buf += w; t += w;\n    }\n    state = 0;\n    setsockopt(fd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));\n    return t;\n}\n\nstatic inline int NumberOfSetBits(int32_t i)\n{\n    i = i - ((i >> 1) & 0x55555555);\n    i = (i & 0x33333333) + ((i >> 2) & 0x33333333);\n    return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;\n}\n#endif /* _VTUN_LIB_H */\n"
  },
  {
    "path": "linkfd.c",
    "content": "/*\n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network.\n\n   Copyright (C) 2011-2016 Vrayo Systems Ltd. team \n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky.\n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n *\n\n/*\n * linkfd.c,v 1.4.2.15.2.2 2006/11/16 04:03:23 mtbishop Exp\n */\n\n/*\n * To fully utilize all capabilities you need linux kernel of at least >=2.6.25\n */\n\n/*\n * TODO:\n * - collect LOSS stats: Packets Between Loss (PBL); Packets Sequentially Lost (PSL)\n * - overcome rtt,rtt2 < 1ms limitation(s)\n * - dynamic buffer: fixed size in MB (e.g. 5MB), dynamic packet list (Start-Byte-Rel; End-Byte-Rel)\n * - stable channels with stabilizing weights\n *\n */\n\n#define _GNU_SOURCE\n#include \"config.h\"\n\n#include <stdio.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <signal.h>\n#include <strings.h>\n#include <string.h>\n#include <errno.h>\n#include <sys/time.h>\n#include <syslog.h>\n#include <time.h>\n#include <semaphore.h>\n#include <stdint.h>\n#include <arpa/inet.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <fcntl.h>\n#include <inttypes.h>\n#include <math.h>\n#include <sys/mman.h>\n#ifdef PROF\n#include <dlfcn.h>\n#endif\n\n#ifdef HAVE_SYS_RESOURCE_H\n#include <sys/resource.h>\n#endif\n\n#ifdef HAVE_SCHED_H\n#include <sched.h>\n#endif\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\n#ifdef HAVE_NETINET_TCP_H\n#include <netinet/tcp.h>\n#include <netinet/udp.h>\n#include <netinet/ip_icmp.h>\n#endif\n\n#include \"udp_states.h\"\n#include \"vtun.h\"\n#include \"linkfd.h\"\n#include \"lib.h\"\n#include \"log.h\"\n#include \"driver.h\"\n#include \"net_structs.h\"\n#include \"netlib.h\"\n#include \"netlink_socket_info.h\"\n#include \"speed_algo.h\"\n#include \"timer.h\"\n#include \"pid.h\"\n\n#ifdef TESTING\n#include \"testing.h\"\n#endif\n\n#include \"packet_code.h\"\n#include <stdarg.h>\nstruct my_ip {\n    u_int8_t\tip_vhl;\t\t/* header length, version */\n#define IP_V(ip)\t(((ip)->ip_vhl & 0xf0) >> 4)\n#define IP_HL(ip)\t((ip)->ip_vhl & 0x0f)\n    u_int8_t\tip_tos;\t\t/* type of service */\n    u_int16_t\tip_len;\t\t/* total length */\n    u_int16_t\tip_id;\t\t/* identification */\n    u_int16_t\tip_off;\t\t/* fragment offset field */\n#define\tIP_DF 0x4000\t\t\t/* dont fragment flag */\n#define\tIP_MF 0x2000\t\t\t/* more fragments flag */\n#define\tIP_OFFMASK 0x1fff\t\t/* mask for fragmenting bits */\n    u_int8_t\tip_ttl;\t\t/* time to live */\n    u_int8_t\tip_p;\t\t/* protocol */\n    u_int16_t\tip_sum;\t\t/* checksum */\n    struct\tin_addr ip_src,ip_dst;\t/* source and dest address */\n};\n\n#define CH_THRESH 30\n#define CS_THRESH 60\n#define SEND_Q_IDLE 7000 // send_q less than this enters idling mode; e.g. head is detected by rtt\n#define SEND_Q_LIMIT_MINIMAL 9000 // 7000 seems to work\n#define SPEED_MINIMAL 100000.0 // 100kb/s minimal speed\n#define SENQ_Q_LIMIT_THRESHOLD_MIN 13000 // the value with which that AG starts\n//#define SENQ_Q_LIMIT_THRESHOLD_MULTIPLIER 10 // send_q AG allowed threshold = RSR / SENQ_Q_LIMIT_THRESHOLD_MULTIPLIER\n#define RATE_THRESHOLD_MULTIPLIER 5 // cut-off by speed only\n#define RTT_THRESHOLD_MULTIPLIER 3 // cut-off by RTT only\n#define RTT_THRESHOLD_GOOD 50 // cut-off by RTT ms\n#define SEND_Q_EFF_WORK 10000 // value for send_q_eff to detect that channel is in use\n#define ACS_NOT_IDLE 50000 // ~50pkts/sec ~= 20ms rtt2 accuracy\n#define LOSS_SEND_Q_MAX 1000 // maximum send_q allowed is now 1000 (for head?)\n#define LOSS_SEND_Q_UNKNOWN -1 // unknown value\n#define MIN_SEND_Q_BESTGUESS_3G_PKT 150 // packets best-guess for 3G\n// TODO: use mean send_q value for the following def\n#define SEND_Q_AG_ALLOWED_THRESH 25000 // depends on RSR_TOP and chan speed. TODO: refine, Q: understand if we're using more B/W than 1 chan has?\n//#define MAX_LATENCY_DROP { 0, 550000 }\n#define MAX_NETWORK_STALL_MS 250 // 50ms maximum network stall\n#define MAX_NETWORK_STALL { 0, MAX_NETWORK_STALL_MS*1000 } // 50ms maximum network stall\n#define MAX_LATENCY_DROP_USEC 200000 // typ. is 204-250 upto 450 max RTO at CUBIC\n#define MAX_LATENCY_DROP_SHIFT 100 // ms. to add to forced_rtt - or use above\n//#define MAX_REORDER_LATENCY { 0, 50000 } // is rtt * 2 actually, default. ACTUALLY this should be in compliance with TCP RTO\n#define MAX_REORDER_LATENCY_MAX 499999 // usec\n#define MAX_REORDER_LATENCY_MIN 200 // usec\n#define MAX_REORDER_PERPATH 8// was 4\n// TODO HERE: TCP Model requried ---vvv\n#define PLP_UNRECOVERABLE_CUTOFF 10000 // in theory about 50 mbit/s at 20ms  // was 1000 - 1000 is okay for like rtt 20ms but not for 100ms\n#define PSL_RECOVERABLE 2 // we can recover this amount of loss\n#define L_PBL_JOIN_EVENTS 50 // join all events within this PBL\n#define DROPPING_LOSSING_DETECT_SECONDS 7 // seconds to pass after drop or loss to say we're not lossing or dropping anymore\n//#define MAX_BYTE_DELIVERY_DIFF 100000 // what size of write buffer pumping is allowed? -> currently =RSR_TOP\n#define SELECT_SLEEP_USEC 50000 // crucial for mean sqe calculation during idle\n#define SUPERLOOP_MAX_LAG_USEC 5000 // 15ms max superloop lag allowed! // cpu lag\n#define FCI_P_INTERVAL 3 // interval in packets to send ACK if ACK is not sent via payload packets\n#define CUBIC_T_DIV 50\n#define TMRTTA 25 // alpha coeff. for RFC6298 for tcp model rtt avg.\n#define SKIP_SENDING_CLD_DIV 2\n#define MSBL_PUSHDOWN_K 30\n#define MSBL_PUSHUP_K 80\n#define MAX_STUB_JITTER 1 // maximum packet jitter that we allow on buffer to happen\n#define AGAG_MAX 255\n#define SLOW_START_MAX_RUN {5, 500000} // max slow_start runtime after idle\n#define SLOW_START_IMMUNE  {10, 100000} // no SS allowed within this period after previous SS\n#define SLOW_START_INCINT 10 // amount of packets to increase MSBL by 1 after\n#define TOKENBUF_ADD_BURST 7 // amount of tokens to wait before adding to reduce integer error in add_token\n\n// PLOSS is a \"probable loss\" event: it occurs if PSL=1or2 for some amount of packets AND we detected probable loss (possible_seq_lost)\n// this LOSS detect method uses the fact that we never push the network with 1 or 2 packets; we always push 5+ (TODO: make sure it is true!)\n#define PLOSS_PSL 2 // this is '1or2'\n#define PLOSS_CHECK_PKTS 15 // how many packets to check for sequential loss to detect PLOSS TODO: find correct value. speed dependent??\n\n#define MAX_SD_W 1700 // stat buf max send_q (0..MAX_SD_W)\n#define SD_PARITY 2 // stat buf len = MAX_SD_W / SD_PARITY\n#define SLOPE_POINTS 30 // how many points ( / SD_PARITY ) to make linear fit from\n#define ZERO_W_THR 2000.0 // ms. when to consider weight of point =0 (value outdated)\n#define SPEED_REDETECT_TV {2,0} // timeval (interval) for chan speed redetect\n#define HEAD_REDETECT_HYSTERESIS_TV {0,800000} // timeval (interval) for chan speed redetect\n#define HEAD_HYSTERESIS_MIN_MS 800 // this replaced the above one\n#define HEAD_TRANSITION_DELAY {0, 400}\n#define SPEED_REDETECT_IMMUNE_SEC 5 // (interval seconds) before next auto-redetection can occur after PROTUP - added to above timer!\n\n#define LIN_RTT_SLOWDOWN 70 // Grow rtt 40x slower than real-time\n#define LIN_FORCE_RTT_GROW 0 // ms // TODO: need to find optimal value for required performance region\n#define FORCE_RTT_JITTER_THRESH_MS 30 // ms of jitter to start growing rtt (subbing?)\n\n#define DEAD_RTT 1500 // ms. RTT to consider chan dead\n#define DEAD_RSR_USG 40 // %. RSR utilization to consider chan dead if ACS=0\n#define DEAD_CHANNEL_RSR 40000 // fixed RSR for dead channel\n\n#define RSR_SMOOTH_GRAN 10 // ms granularity\n#define RSR_SMOOTH_FULL 500 // ms for full convergence\n#define TRAIN_PKTS 80\n#define WRITE_OUT_MAX 30 // write no more than 30 packets at once\n//#define NOCONTROL\n//#define NO_ACK\n\n#define FAST_PCS_PACKETS_CAN_CALC_SPEED 200 // packets count to calculate PCS speed statistically correct\n#define FAST_PCS_MINIMAL_INTERVAL 50 // ms minimal interval\n\n#define RCVBUF_SIZE 1048576\n#define WHO_LOST 1\n#define WHO_LAGGING 2\n\n// #define TIMEWARP\n\n#ifdef TIMEWARP\n    #define TW_MAX 10000000\n\n    char *timewarp;\n    int tw_cur;\n#endif\n\n\n#define PUSH_TO_TOP 2 // push Nth packet, 0 to disable\n\n\n#define get_ds_ts(x) ((x.tv_sec - x.tv_sec / 10000000 * 10000000) * 100 + x.tv_usec / 10000)\n\n\n#ifdef CPULAGCHK\n    #define CHKCPU(x) gettimeofday(&cpulag_tmp, NULL);timersub(&cpulag_tmp, &old_time, &tv_tmp_tmp_tmp);if(tv_tmp_tmp_tmp.tv_usec > SUPERLOOP_MAX_LAG_USEC) vlog(LOG_ERR,\"WARNING! CPU deficiency detected! Cycle lag: %ld.%06ld place %d\", tv_tmp_tmp_tmp.tv_sec, tv_tmp_tmp_tmp.tv_usec, x);\n    struct timeval cpulag_tmp;\n#else\n    #define CHKCPU {}\n#endif\n\nchar lossLog[JS_MAX] = { 0 }; // for send_q compressor\nint lossLog_cur = 0;\n\n// flags:\nuint8_t time_lag_ready;\nint ptt_allow_once = 0; // allow to push-to-top single packet\nint skip=0;\nint forced_rtt_reached=1;\nint select_check=0;\n\nsigset_t block_mask, unblock_mask;\n\nchar rxmt_mode_request = 0; // flag\nlong int weight = 0; // bigger weight more time to wait(weight == penalty)\nlong int weight_cnt = 0;\nint acnt = 0; // assert variable\nchar *out_buf;\nuint16_t dirty_seq_num;\nint sendbuff;\n#define START_SQL 5000\nstruct udp_stats udp_struct[1];\n\nint drop_packet_flag = 0, drop_counter=0;\nint skip_write_flag = 0;\n// these are for retransmit mode... to be removed\nshort retransmit_count = 0;\nchar channel_mode = MODE_NORMAL;\nint hold_mode = 0; // 1 - hold 0 - normal\nint force_hold_mode = 1;\nint buf_len, incomplete_seq_len = 0;\nint16_t my_miss_packets_max = 0; // in ms; calculated here\nint16_t miss_packets_max = 0; // get from another side\nint proto_err_cnt = 0;\nint my_max_send_q_chan_num = 0;\nuint32_t my_max_send_q = 0, max_reorder_byte = 0;\nuint32_t last_channels_mask = 0;\nint32_t send_q_eff = 0;\nint max_chan=-1;\nuint32_t start_of_train = 0, end_of_train = 0;\nstruct timeval flood_start_time = { 0, 0 };\nchar *buf2;\nint buf_len_real=0;\n\nint need_send_loss_FCI_flag = 0;\n#define WB_1MS_SIZE 500\nint wb_1ms[WB_1MS_SIZE] = { 0 };\nint wb_1ms_idx = 2, start_print = 0;\nchar wb_1ms_str[5000] = { '\\0' };\n\n/*Variables for the exact way of measuring speed*/\nstruct timeval send_q_read_time, send_q_read_timer = {0,0}, send_q_read_drop_time = {0, 100000}, send_q_mode_switch_time = {0,0}, net_model_start = {0,0};\nint32_t ACK_coming_speed_avg = 0;\nint32_t send_q_limit = 7000;\nint32_t magic_rtt_avg = 0;\n\n/* Host we are working with.\n * Used by signal handlers that's why it is global.\n */\nstruct vtun_host *lfd_host;\nstruct conn_info *shm_conn_info;\n\nstruct lfd_mod *lfd_mod_head = NULL, *lfd_mod_tail = NULL;\nstruct channel_info *chan_info = NULL;\n\nstruct phisical_status info; /**< We store here all process closed information */\n\nstruct {\n    int packet_sent_ag;\n    int packet_sent_rmit;\n    int byte_sent_ag_full;\n    int byte_sent_rmit_full;\n    int bytes_rcvd_norm;\n    int bytes_rcvd_rx;\n    int pkts_dropped;\n    int rxmit_req; // outdated: use max_latency_hit + max_reorder_hit\n    int rxmit_req_rx;\n    int rxmits;\t// number of resended packets\n    int rxmits_notfound; // number of resend packets which not found\n    int max_latency_hit; // new\n    int max_reorder_hit; // new\n    int mode_switches;\n    int rxm_ntf;\n    int chok_not;\n    int max_latency_drops; // new\n    int bytes_sent_chan[MAX_TCP_LOGICAL_CHANNELS];\n    int bytes_rcvd_chan[MAX_TCP_LOGICAL_CHANNELS];\n    int tokens_max;\n    int maw;\n    int mar;\n    int skip_new_h; // skipping and sending new as we are heading\n    int skip_new_d; // skipping and sending new as we can deliver in time and we have no more packets\n    int skip_r; // skipping as a result of all computations\n    int skip_no; // skipping without sending\n    int skip_l; // skipping by getting last packet\n    int p_tooold;\n    int p_expnum;\n    int p_tooearly;\n    int web_surf_optimization;\n} statb;\n\n\nstruct {\n    int expiration_ms_fromnow;\n    int expnum;\n} log_tmp;\n\nstruct {\n    int v_min;\n    int v_avg;\n    int v_max;\n} v_mma;\n\n\nstruct mini_path_desc\n{\n    int process_num;\n    int rtt;\n    int packets_between_loss;\n};\n\nstruct time_lag_info time_lag_info_arr[MAX_TCP_LOGICAL_CHANNELS];\nstruct time_lag time_lag_local;\nstruct timeval socket_timeout = { 10, 0 };\n\nstruct last_sent_packet last_sent_packet_num[MAX_TCP_LOGICAL_CHANNELS]; // initialized by 0 look for memset(..\n\nfd_set fdset, fdset_w, *pfdset_w;\nint delay_acc; // accumulated send delay\nint delay_cnt;\nuint32_t my_max_speed_chan;\nuint32_t my_holded_max_speed;\n//uint32_t my_max_send_q;\n\n\n//\n//  Declarations.\n//\nint check_delivery_time_path_unsynced(int pnum, int mld_divider);\nint check_delivery_time_unsynced(int mld_divider);\nint check_rtt_latency_drop_chan(int chan_num);\nint get_rto_usec();\nint lost_buf_exists(uint32_t seq_num);\nint plp_avg_pbl_unrecoverable(int pnum);\n\n\n\n\nint fit_wlinear (const double *x, const size_t xstride,\n                 const double *w, const size_t wstride,\n                 const double *y, const size_t ystride,\n                 const size_t n,\n                 double *c0, double *c1,\n                 double *cov_00, double *cov_01, double *cov_11,\n                 double *chisq)\n{\n\n  /* compute the weighted means and weighted deviations from the means */\n\n  /* wm denotes a \"weighted mean\", wm(f) = (sum_i w_i f_i) / (sum_i w_i) */\n\n  double W = 0, wm_x = 0, wm_y = 0, wm_dx2 = 0, wm_dxdy = 0;\n\n  size_t i;\n\n  for (i = 0; i < n; i++)\n    {\n      const double wi = w[i * wstride];\n\n      if (wi > 0)\n        {\n          W += wi;\n          wm_x += (x[i * xstride] - wm_x) * (wi / W);\n          wm_y += (y[i * ystride] - wm_y) * (wi / W);\n        }\n    }\n\n  W = 0;                        /* reset the total weight */\n\n  for (i = 0; i < n; i++)\n    {\n      const double wi = w[i * wstride];\n\n      if (wi > 0)\n        {\n          const double dx = x[i * xstride] - wm_x;\n          const double dy = y[i * ystride] - wm_y;\n\n          W += wi;\n          wm_dx2 += (dx * dx - wm_dx2) * (wi / W);\n          wm_dxdy += (dx * dy - wm_dxdy) * (wi / W);\n        }\n    }\n\n  /* In terms of y = a + b x */\n\n  {\n    double d2 = 0;\n    double b = wm_dxdy / wm_dx2;\n    double a = wm_y - wm_x * b;\n\n    *c0 = a;\n    *c1 = b;\n\n    *cov_00 = (1 / W) * (1 + wm_x * wm_x / wm_dx2);\n    *cov_11 = 1 / (W * wm_dx2);\n\n    *cov_01 = -wm_x / (W * wm_dx2);\n\n    /* Compute chi^2 = \\sum w_i (y_i - (a + b * x_i))^2 */\n\n    for (i = 0; i < n; i++)\n      {\n        const double wi = w[i * wstride];\n\n        if (wi > 0)\n          {\n            const double dx = x[i * xstride] - wm_x;\n            const double dy = y[i * ystride] - wm_y;\n            const double d = dy - b * dx;\n            d2 += wi * d * d;\n          }\n      }\n\n    *chisq = d2;\n  }\n\n  return 1;\n}\n\nint percent_delta_equal(int A, int B, int percent) {\n    int delta = A>B?A-B:B-A;\n    if(delta > 10000000) return 0;\n    if(A < 2 && B < 2) {\n        return 1;\n    }\n    int dp = delta * 100 / (A/2 + B/2);\n    if(dp <= percent) {\n        return 1;\n    }\n    return 0;\n}\n\nint frame_llist_getLostPacket_byRange(struct frame_llist *l, struct frame_llist *l_jw, struct frame_seq *flist, struct packet_sum *packet_sum) {\n    int index = l_jw->rel_head;\n    int prevIndex = -1;\n\n    packet_sum->lostAmount = packet_sum->stop_seq - packet_sum->start_seq + 1;\n#ifdef CODE_LOG\n    vlog(LOG_INFO, \"jwb %d wb %d\",l_jw->length, l->length);\n#endif\n    uint32_t lostSeq = packet_sum->start_seq;\n\n    //search lost packet in wb_just_write_frames\n    while (index > -1) {\n#ifdef CODE_LOG\n        vlog(LOG_INFO, \"jwb iterate idx %d lost amount %d seq_num %\"PRIu32\" lost seq %\"PRIu32\"\", index, packet_sum->lostAmount, flist[index].seq_num, lostSeq);\n#endif\n        if ((flist[index].seq_num >= packet_sum->start_seq) && (flist[index].seq_num <= packet_sum->stop_seq)) {\n            packet_sum->lostAmount--;\n            if (lostSeq == flist[index].seq_num) {\n                lostSeq++;\n            }\n        } else if (flist[index].seq_num > packet_sum->stop_seq) {\n            return lostSeq;\n        }\n        index = flist[index].rel_next;\n    }\n\n    //search lost packet in write buf\n    index = l->rel_head;\n    while (index > -1) {\n#ifdef CODE_LOG\n        vlog(LOG_INFO, \"wb iterate idx %d lost amount %d seq_num %\"PRIu32\" lost seq %\"PRIu32\"\", index, packet_sum->lostAmount, flist[index].seq_num, lostSeq);\n#endif\n        if ((flist[index].seq_num >= packet_sum->start_seq) && (flist[index].seq_num <= packet_sum->stop_seq)) {\n            packet_sum->lostAmount--;\n            if (lostSeq == flist[index].seq_num) {\n                lostSeq++;\n            }\n        } else if (flist[index].seq_num > packet_sum->stop_seq) {\n            return lostSeq;\n        }\n        index = flist[index].rel_next;\n    }\n    return lostSeq;\n}\n\nint frame_llist_check_index_range(int index, int memory_size) {\n    if ((index < 0) || (index >= memory_size)) {\n        return 1;\n    }\n    return 0;\n}\n\n\n\n#define IF_WRITE_CONDITION timersub(&info.current_time, &shm_conn_info->frames_buf[shm_conn_info->write_buf[logical_channel].frames.rel_head].time_stamp, &packet_wait_tv); \\\n        timersub(&info.current_time, &shm_conn_info->write_buf[logical_channel].last_write_time, &since_write_tv); \\\n        forced_rtt_reached=check_tokens(logical_channel); \\\n        cond_flag = ((shm_conn_info->frames_buf[shm_conn_info->write_buf[logical_channel].frames.rel_head].seq_num == (shm_conn_info->write_buf[logical_channel].last_written_seq + 1))) ? 1 : 0; \\\n        buf_len = shm_conn_info->frames_buf[shm_conn_info->write_buf[logical_channel].frames.rel_tail].seq_num - shm_conn_info->write_buf[logical_channel].last_written_seq; \\\n        if ( shm_conn_info->is_single_channel \\\n             || (forced_rtt_reached && ( \\\n                        cond_flag \\\n                      || (buf_len > lfd_host->MAX_ALLOWED_BUF_LEN) \\\n                      || timercmp(&packet_wait_tv, &((struct timeval) MAX_PACKET_WAIT), >=) \\\n                      || (    timercmp(&packet_wait_tv, &max_latency_drop, >=) \\\n                           && timercmp(&since_write_tv, &shm_conn_info->max_network_stall, >=) ) \\\n                      || (shm_conn_info->frames_buf[shm_conn_info->write_buf[logical_channel].frames.rel_head].seq_num < shm_conn_info->seq_num_unrecoverable_loss) \\\n                )) \\\n           )\n\nint update_prev_flushed(int logical_channel, int fprev) {\n    if(shm_conn_info->prev_flushed) {\n        info.flush_sequential += \n            shm_conn_info->frames_buf[fprev].seq_num - (shm_conn_info->write_buf[logical_channel].last_written_seq + 1);\n    } else {\n        // TODO: write avg stats here?\n        info.flush_sequential = \n            shm_conn_info->frames_buf[fprev].seq_num - (shm_conn_info->write_buf[logical_channel].last_written_seq + 1);\n    }\n    shm_conn_info->prev_flushed = 1;\n}\n\n// return who is lagging. \n// NOTE: Need to ensure that we have a missing packet at LWS+1 prior to calling this!\nint flush_reason_chan(int status, int logical_channel, char *pname, int chan_mask, int *who_lost_pnum) {\n    // we let that next seq_num to LWS is lost\n    uint32_t lost_seq_num = shm_conn_info->write_buf[logical_channel].last_written_seq + 1;\n    int lrq = 0;\n    int lagging = 0;\n    *who_lost_pnum = -1;\n    // find possible processes\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if (chan_mask & (1 << i) && (!shm_conn_info->stats[i].channel_dead) && check_rtt_latency_drop_chan(i)) {\n            if( (status == WHO_LAGGING) && ( (shm_conn_info->write_buf[logical_channel].last_received_seq[i]) < lost_seq_num)) {\n                if( (shm_conn_info->write_buf[logical_channel].last_received_seq[i]) > lrq) { // we find the most recent one that fulfills the conditions\n                    strcpy(pname, shm_conn_info->stats[i].name); \n                    *who_lost_pnum = i;\n                    lrq = shm_conn_info->write_buf[logical_channel].last_received_seq[i];\n                }\n            }\n            if( (status == WHO_LOST) && (lost_seq_num <= shm_conn_info->write_buf[logical_channel].possible_seq_lost[i])) {\n                if(shm_conn_info->write_buf[logical_channel].possible_seq_lost[i] > lrq) {\n                    strcpy(pname, shm_conn_info->stats[i].name); \n                    *who_lost_pnum = i;\n                    lrq = shm_conn_info->write_buf[logical_channel].possible_seq_lost[i];\n                }\n            }\n\n        }\n    }\n    // now count only\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if (chan_mask & (1 << i)) {\n            if( (status == WHO_LAGGING) && ( (shm_conn_info->write_buf[logical_channel].last_received_seq[i]) < lost_seq_num)) {\n                lagging++;\n            }\n            if( (status == WHO_LOST) && (lost_seq_num <= shm_conn_info->write_buf[logical_channel].possible_seq_lost[i])) {\n                lagging++;\n            }\n        }\n    }\n\n    if(lagging == 0 && status == WHO_LOST) { // fixing WHO_LOST only\n        // could not detect who lost directly(for example, no seq_num has arrived yet on lossing chan [loss detected by FCI]), doing 'possible' mode\n        pname[0]='L';\n        for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n            if (chan_mask & (1 << i)) {\n                if( (status == WHO_LOST) && shm_conn_info->write_buf[logical_channel].packet_lost_state[i]) {\n                    strcpy(pname+1, shm_conn_info->stats[i].name);\n                    *who_lost_pnum = i;\n                    lagging++;\n                }\n            }\n        }\n    }\n    \n    if(lagging == 0 && status == WHO_LOST) { // fixing WHO_LOST only\n        // now find last one who lost by possible_seq_lost\n        pname[0]='p';\n        unsigned int highest_psl = 0;\n        for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n            if (chan_mask & (1 << i)) {\n                if(shm_conn_info->write_buf[logical_channel].possible_seq_lost[i] > highest_psl) {\n                    highest_psl = shm_conn_info->write_buf[logical_channel].possible_seq_lost[i];\n                    strcpy(pname+1, shm_conn_info->stats[i].name);\n                    *who_lost_pnum = i;\n                    lagging++;\n                }\n            }\n        }\n    }\n\n    return lagging;\n}\n\n\n\n/********** Linker *************/\n/* Termination flag */\nstatic volatile sig_atomic_t linker_term;\n\nvoid segfault_sigaction(int signal, siginfo_t *si, void *arg)\n{\n    printf(\"CRITICAL ERROR Caught mem-free segfault at address %p; will continue anyway since we are USS 1408 Enterprise !! q:-)\\\\-<\\n\", si->si_addr);\n    //exit(0);\n}\n\nstatic void sig_term(int sig)\n{\n    //vlog(LOG_INFO, \"Get sig_term\");\n    //vlog(LOG_ERR, \"Closing connection\");\n    io_cancel();\n    linker_term = VTUN_SIG_TERM;\n}\n\nstatic void sig_hup(int sig)\n{\n    vlog(LOG_INFO, \"Get sig_hup\");\n    vlog(LOG_INFO, \"Reestablishing connection\");\n    io_cancel();\n    linker_term = VTUN_SIG_HUP;\n}\n\nstatic void sig_usr1(int sig)\n{\n    if(!select_check) {\n        vlog(LOG_ERR, \"ASSERT FAILED! SIGUSR1 not in select region!\");\n    }\n    //vlog(LOG_INFO, \"Get sig_usr1, check_shm UP\");\n    //info.check_shm = 1;\n}\n\nvoid sig_send1() {\n    uint32_t chan_mask = shm_conn_info->channels_mask;\n    pid_t pid;\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if ((i == info.process_num) || (!(chan_mask & (1 << i)))) {\n            continue;\n        }\n        sem_wait(&(shm_conn_info->stats_sem));\n        pid = shm_conn_info->stats[i].pid;\n        sem_post(&(shm_conn_info->stats_sem));\n        if (pid != 0 && shm_conn_info->max_chan == i && shm_conn_info->stats[i].hold) {\n            vlog(LOG_INFO, \"Sending signal to unhold HEAD\");\n            kill(pid, SIGUSR1);\n        }\n    }\n}\n\n/**\n * колличество отставших пакетов\n * buf[] - номера пакетов\n */\nint missing_resend_buffer (int chan_num, uint32_t buf[], int *buf_len, uint32_t seq_limit) {\n    int i = shm_conn_info->write_buf[chan_num].frames.rel_head, n;\n    uint32_t isq,nsq, k;\n    int idx=0;\n    int blen=0, lws, chs;\n\n    if(i == -1) {\n        *buf_len = 0;\n        return 0;\n    }\n\n    lws = shm_conn_info->write_buf[chan_num].last_written_seq;\n    chs = shm_conn_info->frames_buf[i].seq_num;\n\n\n    if(  ( (chs - lws) >= FRAME_BUF_SIZE) || ( (lws - chs) >= FRAME_BUF_SIZE)) { // this one will not happen :-\\\n        vlog(LOG_ERR, \"WARNING: frame difference too high: last w seq: %\"PRIu32\" fbhead: %\"PRIu32\" . FIXED. chs %d<->%d lws cn %d\", shm_conn_info->write_buf[chan_num].last_written_seq, shm_conn_info->write_buf[chan_num].frames_buf[i].seq_num, chs, lws, chan_num);\n        shm_conn_info->write_buf[chan_num].last_written_seq = shm_conn_info->frames_buf[i].seq_num-1;\n    }\n\n    // fix for diff btw start\n    for(k=1; k<(shm_conn_info->frames_buf[i].seq_num - shm_conn_info->write_buf[chan_num].last_written_seq); k++) {\n        buf[idx] = shm_conn_info->write_buf[chan_num].last_written_seq + k;\n        idx++;\n        //vlog(LOG_INFO, \"MRB: found in start : tot %d\", idx);\n        if(idx >= FRAME_BUF_SIZE) {\n            vlog(LOG_ERR, \"WARNING: MRB2 frame difference too high: last w seq: %\"PRIu32\" fbhead: %\"PRIu32\" . FIXED. chs %d<->%d lws ch %d\", shm_conn_info->write_buf[chan_num].last_written_seq, shm_conn_info->frames_buf[i].seq_num, chs, lws, chan_num);\n            shm_conn_info->write_buf[chan_num].last_written_seq = shm_conn_info->frames_buf[i].seq_num-1;\n            idx=0;\n            break;\n        }\n    }\n    while(i > -1) {\n        n = shm_conn_info->frames_buf[i].rel_next;\n        //vlog(LOG_INFO, \"MRB: scan1\");\n        if( n > -1 ) {\n\n            isq = shm_conn_info->frames_buf[i].seq_num;\n            nsq = shm_conn_info->frames_buf[n].seq_num;\n            if(nsq > seq_limit) {\n                break;\n            }\n            //vlog(LOG_INFO, \"MRB: scan2 %\"PRIu32\" > %\"PRIu32\" +1 ?\", nsq, isq);\n            if(nsq > (isq+1)) {\n                //vlog(LOG_INFO, \"MRB: scan2 yes!\");\n                for(k=1; k<=(nsq-(isq+1)); k++) {\n                    if(idx >= FRAME_BUF_SIZE) {\n                        vlog(LOG_ERR, \"WARNING: frame seq_num diff in write_buf > FRAME_BUF_SIZE\");\n                        *buf_len = blen;\n                        return idx;\n                    }\n\n                    buf[idx] = isq+k;\n                    idx++;\n                    //vlog(LOG_INFO, \"MRB: found in middle : tot %d\", idx);\n                }\n            }\n        }\n        i = n;\n        blen++;\n    }\n    //vlog(LOG_INFO, \"missing_resend_buf called and returning %d %d \", idx, blen);\n    *buf_len = blen;\n    return idx;\n}\n\nint discard_packets(int chan_num, uint32_t stop_sqn) {\n    int fprev = shm_conn_info->write_buf[chan_num].frames.rel_head;\n    uint32_t sqn = shm_conn_info->frames_buf[fprev].seq_num;\n    int idx = fprev;\n    int n_idx, cnt=0;\n    while(sqn < stop_sqn) {\n        // now jsut discard the packet\n        cnt++;\n        vlog(LOG_INFO, \"Discarding seq_num %ld cnt %d\", sqn, cnt);\n        shm_conn_info->w_stream_pkts[shm_conn_info->frames_buf[idx].shash % W_STREAMS_AMT]--;\n        n_idx = shm_conn_info->frames_buf[idx].rel_next;\n        if(frame_llist_pull(&shm_conn_info->write_buf[chan_num].frames, shm_conn_info->frames_buf, &idx) < 0) {\n            vlog(LOG_ERR, \"WARNING! discard_packets tried to pull from empty write_buf 2!\");\n            return -1;\n        }\n        frame_llist_append(&shm_conn_info->wb_free_frames, idx, shm_conn_info->frames_buf);\n        idx = n_idx;\n        if(idx == -1) {\n            vlog(LOG_ERR, \"ASSERT FAILED: discard_packets did not find stop_sqn in buffer! %ld\", stop_sqn);\n            return -2;\n        }\n        sqn = shm_conn_info->frames_buf[idx].seq_num;\n    }\n    return 0;\n}\n\n\n/**\n * get how many percent to push every 50ms\n * \n */\n \nint calculate_hsqs_percents(int max, int percent_fill) {\n    return max * percent_fill * percent_fill * percent_fill / 100000;\n}\n\n/*\n * count amount of packets lost sequentially and evenly\n *\n * return -1 if packets loss is uneven (like 0 1 1 0 0 1 1 1) or in any other case we will need to wait\n * or return amount of packets lost\n * TODO: can be optimized by using stored buf_len counter and not running this until buf_len reaches PLOSS_CHECK_PKTS\n *\n */\nint count_sequential_loss_unsync(int chan_num) {\n    int i = shm_conn_info->write_buf[chan_num].frames.rel_head, n;\n    int isq, nsq;\n    int beg_lost = 0;\n    int packets_checked = 0;\n\n    // count lost at beginning\n    beg_lost = shm_conn_info->frames_buf[i].seq_num - shm_conn_info->write_buf[chan_num].last_written_seq-1;\n\n    if(beg_lost > PLOSS_PSL) return beg_lost; // optimization: no need to calculate further as we already lost too much\n    \n    if(beg_lost == 0) {\n        vlog(LOG_ERR, \"ASSERT FAILED! beg_lost == 0: should never happen; invoke with packet loss only!\");\n    }\n    // now count losses over N packets\n    while((i > -1) && (packets_checked < PLOSS_CHECK_PKTS)) {\n        n = shm_conn_info->frames_buf[i].rel_next;\n        if( n > -1 ) {\n            isq = shm_conn_info->frames_buf[i].seq_num;\n            nsq = shm_conn_info->frames_buf[n].seq_num;\n            if(nsq > (isq+1)) {\n                return -1; // means loss not sequential; need to wait further\n            }\n        }\n        i = n;\n        packets_checked++;\n    }\n\n    if( packets_checked < PLOSS_CHECK_PKTS ) { // we assume that we've been invoked with at least one packet missing\n        return -1; // this means packets lost AND checked is not enough to make decision yet\n        // need to wait further..\n    }\n\n    return beg_lost; // now all checks done, return what we've got\n}\n\nint fire_event(int *ecount) {\n    (*ecount)++;\n    shm_conn_info->event_mask |= (1 << info.process_num); // warning! some events may not be fired immediately as we may race here\n    sem_post(&(shm_conn_info->event_sem));\n}\n    \n\nint get_wb_oldest_ts_unsync(struct timeval *min_tv) {\n    int i = shm_conn_info->write_buf[1].frames.rel_head, n;\n    int packets_checked = 0;\n    *min_tv = info.current_time;\n\n    while((i > -1) && (packets_checked < 100)) {\n        n = shm_conn_info->frames_buf[i].rel_next;\n        if( n > -1  && timercmp(&shm_conn_info->frames_buf[n].time_stamp, min_tv, <)) {\n            *min_tv = shm_conn_info->frames_buf[n].time_stamp;\n        }\n        i = n;\n        packets_checked++;\n    }\n\n    return 0;\n}\n\n/* check if we are allowed to drop packet again  */\nint check_drop_period_unsync() {\n    struct timeval tv_tm, tv_rtt;\n    timersub(&info.current_time, &shm_conn_info->drop_time, &tv_tm);\n    //ms2tv(&tv_rtt, shm_conn_info->stats[info.process_num].exact_rtt);\n    ms2tv(&tv_rtt, DROP_TIME_IMMUNE/1000); // TODO: unnessessary calculation\n    if(timercmp(&tv_tm, &tv_rtt, >=)) {\n        //vlog(LOG_ERR, \"Last drop passed: %d ms > rtt %d ms\", tv2ms(&tv_tm), tv2ms(&tv_rtt));\n        return 1;\n    }\n    // else\n    return 0;\n}\n\n/* Check if the packet sent right now will be delivered in time */\nint check_delivery_time(int mld_divider) {\n    // RTT-only for now..\n    //    struct timeval max_latency_drop = MAX_LATENCY_DROP;\n    if(info.head_channel) return 1; // this is required! beware when refactoring!\n    sem_wait(&(shm_conn_info->stats_sem));\n    int ret = check_delivery_time_unsynced(mld_divider);\n    sem_post(&(shm_conn_info->stats_sem));\n    return ret;\n}\n\n// this method is crutial as it controls AG/R_MODE operation while in R_MODE\nint check_delivery_time_unsynced(int mld_divider) {\n    return check_delivery_time_path_unsynced(info.process_num, mld_divider);\n}\n\nint check_delivery_time_path_unsynced(int pnum, int mld_divider) {\n    struct timeval max_latency_drop = info.max_latency_drop;\n    // check for dead channel\n    if(shm_conn_info->stats[pnum].channel_dead && (shm_conn_info->max_chan != pnum)) {\n        // vlog(LOG_ERR, \"WARNING check_delivery_time DEAD and not HEAD\"); // TODO: out-once this!\n        return 0;\n    }\n    // TODO: re-think this!\n    if( ( (info.rsr < info.send_q_limit_threshold) || (info.send_q_limit_cubic < info.send_q_limit_threshold)) && (shm_conn_info->max_chan != pnum)) {\n        vlog(LOG_INFO, \"WARNING check_delivery_time RSR %d < THR || CUBIC %d < THR=%d\", info.rsr, (int32_t)info.send_q_limit_cubic, info.send_q_limit_threshold);\n        return 0;\n    }\n    if( ((shm_conn_info->stats[pnum].exact_rtt + shm_conn_info->stats[pnum].rttvar) - shm_conn_info->stats[shm_conn_info->max_chan].exact_rtt) > ((int32_t)(tv2ms(&max_latency_drop)/mld_divider + shm_conn_info->forced_rtt)) ) {\n        // no way to deliver in time\n        //vlog(LOG_ERR, \"WARNING check_delivery_time %d + %d - %d > %d + %d\", shm_conn_info->stats[pnum].exact_rtt,  shm_conn_info->stats[pnum].rttvar, shm_conn_info->stats[shm_conn_info->max_chan].exact_rtt, (int32_t)(tv2ms(&max_latency_drop)/mld_divider), shm_conn_info->forced_rtt);\n        return 0;\n    }\n    //vlog(LOG_ERR, \"CDT OK\");\n    return 1;\n}\n\nint check_rtt_latency_drop() { // TODO: remove this dumb method (refactor some code)\n    return check_rtt_latency_drop_chan(info.process_num);\n}\n\n/*\n    This method allows AG or disallows AG based on latency\n*/\nint check_rtt_latency_drop_chan(int chan_num) {\n    struct timeval max_latency_drop = info.max_latency_drop;\n    if(shm_conn_info->stats[chan_num].channel_dead && (shm_conn_info->max_chan != chan_num)) {\n        return 0;\n    }\n    \n    if(shm_conn_info->stats[chan_num].exact_rtt < RTT_THRESHOLD_GOOD) {\n        return 1;\n    }\n    \n    //int my_rtt = (int)(shm_conn_info->stats[chan_num].exact_rtt + shm_conn_info->stats[chan_num].rttvar);\n    //int min_rtt = (int)shm_conn_info->stats[shm_conn_info->max_chan].exact_rtt;\n    \n    \n    if(shm_conn_info->max_allowed_rtt != 0) {\n        if(info.exact_rtt > (shm_conn_info->max_allowed_rtt + shm_conn_info->stats[shm_conn_info->max_chan].exact_rtt)) {\n            return 0;\n        }\n    } else {\n        //if(my_rtt > min_rtt * RTT_THRESHOLD_MULTIPLIER) {\n            return 0;\n        //}\n    }\n    \n    return 1;\n}\n\n    \nstatic inline int add_tokens(int chan_num, int *next_token_ms) {\n    //shm_conn_info->tokens_in_out = 0;\n    //int tokens_in_out = 0;\n    // TODO: may be sync on write_buf is required??\n    if(shm_conn_info->tokens < 0) {\n        shm_conn_info->tokens = 0;\n    }\n    if(chan_num != 1) {\n        return 1; // for all other chans (e.g. 0-service channel) return drop allowed\n    }\n    int ms_for_token = 1; \n    //int full_rtt = ((shm_conn_info->forced_rtt_recv > shm_conn_info->frtt_local_applied) ? shm_conn_info->forced_rtt_recv : shm_conn_info->frtt_local_applied);\n    //int tail_idx = shm_conn_info->write_buf[chan_num].frames.rel_tail;\n    //int buf_len = shm_conn_info->frames_buf[tail_idx].seq_num - shm_conn_info->write_buf[chan_num].last_written_seq;\n    //int buf_len = shm_conn_info->write_buf[chan_num].last_received_seq[shm_conn_info->remote_head_pnum] - shm_conn_info->write_buf[chan_num].last_written_seq;\n    //int tokens_above_thresh = shm_conn_info->tokenbuf - MAX_STUB_JITTER;\n    //if(tokens_above_thresh < 0) tokens_above_thresh = 0;\n    int buf_len_real = shm_conn_info->write_buf[chan_num].frames.length + shm_conn_info->write_buf[chan_num].frames.stub_total;\n    //buf_len = buf_len_real; \n    //struct timeval packet_dtv;\n    //int BPCS = 0;\n    //int head_idx = shm_conn_info->write_buf[chan_num].frames.rel_head;\n    //struct timeval packet_wait_tv;\n\n    /*\n    int pktdiff = buf_len_real; // current diff is just the real buf_len\n    // now check rtt\n    timersub(&info.current_time, &shm_conn_info->frames_buf[head_idx].time_stamp, &packet_wait_tv);\n\n    // detect stuck condition\n    // stuck means that we are not allowed to drop due to packet not available\n    // whenever we have no packet to drop - we are stuck - even if it is not the time to drop yet\n    \n    int max_total_rtt = (shm_conn_info->total_max_rtt+shm_conn_info->total_max_rtt_var) - (shm_conn_info->total_min_rtt - shm_conn_info->total_min_rtt_var); \n    if (shm_conn_info->frames_buf[shm_conn_info->write_buf[chan_num].frames.rel_head].seq_num\n            != (shm_conn_info->write_buf[chan_num].last_written_seq + 1)) {\n        int packet_lag = tv2ms(&packet_wait_tv);\n        // TODO: unused as this method resulted to failure\n        // we should rather use this info to continue to smoothly push up the value\n        //if(shm_conn_info->max_stuck_rtt < packet_lag && packet_lag < max_total_rtt){\n        //    shm_conn_info->max_stuck_rtt = packet_lag;\n        //}\n        //if(shm_conn_info->max_stuck_buf_len < pktdiff) shm_conn_info->max_stuck_buf_len = pktdiff;\n    }\n    */\n        \n    //int pktdiff = shm_conn_info->frames_buf[shm_conn_info->write_buf[i].frames.rel_tail].seq_num - shm_conn_info->write_buf[i].last_written_seq;\n    //int packet_rtt = tv2ms(&packet_wait_tv) + shm_conn_info->frames_buf[head_idx].current_rtt;\n    /*\n    if(packet_rtt < shm_conn_info->max_stuck_rtt) {\n        shm_conn_info->tokens = 0;\n        if(shm_conn_info->max_stuck_buf_len < pktdiff) shm_conn_info->max_stuck_buf_len = pktdiff; // TODO: use unconditoinal set or not??\n        *next_token_ms = shm_conn_info->max_stuck_rtt - packet_rtt;\n        return 0;\n    }\n    */\n    //int max_msbl = max_msrt_mul * rtt_min * smooth_ACPS;\n    // TOP the MSBL TODO: move out of HERE \n    int max_msbl = MSBL_LIMIT;\n    if(shm_conn_info->max_stuck_buf_len > max_msbl) {\n        shm_conn_info->max_stuck_buf_len = max_msbl;\n    }\n    /*\n    if(buf_len_real >= 10) {\n        timersub(&shm_conn_info->frames_buf[tail_idx].time_stamp, &shm_conn_info->frames_buf[head_idx].time_stamp, &packet_dtv);\n        int pdms = tv2ms(&packet_dtv);\n        if(pdms > 50) { // TODO: is it required??\n            BPCS = buf_len_real * 1000 / pdms;\n            shm_conn_info->write_speed_b = BPCS;\n        }\n    }\n    */\n    \n    int APCS = shm_conn_info->APCS * 8 / 10; // 0.7 of APCS to add to tokenbuf\n    \n    // now do add some tokens ?\n    \n    struct timeval passed_tv;\n    timersub(&info.current_time, &shm_conn_info->tokens_lastadd_tv, &passed_tv);\n    int ms_passed = tv2ms(&passed_tv);\n    int tokens_to_add = APCS * ms_passed / 1000;\n    // if(buf_len_real > 0 && tokens_to_add > TOKENBUF_ADD_BURST) {\n    //     shm_conn_info->tokens_lastadd_tv = info.current_time;\n    //     shm_conn_info->tokenbuf += tokens_to_add;\n    // }\n    if(buf_len_real == 0) {\n        shm_conn_info->tokens_lastadd_tv = info.current_time;\n    } else if (tokens_to_add > TOKENBUF_ADD_BURST) { // TODO: prevent too high jitter by limiting available tokens?\n        shm_conn_info->tokens += tokens_to_add;\n        shm_conn_info->tokens_lastadd_tv = info.current_time;\n    } // else wait ...\n    // if(shm_conn_info->tokenbuf - MAX_STUB_JITTER > shm_conn_info->max_stuck_buf_len) { // no need for tokenbuf larger than MSBL\n    //     shm_conn_info->tokenbuf = shm_conn_info->max_stuck_buf_len + MAX_STUB_JITTER;\n    // }\n    \n    if(shm_conn_info->max_stuck_buf_len > TOKENS_MAXWAIT && shm_conn_info->tokens > shm_conn_info->max_stuck_buf_len) {\n    // if(shm_conn_info->tokens > shm_conn_info->max_stuck_buf_len) { // no need for tokenbuf larger than MSBL\n        shm_conn_info->tokens = shm_conn_info->max_stuck_buf_len;\n    }\n \n    // if(shm_conn_info->slow_start_recv) {\n    //     ms_for_token = 1;\n    //     *next_token_ms = 1;\n    // }\n    if(shm_conn_info->tokens > 0) {\n        // no need to set ms_for_token as get_write_buf_wait_data will shoot anyways\n        return 1;\n    } else {\n        //if(!shm_conn_info->slow_start_recv) {\n        if(APCS == 0) { // i=n caseof ss\n            ms_for_token = 50; // ms before packet drop? (zero speed)\n        } else {\n            ms_for_token = 1000 / APCS * TOKENBUF_ADD_BURST;\n        }\n        //}\n        if(ms_for_token < 1) ms_for_token = 1; // TODO: is this correct?\n        *next_token_ms = ms_for_token;\n        return 0;\n    }\n}\n\nint check_tokens(int chan_num) {\n    if(shm_conn_info->avg_len_in <= AVG_LEN_IN_ACK_THRESH) {\n        shm_conn_info->max_stuck_buf_len = 0;\n        statb.web_surf_optimization |= 1;\n        return 1; \n    }\n    // if(shm_conn_info->slow_start_recv) {\n    //     return 1; // the hope that this will actually help gain back ss\n    //     //struct timeval since_write_tv;\n    //     //timersub(&info.current_time, &shm_conn_info->write_buf[chan_num].last_write_time, &since_write_tv);\n    //     //if(since_write_tv.tv_usec < 1000) {\n    //     //    return 0;\n    //     //}\n    // }\n        \n    if(shm_conn_info->tokens > 0) return 1;\n    int tokens_above_thresh = shm_conn_info->tokenbuf - MAX_STUB_JITTER;\n    if(tokens_above_thresh < 0) tokens_above_thresh = 0;\n    int buf_len_real = shm_conn_info->write_buf[chan_num].frames.length + shm_conn_info->write_buf[chan_num].frames.stub_total + tokens_above_thresh;\n    if(buf_len_real > shm_conn_info->max_stuck_buf_len) { // support for flushing packets w/o packets coming in\n        return 1;\n    }\n    int head_idx = shm_conn_info->write_buf[chan_num].frames.rel_head;\n    if(shm_conn_info->frames_buf[head_idx].len < 100) { // flush ACK immediately\n        return 1;\n    }\n    return 0; \n}\n\nint DL_flag_drop_allowed_unsync_stats(uint32_t chan_mask) {\n    // calculate if ag-send speed is greater than one of the channels self speed. \n    // Return 0 if greater, 1 otherwise (allowed to drop)\n    int ag_speed_total = 0;\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead)) { // hope this works..\n            ag_speed_total += shm_conn_info->stats[i].packet_speed_ag;\n        }\n    }\n    // now dubl 2\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead)) { // hope this works..\n            if( (ag_speed_total < shm_conn_info->stats[i].ACK_speed/info.eff_len) && !percent_delta_equal(ag_speed_total, shm_conn_info->stats[i].ACK_speed/info.eff_len, 10) ) {\n                //vlog(LOG_INFO, \"Allowing to drop flag: as we can send everything thru one chan: total: %d, chan %d ACS: %d\", ag_speed_total, i, shm_conn_info->stats[i].ACK_speed);\n                return 1; // allow to drop AG flag as we can send everything thru one chan\n            }\n        }\n    }\n    return 0;\n}\n\nint get_write_buf_wait_data(uint32_t chan_mask, int *next_token_ms) {\n    // TODO WARNING: is it synchronized? stats_sem! write_buf sem!? TODO! bug #189\n    //struct timeval max_latency_drop = MAX_LATENCY_DROP;\n    // TODO WARNING i do not know why we are still checking packets if we see no rel_head\n    \n    int buf_latency_ms;\n    int buf_len;\n    int cond_flag;\n    struct timeval max_latency_drop;\n    int rtou = get_rto_usec();\n    max_latency_drop.tv_sec = rtou / 1000000;\n    max_latency_drop.tv_usec = rtou % 1000000;\n    struct timeval tv_tmp;\n    int head_lrx = 0, seq_loss = 0;\n    struct timeval packet_wait_tv, since_write_tv;\n    info.ploss_event_flag = 0; // TODO: remove ploss event check\n    int logical_channel = 1; // warning! fixed stream/channel here for IF_WRITE_CONDITION\n    for (int i = 1; i < info.channel_amount; i++) { // chan 0 is service only\n    #ifdef FRTTDBG\n                vlog(LOG_INFO, \"get_write_buf_wait_data(), for chan: %d\", i);\n    #endif\n        info.least_rx_seq[i] = UINT32_MAX;\n        timersub(   \n                    &shm_conn_info->write_buf[i].last_write_time,\n                    &shm_conn_info->frames_buf[shm_conn_info->write_buf[i].frames.rel_head].time_stamp, \n                    &packet_wait_tv);\n        buf_latency_ms = tv2ms(&packet_wait_tv);\n        if(buf_latency_ms < 0) buf_latency_ms = 0;\n        /*\n        seq_loss = 0;\n        if(shm_conn_info->frames_buf[shm_conn_info->write_buf[i].frames.rel_head].seq_num > (shm_conn_info->write_buf[i].last_written_seq + 1)){\n            // means we're waiting for packet. Now check if it is lost!\n            // TODO: optimize here by checking buf_len >= PLOSS_CHECK_PKTS before doing this check!\n            seq_loss = count_sequential_loss_unsync(i); \n            if(seq_loss > 0 && seq_loss < PLOSS_PSL) {\n                // means we detected PLOSS event\n                //seq_loss = 1; // re-use variable\n                // TODO rewrite this if\n                info.ploss_event_flag = 1;\n            } else {\n                seq_loss = 0;\n                info.ploss_event_flag = 0;\n            }\n        }\n        */\n        for(int p=0; p < MAX_TCP_PHYSICAL_CHANNELS; p++) {\n            if (chan_mask & (1 << p)) {\n                if((head_lrx < shm_conn_info->write_buf[i].last_received_seq[p]) && (shm_conn_info->stats[p].remote_head_channel)) { // TODO: two heads possible?\n                    head_lrx = shm_conn_info->write_buf[i].last_received_seq[p];\n                }\n                if(seq_loss && (shm_conn_info->write_buf[i].possible_seq_lost[p] > (shm_conn_info->write_buf[i].last_written_seq + seq_loss)) \n                && (shm_conn_info->write_buf[i].possible_seq_lost[p] < (shm_conn_info->write_buf[i].last_written_seq + PLOSS_CHECK_PKTS))) {\n                    // means we received a local loss with this global seq\n                    // and write buf says it is likely a loss\n                    // TODO: we have a slight chance of doing this by mistake\n                    //.    think how to deal with.. UPDATE: it is already dealt with by writing late packets\n                    // TODO TODO: NOT JUST BIGGER SEQ NUM BUT SOME RANGE TO DETECT WITHIN\n                    info.least_rx_seq[i] = shm_conn_info->write_buf[i].last_received_seq[p];\n                } else {\n                    if(    shm_conn_info->stats[p].channel_dead \n                       //|| ((shm_conn_info->stats[p].exact_rtt - shm_conn_info->stats[shm_conn_info->remote_head_pnum].exact_rtt) > (buf_latency_ms + (MAX_LATENCY_DROP_USEC / 1000)))\n                       ) { // do not wait for late packet only if drtt is > MLD or DEAD\n                    //        || ((shm_conn_info->stats[p].recv_mode == 0)\n                    //        && timercmp(&info.current_time, &shm_conn_info->stats[p].agoff_immunity_tv, >=))\n                    //  ) { \n                        // vlog(LOG_ERR, \"get_write_buf_wait_data(), detected dead channel dead %d, p %d - ertt %d rhd %d - ertt %d, blm %d mld %d\",\n                        //                 shm_conn_info->stats[p].channel_dead, p, shm_conn_info->stats[p].exact_rtt, shm_conn_info->remote_head_pnum, shm_conn_info->stats[shm_conn_info->remote_head_pnum].exact_rtt, buf_latency_ms, (MAX_LATENCY_DROP_USEC / 1000));\n                        continue;\n                    }\n                    if (shm_conn_info->write_buf[i].last_received_seq[p] < info.least_rx_seq[i]) {\n                        info.least_rx_seq[i] = shm_conn_info->write_buf[i].last_received_seq[p];\n                    }\n                }\n            }\n        }\n        if(info.least_rx_seq[i] == UINT32_MAX) { // we did not find any alive channel. Just consider any LRX\n            //vlog(LOG_ERR, \"Warning! Could not detect any alive chan; using head_lrx !\");\n            info.least_rx_seq[i] = head_lrx; // do not detect any loss if head is unknown?\n            //info.least_rx_seq[i] = 0; // do not detect any loss\n            // init least_rx_seq with max value of current chans\n            /* // TODO for #395\n            for(int p=0; p < MAX_TCP_PHYSICAL_CHANNELS; p++) {\n                if ((chan_mask & (1 << p)) && (!shm_conn_info->stats[p].channel_dead)) {\n                    if (shm_conn_info->write_buf[i].last_received_seq[p] > info.least_rx_seq[i]) {\n                        info.least_rx_seq[i] = shm_conn_info->write_buf[i].last_received_seq[p];\n                    }\n                }\n            }\n            */\n        }\n        if (shm_conn_info->write_buf[i].frames.rel_head != -1) {\n            // check if we can write these packets\n            IF_WRITE_CONDITION \n            {\n                return 1;\n            }\n        } else {\n            if(shm_conn_info->write_buf[i].frames.length != 0) {\n                // vlog(LOG_ERR, \"ASSERT FAILED: get_write_buf_wait_data() detected length incosistency %d should be 0.\", shm_conn_info->write_buf[i].frames.length);\n                //shm_conn_info->write_buf[i].frames.length = 0; // fix if it becomes broken for any reason\n            }\n        }\n    }\n    if(shm_conn_info->tokens > TOKENS_MAXWAIT) shm_conn_info->tokens = TOKENS_MAXWAIT; // zero tokens and retry again...\n    // shm_conn_info->tokens = 0; // needed to ensure that we only have tokens when we can write\n    return 0;\n}\n\n\n// get next frame that need to be sent\n// it is either the seq_num referenced as input argument (usually last_sent+1)\n// or oldest non-expired seq_num frame\nint get_resend_frame(int chan_num, uint32_t *seq_num, char **out, int *sender_pid) {\n    int i, j, len = -1;\n    int top_seq_num = shm_conn_info->seq_counter[chan_num];\n    struct timeval expiration_date;\n    struct timeval continuum_date = info.current_time;\n    struct timeval max_latency;\n    struct timeval min_latency;\n    struct timeval hold_period;\n    int expnum = 0;\n\n    int mrl_ms, drtt_ms, expiration_ms_fromnow;\n\n    drtt_ms = shm_conn_info->stats[info.process_num].exact_rtt - shm_conn_info->stats[shm_conn_info->max_chan].exact_rtt;\n    // TODO what time is the expiration time? MLD diff or MAR?\n    //mrl_ms = MAX_LATENCY_DROP_USEC / 1000 / 2;\n    //mrl_ms = shm_conn_info->stats[shm_conn_info->max_chan].rttvar;\n    mrl_ms = 100; // 20 ms lag // should be zero\n    expiration_ms_fromnow = mrl_ms - drtt_ms; // we're OK to be late up to MLD? ms, but we're already drtt ms late!\n    if(expiration_ms_fromnow < 0) { \n        //vlog(LOG_INFO, \"get_resend_frame can't get packets: expiration_ms_fromnow < 0: %d\", expiration_ms_fromnow);\n        return -1; // we can get no frames; handle this above\n    }\n    ms2tv(&max_latency, expiration_ms_fromnow);\n    timersub(&info.current_time, &max_latency, &expiration_date);\n   \n    // I am commenting-out this block as we are OBLIGED to deliver packets ASAP in R_MODE (as in AG_MODE, too)\n    // we should take care of MLDs caused by too fast packets at receiver side\n    //if(drtt_ms < 0) {  // need to set expiration date\n    //    ms2tv(&min_latency, (-drtt_ms)); // we are not allowed to be any faster unlike in 'later' scenario\n    //    timersub(&info.current_time, &min_latency, &continuum_date);\n    //}\n   \n    //find start point\n    j = shm_conn_info->resend_buf_idx - 1 < 0 ? RESEND_BUF_SIZE - 1 : shm_conn_info->resend_buf_idx - 1; // correct: the idx is incremented AFTER write\n    for (int i = 0; i < RESEND_BUF_SIZE; i++) {// TODO need to reduce search depth 100 200 1000 ??????\n//        vlog(LOG_INFO, \"look for %\"PRIu32\" start point step - j %i chan_num %i seq_num %\"PRIu32\" \",*seq_num, j, shm_conn_info->resend_frames_buf[j].chan_num, shm_conn_info->resend_frames_buf[j].seq_num);\n        if (shm_conn_info->resend_frames_buf[j].chan_num == chan_num) {\n            break;\n        }\n        j--;\n        if (j == -1) {\n            j = RESEND_BUF_SIZE - 1;\n        }\n    }\n\n    // now find expiration type II - not too old (by num) to be still able to send up to top within MLD\n    timersub(&info.current_time, &info.hold_time, &hold_period);\n    if((hold_period.tv_sec * 1000 + hold_period.tv_usec / 1000) <= info.exact_rtt) { // if we have been pressed lately, we have topped our real speed\n        // TODO: need info.ACK_speed_correct flag\n        // this will work just because hold is not likely to kick in before ACS is recalculated\n        expnum = (mrl_ms - drtt_ms) * (shm_conn_info->stats[info.process_num].ACK_speed / info.eff_len) / 1000; // send them all to top within MLD!\n    }\n    log_tmp.expiration_ms_fromnow = expiration_ms_fromnow;\n    log_tmp.expnum = expnum;\n    \n    // clamp to high end, clamp to low end AND respect seq_num that we want - otherwise return oldest that we can afford\n    for (int i = 0; i < RESEND_BUF_SIZE; i++) {// TODO need to reduce search depth 100 200 1000 ??????\n//                vlog(LOG_INFO, \"j %i chan_num %i seq_num %\"PRIu32\" \", j, shm_conn_info->resend_frames_buf[j].chan_num, shm_conn_info->resend_frames_buf[j].seq_num);\n        if ((shm_conn_info->resend_frames_buf[j].chan_num == chan_num) && (shm_conn_info->resend_frames_buf[j].len != 0)) {\n            if( shm_conn_info->resend_frames_buf[j].seq_num = *seq_num ) { // AND is the one we're seeking for\n                if(!timercmp(&expiration_date, &shm_conn_info->resend_frames_buf[j].time_stamp, <)) { // packet is not too old\n                    statb.p_tooold++;\n                }\n                if( !((top_seq_num - shm_conn_info->resend_frames_buf[j].seq_num) < expnum ))  { \n                  // AND we can send it and all of the rest to top in MLD time in case of DDS\n                    statb.p_expnum++;\n                }\n                if(!timercmp(&continuum_date, &shm_conn_info->resend_frames_buf[j].time_stamp, >=))  { // AND packet is not too early\n                  statb.p_tooearly++;\n                }\n            }\n            if (   \n                      timercmp(&expiration_date, &shm_conn_info->resend_frames_buf[j].time_stamp, <) // packet is not too old\n                      && ( (top_seq_num - shm_conn_info->resend_frames_buf[j].seq_num) < expnum ) // AND we can send it and all of the rest to top in MLD time in case of DDS\n                      && timercmp(&continuum_date, &shm_conn_info->resend_frames_buf[j].time_stamp, >=) // AND packet is not too early\n                      && ( shm_conn_info->resend_frames_buf[j].seq_num = *seq_num ) // AND is the one we're seeking for\n            ) {\n                *seq_num = shm_conn_info->resend_frames_buf[j].seq_num;\n                len = shm_conn_info->resend_frames_buf[j].len;\n                *((uint16_t *) (shm_conn_info->resend_frames_buf[j].out + LINKFD_FRAME_RESERV+ (len+sizeof(uint32_t)))) = (uint16_t)htons(chan_num +FLAGS_RESERVED); // WAS: channel-mode. TODO: RXMIT mode broken HERE!! // clean flags?\n                *out = shm_conn_info->resend_frames_buf[j].out + LINKFD_FRAME_RESERV;\n                *sender_pid = shm_conn_info->resend_frames_buf[j].sender_pid;\n//                vlog(LOG_INFO, \"previous j %i chan_num %i seq_num %\"PRIu32\" \", j_previous, shm_conn_info->resend_frames_buf[j].chan_num, shm_conn_info->resend_frames_buf[j_previous].seq_num );\n                return len;\n            } \n            if( (timercmp(&expiration_date, &shm_conn_info->resend_frames_buf[j].time_stamp, >=) // packet is too old, return it\n                    || ( (top_seq_num - shm_conn_info->resend_frames_buf[j].seq_num) >= expnum )) // or the packet is the one from which later on we cannot send in MLD all to top\n                    && timercmp(&continuum_date, &shm_conn_info->resend_frames_buf[j].time_stamp, >=) ) { // AND packet is still not too early\n                *seq_num = shm_conn_info->resend_frames_buf[j].seq_num;\n                len = shm_conn_info->resend_frames_buf[j].len;\n                *((uint16_t *) (shm_conn_info->resend_frames_buf[j].out + LINKFD_FRAME_RESERV+ (len+sizeof(uint32_t)))) = (uint16_t)htons(chan_num +FLAGS_RESERVED); // WAS: channel-mode. TODO: RXMIT mode broken HERE!! // clean flags?\n                *out = shm_conn_info->resend_frames_buf[j].out + LINKFD_FRAME_RESERV;\n                *sender_pid = shm_conn_info->resend_frames_buf[j].sender_pid;\n                return len;\n            }\n        }\n        j--;\n        if (j == -1) {\n            j = RESEND_BUF_SIZE - 1;\n        }\n    }\n    // last packet could only be possible in case of uninitailized buffer (at start)\n    \n    vlog(LOG_INFO, \"WARNING: get_resend_frame can't get packets: expiration_ms_fromnow= %d, expnum=%d\", expiration_ms_fromnow, expnum);\n    return -1;// means we have not found the most recent frame in resend_buf\n}\n\n\n// the same GRF but no expiration\nint get_resend_frame_unconditional(int chan_num, uint32_t *seq_num, char **out, int *sender_pid) {\n    int i, j, j_previous, len = -1;\n    \n    //find start point\n    j = shm_conn_info->resend_buf_idx - 1 < 0 ? RESEND_BUF_SIZE - 1 : shm_conn_info->resend_buf_idx - 1;\n    j_previous = j;\n    for (int i = 0; i < RESEND_BUF_SIZE; i++) {// TODO need to reduce search depth 100 200 1000 ??????\n        if (shm_conn_info->resend_frames_buf[j].chan_num == chan_num) {\n            j_previous = j;\n            break;\n        }\n        j--;\n        if (j == -1) {\n            j = RESEND_BUF_SIZE - 1;\n        }\n    }\n\n    for (int i = 0; i < RESEND_BUF_SIZE; i++) {// TODO need to reduce search depth 100 200 1000 ??????\n//                vlog(LOG_INFO, \"j %i chan_num %i seq_num %\"PRIu32\" \", j, shm_conn_info->resend_frames_buf[j].chan_num, shm_conn_info->resend_frames_buf[j].seq_num);\n        if ((shm_conn_info->resend_frames_buf[j].chan_num == chan_num) || (shm_conn_info->resend_frames_buf[j].chan_num == 0)) {\n            if (shm_conn_info->resend_frames_buf[j].seq_num == *seq_num) {\n                j_previous = j;\n                *seq_num = shm_conn_info->resend_frames_buf[j_previous].seq_num;\n                len = shm_conn_info->resend_frames_buf[j_previous].len;\n                *((uint16_t *) (shm_conn_info->resend_frames_buf[j_previous].out + LINKFD_FRAME_RESERV+ (len+sizeof(uint32_t)))) = (uint16_t)htons(chan_num +FLAGS_RESERVED); // WAS: channel-mode. TODO: RXMIT mode broken HERE!! // clean flags?\n                *out = shm_conn_info->resend_frames_buf[j_previous].out + LINKFD_FRAME_RESERV;\n                *sender_pid = shm_conn_info->resend_frames_buf[j_previous].sender_pid;\n//                vlog(LOG_INFO, \"bottom ret j %i chan_num %i seq_num %\"PRIu32\" \", j_previous, shm_conn_info->resend_frames_buf[j].chan_num, shm_conn_info->resend_frames_buf[j_previous].seq_num );\n                return len;\n            } else {\n                j_previous = j;\n            }\n        }\n        j--;\n        if (j == -1) {\n            j = RESEND_BUF_SIZE - 1;\n        }\n    }\n\n    return len;\n}\n\n// the same GRF but no expiration\nint get_resend_frame_local_sqn(int chan_num, int process_num, uint32_t local_seq_num, uint32_t *seq_num, char **out, int *sender_pid, int *idx) {\n    int i, j, j_previous, len = -1;\n    \n    //find start point\n    j = shm_conn_info->resend_buf_idx - 1 < 0 ? RESEND_BUF_SIZE - 1 : shm_conn_info->resend_buf_idx - 1;\n    j_previous = j;\n    for (int i = 0; i < RESEND_BUF_SIZE; i++) {// TODO need to reduce search depth 100 200 1000 ??????\n        if (shm_conn_info->resend_frames_buf[j].chan_num == chan_num) {\n            j_previous = j;\n            break;\n        }\n        j--;\n        if (j == -1) {\n            j = RESEND_BUF_SIZE - 1;\n        }\n    }\n\n    for (int i = 0; i < RESEND_BUF_SIZE; i++) {// TODO need to reduce search depth 100 200 1000 ??????\n        if ((shm_conn_info->resend_frames_buf[j].chan_num == chan_num) || (shm_conn_info->resend_frames_buf[j].chan_num == 0)) {\n            if (shm_conn_info->resend_frames_buf[j].local_seq_num[process_num] == local_seq_num) {\n                j_previous = j;\n                *seq_num = shm_conn_info->resend_frames_buf[j_previous].seq_num;\n                len = shm_conn_info->resend_frames_buf[j_previous].len;\n                *((uint16_t *) (shm_conn_info->resend_frames_buf[j_previous].out + LINKFD_FRAME_RESERV+ (len+sizeof(uint32_t)))) = (uint16_t)htons(chan_num +FLAGS_RESERVED); // WAS: channel-mode. TODO: RXMIT mode broken HERE!! // clean flags?\n                *out = shm_conn_info->resend_frames_buf[j_previous].out + LINKFD_FRAME_RESERV;\n                *sender_pid = shm_conn_info->resend_frames_buf[j_previous].sender_pid;\n                *idx = j_previous;\n                return len;\n            } else {\n                j_previous = j;\n            }\n        }\n        j--;\n        if (j == -1) {\n            j = RESEND_BUF_SIZE - 1;\n        }\n    }\n\n    return len;\n}\n\nint is_priority_packet(char *buf) {\n    struct my_ip *ip;\n    ip = (struct my_ip*) (buf);\n    if (ip->ip_p == 1) { // ICMP\n        return 1;\n    }\n    if(ip->ip_p == 6 && getTcpSeq(buf) == 0) {\n        return 1;\n    }\n    return 0;\n}\n\nunsigned int get_l4_hash(char *buf, unsigned int *tcp_seq) {\n    struct my_ip *ip;\n    struct tcphdr *tcp;\n    struct udphdr *udp;\n    ip = (struct my_ip*) (buf);\n    unsigned int hash = (unsigned int) (ip->ip_src.s_addr);\n    hash += (unsigned int) (ip->ip_dst.s_addr);\n    hash += ip->ip_p;\n    // WARNING: do we have to ntohl() here #856?\n    if (ip->ip_p == 6) { // TCP...\n        tcp = (struct tcphdr*) (buf + sizeof(struct my_ip));\n        hash += tcp->source;\n        hash += tcp->dest;\n        *tcp_seq = ntohl(tcp->seq);\n    }\n    if (ip->ip_p == 17) { // UDP...\n        udp = (struct udphdr*) (buf + sizeof(struct my_ip));\n        hash += udp->source;\n        hash += udp->dest;\n    }\n    if (ip->ip_p == 1) { // ICMP\n        struct icmphdr *icmp = (struct icmphdr*) (buf + sizeof(struct my_ip));\n        hash += icmp->un.echo.id;\n    }\n    \n    return hash;\n}\n\n// cycle resend buffer from top down to old to get any packet\nint get_last_packet_seq_num(int chan_num, uint32_t *seq_num) {\n    int j = shm_conn_info->resend_buf_idx-1;\n    for (int i = 0; i < RESEND_BUF_SIZE; i++) {\n        if ( (shm_conn_info->resend_frames_buf[j].chan_num == chan_num)\n         && (shm_conn_info->resend_frames_buf[j].len != 0)) {\n            *seq_num = shm_conn_info->resend_frames_buf[j].seq_num;\n            return j;\n        }\n        j--;\n        if (j < 0) {\n            j = RESEND_BUF_SIZE - 1;\n        }\n    }\n    return -1;\n}\n\nint get_oldest_packet_seq_num(int chan_num, uint32_t *seq_num) {\n    int j = shm_conn_info->resend_buf_idx;\n    j++;\n    for (int i = 0; i < RESEND_BUF_SIZE; i++) {\n        if (j == RESEND_BUF_SIZE) {\n            j = 0;\n        }\n        if (shm_conn_info->resend_frames_buf[j].chan_num == chan_num) {\n            *seq_num = shm_conn_info->resend_frames_buf[j].seq_num;\n            return j;\n        }\n        j++;\n    }\n    return -1;\n}\n\nint get_last_packet(int chan_num, uint32_t *seq_num, char **out, int *sender_pid) {\n    // there are two cases: we are unable to send packets either because they are too late or too early(which is unlikely) so we will be sending most early\n    int j = get_last_packet_seq_num(chan_num, seq_num);\n    if(j == -1) return -1;\n    int len = shm_conn_info->resend_frames_buf[j].len;\n    *((uint16_t *) (shm_conn_info->resend_frames_buf[j].out + LINKFD_FRAME_RESERV+ (len+sizeof(uint32_t)))) = (uint16_t)htons(chan_num +FLAGS_RESERVED); // WAS: channel-mode. TODO: RXMIT mode broken HERE!! // clean flags?\n    *out = shm_conn_info->resend_frames_buf[j].out + LINKFD_FRAME_RESERV;\n    *sender_pid = shm_conn_info->resend_frames_buf[j].sender_pid;\n    return len;\n}\n\nint seqn_break_tail(char *out, int len, uint32_t *seq_num, uint16_t *flag_var, uint32_t *local_seq_num, uint16_t *mini_sum, uint32_t *last_recv_lsn, uint32_t *packet_recv_spd) {\n    uint32_t local_seq_num_n, last_recv_lsn_n, packet_recv_spd_n;\n    if (*flag_var == FRAME_REDUNDANCY_CODE) {\n        memcpy(&local_seq_num_n, out + len - (sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t)), sizeof(uint32_t));\n        memcpy(&last_recv_lsn_n, out + len - (sizeof(uint32_t) + sizeof(uint32_t)), sizeof(uint32_t));\n        memcpy(&packet_recv_spd_n, out + len - sizeof(uint32_t), sizeof(uint32_t));\n        *local_seq_num = ntohl(local_seq_num_n);\n        *last_recv_lsn = ntohl(last_recv_lsn_n);\n        *packet_recv_spd = ntohl(packet_recv_spd_n);\n        return len - (sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t));\n    }\n    *seq_num = ntohl(*((uint32_t *) (&out[len - sizeof(uint32_t) - sizeof(uint16_t) - sizeof(uint32_t) - sizeof(uint16_t) - sizeof(uint32_t)\n                        - sizeof(uint32_t)])));\n    *flag_var = ntohs(*((uint16_t *) (&out[len - sizeof(uint16_t) - sizeof(uint32_t) - sizeof(uint16_t) - sizeof(uint32_t) - sizeof(uint32_t)])));\n    *local_seq_num = ntohl(*((uint32_t *) (&out[len - sizeof(uint32_t) - sizeof(uint16_t) - sizeof(uint32_t) - sizeof(uint32_t)])));\n    *mini_sum = ntohs(*((uint16_t *) (&out[len - sizeof(uint16_t) - sizeof(uint32_t) - sizeof(uint32_t)])));\n    *last_recv_lsn = ntohl(*((uint32_t *) (&out[len - sizeof(uint32_t) - sizeof(uint32_t)])));\n    *packet_recv_spd = ntohl(*((uint32_t *) (&out[len - sizeof(uint32_t)])));\n    return len - sizeof(uint32_t) - sizeof(uint16_t) - sizeof(uint32_t) - sizeof(uint16_t) - sizeof(uint32_t) - sizeof(uint32_t);\n}\n\n/**\n * Function for add flag and seq_num to packet\n */\nint pack_packet(int chan_num, char *buf, int len, uint32_t seq_num, uint32_t local_seq_num, int flag) {\n    uint16_t flag_n = htons(flag);\n    \n    uint32_t local_seq_num_n = htonl(local_seq_num);\n    uint16_t mini_sum = htons((uint16_t)(seq_num + local_seq_num + info.channel[chan_num].local_seq_num_recv));\n    uint32_t last_recv_lsn = htonl(info.channel[chan_num].local_seq_num_recv);\n    uint32_t packet_recv_spd = htonl(info.channel[chan_num].packet_download);\n    if (flag == FRAME_REDUNDANCY_CODE) {\n        memcpy(buf + len, &local_seq_num_n, sizeof(uint32_t));\n        memcpy(buf + len + sizeof(uint32_t), &last_recv_lsn, sizeof(uint32_t));\n        memcpy(buf + len + sizeof(uint32_t) + sizeof(uint32_t), &packet_recv_spd, sizeof(uint32_t));\n//        memcpy(buf + len + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t), &mini_sum, sizeof(uint16_t));\n        return len + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t);\n    }\n    uint32_t seq_num_n = htonl(seq_num);\n    memcpy(buf + len, &seq_num_n, sizeof(uint32_t));\n    memcpy(buf + len + sizeof(uint32_t), &flag_n, sizeof(uint16_t));\n    memcpy(buf + len + sizeof(uint32_t) + sizeof(uint16_t), &local_seq_num_n, sizeof(local_seq_num_n));\n    memcpy(buf + len + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(local_seq_num_n), &mini_sum, sizeof(uint16_t));\n    memcpy(buf + len + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(local_seq_num_n) + sizeof(uint16_t), &last_recv_lsn, sizeof(uint32_t));\n    memcpy(buf + len + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(local_seq_num_n) + sizeof(uint16_t) + sizeof(uint32_t), &packet_recv_spd, sizeof(uint32_t));\n    return len + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t);\n}\n\n/**\n * Generate new packet number, wrapping packet and add to resend queue. (unsynchronized)\n *\n * @param conn_num\n * @param buf - data for send\n * @param out - pointer to pointer to output packet\n * @param len - data length\n * @param seq_num - output packet number\n * @param flag\n * @param sender_pid\n */\nint seqn_add_tail(int conn_num, char *buf, int len, uint32_t seq_num, uint16_t flag, int sender_pid) {\n    int newf = shm_conn_info->resend_buf_idx;\n\n    shm_conn_info->resend_buf_idx++;\n    if (shm_conn_info->resend_buf_idx == RESEND_BUF_SIZE) {\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"seqn_add_tail() resend_frames_buf loop end\");\n#endif\n        shm_conn_info->resend_buf_idx = 0;\n    }\n\n    shm_conn_info->resend_frames_buf[newf].seq_num = seq_num;\n    memset(shm_conn_info->resend_frames_buf[newf].local_seq_num, 0, sizeof(shm_conn_info->resend_frames_buf[newf].local_seq_num));\n    shm_conn_info->resend_frames_buf[newf].sender_pid = sender_pid;\n    shm_conn_info->resend_frames_buf[newf].chan_num = conn_num;\n    shm_conn_info->resend_frames_buf[newf].len = len;\n    gettimeofday(&info.current_time, NULL );\n    shm_conn_info->resend_frames_buf[newf].time_stamp = info.current_time;\n    memcpy((shm_conn_info->resend_frames_buf[newf].out + LINKFD_FRAME_RESERV), buf, len);\n    return newf;\n}\n\n/**\n * Add packet to fast resend buffer\n *\n * @param conn_num\n * @param buf - pointer to packet\n * @return -1 - error if buffer full and packet's quantity if success\n */\nint add_fast_resend_frame(int conn_num, char *buf, int len, uint32_t seq_num) {\n    if (shm_conn_info->fast_resend_buf_idx >= FAST_RESEND_BUF_SIZE) {\n        return -1; // fast_resend_buf is full\n    }\n    int i = shm_conn_info->fast_resend_buf_idx; // get next free index\n    ++(shm_conn_info->fast_resend_buf_idx);\n    uint16_t flag = MODE_NORMAL;\n    shm_conn_info->fast_resend_buf[i].seq_num = seq_num;\n    shm_conn_info->fast_resend_buf[i].sender_pid = 0;\n    shm_conn_info->fast_resend_buf[i].chan_num = conn_num;\n    shm_conn_info->fast_resend_buf[i].len = len;\n\n    memcpy(shm_conn_info->fast_resend_buf[i].out, buf, len & VTUN_FSIZE_MASK);\n    return shm_conn_info->fast_resend_buf_idx;\n}\n\n/**\n * Add packet to fast resend buffer\n *\n * @param conn_num - pointer for available variable\n * @param buf - pointer to allocated memory\n * @return\n */\nint get_fast_resend_frame(int *conn_num, char *buf, int *len, uint32_t *seq_num) {\n    if (!check_fast_resend()) {\n        return -1; // buffer is blank\n    }\n    int i = --(shm_conn_info->fast_resend_buf_idx);\n    memcpy(buf, shm_conn_info->fast_resend_buf[i].out, shm_conn_info->fast_resend_buf[i].len & VTUN_FSIZE_MASK);\n    *conn_num = shm_conn_info->fast_resend_buf[i].chan_num;\n    *seq_num = shm_conn_info->fast_resend_buf[i].seq_num;\n    *len = shm_conn_info->fast_resend_buf[i].len;\n    return i+1;\n}\n\nvoid print_head_of_packet(char *buf, char* str, uint32_t seq_num, int len) {\n    char packet_string[500];\n    memset(packet_string, '\\0', 500);\n    sprintf(packet_string, \"len %i seq_num %\"PRIu32\": \", len, seq_num);\n    char* str_point = packet_string + strlen(packet_string);\n    int i = 0;\n    for (; ((i < 60) && (i < len)); i++) {\n        sprintf(str_point, \"%02X-\", (uint8_t) buf[i]);\n        str_point += sizeof(buf[i]) + 2;\n    }\n    *(str_point - 1) = '\\0';\n    if (i <= len)\n        vlog(LOG_INFO, \"%s %s\", str, packet_string);\n    else\n        vlog(LOG_INFO, \"%s %s...\", str, packet_string);\n}\n\n/**\n *\n * @return 0 if buffer blank\n */\nint check_fast_resend() {\n    if (shm_conn_info->fast_resend_buf_idx == 0) {\n        return 0; // buffer is blank\n    }\n    if((info.process_num == shm_conn_info->max_rtt_pnum_checkonly) && is_priority_packet(shm_conn_info->fast_resend_buf[shm_conn_info->fast_resend_buf_idx-1].out)) {\n        return 0;\n    }\n    return 1;\n}\n\nint is_fast_resend_available() {\n    if (shm_conn_info->fast_resend_buf_idx >= FAST_RESEND_BUF_SIZE) {\n        return 0; // fast_resend_buf is full\n    }\n    return 1;\n}\n\nint is_single() {\n    if(NumberOfSetBits(shm_conn_info->channels_mask) == 1) {\n        return 1;\n    }\n    return 0;\n}\n\nint send_packet(int chan_num, char *buf, int len) {\n     \n    // TODO: add select() here!\n    // TODO: optimize here\n    uint32_t tmp_seq_counter;\n    uint32_t local_seq_num_p;\n    uint16_t tmp_flag = 0;\n    uint16_t sum;\n    len = seqn_break_tail(buf, len, &tmp_seq_counter, &tmp_flag, &local_seq_num_p, &sum, &local_seq_num_p, &local_seq_num_p); // last four unused\n    len = pack_packet(chan_num, buf, len, tmp_seq_counter, info.channel[chan_num].local_seq_num, tmp_flag);\n    \n    // send DATA\n    int len_ret = udp_write(info.channel[chan_num].descriptor, buf, len);\n    if (len && (len_ret < 0)) {\n        vlog(LOG_INFO, \"error retransmit to socket chan %d! reason: %s (%d)\", chan_num, strerror(errno), errno);\n        return BREAK_ERROR;\n    }\n    info.channel[chan_num].local_seq_num++;\n    // TODO: all the stats here??\n}\n\n/*\n          _                                 _ _                            _ \n         | |                               (_) |                          | |\n _ __ ___| |_ _ __ __ _ _ __  ___ _ __ ___  _| |_       ___  ___ _ __   __| |\n| '__/ _ \\ __| '__/ _` | '_ \\/ __| '_ ` _ \\| | __|     / __|/ _ \\ '_ \\ / _` |\n| | |  __/ |_| | | (_| | | | \\__ \\ | | | | | | |_      \\__ \\  __/ | | | (_| |\n|_|  \\___|\\__|_|  \\__,_|_| |_|___/_| |_| |_|_|\\__|     |___/\\___|_| |_|\\__,_|\n                                               ______                        \n                                              |______|                       \n*/\n\n/**\n * Function for trying resend\n */ \nint retransmit_send(char *out2) {\n    if (drop_packet_flag) {\n        return LASTPACKETMY_NOTIFY; // go dropping\n    } else if (drop_counter > 0) {\n        // vlog(LOG_INFO, \"drop_packet_flag (retransmit_send) TOTAL %d pkts; info.rsr %d info.W %d, max_send_q %d, send_q_eff %d, head %d, w %d, rtt %d\", drop_counter, info.rsr, info.send_q_limit_cubic, info.max_send_q, send_q_eff, info.head_channel, shm_conn_info->stats[info.process_num].W_cubic, shm_conn_info->stats[info.process_num].rtt_phys_avg);\n        // drop_counter = 0;\n    }\n    if (hold_mode) {\n        return CONTINUE_ERROR;\n    }\n    struct timeval tv = {0,0};\n\n    int len = 0, send_counter = 0, mypid, get_unconditional = 0;\n    uint32_t top_seq_num, seq_num_tmp = 1, remote_lws = SEQ_START_VAL;\n    sem_wait(&(shm_conn_info->resend_buf_sem));\n    if (check_fast_resend()){ // fast_resend technique is used for info.channel_amount > 1\n        sem_post(&(shm_conn_info->resend_buf_sem));\n        return HAVE_FAST_RESEND_FRAME;\n    }\n    sem_post(&(shm_conn_info->resend_buf_sem));\n    for (int i = 1; i < info.channel_amount; i++) {\n        sem_wait(&(shm_conn_info->common_sem));\n        top_seq_num = shm_conn_info->seq_counter[i];\n        sem_post(&(shm_conn_info->common_sem));\n        sem_wait(&(shm_conn_info->write_buf_sem));\n        remote_lws = shm_conn_info->write_buf[i].remote_lws;\n        if (remote_lws > top_seq_num) { // do we ever need this???\n            shm_conn_info->write_buf[i].remote_lws = top_seq_num; // ????top_seq_num - 1\n            remote_lws = top_seq_num;\n        }\n        sem_post(&(shm_conn_info->write_buf_sem));\n        if ((last_sent_packet_num[i].seq_num + 1) <= remote_lws) {\n            last_sent_packet_num[i].seq_num = remote_lws;\n        }\n\n        if ((top_seq_num <= last_sent_packet_num[i].seq_num) || (top_seq_num == SEQ_START_VAL)) {\n#ifdef DEBUGG\n           vlog(LOG_INFO, \"debug: retransmit_send skipping logical channel #%i my last seq_num %\"PRIu32\" top seq_num %\"PRIu32\"\", i, last_sent_packet_num[i].seq_num, top_seq_num);\n#endif\n            // TODO MOVE THE FOLLOWING LINE TO DEBUG! --vvv\n            if (top_seq_num < last_sent_packet_num[i].seq_num) vlog(LOG_INFO, \"WARNING! impossible: chan#%i last sent seq_num %\"PRIu32\" is > top seq_num %\"PRIu32\"\", i, last_sent_packet_num[i].seq_num, top_seq_num);\n            // WARNING! disabled push-to-top policy!\n            if(PUSH_TO_TOP && ptt_allow_once && ((!info.head_channel) && (shm_conn_info->dropping || shm_conn_info->head_lossing))) {\n                last_sent_packet_num[i].seq_num--; // push to top! (push policy)\n                get_unconditional = 1;\n                ptt_allow_once = 0;\n            } else {\n                if(check_delivery_time(SKIP_SENDING_CLD_DIV) && (!shm_conn_info->slow_start || info.head_channel)) { // TODO: head always passes! \n                    statb.skip_new_h++;\n                    continue; // means that we have sent everything from rxmit buf and are ready to send new packet: no send_counter increase\n                }\n                // else means that we need to send something old\n                //vlog(LOG_ERR, \"WARNING cannot send new packets as we won't deliver in time; skip sending\"); // TODO: add skip counter\n                send_counter++;\n                statb.skip_no++;\n                continue; // do not send anything at all\n            }\n        }\n\n        // perform check that we can write w/o blocking I/O; take into account that we need to notify that we still need to retransmit\n        fd_set fdset2;\n        FD_ZERO(&fdset2);\n        FD_SET(info.channel[i].descriptor, &fdset2);\n        int sel_ret = select(info.channel[i].descriptor + 1, NULL, &fdset2, NULL, &tv);\n        if (sel_ret == 0) {\n            send_counter++; // deny meaning that we've sent everything from retransmit and must no go on sending new packets\n            statb.skip_no++;\n            continue; // continuing w/o reading/sending pkts AND send_counter++ will cause to fast-loop; we effectively do a poll here\n        } else if (sel_ret == -1) {\n            vlog(LOG_ERR, \"retransmit send Could not select chan %d reason %s (%d)\", i, strerror(errno), errno);\n        }\n        // now we have something to retransmit:\n\n        last_sent_packet_num[i].seq_num++;\n        seq_num_tmp = last_sent_packet_num[i].seq_num; // save old seq_num for test\n\n#ifdef DEBUGG\n            vlog(LOG_INFO, \"debug: logical channel #%i my last seq_num %\"PRIu32\" top seq_num %\"PRIu32\"\", i, last_sent_packet_num[i].seq_num, top_seq_num);\n#endif\n        sem_wait(&(shm_conn_info->resend_buf_sem));\n        if(info.head_channel == 1) {\n            // on head channel, do not allow to skip even if we see outdated packets?\n            len = get_resend_frame_unconditional(i, &last_sent_packet_num[i].seq_num, &out2, &mypid); // TODO: is it correct?\n            if (len == -1) {\n                if (check_delivery_time(1)) { // TODO: head channel will always pass this test\n                    sem_post(&(shm_conn_info->resend_buf_sem));\n                    vlog(LOG_INFO, \"WARNING no packets found in RB on head_channel and we can deliver new in time; sending new\");\n                    statb.skip_new_d++;\n                    continue; // ok to send new packet\n                } \n                len = get_last_packet(i, &last_sent_packet_num[i].seq_num, &out2, &mypid);\n                vlog(LOG_INFO, \"WARNING all RB packets expired on head_channel!!! & can not deliver new packet in time; getting newest packet from RB... seq_num %\"PRIu32\" top %d\", last_sent_packet_num[i].seq_num, top_seq_num);\n                if(len == -1) {\n                    sem_post(&(shm_conn_info->resend_buf_sem));\n                    vlog(LOG_INFO, \"WARNING no packets found in RB; HEAD sending new\");\n                    statb.skip_new_d++;\n                    continue;\n                }\n            }\n        } else {\n            // this is required to not read new packets if being pushed to top and all packets exhausted ->>>\n            //if(get_unconditional) len = get_resend_frame_unconditional(i, &last_sent_packet_num[i].seq_num, &out2, &mypid);\n            //else                  \n            len = get_resend_frame(i, &last_sent_packet_num[i].seq_num, &out2, &mypid);\n            if (len == -1) {\n                last_sent_packet_num[i].seq_num--;\n                if (check_delivery_time(2)  && !shm_conn_info->slow_start) {\n                    sem_post(&(shm_conn_info->resend_buf_sem));\n                    // TODO: disable AG in case of this event!\n                    vlog(LOG_INFO, \"WARNING all packets in RB are sent AND we can deliver new in time; sending new\");\n                    statb.skip_new_d++;\n                    continue; // ok to send new packet\n                } \n                // else there is no way we can deliver anything in time; now get latest packet\n                len = get_last_packet(i, &last_sent_packet_num[i].seq_num, &out2, &mypid);\n                // TODO: counter here -->\n                //vlog(LOG_ERR, \"WARNING all RB packets expired & can not deliver new packet in time; getting newest packet from RB... seq_num %\"PRIu32\" top %d\", last_sent_packet_num[i].seq_num, top_seq_num);\n                if(len == -1) {\n                    sem_post(&(shm_conn_info->resend_buf_sem));\n                    vlog(LOG_INFO, \"WARNING no packets found in RB; hd==0 sending new!!!\");\n                    statb.skip_new_d++;\n                    continue;\n                }\n                statb.skip_l++;\n            }\n        }\n        if(last_sent_packet_num[i].seq_num != seq_num_tmp) {\n            if(info.head_channel == 1) {\n                vlog(LOG_INFO, \"WARNING retransmit_send on head channel skippig seq's from %\"PRIu32\" to %\"PRIu32\" chan %d len %d\", seq_num_tmp, last_sent_packet_num[i].seq_num, i, len);\n            }\n            statb.skip_r++;\n        }\n        memcpy(out_buf, out2, len);\n        sem_post(&(shm_conn_info->resend_buf_sem));\n\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"debug: R_MODE resend frame ... chan %d seq %\"PRIu32\" len %d\", i, last_sent_packet_num[i].seq_num, length);\n#endif\n        if(debug_trace) {\n            vlog(LOG_INFO, \"debug: R_MODE resend frame ... chan %d seq %\"PRIu32\" len %d\", i, last_sent_packet_num[i].seq_num, len);\n        }\n\n        \n        // TODO: add select here!\n        // TODO: optimize here\n        uint32_t tmp_seq_counter;\n        uint32_t local_seq_num_p;\n        uint16_t tmp_flag = 0;\n        uint16_t sum;\n        len = seqn_break_tail(out_buf, len, &tmp_seq_counter, &tmp_flag, &local_seq_num_p, &sum, &local_seq_num_p, &local_seq_num_p); // last four unused\n        len = pack_packet(i, out_buf, len, tmp_seq_counter, info.channel[i].local_seq_num, tmp_flag);\n        // if( (info.rtt2_lsn[i] == 0) && ((shm_conn_info->stats[info.process_num].ACK_speed /info.eff_len) > (1000/shm_conn_info->stats[info.process_num].exact_rtt)) ) {\n        if(info.rtt2_lsn[i] == 0) {\n            info.rtt2_lsn[i] = info.channel[i].local_seq_num;\n            info.rtt2_tv[i] = info.current_time;\n            info.rtt2_send_q[i] = info.channel[i].send_q;\n        }\n        // send DATA\n        int len_ret = udp_write(info.channel[i].descriptor, out_buf, len);\n        info.channel[i].packet_recv_counter = 0;\n        if (len && (len_ret < 0)) {\n            vlog(LOG_INFO, \"error write to socket chan %d! reason: %s (%d)\", i, strerror(errno), errno);\n            return BREAK_ERROR;\n        }\n        info.channel[i].local_seq_num++;\n        if(PUSH_TO_TOP && (info.channel[i].local_seq_num % PUSH_TO_TOP == 0)) {\n            ptt_allow_once = 1;\n        }\n    \n        shm_conn_info->stats[info.process_num].speed_chan_data[i].up_data_len_amt += len_ret;\n        shm_conn_info->stats[info.process_num].packet_upload_cnt++;\n        statb.packet_sent_rmit += 1000;\n        if(shm_conn_info->stats[info.process_num].l_pbl_tmp < INT32_MAX)\n            shm_conn_info->stats[info.process_num].l_pbl_tmp++;\n        if(shm_conn_info->stats[info.process_num].l_pbl_tmp_unrec < INT32_MAX)\n            shm_conn_info->stats[info.process_num].l_pbl_tmp_unrec++;\n        info.channel[i].up_len += len_ret;\n        statb.byte_sent_rmit_full += len_ret;\n        info.channel[i].up_packets++;\n        info.channel[i].bytes_put++;\n//if(drop_packet_flag) {  vlog(LOG_INFO, \"bytes_pass++ retransmit_send\"); } \n        info.byte_r_mode += len_ret;\n\n        send_counter++;\n    }\n    \n    if (send_counter == 0) {\n        if (check_delivery_time(1)) { // TODO: REMOVE THIS EXTRA CHECK (debug only; should never happen due to previous checks)\n            return LASTPACKETMY_NOTIFY;\n        } else {\n            vlog(LOG_ERR, \"WARNING STILL can not deliver new packet in time; skipping read from tun\");\n            return CONTINUE_ERROR;\n        }\n    }\n        \n    return 1;\n}\n\n/**\n * calculate total send_q_eff_mean\n * \n */\n \nint get_total_sqe_mean_pkt(int *aavg, int *lim_pkt, int ignore_msqa) {\n    int sqe_tot = 0;\n    int sqe_pkt;\n    *aavg = 1;\n    uint32_t chan_mask = shm_conn_info->channels_mask;\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        // waring: ag_mask depends only on ag_flag_local, not on agag value so it may not be correct\n        if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (shm_conn_info->ag_mask & (1 << i))) { // hope this works..\n            sqe_pkt = shm_conn_info->stats[i].sqe_mean / info.eff_len;\n            sqe_tot += sqe_pkt;\n            if(shm_conn_info->stats[i].W_cubic < shm_conn_info->stats[i].rsr) {\n                if(!ignore_msqa && shm_conn_info->stats[i].max_send_q_available < shm_conn_info->stats[i].W_cubic) {\n                    *lim_pkt += shm_conn_info->stats[i].max_send_q_available / info.eff_len;\n                } else {\n                    *lim_pkt += shm_conn_info->stats[i].W_cubic / info.eff_len;\n                }\n            } else {\n                if(!ignore_msqa && shm_conn_info->stats[i].max_send_q_available < shm_conn_info->stats[i].rsr) {\n                    *lim_pkt += shm_conn_info->stats[i].max_send_q_available / info.eff_len;\n                } else {\n                    *lim_pkt += shm_conn_info->stats[i].rsr / info.eff_len;\n                }\n            }\n            if(sqe_pkt > 0) {\n                *aavg += shm_conn_info->stats[i].ACK_speed_avg / sqe_pkt;\n            }\n        }\n    }\n    return sqe_tot;\n}\n\n/**\n * check that the system is in a-hold mode\n * \n */\n \nint is_a_hold() {\n    int limit;\n    int sqe;\n    uint32_t chan_mask = shm_conn_info->channels_mask;\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        // this does not work - see ag_mask_recv and mode\n        if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (shm_conn_info->ag_mask & (1 << i))) { // hope this works..\n            limit = shm_conn_info->stats[i].W_cubic < shm_conn_info->stats[i].rsr ? shm_conn_info->stats[i].W_cubic : shm_conn_info->stats[i].rsr;\n            sqe = shm_conn_info->stats[i].sqe_mean;\n            if( percent_delta_equal(sqe, limit, 15) || (sqe > limit) ) {\n                // means hold\n            } else {\n                return 0;\n            }\n        }\n    }\n    return 1;\n}\n\n    \n\nint select_net_write(int chan_num) {\n    struct timeval tv;\n\n    fd_set fdset2;\n    tv.tv_sec = 0;\n    tv.tv_usec = 0;\n    FD_ZERO(&fdset2);\n    FD_SET(info.channel[chan_num].descriptor, &fdset2);\n    int sel_ret = select(info.channel[chan_num].descriptor + 1, NULL, &fdset2, NULL, &tv);\n    if (sel_ret == 0) {\n        return 0; // save rtt!\n    } else if (sel_ret == -1) {\n        vlog(LOG_ERR, \"select_net_write() select error! errno %d\",errno);\n        return 0;\n    }\n    return 1;\n}\n\n/*\n          _           _                            _ \n         | |         | |                          | |\n ___  ___| | ___  ___| |_       ___  ___ _ __   __| |\n/ __|/ _ \\ |/ _ \\/ __| __|     / __|/ _ \\ '_ \\ / _` |\n\\__ \\  __/ |  __/ (__| |_      \\__ \\  __/ | | | (_| |\n|___/\\___|_|\\___|\\___|\\__|     |___/\\___|_| |_|\\__,_|\n                       ______                        \n                      |______|                       \n*/\n/**\n * Procedure select all(only tun_device now) file descriptors and if data available read from tun device, pack and write to net\n *\n *  @return - number of error or sent len\n *      -1 - continue error (CONTINUE_ERROR)\n *      -2 - break error (BREAK_ERROR)\n *\n *\n */\nint select_devread_send(char *buf, char *out2) {\n    if(hold_mode) return TRYWAIT_NOTIFY; // no send in HOLD\n    int len, len_sum, select_ret, idx;\n    uint32_t tmp_seq_counter = 0;\n    int chan_num;\n    struct timeval tv;\n    int new_packet = 0;\n    fd_set fdset_tun;\n    FD_ZERO(&fdset_tun);\n    int packet_code_ready = 0;\n    int current_selection;\n    uint32_t local_seq_num_p;\n    uint16_t tmp_flag;\n    uint16_t sum;\n    sem_wait(&(shm_conn_info->resend_buf_sem));\n    idx = get_fast_resend_frame(&chan_num, buf, &len, &tmp_seq_counter);\n    sem_post(&(shm_conn_info->resend_buf_sem));\n    if (idx == -1) {\n        if (!FD_ISSET(info.tun_device, &fdset)) {\n#ifdef DEBUGG\n            if(drop_packet_flag) {\n                vlog(LOG_INFO, \"debug: Nothing to read from tun device (first FD_ISSET)\");\n            }\n#endif\n            return TRYWAIT_NOTIFY;\n        }\n        FD_ZERO(&fdset_tun);\n        FD_SET(info.tun_device, &fdset_tun);\n        int try_flag = sem_trywait(&(shm_conn_info->tun_device_sem));\n        if (try_flag != 0) { // if semaphore is locked then go out\n            return TRYWAIT_NOTIFY;\n        }\n        tv.tv_sec = 0;\n        tv.tv_usec = 0;\n        select_ret = select(info.tun_device + 1, &fdset_tun, NULL, NULL, &tv);\n        if (select_ret < 0) {\n            if (errno != EAGAIN && errno != EINTR) {\n                sem_post(&(shm_conn_info->tun_device_sem));\n                vlog(LOG_INFO, \"select error; exit\");\n                return BREAK_ERROR;\n            } else {\n                sem_post(&(shm_conn_info->tun_device_sem));\n#ifdef DEBUGG\n                vlog(LOG_INFO, \"select error; continue norm\");\n#endif\n                return CONTINUE_ERROR;\n            }\n        } else if (select_ret == 0) {\n            sem_post(&(shm_conn_info->tun_device_sem));\n#ifdef DEBUGG\n            vlog(LOG_INFO, \"debug: we don't have data on tun device; continue norm.\");\n#endif\n            return CONTINUE_ERROR; // Nothing to read, continue.\n        }\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"debug: we have data on tun device...\");\n#endif\n        if (FD_ISSET(info.tun_device, &fdset_tun)) {\n        } else {\n            sem_post(&(shm_conn_info->tun_device_sem));\n            return CONTINUE_ERROR;\n        }\n        // we aren't checking FD_ISSET because we did select one descriptor\n        len = dev_read(info.tun_device, buf, VTUN_FRAME_SIZE - 11);\n        sem_post(&(shm_conn_info->tun_device_sem));\n        // TODO WARNING! packet reordering will happen here: we lost sync before seq_counter incremented -->>>\n\n        if (len < 0) { // 10 bytes for seq number (long? = 4 bytes)\n            if (errno != EAGAIN && errno != EINTR) {\n                vlog(LOG_INFO, \"sem_post! dev read err\");\n                return BREAK_ERROR;\n            } else { // non fatal error\n#ifdef DEBUGG\n            vlog(LOG_INFO, \"sem_post! else dev read err\"); // usually means non-blocking zeroing\n#endif\n                return CONTINUE_ERROR;\n            }\n        } else if (len == 0) {\n#ifdef DEBUGG\n            vlog(LOG_INFO, \"sem_post! dev_read() have read nothing\");\n#endif\n            return CONTINUE_ERROR;\n        }\n        shm_conn_info->avg_len_out = EFF_LEN_AVG_N * shm_conn_info->avg_len_out / EFF_LEN_AVG_D + len / EFF_LEN_AVG_D;\n\n        if (drop_packet_flag == 1) {\n            // #876\n            drop_counter++;\n//#ifdef DEBUGG\n            int other_chan = 0;\n            if (info.process_num == 0)\n                other_chan = 1;\n            else\n                other_chan = 0;\n            info.dropping = 1;\n            //if (debug_trace) {\n                vlog(LOG_INFO, \"drop_packet_flag info.rsr %d info.W %d, max_send_q %d, send_q_eff %d, head %d, w %d, rtt %d, hold_!head: %d\",\n                        info.rsr, info.send_q_limit_cubic, info.max_send_q, send_q_eff, info.head_channel,\n                        shm_conn_info->stats[info.process_num].W_cubic, shm_conn_info->stats[info.process_num].rtt_phys_avg,\n                        shm_conn_info->stats[other_chan].hold);\n                //info.max_send_q = 0;\n            //}\n\n            sem_wait(&(shm_conn_info->AG_flags_sem));\n            uint32_t chan_mask = shm_conn_info->channels_mask;\n            sem_post(&(shm_conn_info->AG_flags_sem));\n\n            // set dropped_flag here\n\n            /*\n             for (int p = 0; p < MAX_TCP_PHYSICAL_CHANNELS; p++) {\n             if (chan_mask & (1 << p)) {\n             vlog(LOG_INFO, \"pnum %d, w %d, rtt %d, wspd %d\", p, shm_conn_info->stats[p].W_cubic, shm_conn_info->stats[p].rtt_phys_avg, (shm_conn_info->stats[p].W_cubic / shm_conn_info->stats[p].rtt_phys_avg));\n             }\n             }\n             */\n//#endif\n            /*\n             struct timeval time_tmp;\n\n             sem_wait(&(shm_conn_info->common_sem));\n             timersub(&info.current_time, &shm_conn_info->last_flood_sent, &time_tmp);\n             struct timeval time_tmp2 = { 20, 0 };\n\n             if (timercmp(&time_tmp, &time_tmp2, >)) {\n             for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n             if (chan_mask & (1 << i)) {\n             shm_conn_info->flood_flag[i] = 1;\n             }\n             }\n             shm_conn_info->last_flood_sent.tv_sec=info.current_time.tv_sec;\n             shm_conn_info->last_flood_sent.tv_usec=info.current_time.tv_usec;\n             }\n             sem_post(&(shm_conn_info->common_sem));\n             */\n             // introduce immunity timer here\n            \n            sem_wait(&(shm_conn_info->stats_sem));\n            if(check_drop_period_unsync()) {\n            sem_post(&(shm_conn_info->stats_sem));\n                shm_conn_info->drop_time = info.current_time;\n                return CONTINUE_ERROR;\n            } \n            sem_post(&(shm_conn_info->stats_sem));\n        } else {\n            if (drop_counter > 0) {\n                // vlog(LOG_INFO, \"drop_packet_flag TOTAL %d pkts; info.rsr %d info.W %d, max_send_q %d, send_q_eff %d, head %d, w %d, rtt %d\",\n                //         drop_counter, info.rsr, info.send_q_limit_cubic, info.max_send_q, send_q_eff, info.head_channel,\n                //         shm_conn_info->stats[info.process_num].W_cubic, shm_conn_info->stats[info.process_num].rtt_phys_avg);\n                // drop_counter = 0;\n            }\n        }\n\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"debug: we have read data from tun device and going to send it through net\");\n#endif\n\n        // now determine packet IP..\n        // unsigned int tcp_seq2 = 0;\n        // unsigned int hash = get_l4_hash(buf, &tcp_seq2);\n        // chan_num = (hash % (info.channel_amount - 1)) + 1; // send thru 1-n channel\n        chan_num = 1;\n        // info.encap_streams_bitcnt |= (1 << (hash % 31)); // set bin mask to 1 \n        // if (shm_conn_info->streams[hash % 31] < 255)\n        //     shm_conn_info->streams[hash % 31]++; // WARNING unsync but seems okay\n        sem_wait(&(shm_conn_info->common_sem));\n        if(shm_conn_info->ag_mask_recv & (1 << info.process_num)) {\n            shm_conn_info->t_model_rtt100 = ((TMRTTA - 1) * shm_conn_info->t_model_rtt100 + info.exact_rtt * 100) / TMRTTA; // RFC6298 compliant\n        }\n        (shm_conn_info->seq_counter[chan_num])++;\n        tmp_seq_counter = shm_conn_info->seq_counter[chan_num];\n\n        // packet code section\n#ifdef SUM_SEND\n#ifdef CODE_LOG\n        print_head_of_packet(buf, \"add to sum \", tmp_seq_counter, len);\n        vlog(LOG_INFO, \"FRAME_REDUNDANCY_CODE check seq_counter %\"PRIu32\"\", tmp_seq_counter);\n#endif\n\n        current_selection = (tmp_seq_counter - (SEQ_START_VAL + 1)) % SELECTION_NUM;\n\n        if (tmp_seq_counter == SEQ_START_VAL + 1) {\n            struct timeval redund_code_timer_time = REDUNDANT_CODE_TIMER_TIME;\n            for (int i = 0; i < SELECTION_NUM; i++) {\n                sum_init(&shm_conn_info->packet_code[i][chan_num], tmp_seq_counter + i, tmp_seq_counter + REDUNDANCY_CODE_LAG - SELECTION_NUM + i, i,\n                        1500);\n                set_timer(&shm_conn_info->packet_code[i][chan_num].timer, &redund_code_timer_time);\n            }\n            add_packet_code(buf, &shm_conn_info->packet_code[current_selection][chan_num], len);\n            shm_conn_info->packet_code[current_selection][chan_num].current_seq = tmp_seq_counter;\n        } else if (shm_conn_info->packet_code[current_selection][chan_num].stop_seq > tmp_seq_counter) {\n            add_packet_code(buf, &shm_conn_info->packet_code[current_selection][chan_num], len);\n        } else if (shm_conn_info->packet_code[current_selection][chan_num].stop_seq == tmp_seq_counter) {\n            add_packet_code(buf, &shm_conn_info->packet_code[current_selection][chan_num], len);\n            packet_code_ready = 1;\n        }\n        shm_conn_info->packet_code[current_selection][chan_num].current_seq = tmp_seq_counter;\n#endif\n        len = pack_packet(chan_num, buf, len, tmp_seq_counter, info.channel[chan_num].local_seq_num, channel_mode);\n#ifdef SUM_SEND\n        if (packet_code_ready) {\n            len_sum = pack_redundancy_packet_code(buf2, &shm_conn_info->packet_code[current_selection][chan_num], tmp_seq_counter, current_selection,\n                    FRAME_REDUNDANCY_CODE);\n            fast_update_timer(&shm_conn_info->packet_code[current_selection][chan_num].timer, &info.current_time);\n            sem_post(&(shm_conn_info->common_sem));\n        } else {\n            sem_post(&(shm_conn_info->common_sem));\n        }\n#else\n        sem_post(&(shm_conn_info->common_sem));\n#endif\n\n        new_packet = 1;\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"local_seq_num %\"PRIu32\" seq_num %\"PRIu32\" len %d\", info.channel[chan_num].local_seq_num, tmp_seq_counter, length);\n#endif\n    } else {\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"we have fast resend frame sending...\");\n#endif\n    }\n#ifdef DEBUGG\n    else {\n        vlog(LOG_INFO, \"Trying to send from fast resend buf chan_num - %i, len - %i, seq - %\"PRIu32\", packet amount - %i\", chan_num, length, tmp_seq_counter, idx);\n    }\n#endif\n\n    FD_ZERO(&fdset_tun);\n    FD_SET(info.channel[chan_num].descriptor, &fdset_tun);\n    tv.tv_sec = 0;\n    tv.tv_usec = 0;\n    select_ret = select(info.channel[chan_num].descriptor + 1, NULL, &fdset_tun, NULL, &tv);\n#ifdef DEBUGG\n    vlog(LOG_INFO, \"Trying to select descriptor %i channel %d\", info.channel[chan_num].descriptor, chan_num);\n#endif\n    if ((select_ret != 1) || ((info.process_num == shm_conn_info->max_rtt_pnum_checkonly) && is_priority_packet(buf) && is_fast_resend_available())) {\n        sem_wait(&(shm_conn_info->resend_buf_sem));\n        idx = add_fast_resend_frame(chan_num, buf, len, tmp_seq_counter); // fast_resend technique is used for info.channel_amount > 1\n        sem_post(&(shm_conn_info->resend_buf_sem));\n        //if(new_packet) {\n        //    info.channel[chan_num].local_seq_num--; // send next time... another pkt will have this lsn soon!\n        //}\n        if (idx == -1) {\n            vlog(LOG_ERR, \"ERROR: fast_resend_buf is full\");\n        }\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"BUSY - descriptor %i channel %d\");\n#endif\n        return NET_WRITE_BUSY_NOTIFY;\n    }\n#ifdef DEBUGG\n    vlog(LOG_INFO, \"READY - descriptor %i channel %d\");\n#endif\n    int resend_frame_idx = -1;\n    if (tmp_seq_counter) {\n        sem_wait(&(shm_conn_info->resend_buf_sem));\n        resend_frame_idx = seqn_add_tail(chan_num, buf, len, tmp_seq_counter, channel_mode, info.pid);\n        sem_post(&(shm_conn_info->resend_buf_sem));\n\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"writing to net.. sem_post! finished blw len %d seq_num %d, mode %d chan %d, dirty_seq_num %u\", length, shm_conn_info->seq_counter[chan_num], (int) channel_mode, chan_num, (dirty_seq_num+1));\n        vlog(LOG_INFO, \"select_devread_send() frame ... chan %d seq %\"PRIu32\" len %d\", chan_num, tmp_seq_counter, length);\n#endif\n        if (debug_trace) {\n            vlog(LOG_INFO, \"writing to net.. sem_post! finished blw len %d seq_num %d, mode %d chan %d, dirty_seq_num %u\", len,\n                    shm_conn_info->seq_counter[chan_num], (int) channel_mode, chan_num, (dirty_seq_num + 1));\n        }\n\n        // now add correct mini_sum and local_seq_num\n        //if(!new_packet) {\n        local_seq_num_p = 0;\n        tmp_flag = 0;\n        sum = 0;\n\n        len = seqn_break_tail(buf, len, &tmp_seq_counter, &tmp_flag, &local_seq_num_p, &sum, &local_seq_num_p, &local_seq_num_p); // last four unused\n        len = pack_packet(chan_num, buf, len, tmp_seq_counter, info.channel[chan_num].local_seq_num, tmp_flag);\n        // if ((info.rtt2_lsn[chan_num] == 0)\n        //         && ((shm_conn_info->stats[info.process_num].ACK_speed / info.eff_len) > (1000 / shm_conn_info->stats[info.process_num].exact_rtt))) {\n        if(info.rtt2_lsn[chan_num] == 0) {\n            info.rtt2_lsn[chan_num] = info.channel[chan_num].local_seq_num;\n            info.rtt2_tv[chan_num] = info.current_time;\n            info.rtt2_send_q[chan_num] = info.channel[chan_num].send_q;\n        }\n        //}\n    } else { // this is sum packet\n        \n    }\n#ifdef DEBUGG\n    struct timeval send1; // need for mean_delay calculation (legacy)\n    struct timeval send2; // need for mean_delay calculation (legacy)\n    gettimeofday(&send1, NULL );\n#endif\n    // send DATA\n    int len_ret = udp_write(info.channel[chan_num].descriptor, buf, len);\n    info.channel[chan_num].packet_recv_counter = 0;\n    if (len && (len_ret < 0)) {\n        vlog(LOG_INFO, \"error write to socket chan %d! reason: %s (%d)\", chan_num, strerror(errno), errno);\n        return BREAK_ERROR;\n    }\n    // sem_wait(&shm_conn_info->common_sem);\n    if (shm_conn_info->eff_len.warming_up < EFF_LEN_BUFF) {\n        shm_conn_info->eff_len.warming_up++;\n    }\n    shm_conn_info->eff_len.len_num[shm_conn_info->eff_len.counter] = len_ret;\n    if (shm_conn_info->eff_len.counter++ >= EFF_LEN_BUFF) {\n        shm_conn_info->eff_len.counter = 0;\n    }\n    shm_conn_info->eff_len.sum = shm_conn_info->eff_len.len_num[0];\n    for (int i = 1; i < shm_conn_info->eff_len.warming_up; i++) {\n        shm_conn_info->eff_len.sum += shm_conn_info->eff_len.len_num[i];\n    }\n    shm_conn_info->eff_len.sum /= shm_conn_info->eff_len.warming_up;\n    if (shm_conn_info->eff_len.sum <= 0)\n        shm_conn_info->eff_len.sum = 1;\n    // sem_post(&shm_conn_info->common_sem);\n#ifdef DEBUGG\n    gettimeofday(&send2, NULL );\n#endif\n    if (tmp_seq_counter) { // this is not sum packet\n        if(resend_frame_idx != -1) {\n            shm_conn_info->resend_frames_buf[resend_frame_idx].local_seq_num[info.process_num] = info.channel[chan_num].local_seq_num;\n        }\n\n        info.channel[chan_num].local_seq_num++;\n        if (info.channel[chan_num].local_seq_num == (UINT32_MAX - 1)) {\n            info.channel[chan_num].local_seq_num = 0; // TODO: 1. not required; 2. disaster at CLI-side! 3. max. ~4TB of data\n        }\n\n#ifdef DEBUGG\n        delay_acc += (int) ((send2.tv_sec - send1.tv_sec) * 1000000 + (send2.tv_usec - send1.tv_usec)); // need for mean_delay calculation (legacy)\n        delay_cnt++; // need for mean_delay calculation (legacy)\n        if((delay_acc/delay_cnt) > 100) vlog(LOG_INFO, \"SEND DELAY: %u us\", (delay_acc/delay_cnt));\n#endif\n\n        shm_conn_info->stats[info.process_num].speed_chan_data[chan_num].up_data_len_amt += len_ret;\n        shm_conn_info->stats[info.process_num].packet_upload_cnt++;\n        statb.packet_sent_ag += 1000;\n        if (shm_conn_info->stats[info.process_num].l_pbl_tmp < INT32_MAX)\n            shm_conn_info->stats[info.process_num].l_pbl_tmp++;\n        if (shm_conn_info->stats[info.process_num].l_pbl_tmp_unrec < INT32_MAX)\n            shm_conn_info->stats[info.process_num].l_pbl_tmp_unrec++;\n        info.channel[chan_num].up_len += len_ret;\n        statb.byte_sent_ag_full += len_ret;\n        info.channel[chan_num].up_packets++;\n        info.channel[chan_num].bytes_put++;\n        if (drop_packet_flag) {\n            vlog(LOG_INFO, \"bytes_pass++ select_send\");\n        }\n        info.byte_efficient += len_ret;\n\n        last_sent_packet_num[chan_num].seq_num = tmp_seq_counter;\n    }\n#ifdef SUM_SEND\n    if (packet_code_ready) {\n        len_sum = pack_packet(chan_num, buf2, len_sum, 0, 0 /* local seq */, FRAME_REDUNDANCY_CODE);\n\n        //try send or store packet in fast resend buf\n        FD_ZERO(&fdset_tun);\n        FD_SET(info.channel[chan_num].descriptor, &fdset_tun);\n        tv.tv_sec = 0;\n        tv.tv_usec = 0;\n        select_ret = select(info.channel[chan_num].descriptor + 1, NULL, &fdset_tun, NULL, &tv);\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"Trying to select descriptor %i channel %d\", info.channel[chan_num].descriptor, chan_num);\n#endif\n        if (select_ret == 1) {\n#ifdef CODE_LOG\n            vlog(LOG_INFO, \"send FRAME_REDUNDANCY_CODE selection %d packet_code ready %i seq start %\"PRIu32\" stop %\"PRIu32\" seq_num %\"PRIu32\" len %i len new %i\", current_selection, packet_code_ready,shm_conn_info->packet_code[current_selection][chan_num].start_seq, shm_conn_info->packet_code[current_selection][chan_num].stop_seq, tmp_seq_counter, shm_conn_info->packet_code[current_selection][chan_num].len_sum,len);\n#endif\n            len_ret = udp_write(info.channel[chan_num].descriptor, buf2, len_sum | VTUN_BAD_FRAME);\n            if(len_sum <= 0) {\n                vlog(LOG_ERR, \"error sum len %d! reason: %s (%d)\", len_sum, strerror(errno), errno);\n            }\n            if (len_sum && (len_ret <= 0)) {\n                vlog(LOG_INFO, \"error direct send sum to socket chan %d! reason: %s (%d)\", chan_num, strerror(errno), errno);\n            } else {\n//                info.channel[chan_num].local_seq_num++;\n                if (info.channel[chan_num].local_seq_num == (UINT32_MAX - 1)) {\n                    info.channel[chan_num].local_seq_num = 0; // TODO: 1. not required; 2. disaster at CLI-side! 3. max. ~4TB of data\n                }\n            }\n        } else {\n#ifdef CODE_LOG\n            vlog(LOG_INFO, \"add FRAME_REDUNDANCY_CODE to fast resend selection %d packet_code ready %i seq start %\"PRIu32\" stop %\"PRIu32\" seq_num %\"PRIu32\" len %i len new %i\", current_selection, packet_code_ready,shm_conn_info->packet_code[current_selection][chan_num].start_seq, shm_conn_info->packet_code[current_selection][chan_num].stop_seq, tmp_seq_counter, shm_conn_info->packet_code[current_selection][chan_num].len_sum,len);\n#endif\n            sem_wait(&(shm_conn_info->resend_buf_sem));\n            int idx = add_fast_resend_frame(chan_num, buf2, len_sum | VTUN_BAD_FRAME, 0);\n            sem_post(&(shm_conn_info->resend_buf_sem));\n            if (idx == -1) {\n                vlog(LOG_ERR, \"ERROR: fast_resend_buf is full\");\n            }\n//               return NET_WRITE_BUSY_NOTIFY;\n        }\n    }\n#endif\n    return len & VTUN_FSIZE_MASK;\n}\n\nint write_buf_check_n_flush(int logical_channel) {\n    int fprev = -1;\n    int fold = -1;\n    int len;\n    //struct timeval max_latency_drop = MAX_LATENCY_DROP;\n    struct timeval max_latency_drop;\n    uint32_t incomplete_seq_buf[FRAME_BUF_SIZE];\n    int rtou = get_rto_usec();\n    max_latency_drop.tv_sec = rtou / 1000000;\n    max_latency_drop.tv_usec = rtou % 1000000;\n    int rtt_fix; //in ms\n    struct timeval tv_tmp, rtt_fix_tv;\n    struct timeval tv;\n    struct timeval since_write_tv, packet_wait_tv;\n    int ts;\n    fprev = shm_conn_info->write_buf[logical_channel].frames.rel_head;\n    shm_conn_info->write_buf[logical_channel].complete_seq_quantity = 0;\n    //int buf_len = shm_conn_info->write_buf[logical_channel].frames.len; // disabled for #400\n    //int tail_idx = shm_conn_info->write_buf[logical_channel].frames.rel_tail;\n    int buf_len;\n\n    // first select tun\n    fd_set fdset2;\n    tv.tv_sec = 0;\n    tv.tv_usec = 0;\n    FD_ZERO(&fdset2);\n    FD_SET(info.tun_device, &fdset2);\n    int sel_ret = select(info.tun_device + 1, NULL, &fdset2, NULL, &tv);\n    if (sel_ret == 0) {\n    #ifdef FRTTDBG\n        vlog(LOG_ERR, \"write_buf_check_n_flush select - no select%d\",errno);\n    #endif\n        return 0; // save rtt!\n    } else if (sel_ret == -1) {\n        vlog(LOG_ERR, \"write_buf_check_n_flush select error! errno %d\",errno);\n        return 0;\n    }\n\n#ifdef DEBUGG\n    if (fprev == -1) {\n        vlog(LOG_INFO, \"no data to write at all!\");\n    } else {\n        vlog(LOG_INFO, \"trying to write to to dev: seq_num %\"PRIu32\" lws %\"PRIu32\" chan %d\", shm_conn_info->frames_buf[fprev].seq_num,\n                shm_conn_info->write_buf[logical_channel].last_written_seq, logical_channel);\n    }\n#endif\n    acnt = 0;\n    if (fprev > -1) {\n        #ifdef FRTTDBG\n        vlog(LOG_ERR, \"WBF forced reached: %d\", forced_rtt_reached);\n        #endif\n        if(info.least_rx_seq[logical_channel] == UINT32_MAX) {\n            info.least_rx_seq[logical_channel] = 0; // protect us from possible failures to calculate LRS in get_write_buf_wait_data()\n        }\n        if(shm_conn_info->frames_buf[fprev].stub_counter) {\n            shm_conn_info->frames_buf[fprev].stub_counter--;\n            shm_conn_info->write_buf[logical_channel].frames.stub_total--;\n            if (shm_conn_info->tokens > 0) {\n                shm_conn_info->tokens--; // remove a token...\n            }\n            if(shm_conn_info->write_buf[logical_channel].frames.stub_total < 0) {\n                vlog(LOG_ERR, \"ASSERT FAILED!: stub_total <0!\");\n                shm_conn_info->write_buf[logical_channel].frames.stub_total = 0;\n            }\n            shm_conn_info->write_buf[logical_channel].last_write_time = info.current_time;\n            return 0;\n        }\n        if(shm_conn_info->frames_buf[fprev].seq_num == shm_conn_info->write_buf[logical_channel].last_written_seq) {\n            vlog(LOG_ERR, \"ASSERT FAILED! Duplicate packet in WB! %lu == lws %lu\", shm_conn_info->frames_buf[fprev].seq_num, shm_conn_info->write_buf[logical_channel].last_written_seq);\n        }\n        if(shm_conn_info->frames_buf[fprev].seq_num < shm_conn_info->write_buf[logical_channel].last_written_seq) {\n            vlog(LOG_ERR, \"ASSERT FAILED! Negative packet seq_num diff in WB! seq %lu < lws %lu\", shm_conn_info->frames_buf[fprev].seq_num, shm_conn_info->write_buf[logical_channel].last_written_seq);\n        }\n        int cond_flag;\n        \n        IF_WRITE_CONDITION \n        {\n            if (!cond_flag) {\n                char lag_pname[SESSION_NAME_SIZE] = \"E\\0\";\n                int r_amt = 0;\n                shm_conn_info->tflush_counter += shm_conn_info->frames_buf[fprev].seq_num\n                        - (shm_conn_info->write_buf[logical_channel].last_written_seq + 1);\n#ifdef TRACE_BUF_LEN\n                udp_struct->lport = info.channel[1].lport;\n                udp_struct->rport = info.channel[1].rport;\n                char tmp[2000] = {0};\n                if (get_udp_stats(udp_struct, 1)) {\n                    sprintf(tmp, \"udp stat tx_q %d rx_q %d drops %d \", udp_struct->tx_q, udp_struct->rx_q, udp_struct->drops);\n                }\n#endif\n                int loss_flag = 0;\n                int who_lost_pnum = -1;\n                if (buf_len > lfd_host->MAX_ALLOWED_BUF_LEN) {\n                    update_prev_flushed(logical_channel, fprev);\n                    r_amt = flush_reason_chan(WHO_LAGGING, logical_channel, lag_pname, shm_conn_info->channels_mask, &who_lost_pnum);\n                    loss_flag = 1;\n                } else if (timercmp(&packet_wait_tv, &max_latency_drop, >=)\n                           && timercmp(&since_write_tv, &((struct timeval) MAX_NETWORK_STALL), >=)\n                           //&& (shm_conn_info->frames_buf[fprev].seq_num <= shm_conn_info->write_buf[logical_channel].last_received_seq[shm_conn_info->remote_head_pnum])\n                ) {\n                    update_prev_flushed(logical_channel, fprev);\n                    r_amt = flush_reason_chan(WHO_LAGGING, logical_channel, lag_pname, shm_conn_info->channels_mask, &who_lost_pnum);\n                    loss_flag = 1;\n                    if(info.least_rx_seq[logical_channel] > 0 && info.least_rx_seq[logical_channel] != UINT32_MAX) {\n                        // now drop everything suspicious\n                        int last_idx = missing_resend_buffer(logical_channel, incomplete_seq_buf, &buf_len, info.least_rx_seq[logical_channel]) - 1;\n                        if(last_idx >= 0) {\n                            uint32_t last_loss_sqn = incomplete_seq_buf[last_idx];\n                            if(discard_packets(logical_channel, last_loss_sqn) < 0) {\n                                vlog(LOG_ERR, \"ERROR merging loss\");\n                                return 0;\n                            }\n                        }\n                    }\n\n                } else if (info.ploss_event_flag && (shm_conn_info->frames_buf[fprev].seq_num < info.least_rx_seq[logical_channel])) {\n                    update_prev_flushed(logical_channel, fprev);\n                    r_amt = flush_reason_chan(WHO_LOST, logical_channel, lag_pname, shm_conn_info->channels_mask, &who_lost_pnum);\n                    if(r_amt == 0) {\n                        if (shm_conn_info->tokens > 0) {\n                            shm_conn_info->tokens--; // remove a token...\n                        }\n                        return 0;\n                    }\n                    loss_flag = 1;\n                } else if (!info.ploss_event_flag && (shm_conn_info->frames_buf[fprev].seq_num < info.least_rx_seq[logical_channel])) {\n                    update_prev_flushed(logical_channel, fprev);\n                    r_amt = flush_reason_chan(WHO_LOST, logical_channel, lag_pname, shm_conn_info->channels_mask, &who_lost_pnum);\n                    if(r_amt == 0) {\n                        if (shm_conn_info->tokens > 0) {\n                            shm_conn_info->tokens--; // remove a token...\n                        }\n                        return 0;\n                    }\n                    loss_flag = 1;\n                } else if (shm_conn_info->frames_buf[fprev].seq_num < shm_conn_info->seq_num_unrecoverable_loss) {\n                    info.flush_sequential = shm_conn_info->seq_num_unrecoverable_loss - shm_conn_info->frames_buf[fprev].seq_num;\n                    update_prev_flushed(logical_channel, fprev);\n                    r_amt = flush_reason_chan(WHO_LAGGING, logical_channel, lag_pname, shm_conn_info->channels_mask, &who_lost_pnum);\n                    int r = discard_packets(logical_channel, shm_conn_info->seq_num_unrecoverable_loss);\n                    if(r < 0) {\n                        if(r == -2) shm_conn_info->seq_num_unrecoverable_loss = 1;\n                        return 0;\n                    }\n                    loss_flag = 1;\n                } else {\n                    update_prev_flushed(logical_channel, fprev);\n                    r_amt = flush_reason_chan(WHO_LOST, logical_channel, lag_pname, shm_conn_info->channels_mask, &who_lost_pnum);\n                }\n                if (loss_flag && !lost_buf_exists(shm_conn_info->write_buf[logical_channel].last_written_seq)) {\n                    // TODO: check if there is no such entry (this sqn) in the list\n                    shm_conn_info->loss_idx++;\n                    if (shm_conn_info->loss_idx == LOSS_ARRAY) {\n                        shm_conn_info->loss_idx = 0;\n                    }\n                    shm_conn_info->loss[shm_conn_info->loss_idx].timestamp = info.current_time;\n                    shm_conn_info->loss[shm_conn_info->loss_idx].pbl = shm_conn_info->write_sequential;\n                    shm_conn_info->loss[shm_conn_info->loss_idx].psl = info.flush_sequential;\n                    if(who_lost_pnum != -1) {\n                        shm_conn_info->loss[shm_conn_info->loss_idx].who_lost = shm_conn_info->stats[who_lost_pnum].hsnum;\n                    } else {\n                        shm_conn_info->loss[shm_conn_info->loss_idx].who_lost = -1;\n                    }\n                    shm_conn_info->loss[shm_conn_info->loss_idx].sqn = shm_conn_info->write_buf[logical_channel].last_written_seq + 1;\n                }\n            }\n            \n            if(shm_conn_info->prev_flushed) {\n                // TODO: write avg stats here?\n                shm_conn_info->write_sequential = 1;\n            } else {\n                shm_conn_info->write_sequential++;\n            }\n            shm_conn_info->prev_flushed = 0;\n\n            struct frame_seq *frame_seq_tmp = &shm_conn_info->frames_buf[fprev];\n\n            // calculate this stream TCP_seq_nums etc.\n            unsigned int tcp_seq2 = 0, hash, tcp_seq;\n            shm_conn_info->w_stream_pkts[shm_conn_info->frames_buf[fprev].shash % W_STREAMS_AMT]--;\n            // unsigned int hash = get_l4_hash(frame_seq_tmp->out, &tcp_seq2);\n            // unsigned int tcp_seq = getTcpSeq(frame_seq_tmp->out);\n            // shm_conn_info->w_streams[hash % W_STREAMS_AMT].ts = info.current_time;\n            // if(shm_conn_info->w_streams[hash % W_STREAMS_AMT].seq < tcp_seq) {\n            //     shm_conn_info->w_streams[hash % W_STREAMS_AMT].seq = tcp_seq;\n            // }\n            // TODO: drop here may be pre-calculated once in 500ms - no need to do it each packet\n            int need_drop = (shm_conn_info->frames_buf[fprev].unconditional_write_flag == 1) || ((shm_conn_info->write_buf[1].frames.length > (MSBL_LIMIT - MSBL_RESERV)) && (shm_conn_info->max_stuck_buf_len > (MSBL_LIMIT - MSBL_RESERV)) && check_drop_period_unsync());\n            if(frame_seq_tmp->len > 0 && !need_drop) {\n                if ((len = dev_write(info.tun_device, frame_seq_tmp->out, frame_seq_tmp->len)) < 0) {\n                    vlog(LOG_ERR, \"error writing to device %d %s chan %d\", errno, strerror(errno), logical_channel);\n                    if (errno != EAGAIN && errno != EINTR) { // TODO: WTF???????\n                        vlog(LOG_ERR, \"dev write not EAGAIN or EINTR\");\n                    } else {\n                        vlog(LOG_ERR, \"dev write intr - need cont\");\n                        return 0;\n                    }\n    \n                } else {\n                    if (len < frame_seq_tmp->len) {\n                        vlog(LOG_ERR, \"ASSERT FAILED! could not write to device immediately; dunno what to do!! bw: %d; b rqd: %d\", len,\n                                shm_conn_info->frames_buf[fprev].len);\n                    }\n                }\n            } else {\n                vlog(LOG_INFO, \"dropping frame at write seq_num %lu unf %d\", shm_conn_info->frames_buf[fprev].seq_num, shm_conn_info->frames_buf[fprev].unconditional_write_flag);\n                drop_counter++;\n                // shm_conn_info->write_buf[logical_channel].frames.stub_total--;\n                \n                if(need_drop) {\n                    shm_conn_info->drop_time = info.current_time;\n                }\n            }\n            \n            if (debug_trace) {\n                vlog(LOG_INFO, \"writing to dev: bln is %d icpln is %d, sqn: %\"PRIu32\", lws: %\"PRIu32\" mode %d, ns: %d, w: %d len: %d, chan %d ts %ld.%06ld cur %ld.%06ld rtt %d pnum %d, tokens %d, tcp_seq %u == %u, hs %u\", buf_len, incomplete_seq_len,\n                        shm_conn_info->frames_buf[fprev].seq_num, shm_conn_info->write_buf[logical_channel].last_written_seq, (int) channel_mode, shm_conn_info->normal_senders,\n                        weight, shm_conn_info->frames_buf[fprev].len, logical_channel, shm_conn_info->frames_buf[fprev].time_stamp, info.current_time, shm_conn_info->frames_buf[fprev].current_rtt, shm_conn_info->frames_buf[fprev].physical_channel_num, shm_conn_info->tokens, tcp_seq, tcp_seq2, hash);\n            }\n            if(shm_conn_info->frames_buf[fprev].unconditional_write_flag != -1) {\n                if (shm_conn_info->tokens > 0) {\n                    shm_conn_info->tokens--; // remove a token...\n                }\n            }\n            shm_conn_info->flushed_packet[shm_conn_info->frames_buf[fprev].seq_num % FLUSHED_PACKET_ARRAY_SIZE] = shm_conn_info->frames_buf[fprev].seq_num;\n            shm_conn_info->write_buf[logical_channel].last_written_seq = shm_conn_info->frames_buf[fprev].seq_num;\n            shm_conn_info->last_written_recv_ts = shm_conn_info->frames_buf[fprev].time_stamp;\n            shm_conn_info->write_buf[logical_channel].last_write_time = info.current_time;\n            fold = fprev;\n            fprev = shm_conn_info->frames_buf[fprev].rel_next;\n//            frame_llist_free(&shm_conn_info->write_buf[logical_channel].frames, &shm_conn_info->wb_free_frames, shm_conn_info->frames_buf, fold);\n//            return 1;\n            if(frame_llist_pull(&shm_conn_info->write_buf[logical_channel].frames, shm_conn_info->frames_buf, &fold) < 0) {\n                vlog(LOG_ERR, \"WARNING! tried to pull from empty write_buf!\");\n                return 0;\n            }\n            frame_llist_append(&shm_conn_info->wb_just_write_frames[logical_channel], fold, shm_conn_info->frames_buf);\n            if (shm_conn_info->wb_just_write_frames[logical_channel].length > PACKET_CODE_BUFFER_SIZE) {\n                int frame_index;\n                if(frame_llist_pull(&shm_conn_info->wb_just_write_frames[logical_channel], shm_conn_info->frames_buf, &frame_index) < 0) {\n                    vlog(LOG_ERR, \"ASSERT FAILED! can not pull anything from wjf!\");\n                    return 0;\n                }\n                frame_llist_append(&shm_conn_info->wb_free_frames, frame_index, shm_conn_info->frames_buf);\n            }\n            \n            return 1;\n        } \n    } else {\n        return 0;\n    }\n    return 0;\n}\n\n/**\n * push up msbl in case of loss for current channel\n * \n */\n \nvoid msbl_push_up_loss_unsync() {\n    struct timeval loss_tv;\n    if((shm_conn_info->stats[info.process_num].recv_mode == AG_MODE || shm_conn_info->stats[info.process_num].remote_head_channel) && timercmp(&info.recv_loss_immune, &info.current_time, <=)) {\n        vlog(LOG_INFO, \"Loss detected - pushing the MSBL up by %d\", (shm_conn_info->stats[info.process_num].remote_sqe_mean_pkt - (int) ((double)shm_conn_info->stats[info.process_num].remote_sqe_mean_pkt * (2.0 - info.B) / 2.0)));\n        shm_conn_info->max_stuck_buf_len += shm_conn_info->stats[info.process_num].remote_sqe_mean_pkt - (int) ((double)shm_conn_info->stats[info.process_num].remote_sqe_mean_pkt * (2.0 - info.B) / 2.0);\n        ms2tv(&loss_tv, info.exact_rtt);\n        timeradd(&info.current_time, &loss_tv, &info.recv_loss_immune);\n    }\n} \n\n// void msbl_push_down_drop_unsync() {\n//     struct timeval loss_tv;\n//         shm_conn_info->max_stuck_buf_len -= shm_conn_info->stats[info.process_num].remote_sqe_mean_pkt - (int) ((double)shm_conn_info->stats[info.process_num].remote_sqe_mean_pkt * (2.0 - info.B) / 2.0);\n//         ms2tv(&loss_tv, info.exact_rtt);\n//         timeradd(&info.current_time, &loss_tv, &info.recv_loss_immune);\n// }\n\n\n/*\n               _ _             _            __               _     _ \n              (_) |           | |          / _|             | |   | |\n__      ___ __ _| |_ ___      | |__  _   _| |_      __ _  __| | __| |\n\\ \\ /\\ / / '__| | __/ _ \\     | '_ \\| | | |  _|    / _` |/ _` |/ _` |\n \\ V  V /| |  | | ||  __/     | |_) | |_| | |     | (_| | (_| | (_| |\n  \\_/\\_/ |_|  |_|\\__\\___|     |_.__/ \\__,_|_|      \\__,_|\\__,_|\\__,_|\n                      ______              ______                     \n                     |______|            |______|                    \n*/\n\nint write_buf_add(int conn_num, char *out, int len, uint32_t seq_num, uint32_t incomplete_seq_buf[], int *buf_len, int mypid, char *succ_flag) {\n    char *ptr;\n    int mlen = 0;\n#ifdef DEBUGG\n    vlog(LOG_INFO, \"write_buf_add called! len %d seq_num %\"PRIu32\" chan %d\", length, seq_num, conn_num);\n#endif\n    if(debug_trace) {\n        vlog(LOG_INFO, \"write_buf_add called! len %d seq_num %\"PRIu32\" chan %d\", len, seq_num, conn_num);\n    }\n    // place into correct position first..\n    int i = shm_conn_info->write_buf[conn_num].frames.rel_head, n;\n    int newf;\n    int j=0;\n    shm_conn_info->avg_len_in = EFF_LEN_AVG_N * shm_conn_info->avg_len_in / EFF_LEN_AVG_D + len / EFF_LEN_AVG_D;\n\n    if (i == -1) {\n        shm_conn_info->write_buf[conn_num].last_write_time = info.current_time;\n    }\n    int tail_idx = shm_conn_info->write_buf[conn_num].frames.rel_tail;\n#ifdef SYSLOG\n    if ((tail_idx != -1) && ( (seq_num > shm_conn_info->frames_buf[tail_idx].seq_num ) &&\n            (seq_num - shm_conn_info->frames_buf[tail_idx].seq_num ) >= STRANGE_SEQ_FUTURE )) {\n        vlog(LOG_INFO, \"WARNING! DROP BROKEN PKT SRANGE_SEQ_FUTURE logical channel %i seq_num %\"PRIu32\" lws %\"PRIu32\"; diff is: %d >= 1000 tail seq %lu\", conn_num, seq_num, shm_conn_info->write_buf[conn_num].last_written_seq, (seq_num - shm_conn_info->frames_buf[tail_idx].seq_num), shm_conn_info->frames_buf[tail_idx].seq_num);\n    }\n    if( (tail_idx != -1) && (seq_num < shm_conn_info->write_buf[conn_num].last_written_seq) &&\n              ((shm_conn_info->write_buf[conn_num].last_written_seq - seq_num) >= STRANGE_SEQ_PAST) ) { // this ABS comparison makes checks in MRB unnesesary...\n        vlog(LOG_INFO, \"WARNING! DROP BROKEN PKT STRANGE_SEQ_PAST logical channel %i seq_num %\"PRIu32\" lws %\"PRIu32\"; diff is: %d >= 1000\", conn_num, seq_num, shm_conn_info->write_buf[conn_num].last_written_seq, (shm_conn_info->write_buf[conn_num].last_written_seq - seq_num));\n    }\n#endif\n\n    if ( (seq_num <= shm_conn_info->write_buf[conn_num].last_written_seq)) {\n        //check for oldest dups\n        if (shm_conn_info->flushed_packet[seq_num % FLUSHED_PACKET_ARRAY_SIZE] != seq_num) {\n            shm_conn_info->flushed_packet[seq_num % FLUSHED_PACKET_ARRAY_SIZE] = seq_num;\n            struct timeval work_loop1, work_loop2, tmp_tv;\n            //gettimeofday(&work_loop1, NULL );\n            int len_ret = dev_write(info.tun_device, out, len);\n            //gettimeofday(&work_loop2, NULL );\n            //timersub(&work_loop2, &work_loop1, &tmp_tv);\n            vlog(LOG_INFO, \"latecomer seq_num %u lws %u time write %\"PRIu64\" ts %ld.%06ld\", seq_num, shm_conn_info->write_buf[conn_num].last_written_seq, tv2ms(&tmp_tv), info.current_time.tv_sec, info.current_time.tv_usec);\n            if (len_ret < 0) {\n                vlog(LOG_ERR, \"error writing to device %d %s chan %d\", errno, strerror(errno), conn_num);\n                if (errno != EAGAIN && errno != EINTR) { // TODO: WTF???????\n                    vlog(LOG_ERR, \"dev write not EAGAIN or EINTR\");\n                } else {\n                    vlog(LOG_ERR, \"dev write intr - need cont\");\n                    return 0;\n                }\n\n            } else if (len_ret < len) {\n                vlog(LOG_ERR, \"ASSERT FAILED! could not write to device immediately; dunno what to do!! bw: %d; b rqd: %d\", len_ret, len);\n            }\n\n        }\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"drop dup pkt seq_num %\"PRIu32\" lws %\"PRIu32\"\", seq_num, shm_conn_info->write_buf[conn_num].last_written_seq);\n#endif\n        *succ_flag = -2;\n        return 0; //missing_resend_buffer (conn_num, incomplete_seq_buf, buf_len);\n    }\n    /*\n    unsigned int tcp_seq = getTcpSeq(out);\n    unsigned int tcp_seq2 = 0;\n    unsigned int hash = get_l4_hash(out, &tcp_seq2);\n    if(0 && shm_conn_info->w_streams[hash % W_STREAMS_AMT].seq > tcp_seq) {\n        struct timeval tv_tmp;\n        timersub(&info.current_time, &shm_conn_info->w_streams[hash % W_STREAMS_AMT].ts, &tv_tmp);\n        if(timercmp(&tv_tmp, &((struct timeval) {5, 0}), >=)) { // 5 seconds session timeout\n            shm_conn_info->w_streams[hash % W_STREAMS_AMT].seq = 0;\n        } else {\n            int len_ret = dev_write(info.tun_device, out, len);\n            vlog(LOG_ERR, \"tcp retransmission segment seq_num %u lws %u tcp_seq %u == %u last tseq: %u, hs %u ts %ld.%06ld\", seq_num, shm_conn_info->write_buf[conn_num].last_written_seq, tcp_seq, tcp_seq2, shm_conn_info->w_streams[hash % W_STREAMS_AMT].seq, hash, info.current_time.tv_sec, info.current_time.tv_usec);\n            if (len_ret < 0) {\n                vlog(LOG_ERR, \"ERROR writing (tcprxm) to device %d %s chan %d\", errno, strerror(errno), conn_num);\n                if (errno != EAGAIN && errno != EINTR) { // TODO: WTF???????\n                    vlog(LOG_ERR, \"ERROR tcprxm dev write not EAGAIN or EINTR\");\n                } else {\n                    vlog(LOG_ERR, \"ERROR tcprxm dev write intr - need cont\");\n                }\n\n            } else if (len_ret < len) {\n                vlog(LOG_ERR, \"ASSERT FAILED! tcprxm could not write to device immediately; dunno what to do!! bw: %d; b rqd: %d\", len_ret, len);\n            }\n            len = 0; // indicate that this is stub packet\n            //seq_num = 0; // to make stub packet support work at flushing? // actually not required since these are OK in seq_num\n        }\n    }\n    */\n\n    // now check if we can find it in write buf current .. inline!\n    // TODO: run from BOTTOM! if seq_num[i] < seq_num: break\n    /*\n    if(seq_num <= shm_conn_info->frames_buf[shm_conn_info->write_buf[conn_num].frames.rel_tail].seq_num) {\n        while( i > -1 ) {\n            if(shm_conn_info->frames_buf[i].seq_num == seq_num) {\n#ifdef DEBUGG\n                vlog(LOG_INFO, \"drop exist pkt seq_num %\"PRIu32\" sitting in write_buf chan %i\", seq_num, conn_num);\n#endif\n                return 0;\n            }\n            i = shm_conn_info->frames_buf[i].rel_next;\n        }\n    }\n    */\n    shm_conn_info->flushed_packet[seq_num % FLUSHED_PACKET_ARRAY_SIZE] = seq_num;\n    i = shm_conn_info->write_buf[conn_num].frames.rel_head;\n\n    if (frame_llist_pull(&shm_conn_info->wb_free_frames, shm_conn_info->frames_buf, &newf) < 0) {\n        // try a fix\n        vlog(LOG_ERR, \"WARNING! No free elements in wbuf! trying to free some...\");\n        if(frame_llist_pull(&shm_conn_info->wb_free_frames,\n                            shm_conn_info->frames_buf,\n                            &newf) < 0) {\n            vlog(LOG_ERR, \"FATAL: could not fix free wb.\");\n            *succ_flag = -1;\n            return -1;\n        }\n    }\n    // if(seq_num == 0 || len == 0) { // add stub packet counter in case of retransmission packet\n    //     shm_conn_info->write_buf[conn_num].frames.stub_total++;\n    // }\n    // now add stubs, if any\n    // if(shm_conn_info->tokenbuf > MAX_STUB_JITTER) {\n    //     shm_conn_info->frames_buf[newf].stub_counter = shm_conn_info->tokenbuf - MAX_STUB_JITTER;\n    //     shm_conn_info->write_buf[conn_num].frames.stub_total += shm_conn_info->frames_buf[newf].stub_counter;\n    //     shm_conn_info->tokenbuf = MAX_STUB_JITTER;\n    // } else {\n    //     shm_conn_info->frames_buf[newf].stub_counter = 0;\n    // }\n        \n    shm_conn_info->frames_buf[newf].seq_num = seq_num;\n    // do not do the copy until written\n    //memcpy(shm_conn_info->frames_buf[newf].out, out, len);\n    shm_conn_info->frames_buf[newf].len = len;\n    shm_conn_info->frames_buf[newf].sender_pid = mypid;\n    shm_conn_info->frames_buf[newf].physical_channel_num = info.process_num;\n    shm_conn_info->frames_buf[newf].time_stamp = info.current_time;\n    shm_conn_info->frames_buf[newf].current_rtt = info.exact_rtt;\n    shm_conn_info->frames_buf[newf].unconditional_write_flag = 0;\n    struct timeval t_rtt, t_frtt, tv_tmp;\n    int full_rtt = ((shm_conn_info->forced_rtt_recv > shm_conn_info->frtt_local_applied) ? shm_conn_info->forced_rtt_recv : shm_conn_info->frtt_local_applied);\n    if(info.exact_rtt < full_rtt) {\n        ms2tv(&t_rtt, info.exact_rtt);\n        ms2tv(&t_frtt, full_rtt);\n        timersub(&t_frtt, &t_rtt, &tv_tmp);\n        timeradd(&info.current_time, &tv_tmp, &shm_conn_info->frames_buf[newf].flush_time);\n    } else {\n        shm_conn_info->frames_buf[newf].flush_time = info.current_time;\n    }\n    shm_conn_info->write_buf[conn_num].frames.length++;\n    if (buf_len_real < shm_conn_info->write_buf[1].frames.length) {\n//    vlog(LOG_ERR, \"FRAME_CHANNEL_INFO update buf_len %d was %d\",shm_conn_info->write_buf[1].frames.length,shm_conn_info->buf_len);\n        buf_len_real = shm_conn_info->write_buf[1].frames.length;\n        }\n    // if(shm_conn_info->tokenbuf > 0) shm_conn_info->tokenbuf--;\n    int buf_len_real = shm_conn_info->write_buf[conn_num].frames.length;\n    int tokens_in_out = buf_len_real - shm_conn_info->max_stuck_buf_len;\n    if(tokens_in_out > 0) {\n        #ifdef FRTTDBG\n        vlog(LOG_INFO, \"adding token+1\");\n        #endif\n        shm_conn_info->tokens++;\n        if( ((shm_conn_info->head_send_q_shift_recv == 10000) || (shm_conn_info->slow_start_recv)) && ((seq_num % SLOW_START_INCINT) == 0)) {\n            vlog(LOG_INFO, \"FAST PUSHING MSBL UP ???????\");\n           shm_conn_info->max_stuck_buf_len += 1;\n        }\n        //if(shm_conn_info->max_stuck_buf_len == 950) {\n        //    // drop exactly one packet (at least try to)\n        //    shm_conn_info->frames_buf[newf].len = 0;\n        //}\n    }\n    int written = 0;\n    unsigned int tcp_seq2 = 0;\n    unsigned int shash = get_l4_hash(out, &tcp_seq2);\n    int unf = -1;\n    \n    if(i<0) { // buffer empty.\n        shm_conn_info->frames_buf[newf].rel_next = -1;\n        shm_conn_info->write_buf[conn_num].frames.rel_head = shm_conn_info->write_buf[conn_num].frames.rel_tail = newf;\n        mlen = 0;\n        *succ_flag=0;\n        memcpy(shm_conn_info->frames_buf[newf].out, out, len); // now actually copy the data.. just a tiny optimization\n        unsigned int hash = seq_num * 2654435761 % 4294967296 % WBUF_HASH_SIZE;\n        shm_conn_info->write_buf_hashtable[hash].seq = seq_num;\n        shm_conn_info->write_buf_hashtable[hash].n = newf;\n        shm_conn_info->APCS_cnt++;\n        shm_conn_info->w_stream_pkts[shash % W_STREAMS_AMT]++;\n        shm_conn_info->frames_buf[newf].shash = shash;\n        return mlen;\n    } else { // buffer not empty\n        // if(shm_conn_info->frames_buf[shm_conn_info->write_buf[conn_num].frames.rel_tail].seq_num == seq_num - 2) {\n        //     vlog(LOG_ERR, \"WARNING! added one packet loss! %lu +2= %lu\", shm_conn_info->frames_buf[shm_conn_info->write_buf[conn_num].frames.rel_tail].seq_num, seq_num);\n        // }\n        if( (shm_conn_info->frames_buf[i].seq_num > seq_num) &&\n                (shm_conn_info->frames_buf[i].rel_next > -1)) { // new packet is older (&lt) than all the buffer\n            // append to head\n            // no check for dups is required here as we are sure that all the buffer is newer than this packet\n            shm_conn_info->write_buf[conn_num].frames.rel_head = newf;\n            shm_conn_info->frames_buf[newf].rel_next = i;\n            written = 1;\n        } else {\n            if(shm_conn_info->frames_buf[i].rel_next > -1) {\n                // TODO HERE: do extreme optimization: \n                // 1. always use hashed search first\n                // 2. try c=1 first, then x2, x3, etc.\n                if(shm_conn_info->write_buf[conn_num].frames.length > MAX_WBUF_HASH_DEPTH && seq_num > 0) {\n                    unsigned int hash = seq_num * 2654435761 % 4294967296 % WBUF_HASH_SIZE;\n                    int c = 0;\n                    while( (c < MAX_WBUF_HASH_DEPTH) \n                        && ((seq_num - c) > shm_conn_info->write_buf[conn_num].last_written_seq) \n                        && (shm_conn_info->write_buf_hashtable[hash].seq != (seq_num - c))) {\n                        c+=1;\n                        hash = (seq_num - c) * 2654435761 % 4294967296 % WBUF_HASH_SIZE;\n                    }\n                    if(c >= MAX_WBUF_HASH_DEPTH || (seq_num - c) <= shm_conn_info->write_buf[conn_num].last_written_seq) {\n                        /*\n                        hash = seq_num * 2654435761 % 4294967296 % WBUF_HASH_SIZE;\n                        vlog(LOG_INFO, \"Warning! hash lookup failed, falling back to search from top seq %ld hash %d\", seq_num, hash);\n                        */\n                    } else {\n                        //vlog(LOG_INFO, \"New search start %d bl %d seq %ld (new hash %d) - found seq %ld hash %d tries %d\", shm_conn_info->write_buf_hashtable[hash].n, shm_conn_info->write_buf[conn_num].frames.length, seq_num, seq_num * 2654435761 % 4294967296 % WBUF_HASH_SIZE, seq_num-c, hash, c);\n                        i = shm_conn_info->write_buf_hashtable[hash].n;\n                        /*\n                        // TODO: remove this\n                        if(c == 0) {\n                            vlog(LOG_INFO, \"zero tries: seq %ld n %d n.seq %ld\", seq_num, i, shm_conn_info->frames_buf[i].seq_num);                   \n                        }\n                        // now make sure that the entry point we have found is actually found inside the wb\n                        int k;\n                        for (k = shm_conn_info->write_buf[conn_num].frames.rel_head; k != -1; k = shm_conn_info->frames_buf[k].rel_next) {\n                            if(k == i) break;\n                        }\n                        if(k == -1) {\n                            vlog(LOG_ERR, \"ASSERT FAILED! entry point is outside the write_buf!\");\n                        }\n                        */\n                    }\n                }\n                \n                while( i > -1 ) {\n                    if( shm_conn_info->frames_buf[i].seq_num == seq_num) {\n                        break; // found a dup, not setting written flag\n                    }\n                    n = shm_conn_info->frames_buf[i].rel_next;\n                    if(n > -1) {\n                        if( shm_conn_info->frames_buf[n].seq_num > seq_num) {\n                            shm_conn_info->frames_buf[i].rel_next = newf;\n                            shm_conn_info->frames_buf[newf].rel_next = n;\n                            written = 1;\n                            break;\n                        } // else try next...\n                    } else {\n                        // append to tail\n                        #ifdef SYSLOG\n                        if(i != shm_conn_info->write_buf[conn_num].frames.rel_tail) {\n                            vlog(LOG_ERR, \"ASSERT FAILED! i!=tail: sqn %ld, %d %d: wb: %d, jwb: %d, fr: %d, lws: %ld\", shm_conn_info->frames_buf[i].seq_num, i, shm_conn_info->write_buf[conn_num].frames.rel_tail, shm_conn_info->write_buf[conn_num].frames.rel_tail, shm_conn_info->wb_just_write_frames[conn_num].rel_tail, shm_conn_info->wb_free_frames.rel_tail, shm_conn_info->write_buf[conn_num].last_written_seq);\n                        }\n                        #endif\n                        shm_conn_info->frames_buf[i].rel_next=newf;\n                        shm_conn_info->frames_buf[newf].rel_next = -1;\n                        shm_conn_info->write_buf[conn_num].frames.rel_tail = newf;\n                        written = 1;\n                        break;\n                    }\n                    i = n;\n                }\n\n            } else {\n                if(shm_conn_info->frames_buf[i].seq_num != seq_num) { // dup protect?\n                    if(shm_conn_info->frames_buf[i].seq_num > seq_num) {\n                        shm_conn_info->write_buf[conn_num].frames.rel_head = newf;\n                        shm_conn_info->frames_buf[newf].rel_next = i;\n                    } else {\n                        shm_conn_info->write_buf[conn_num].frames.rel_tail = newf;\n                        shm_conn_info->frames_buf[i].rel_next = newf;\n                        shm_conn_info->frames_buf[newf].rel_next = -1;\n                    }\n                    written = 1;\n                }\n            }\n        }\n    }\n    \n    if(!written) {\n        // means we were unable to write, put the packet back to free\n        // vlog(LOG_INFO, \"Unable to find position to add packet! %ld\", seq_num); // dup detected\n        shm_conn_info->write_buf[conn_num].frames.length--; // we have not written that packet to buffer...\n        frame_llist_prepend(&shm_conn_info->wb_free_frames, newf, shm_conn_info->frames_buf);\n        *succ_flag= 0;\n        return 0;\n    }\n    \n    if(   shm_conn_info->write_buf[conn_num].frames.rel_head >= 0 && \n          shm_conn_info->write_buf[conn_num].frames.length > 20 && \n          shm_conn_info->w_stream_pkts[shash % W_STREAMS_AMT] == 0 && \n          shm_conn_info->frames_buf[shm_conn_info->write_buf[conn_num].frames.rel_head].unconditional_write_flag != -1 && \n          shm_conn_info->frames_buf[shm_conn_info->write_buf[conn_num].frames.rel_head].seq_num != seq_num) {\n        // duplicate this packet in front of queue\n        if (frame_llist_pull(&shm_conn_info->wb_free_frames, shm_conn_info->frames_buf, &unf) < 0) {\n            vlog(LOG_ERR, \"WARNING! Can not write new stream packet in front: no free elements in buffer\");\n        } else {\n            frame_llist_prepend(&shm_conn_info->write_buf[conn_num].frames, unf, shm_conn_info->frames_buf);\n            \n            shm_conn_info->frames_buf[unf].unconditional_write_flag = -1;\n            shm_conn_info->frames_buf[unf].seq_num = shm_conn_info->write_buf[conn_num].last_written_seq;\n            shm_conn_info->write_buf[conn_num].last_written_seq = shm_conn_info->frames_buf[unf].seq_num - 1;\n            shm_conn_info->frames_buf[unf].len = len;\n            shm_conn_info->frames_buf[unf].sender_pid = mypid;\n            shm_conn_info->frames_buf[unf].physical_channel_num = info.process_num;\n            shm_conn_info->frames_buf[unf].time_stamp = info.current_time;\n            shm_conn_info->frames_buf[unf].current_rtt = info.exact_rtt;\n            memcpy(shm_conn_info->frames_buf[unf].out, out, len); // now actually copy the data.. just a tiny optimization\n            shm_conn_info->w_stream_pkts[shash % W_STREAMS_AMT]++;\n            shm_conn_info->frames_buf[unf].shash = shash;\n            vlog(LOG_ERR, \"Adding priority packet seq %lu imitated %lu, next is %lu\", seq_num, shm_conn_info->frames_buf[unf].seq_num, shm_conn_info->frames_buf[shm_conn_info->frames_buf[unf].rel_next].seq_num);\n        }\n    }\n    \n    memcpy(shm_conn_info->frames_buf[newf].out, out, len); // now actually copy the data.. just a tiny optimization\n    unsigned int hash = seq_num * 2654435761 % 4294967296 % WBUF_HASH_SIZE;\n    shm_conn_info->write_buf_hashtable[hash].seq = seq_num;\n    shm_conn_info->write_buf_hashtable[hash].n = newf;\n    shm_conn_info->APCS_cnt++;\n    shm_conn_info->w_stream_pkts[shash % W_STREAMS_AMT]++;\n    shm_conn_info->frames_buf[newf].shash = shash;\n    if(unf >= 0) {\n        shm_conn_info->frames_buf[newf].unconditional_write_flag = 1;\n    }\n\n    mlen = 0; //missing_resend_buffer (conn_num, incomplete_seq_buf, buf_len);\n\n    *succ_flag= 0;\n    return mlen;\n}\n\nvoid sem_post_if(int *dev_my, sem_t *rd_sem) {\n    if(*dev_my) sem_post(rd_sem);\n    else {\n        // it is actually normal to try to post sem in idle-beg and in net-end blocks\n        // vlog(LOG_INFO, \"ASSERT FAILED! posting posted rd_sem\");\n    }\n    *dev_my = 0;\n}\n\n/**\n * не отправлен ли потерянный пакет уже на перезапрос\n */\nint check_sent (uint32_t seq_num, struct resent_chk sq_rq_buf[], int *sq_rq_pos, int chan_num) {\n    int i;\n    for(i=(RESENT_MEM-1); i>=0; i--) {\n        if( (sq_rq_buf[i].seq_num == seq_num) && (sq_rq_buf[i].chan_num == chan_num)) {\n            return 1;\n        }\n    }\n    // else - increment pos;\n\n    sq_rq_buf[*sq_rq_pos].seq_num = seq_num;\n    sq_rq_buf[*sq_rq_pos].chan_num = chan_num;\n    (*sq_rq_pos) ++;\n    if(*sq_rq_pos >= RESENT_MEM) {\n        *sq_rq_pos = 0;\n    }\n    return 0;\n}\n\n// TODO: profiler says it is expensive function. get rid of timed wait! it is\n//  for debugging only!\nint sem_wait_tw(sem_t *sem) { \n    struct timeval tv;\n    struct timespec ts;\n    int sval;\n    gettimeofday(&tv, NULL);\n    //ts.tv_sec = tv.tv_sec + 2 + (tv.tv_usec % 3);\n    ts.tv_sec = tv.tv_sec + 5 + (tv.tv_usec % 3);\n    ts.tv_nsec = 0;\n\n    sem_getvalue(sem, &sval);\n    if(sval > 1) {\n        vlog(LOG_ERR, \"ASSERT FAILED! Semaphore value > 1: %d, doing one more sem_wait\", sval);\n        sem_wait(sem);\n    }\n\n    if( sem_timedwait(sem, &ts) < 0 ) {\n        vlog(LOG_ERR, \"ASSERT FAILED! Emergrency quit semaphore waiting\");\n        sem_post(sem);\n    }\n    return 0;\n}\n\n\nint set_max_chan(uint32_t chan_mask) {\n    //must sync on stats_sem\n    int min_bdp = 1000000;\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if ((chan_mask & (1 << i))\n            && (!shm_conn_info->stats[i].channel_dead)) { // hope this works..\n            if(tv2ms(&shm_conn_info->stats[i].bdp1) < min_bdp) {\n                min_bdp = tv2ms(&shm_conn_info->stats[i].bdp1);\n                max_chan = i;\n            }\n        }\n    }\n    vlog(LOG_INFO, \"Head change BDP\");\n    shm_conn_info->max_chan = max_chan;\n}\n\nint check_plp_ok(int pnum, int32_t chan_mask) { // TODO TCP model => remove\n    #define PBL_THRESH 2500 // PBL after which chan is ok to use for normal OP\n    int chali = 0;\n    int pmax =0;\n    int imax=-1;\n    int l_pbl;\n    int rtt_min = INT32_MAX;\n    // 1. set chan thresh\n    // 2. check all other chans for thresh. if no chans are OK -> use chan with highest PBL\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead)) { // hope this works..\n            l_pbl = plp_avg_pbl_unrecoverable(i);\n            if(l_pbl > PBL_THRESH) {\n                chali++;\n            }\n            if(pmax < l_pbl) {\n                pmax = l_pbl;\n                imax=i;\n            }\n            if(rtt_min > shm_conn_info->stats[i].exact_rtt){\n                rtt_min = shm_conn_info->stats[i].exact_rtt;\n            }\n        }\n    }\n    if((shm_conn_info->stats[pnum].exact_rtt - rtt_min) > MAX_LATENCY_DROP_USEC/1000) { // TODO remove when FRTT theory will kick in\n        return 0;\n    } else {\n        if(chali) {\n            return (plp_avg_pbl_unrecoverable(pnum) > PBL_THRESH);\n        } else {\n           return (pnum == imax);\n        }\n    }\n}\n\nint transition_period_time(int hsqs) {\n    int j=0;\n    int i;\n    int min_diff = 10; // TODO: variable/constant\n    for(i=hsqs; i>min_diff; i=i-i/5) j++; // TODO: same constant as in MSBL\n    return j * (SELECT_SLEEP_USEC/1000); // return milliseconds to converge\n}\n\nint redetect_head_unsynced(int32_t chan_mask, int exclude) { // TODO: exclude is only used to change head!\n    // shm_conn_info->max_chan = 0; // change immedialtey\n    // shm_conn_info->max_chan_new = 0;\n    // return 1;\n    \n    int fixed = 0;\n    int htime = 0;\n    int Ch = 0;\n    int Cs = 0;\n     // This is AG_MODE algorithm\n    int moremax = 0;\n    int max_chan_H = -1;\n    int max_chan_CS = -1;\n    int min_rtt = INT32_MAX;\n    int max_ACS = 0;\n    int max_ACS_chan = -1;\n    int max_chan = shm_conn_info->max_chan;\n    int immune_sec = 0;\n    struct timeval tv_tmp;\n    int new_max_chan = -1;\n\n    if( exclude == max_chan) { // the only case right now\n        // choose first (random) head, excluding 'excluded', then do following redetect\n        int new_head = -1;\n        for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n            if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (i != exclude)) {\n                new_head = i;\n                break;\n            }\n        }\n        if(new_head != -1) { // means we've found one alive and not excluded\n            shm_conn_info->max_chan = new_head;\n            shm_conn_info->max_chan_new = new_head;\n            max_chan = new_head;\n            // set redetect time to future\n            immune_sec = SPEED_REDETECT_IMMUNE_SEC;\n        }\n    }\n\n    if(shm_conn_info->idle) {\n        // use RTT-only choosing of head while idle!\n        int min_rtt = INT32_MAX;\n        int min_rtt_chan = 0;\n        for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n            if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead)) { // hope this works..\n                if(min_rtt > shm_conn_info->stats[i].exact_rtt) {\n                    min_rtt = shm_conn_info->stats[i].exact_rtt;\n                    min_rtt_chan = i;\n                }\n            }\n        }\n        //vlog(LOG_INFO, \"IDLE: Head is %d due to lowest rtt %d\", min_rtt_chan, min_rtt);\n        shm_conn_info->max_chan = min_rtt_chan;\n        shm_conn_info->max_chan_new = min_rtt_chan;\n        fixed = 1;\n        shm_conn_info->last_switch_time = info.current_time; // nothing bad in this..\n        shm_conn_info->last_switch_time.tv_sec += immune_sec;\n    } else {\n        // ---> ACS == and rtt\n        min_rtt = shm_conn_info->stats[shm_conn_info->max_chan].exact_rtt;\n        for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n            if ( (chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (i != shm_conn_info->max_chan) && (i != exclude) && check_plp_ok(i, chan_mask) ) {\n                if(percent_delta_equal(shm_conn_info->stats[i].ACK_speed_avg, shm_conn_info->stats[shm_conn_info->max_chan].ACK_speed_avg, 10)) { // 15% corridor to consider speeds the same\n                    // new ALGO: Si ~= Sh => we almost certainly selected head wrong.\n                    // now choose best rtt2 from all chans that have same speed!\n                    if(min_rtt > shm_conn_info->stats[i].exact_rtt) {\n                        min_rtt = shm_conn_info->stats[i].exact_rtt;\n                        max_chan_H = i;\n                    }\n                    // TODO: need smoothed percent compare! with selections auto-mgmt!\n                }\n            }\n        }\n\n        if(max_chan_H > -1) {\n            vlog(LOG_INFO, \"ACS~=: Need changing HEAD to %d with ACS %d and rtt %d\", max_chan_H, shm_conn_info->stats[max_chan_H].ACK_speed_avg, shm_conn_info->stats[max_chan_H].exact_rtt);\n        }\n\n        // TODO: what to do if these two methods disagree? Is it possible?\n        \n        for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n            if ( (chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (i != shm_conn_info->max_chan) && (i != exclude) /* && check_plp_ok(i, chan_mask)*/) {\n                if( !percent_delta_equal(shm_conn_info->stats[i].ACK_speed_avg, shm_conn_info->stats[shm_conn_info->max_chan].ACK_speed_avg, 10)\n                         && ( shm_conn_info->stats[i].ACK_speed_avg > shm_conn_info->stats[shm_conn_info->max_chan].ACK_speed_avg )) { // 15% corridor to consider speeds the same\n                    max_chan_H = i;\n                    vlog(LOG_INFO, \"ACS>>: Need changing HEAD to %d with ACS %d > ACS(max) %d\", i, shm_conn_info->stats[i].ACK_speed_avg, shm_conn_info->stats[shm_conn_info->max_chan].ACK_speed_avg);\n                }\n            }\n        }\n        \n        // TODO HERE: What if Wf < Wh and Sf > Sh => RSRf < RSRh => f can not get full speed due to RSRf\n        if(max_chan_H != -1 && max_chan_CS == -1) {\n//                        vlog(LOG_INFO, \"Head change H\");\n            //shm_conn_info->max_chan = max_chan_H;\n            new_max_chan = max_chan_H;\n            fixed = 1;\n            shm_conn_info->last_switch_time = info.current_time;\n            shm_conn_info->last_switch_time.tv_sec += immune_sec;\n        } else if (max_chan_H == -1 && max_chan_CS != -1) {\n            vlog(LOG_INFO, \"Head change CS\");\n            //shm_conn_info->max_chan = max_chan_CS;\n            new_max_chan = max_chan_CS;\n            fixed = 1;\n            shm_conn_info->last_switch_time = info.current_time;\n            shm_conn_info->last_switch_time.tv_sec += immune_sec;\n        } else if (max_chan_H != -1 && max_chan_CS != -1) {\n            if(max_chan_H != max_chan_CS) {\n                vlog(LOG_INFO, \"Head change: CS/CH don't agree with Si/Sh: using latter\");\n            }\n            //shm_conn_info->max_chan = max_chan_H;\n            new_max_chan = max_chan_H;\n            fixed = 1;\n            shm_conn_info->last_switch_time = info.current_time;\n            shm_conn_info->last_switch_time.tv_sec += immune_sec;\n        } else { // means max_chan = -1; find first alive chan\n            // Two possibilities here: 1. we detected correct channel 2. there is only one channel alive\n            // 3. it may come that chan is excluded and only one chan is there\n            int alive_cnt = 0;\n            int alive_chan = -1;\n            for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (i != exclude)) { // excluded = dead\n                    alive_chan = i;\n                    alive_cnt++;\n                }\n            }\n            if(alive_cnt == 1) {\n                vlog(LOG_INFO, \"Head change - first alive (default): %s(%d), excluded: %d ACS2=%d,PCS2=%d (idle? %d)\",\n                        shm_conn_info->stats[alive_chan].name, alive_chan, exclude, shm_conn_info->stats[alive_chan].max_ACS2,\n                        shm_conn_info->stats[alive_chan].max_PCS2, shm_conn_info->idle);\n                shm_conn_info->max_chan = alive_chan; // change immedialtey\n                shm_conn_info->max_chan_new = alive_chan;\n                new_max_chan = alive_chan;\n            }\n            if(alive_cnt == 0) { // no chan is alive, do without excluded\n                int alive_cnt = 0;\n                int alive_chan = -1;\n                for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                    if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead)) {\n                        alive_chan = i;\n                        alive_cnt++;\n                    }\n                }\n                if(alive_cnt == 1) {\n                    vlog(LOG_INFO, \"Head no change - first and only channel dead: %d, excluded: %d\", alive_chan, exclude);\n                    shm_conn_info->max_chan = alive_chan;\n                    shm_conn_info->max_chan_new = alive_chan;\n                    new_max_chan = alive_chan;\n                } else {\n                    vlog(LOG_ERR, \"WARNING! No chan is alive; no head (undefined): %d\", shm_conn_info->max_chan);\n                }\n            }\n            if(alive_cnt > 1) {\n                // all is OK\n                vlog(LOG_INFO, \"Head detect - current max chan is correct: max_chan=%d, exclude=%d\", shm_conn_info->max_chan, exclude);\n            }\n        }\n    }\n    if(new_max_chan == -1) {\n        //vlog(LOG_INFO, \"Head detect - no new head max_chan=%d, exclude=%d\", shm_conn_info->max_chan, exclude);\n        shm_conn_info->head_detected_ts = info.current_time;\n        shm_conn_info->max_chan_new = shm_conn_info->max_chan;\n        return fixed;\n    }\n    if(new_max_chan != shm_conn_info->max_chan_new) {\n        shm_conn_info->head_detected_ts = info.current_time;\n        shm_conn_info->max_chan_new = new_max_chan;\n        // TODO HERE: for AG_MODE use different hsqs calc! see #731\n        int hsqs = shm_conn_info->stats[shm_conn_info->max_chan].sqe_mean - shm_conn_info->stats[shm_conn_info->max_chan_new].sqe_mean;\n        if(hsqs <= 0) htime = 0;\n        else htime = transition_period_time(hsqs);\n        if(htime < HEAD_HYSTERESIS_MIN_MS) shm_conn_info->head_change_htime = HEAD_HYSTERESIS_MIN_MS; // ms? // TODO: variable constant!\n        ms2tv(&shm_conn_info->head_change_htime_tv, shm_conn_info->head_change_htime);\n        vlog(LOG_INFO, \"Head detect - New head wait start max_chan=%d, exclude=%d TIME=%d ms\", shm_conn_info->max_chan, exclude, shm_conn_info->head_change_htime);\n    } else {\n        vlog(LOG_INFO, \"Head detect - New head is not new - NO WAIT max_chan=%d, exclude=%d\", shm_conn_info->max_chan, exclude);\n    }\n    \n    timersub(&info.current_time, &shm_conn_info->head_detected_ts, &tv_tmp);\n    //if(timercmp(&tv_tmp, &((struct timeval) HEAD_REDETECT_HYSTERESIS_TV), >=)) {\n    if(timercmp(&tv_tmp, &shm_conn_info->head_change_htime_tv, >=)) {\n        vlog(LOG_INFO, \"Head detect - wait timer triggered max_chan=%d, exclude=%d\", shm_conn_info->max_chan, exclude);\n        shm_conn_info->max_chan = shm_conn_info->max_chan_new;\n        shm_conn_info->head_detected_ts = info.current_time;\n    }\n    // now re-calculate lossing for new head\n    timersub(&(info.current_time), &(shm_conn_info->stats[max_chan].real_loss_time), &tv_tmp);\n    if(timercmp(&tv_tmp, &((struct timeval) {DROPPING_LOSSING_DETECT_SECONDS, 0}), >=)) {\n        // noop\n    } else {\n        shm_conn_info->head_lossing = 1;\n        shm_conn_info->idle = 0;\n    }    \n    return fixed;\n}\n\nint hsnum2pnum(int hsnum) {\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if(hsnum == shm_conn_info->stats[i].hsnum) {\n            return i;\n        }\n    }\n    if(hsnum == 65535) { // it is okay to have this value - means we ignore\n        return -1;\n    }\n    vlog(LOG_ERR, \"ASSERT FAILED: hsnum not found: %d\", hsnum);\n    return -1;\n}\n\nuint32_t name2hsnum(char *name) {\n    int i = 0;\n    unsigned char ch = name[0];\n    uint32_t sum = 0;\n    while(ch != 0) {\n        ch = name[i];\n        sum += ch;\n        i++;\n    }\n    return sum % 31;\n}\n\nuint32_t ag_mask2hsag_mask(uint32_t ag_mask) {\n    uint32_t hsag_mask = 0;\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if(ag_mask & (1 << i)) {\n            hsag_mask |= (1 << shm_conn_info->stats[i].hsnum); // set bin mask to 1\n        }\n    }\n    return hsag_mask;\n}\n\nuint32_t hsag_mask2ag_mask(uint32_t hsag_mask) {\n    uint32_t ag_mask = 0;\n    int hs;\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if(hsag_mask & (1 << i)) {\n            hs = hsnum2pnum(i);\n            if(hs > -1) {\n                ag_mask |= (1 << hs); // set bin mask to 1\n            }\n        }\n    }\n    return ag_mask;\n}\n/* M = Wmax, W = desired Wcubic */\ndouble t_from_W (double W, double M, double B, double C) {\n    // Math form: t = ((B M)/C)^(1/3)+(C^2 W-C^2 M)^(1/3)/C\n    //vlog(LOG_INFO, \"t_from_W = %d\", (int)(cbrt(B * M / C) + cbrt( (W - M) / C )));\n    return cbrt(B * M / C) + cbrt( (W - M) / C );\n}\n\nint get_t_loss(struct timeval *loss_tv, int tmax) {\n    struct timeval t_tv;\n    timersub(&(info.current_time), loss_tv, &t_tv);\n    int t = t_tv.tv_sec * 1000 + t_tv.tv_usec/1000;\n    t = t / CUBIC_T_DIV;\n    t = t > tmax ? tmax : t; // 400s limit\n    return t;\n}\n\nint cubic_recalculate(int t, int cubic_max, double beta, double c) {\n    double K = cbrt((((double) cubic_max) * beta) / c);\n    double tp = ((double) (t)) - K;\n    return (uint32_t) (c * tp*tp*tp + cubic_max); // TODO: calculate in integers!\n}\n\nint set_W_cubic_unrecoverable(int t) {\n    shm_conn_info->stats[info.process_num].W_cubic_u = cubic_recalculate(t, info.W_u_max, info.Bu, info.Cu);\n}\n\n// t in ms\nint set_W_unsync(int t) {\n    info.send_q_limit_cubic = cubic_recalculate(t, info.send_q_limit_cubic_max, info.B, info.C);\n    shm_conn_info->stats[info.process_num].W_cubic = info.send_q_limit_cubic;\n    //vlog(LOG_INFO, \"set W t=%d, W=%d, Wmax=%d\", t, info.send_q_limit_cubic, info.send_q_limit_cubic_max);\n    return 1;\n}\n\nint set_W_to(int send_q, int slowness, struct timeval *loss_time) {\n    *loss_time = info.current_time;\n    //vlog(LOG_INFO, \"set W to, sq=%d\", send_q);\n    info.send_q_limit_cubic_max = send_q;\n    set_W_unsync(0);\n}\n\nint set_Wu_to(int send_q) {\n    info.u_loss_tv = info.current_time;\n    info.W_u_max = send_q;\n    info.cubic_t_max_u = t_from_W(RSR_TOP, info.W_u_max, info.Bu, info.Cu); // TODO: place it everywhere whenever W_u_max changes??\n    shm_conn_info->stats[info.process_num].W_cubic_u = cubic_recalculate(0, info.W_u_max, info.Bu, info.Cu);\n}\n\nint set_IDLE() {\n    uint32_t chan_mask = shm_conn_info->channels_mask;\n    struct timeval tv_tmp_tmp_tmp;\n   \n    sem_wait(&(shm_conn_info->stats_sem));\n    timersub(&info.current_time, &shm_conn_info->last_switch_time, &tv_tmp_tmp_tmp);\n    int idle = 1;\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead)) { // hope this works..\n            if( (shm_conn_info->stats[i].sqe_mean > SEND_Q_EFF_WORK) || (shm_conn_info->stats[i].ACK_speed > ACS_NOT_IDLE) ) {\n                idle = 0;\n            }\n        }\n    }\n\n    if(!idle) {\n        shm_conn_info->idle = 0; \n    } else {\n        shm_conn_info->idle = 1;\n        shm_conn_info->slow_start = 0; // Second slow_start exit here: at IDLE - just in case. No specific purpose.\n    }\n    \n    if(shm_conn_info->idle) {\n        shm_conn_info->stats[info.process_num].l_pbl_tmp = INT32_MAX; // when idling, PBL is unknown!\n        shm_conn_info->stats[info.process_num].l_pbl_tmp_unrec = INT32_MAX; // when idling, PBL is unknown!\n        shm_conn_info->stats[info.process_num].loss_send_q = LOSS_SEND_Q_UNKNOWN;\n    }\n    \n    sem_post(&(shm_conn_info->stats_sem));\n    return 0;\n}\n\nint plp_avg_pbl(int pnum) {\n    if(shm_conn_info->stats[pnum].l_pbl_tmp > shm_conn_info->stats[pnum].l_pbl_recv) {\n        shm_conn_info->stats[pnum].l_pbl = shm_conn_info->stats[pnum].l_pbl_tmp;\n        return shm_conn_info->stats[pnum].l_pbl_tmp;\n    } else {\n        shm_conn_info->stats[pnum].l_pbl = shm_conn_info->stats[pnum].l_pbl_recv;\n        return shm_conn_info->stats[pnum].l_pbl_recv;\n    }\n}\n\nint plp_avg_pbl_unrecoverable(int pnum) {\n    if(shm_conn_info->stats[pnum].l_pbl_tmp_unrec > shm_conn_info->stats[pnum].l_pbl_unrec_avg) {\n        if(shm_conn_info->stats[pnum].l_pbl_unrec_avg < INT32_MAX / PBL_SMOOTH_NUMERATOR) {\n            return PBL_SMOOTH_NUMERATOR * shm_conn_info->stats[pnum].l_pbl_unrec_avg / PBL_SMOOTH_DENOMINATOR + shm_conn_info->stats[pnum].l_pbl_tmp_unrec / PBL_SMOOTH_DENOMINATOR;\n        } else {\n            return shm_conn_info->stats[pnum].l_pbl_unrec_avg;\n        }\n    } else {\n        return shm_conn_info->stats[pnum].l_pbl_unrec_avg;\n    }\n}\n\nint fill_path_descs_unsync(struct mini_path_desc *path_descs, uint32_t chan_mask) {\n    int p=0;\n    memset((void *)path_descs, 0, sizeof(path_descs));\n    \n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if ((chan_mask & (1 << i))\n            && (!shm_conn_info->stats[i].channel_dead)) {\n            path_descs[p].process_num = i;\n            path_descs[p].rtt = shm_conn_info->stats[i].srtt2_100/100;\n            path_descs[p].packets_between_loss = shm_conn_info->stats[i].l_pbl;\n            p++;\n        }\n    }\n    return p;\n}\n\nint compare_descs_pbl (struct mini_path_desc *a, struct mini_path_desc *b) {\n     int temp = b->packets_between_loss - a->packets_between_loss; // b-a = descending\n     if (temp > 0)\n          return 1;\n     else if (temp < 0)\n          return -1;\n     else\n          return 0;\n}\n\nint calc_xhi(struct mini_path_desc *path_descs, int count) {\n    int xhi = 0;\n    double rtt,Ps,Ps_u=0,Ps_d = 0,spd;\n    //int max_rtt = -1;\n    int min_rtt = INT32_MAX;\n    int sum_rtt = 0;\n    if(count == 0) return 0;\n    for (int i=0; i< count; i++ ) {\n        if(shm_conn_info->stats[path_descs[i].process_num].brl_ag_enabled) {\n            spd = (double) shm_conn_info->stats[path_descs[i].process_num].ACK_speed/info.eff_len;\n            Ps_u += spd / (double)path_descs[i].packets_between_loss;\n            Ps_d += spd;\n            sum_rtt += path_descs[i].rtt;\n            //if(path_descs[i].rtt > max_rtt) {\n            //    max_rtt = path_descs[i].rtt;\n            //}\n            if(path_descs[i].rtt && (path_descs[i].rtt < min_rtt)) {\n                min_rtt = path_descs[i].rtt;\n            }\n        }\n    }\n\n    Ps = Ps_u / Ps_d;\n    //rtt = (double) (sum_rtt / count);\n    rtt = (double) min_rtt;\n    rtt /= 1000; // ms -> s\n\n    double maxwin = 1.17 * pow( rtt/Ps, 3.0/4.0 );\n#define TCP_MINWIN 49.0\n    if(maxwin < TCP_MINWIN) maxwin = TCP_MINWIN; // protect us from dropping window too much on very-high-speed links (see office wi-fi)\n    // TODO: this is uninvestigated area: cubic seems to behave differently on lower-cwnd areas and lower RTTs (hystart?)\n    xhi = (int) round( maxwin / rtt );\n\n    return xhi;\n}\n\ndouble xhi_function(int rtt_ms, int pbl) {\n    double rtt = rtt_ms;\n    rtt /= 1000.0;\n    double plp = pbl;\n    plp = 1.0 / plp;\n    \n    double maxwin = 1.17 * pow( rtt / plp, 3.0/4.0 );\n    int xhi = (int) round( maxwin / rtt );\n    return xhi * info.eff_len;\n}\n\nint print_xhi_data(struct mini_path_desc *path_descs, int count) {\n    for (int i=0; i< count; i++ ) {\n        vlog(LOG_INFO, \"XHI: pnum=%d rtt=%d, pbl=%d, ACS=%d, ENB=%d\", path_descs[i].process_num, \n                path_descs[i].rtt, path_descs[i].packets_between_loss, shm_conn_info->stats[path_descs[i].process_num].ACK_speed/info.eff_len, shm_conn_info->stats[path_descs[i].process_num].brl_ag_enabled);\n    }\n}\n\nint set_xhi_brl_flags_unsync() {\n    uint32_t chan_mask = shm_conn_info->channels_mask;\n    struct mini_path_desc path_descs[MAX_TCP_PHYSICAL_CHANNELS];\n    int count = fill_path_descs_unsync(path_descs, chan_mask);\n    int xhi;\n    // TODO; what if highest speed chan != lowest p chan?\n    // maybe sort by speed instead?\n    qsort(path_descs, count, sizeof(struct mini_path_desc), compare_descs_pbl);\n    // 1. find worst rtt from AG chans\n    // 1.1 calculate sum speed of ALL alive chans\n    int sum_speed = 0;\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if (       (chan_mask & (1 << i)) \n                && (!shm_conn_info->stats[i].channel_dead)) {\n            sum_speed += shm_conn_info->stats[i].ACK_speed / info.eff_len;\n        }\n    }\n\n    // 2. now calc xhi and Ps and set flags per chans\n    // 2.1 first, enable one channel\n    shm_conn_info->stats[path_descs[0].process_num].brl_ag_enabled = 1;\n    print_xhi_data(path_descs, count);\n    xhi = calc_xhi(path_descs, count);\n    vlog(LOG_INFO, \"XHI: %d, TOTspeed: %d\", xhi, sum_speed);\n\n    // 2.2 try to add each chan one-by-one and calculate total xhi\n    for(int j=1; j<count; j++) {\n        shm_conn_info->stats[path_descs[j].process_num].brl_ag_enabled = 1;\n        print_xhi_data(path_descs, count);\n        xhi = calc_xhi(path_descs, count);\n        vlog(LOG_INFO, \"XHI: %d, TOTspeed: %d\", xhi, sum_speed);\n        if(xhi < sum_speed) { // TODO: really sum_speed ? or maybe sum of the above? or just max speed chan?\n            shm_conn_info->stats[path_descs[j].process_num].brl_ag_enabled = 0;\n            break;\n        }\n    }\n    return xhi;\n}\n\nint lossed_count() {\n    int cnt = 0;\n    int idx_prev = info.lossed_complete_received;\n    int idx = idx_prev;\n    uint32_t last_sqn_lost = 0;\n    unsigned int old_lsn = info.lossed_loop_data[idx].local_seq_num;\n    int pkt_shift = 1;\n    while(idx != info.lossed_last_received) {\n        idx++;\n        if(idx >= LOSSED_BACKLOG_SIZE) idx = 0;\n        if((info.lossed_loop_data[info.lossed_complete_received].local_seq_num + pkt_shift) == info.lossed_loop_data[idx].local_seq_num) {\n            // ok\n        } else {\n            cnt++;\n            last_sqn_lost = info.lossed_loop_data[info.lossed_complete_received].local_seq_num + pkt_shift;\n            if(cnt == 1) {\n                info.lossed_local_seq_num_lost_start = last_sqn_lost;\n            }\n        }\n        idx_prev = idx;\n        pkt_shift++;\n    }\n    // WARNING: TODO: replacing normal loss-only counter by full range of loss including non-lost here\n    //return cnt;\n    return last_sqn_lost - info.lossed_local_seq_num_lost_start + 1;\n}\n\nint lossed_latency_drop(unsigned int *last_received_seq) {\n    // finish waiting for packets by latency; should be called by FCI process\n    if(!lossed_count()) {\n        vlog(LOG_ERR, \"ASSERT FAILED: lossed_latency_drop called with no loss!\");\n    }\n    vlog(LOG_INFO, \"Registering loss +%d by LATENCY lsn: %d; last lsn: %d, sqn: %d, last ok lsn: %d\", lossed_count(), info.lossed_loop_data[info.lossed_last_received].local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, info.lossed_loop_data[info.lossed_last_received].seq_num, info.lossed_loop_data[info.lossed_complete_received].local_seq_num);\n    //lossed_print_debug();\n    int loss = lossed_count();\n    msbl_push_up_loss_unsync();\n    if(loss > UNRECOVERABLE_LOSS) {\n        vlog(LOG_INFO, \"Detected unrecoverable loss of %d packets\", loss);\n        shm_conn_info->seq_num_unrecoverable_loss = shm_conn_info->write_buf[1].last_received_seq[info.process_num];\n    }\n    info.lossed_complete_received = info.lossed_last_received;\n    *last_received_seq = info.lossed_loop_data[info.lossed_last_received].local_seq_num;\n    return loss;\n}\n\nint is_loss() {\n    if(info.lossed_last_received != info.lossed_complete_received) {\n        return 1;\n    }\n    return 0;\n}\n\nint lossed_consume(unsigned int local_seq_num, unsigned int seq_num, unsigned int *last_received_seq, unsigned int *last_local_received_seq) {\n    // 1. try to fill in the array with lsn\n    // 1.1 shift the cursors if all OK\n    // 2. detect loss events by setting flags for FCI\n    // 3. set up loss cutoff for tflush\n    // 4. upon loss, shift the cursor\n   \n    // TODO: local seq add at FCI receive\n    // TODO: rtt and send_q calculations\n    \n    // TODO: may be optimized by not doing excessive *last_local_received_seq = local_seq_num\n   \n    // local_seq_num is init at 1 so it is okay to start right-away\n    int s_shift = local_seq_num - info.lossed_loop_data[info.lossed_last_received].local_seq_num;\n    int new_idx = info.lossed_last_received + s_shift;\n    \n    if(new_idx >= LOSSED_BACKLOG_SIZE) {\n        new_idx = new_idx - LOSSED_BACKLOG_SIZE;\n    }\n    \n/*    \n    if(new_idx >= LOSSED_BACKLOG_SIZE) {\n        vlog(LOG_INFO, \"WARNING lossed_consume protecting from OVERFLOW new_idx is %d, lsn: %d; last lsn: %d, sqn: %d\", new_idx, local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n        new_idx = 0;\n    }\n*/  \n\n    if(new_idx < 0) {\n        new_idx = LOSSED_BACKLOG_SIZE + new_idx;\n    }\n    \n/*    \n    if(new_idx < 0) {\n        vlog(LOG_INFO, \"WARNING lossed_consume protecting from OVERFLOW #2 new_idx is %d, lsn: %d; last lsn: %d, sqn: %d\", new_idx, local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n        new_idx = 0;\n    }\n    \n    if(new_idx >= LOSSED_BACKLOG_SIZE) {\n        // TODO: remove this - should never fire!\n        vlog(LOG_INFO, \"WARNING lossed_consume protecting from OVERFLOW #3 new_idx is %d, lsn: %d; last lsn: %d, sqn: %d\", new_idx, local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n        new_idx = 0;\n    }\n*/\n\n    if(new_idx >= LOSSED_BACKLOG_SIZE || new_idx < 0) {\n        //lossed_print_debug();\n        vlog(LOG_ERR, \"Warning! Reorder buffer overflow LOSSED_BACKLOG_SIZE=%d; lsn: %d; last lsn: %d, sqn: %d\", LOSSED_BACKLOG_SIZE, local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n        need_send_loss_FCI_flag = LOSSED_BACKLOG_SIZE;\n        vlog(LOG_INFO, \"Detected unrecoverable loss of at least %d packets\", LOSSED_BACKLOG_SIZE);\n        shm_conn_info->seq_num_unrecoverable_loss = seq_num;\n        msbl_push_up_loss_unsync();\n        info.lossed_complete_received = 0;\n        info.lossed_last_received = 0;\n        info.lossed_loop_data[0].local_seq_num = local_seq_num;\n        info.lossed_loop_data[0].seq_num = seq_num;\n        *last_received_seq = seq_num;\n        *last_local_received_seq = local_seq_num;\n        return 0;\n    }\n    \n    if(s_shift >= LOSSED_BACKLOG_SIZE) {\n        //lossed_print_debug();\n        vlog(LOG_ERR, \"Warning! Reordering (or loss) is larger than LOSSED_BACKLOG_SIZE=%d; lsn: %d; last lsn: %d, sqn: %d\", LOSSED_BACKLOG_SIZE, local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n        need_send_loss_FCI_flag = LOSSED_BACKLOG_SIZE;\n        vlog(LOG_INFO, \"Detected unrecoverable loss of at least %d packets\", LOSSED_BACKLOG_SIZE);\n        shm_conn_info->seq_num_unrecoverable_loss = seq_num;\n        msbl_push_up_loss_unsync();\n        info.lossed_complete_received = new_idx;\n        info.lossed_last_received = new_idx;\n        info.lossed_loop_data[new_idx].local_seq_num = local_seq_num;\n        info.lossed_loop_data[new_idx].seq_num = seq_num;\n        *last_received_seq = seq_num;\n        *last_local_received_seq = local_seq_num;\n        return 0;\n    }\n    \n    if( (s_shift == 1) && (info.lossed_complete_received == info.lossed_last_received)) {\n        //vlog(LOG_INFO, \"Lossed: normally consuming packet lsn: %d; last lsn: %d, sqn: %d, new_idx: %d\", local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num, new_idx);\n        info.lossed_last_received = new_idx;\n        info.lossed_complete_received = new_idx;\n        info.lossed_loop_data[new_idx].local_seq_num = local_seq_num;\n        info.lossed_loop_data[new_idx].seq_num = seq_num;\n        *last_received_seq = seq_num;\n        *last_local_received_seq = local_seq_num;\n        //lossed_print_debug();\n        return 0;\n    }\n    \n    if(local_seq_num < info.lossed_loop_data[info.lossed_complete_received].local_seq_num) {\n        //lossed_print_debug();\n        // now check if it is dup or LATE\n        if(info.lossed_loop_data[new_idx].local_seq_num == local_seq_num) {\n            vlog(LOG_INFO, \"DUP lsn: %d; last lsn: %d, sqn: %d\", local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n        } else {\n            vlog(LOG_INFO, \"LATE? max_reorder is %d, lsn: %d; last lsn: %d, sqn: %d\", (info.lossed_last_received-new_idx), local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n            need_send_loss_FCI_flag = -1; // inform that we are experiencing reorder\n            if(shm_conn_info->stats[info.process_num].pbl_lossed_saved != 0) {\n                vlog(LOG_INFO, \"Restoring local pbl counters pbl_lossed %d, pbl_lossed_cnt %d\", shm_conn_info->stats[info.process_num].pbl_lossed_saved, shm_conn_info->stats[info.process_num].pbl_lossed_cnt_saved);\n                shm_conn_info->stats[info.process_num].pbl_lossed = shm_conn_info->stats[info.process_num].pbl_lossed_saved;\n                shm_conn_info->stats[info.process_num].pbl_lossed_cnt = shm_conn_info->stats[info.process_num].pbl_lossed_cnt_saved;\n                \n                shm_conn_info->stats[info.process_num].pbl_lossed_saved = 0;\n            }\n        }\n        *last_received_seq = info.lossed_loop_data[info.lossed_complete_received].seq_num;\n        *last_local_received_seq = info.lossed_loop_data[info.lossed_complete_received].local_seq_num;\n        return -1;\n    }\n   \n    int reordering = local_seq_num - info.lossed_loop_data[info.lossed_complete_received].local_seq_num;\n    if(reordering > MAX_REORDER_PERPATH) {\n        *last_received_seq = seq_num;\n        *last_local_received_seq = local_seq_num;\n        info.lossed_loop_data[new_idx].local_seq_num = local_seq_num;\n        info.lossed_loop_data[new_idx].seq_num = seq_num;\n        info.lossed_last_received = new_idx;\n        int loss_calc = lossed_count();\n        vlog(LOG_INFO, \"Detected loss +%d by REORDER lsn: %d; last lsn: %d, sqn: %d, lsq before loss %d\", loss_calc, local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num, info.lossed_loop_data[info.lossed_complete_received].local_seq_num);\n        if(loss_calc > UNRECOVERABLE_LOSS) {\n            vlog(LOG_INFO, \"Detected unrecoverable loss of %d packets\", loss_calc);\n            shm_conn_info->seq_num_unrecoverable_loss = seq_num;\n        }\n        info.lossed_complete_received = new_idx;\n        // now push up MSBL\n        msbl_push_up_loss_unsync();\n        need_send_loss_FCI_flag = loss_calc;\n        //lossed_print_debug();\n        return loss_calc;\n    }\n    \n    // now we have finished error handling - now account for pure data receipt\n    \n    if(s_shift > 1) {\n        //lossed_print_debug();\n        vlog(LOG_INFO, \"loss +%d lsn: %d; last lsn: %d, sqn: %d\", (s_shift - 1), local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n        info.lossed_last_received = new_idx;\n        info.lossed_loop_data[new_idx].local_seq_num = local_seq_num;\n        info.lossed_loop_data[new_idx].seq_num = seq_num;\n        *last_received_seq = info.lossed_loop_data[info.lossed_complete_received].seq_num;\n        *last_local_received_seq = info.lossed_loop_data[info.lossed_complete_received].local_seq_num;\n        return s_shift - 1;\n    }\n    \n    if(s_shift == 1) {\n        // if s_shift == 1 && (info.lossed_complete_received != info.lossed_last_received)\n        vlog(LOG_INFO, \"Append packet +REORDER lsn: %d; last lsn: %d, sqn: %d\", local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n        info.lossed_last_received = new_idx;\n        info.lossed_loop_data[new_idx].local_seq_num = local_seq_num;\n        info.lossed_loop_data[new_idx].seq_num = seq_num;\n        *last_received_seq = info.lossed_loop_data[info.lossed_complete_received].seq_num;\n        *last_local_received_seq = info.lossed_loop_data[info.lossed_complete_received].local_seq_num;\n        //lossed_print_debug();\n        return -3;\n    }\n    \n    // again, detect DUPs\n    if(local_seq_num == info.lossed_loop_data[new_idx].local_seq_num) {\n        //lossed_print_debug();\n        vlog(LOG_INFO, \"DUP +REORDER lsn: %d; last lsn: %d, sqn: %d\", local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n        *last_received_seq = info.lossed_loop_data[info.lossed_complete_received].seq_num;\n        *last_local_received_seq = info.lossed_loop_data[info.lossed_complete_received].local_seq_num;\n        return -2;\n    }\n    \n    // now try to re-assemble\n    // [ 0 1[2]  4 5 6 7 8 9 ]\n    //         3\n    \n    // add data to its position\n    //lossed_print_debug();\n    vlog(LOG_INFO, \"reorder -1 lsn: %d; last lsn: %d, sqn: %d\", local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n    info.lossed_loop_data[new_idx].local_seq_num = local_seq_num;\n    info.lossed_loop_data[new_idx].seq_num = seq_num;\n    \n    int next_missed;\n    \n    while(1) {\n        next_missed = info.lossed_complete_received + 1;\n        if(next_missed >= LOSSED_BACKLOG_SIZE) next_missed = next_missed - LOSSED_BACKLOG_SIZE;\n        //TODO here: protect from double overflow\n        if(next_missed >= LOSSED_BACKLOG_SIZE) { \n            next_missed = 0;\n            vlog(LOG_INFO, \"WARNING lossed_consume protecting from OVERFLOW next_missed is %d, lsn: %d; last lsn: %d, sqn: %d\", next_missed, local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n        }\n        \n        if(info.lossed_loop_data[next_missed].local_seq_num == info.lossed_loop_data[info.lossed_complete_received].local_seq_num + 1) {\n            info.lossed_complete_received = next_missed;\n            if(info.lossed_loop_data[next_missed].seq_num != 0) { // 0 is set by FCI seq_num (0)\n                *last_received_seq = info.lossed_loop_data[next_missed].seq_num;\n                *last_local_received_seq = info.lossed_loop_data[next_missed].local_seq_num;\n            } else {\n                vlog(LOG_INFO, \"Warning! Cannot set last_received_seq as it is 0! lsn: %d; last lsn: %d, sqn: %d\", local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n                *last_local_received_seq = info.lossed_loop_data[next_missed].local_seq_num;\n            }\n        } else {\n            return info.lossed_complete_received - info.lossed_complete_received - 1;\n        }\n        \n        if(info.lossed_complete_received == info.lossed_last_received) {\n            //lossed_print_debug();\n            vlog(LOG_INFO, \"reorder reassembled. lsn: %d; last lsn: %d, sqn: %d\", local_seq_num, info.lossed_loop_data[info.lossed_last_received].local_seq_num, seq_num);\n            return 0;\n        }\n    }\n    return -1;\n}\n\nint get_rttlag(uint32_t ag_mask) {\n    uint32_t chan_mask = shm_conn_info->channels_mask;\n    if(NumberOfSetBits(ag_mask)< 2) {\n        return 0;\n    } else {\n        int min_rtt = INT32_MAX;\n        int max_rtt = 0;\n        int chamt = 0;\n        for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n            if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (ag_mask & (1 << i))) { \n                if(min_rtt > shm_conn_info->stats[i].exact_rtt) {\n                    min_rtt = shm_conn_info->stats[i].exact_rtt;\n                }\n\n                if(max_rtt < shm_conn_info->stats[i].exact_rtt) {\n                    max_rtt = shm_conn_info->stats[i].exact_rtt;\n                }\n                chamt++;\n            }\n        }\n        if(chamt > 1) {\n            // now check that max_rtt_lag is adequate\n            if(max_rtt > (min_rtt * RTT_THRESHOLD_MULTIPLIER)) {\n                vlog(LOG_INFO, \"WARNING! max_rtt_lag is %d > min_rtt * 7 %d\", max_rtt, min_rtt);\n                max_rtt = min_rtt * RTT_THRESHOLD_MULTIPLIER;\n            }\n            return max_rtt; // correct is max_rtt only // assume whole RTT is bufferbloat so PT >> rtt_phys\n        } else {\n            return 0; // correct is max_rtt only\n        }\n    }\n}\n\nint get_rto_usec() {\n    int sum_rtt = (shm_conn_info->rttvar_worst) * 1000;\n    if(sum_rtt > info.max_latency_drop.tv_usec) {\n        return sum_rtt;\n    }\n    return info.max_latency_drop.tv_usec;\n}\n\n// compute controlled - \"lagger\" based buf len\nint get_lbuf_len() {\n    uint32_t chan_mask = shm_conn_info->channels_mask;\n    int tail_idx = shm_conn_info->write_buf[1].frames.rel_tail;\n    if(tail_idx == -1) {\n        return 0;\n    }\n    int pktdiff = shm_conn_info->frames_buf[tail_idx].seq_num - shm_conn_info->write_buf[1].last_written_seq;\n    return pktdiff; // always return ibl\n    if(NumberOfSetBits(shm_conn_info->ag_mask_recv)< 2) {\n       int lbl =  shm_conn_info->write_buf[1].last_received_seq[shm_conn_info->remote_head_pnum] - shm_conn_info->write_buf[1].last_written_seq; // tcp_cwnd = lbl + gSQ\n        //shm_conn_info->lbuf_len = lbl; // we are writing versus HEAD?\n        return lbl;\n    }\n    return info.least_rx_seq[1] - shm_conn_info->write_buf[1].last_written_seq; // this can result in negative values when AG-on switch happens\n}\nint set_rttlag() { // TODO: rewrite using get_rttlag\n    uint32_t chan_mask = shm_conn_info->channels_mask;\n    int min_rtt = INT32_MAX;\n    int min_rtt_chan = shm_conn_info->max_chan;\n    int max_rtt = 0;\n    int max_rtt_chan = shm_conn_info->max_chan;\n    int chamt = 0;\n    \n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        // if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (shm_conn_info->ag_mask_recv & (1 << i))) { // hope this works..\n        if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (shm_conn_info->ag_mask & (1 << i))) { // hope this works..\n            if(min_rtt > shm_conn_info->stats[i].exact_rtt) {\n                min_rtt = shm_conn_info->stats[i].exact_rtt;\n                min_rtt_chan = i;\n            }\n\n            if(max_rtt < shm_conn_info->stats[i].exact_rtt) {\n                max_rtt = shm_conn_info->stats[i].exact_rtt;\n                max_rtt_chan = i;\n            }\n            chamt++;\n        }\n    }\n    \n    if(chamt > 1) {\n        shm_conn_info->max_rtt_pnum_checkonly = max_rtt_chan;\n        shm_conn_info->min_rtt_pnum_checkonly = min_rtt_chan;\n        // now check that max_rtt_lag is adequate\n        // if(max_rtt > (min_rtt * RTT_THRESHOLD_MULTIPLIER)) {\n        //     vlog(LOG_INFO, \"WARNING! max_rtt_lag is %d > min_rtt * 7 %d\", max_rtt, min_rtt);\n        //     max_rtt = min_rtt * RTT_THRESHOLD_MULTIPLIER;\n        // }\n        // shm_conn_info->max_rtt_lag = max_rtt; // correct is max_rtt only // assume whole RTT is bufferbloat so PT >> rtt_phys\n    } else {\n        // shm_conn_info->max_rtt_lag = 0; // correct is max_rtt only\n        shm_conn_info->max_rtt_pnum_checkonly = -1;\n        shm_conn_info->min_rtt_pnum_checkonly = -1;\n    }\n    \n}\n\nint set_rttlag_total() {  // unused TODO REMOVE\n    uint32_t chan_mask = shm_conn_info->channels_mask;\n    int min_rtt = INT32_MAX;\n    int min_rtt_var = INT32_MAX;\n    int min_rtt_chan = shm_conn_info->max_chan;\n    int max_rtt = 0;\n    int max_rtt_var = 0;\n    int max_rtt_chan = shm_conn_info->max_chan;\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        // TODO HERE: WARNING: here we determine max allowed channels latency difference as MLD*2 milliseconds (see #659)\n        if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && \n                (shm_conn_info->stats[i].exact_rtt - shm_conn_info->stats[shm_conn_info->max_chan].exact_rtt < MAX_LATENCY_DROP_USEC/500)) { // get total possible lag\n            if(min_rtt > shm_conn_info->stats[i].exact_rtt) {\n                min_rtt = shm_conn_info->stats[i].exact_rtt;\n                min_rtt_var = shm_conn_info->stats[i].rttvar;\n                min_rtt_chan = i;\n            }\n\n            if(max_rtt < shm_conn_info->stats[i].exact_rtt) {\n                max_rtt = shm_conn_info->stats[i].exact_rtt;\n                max_rtt_var = shm_conn_info->stats[i].rttvar;\n                max_rtt_chan = i;\n            }\n        }\n    }\n    shm_conn_info->total_min_rtt = min_rtt;\n    shm_conn_info->total_min_rtt_var = min_rtt_var;\n    shm_conn_info->total_max_rtt = max_rtt;\n    shm_conn_info->total_max_rtt_var = max_rtt_var;\n    //vlog(LOG_INFO, \"computed max_rtt: %d, max_rtt_var: %d, min_rtt %d, min_rtt_var: %d\", max_rtt, max_rtt_var, min_rtt, min_rtt_var);\n}\n\nint infer_lost_seq_num(uint32_t *incomplete_seq_buf) {\n    // Search write_buf for lost seq_num\n    int ms_token;\n    int buf_len;\n    uint32_t chan_mask = shm_conn_info->channels_mask;\n    get_write_buf_wait_data(chan_mask, &ms_token);\n    // now that least_rx_seq calculated, see if we have direct loss detected\n    // TODO: speculative loss detection\n    //      speculative loss is less effective here though as waiting for 20+ packets is crucial time\n    int incomplete_seq_len = missing_resend_buffer(1, incomplete_seq_buf, &buf_len, info.least_rx_seq[1]);    \n    if(incomplete_seq_len <= 2) { // TODO: how will this interact with per-local-seq retransmissions?\n        for(int i=0; i<incomplete_seq_len; i++) {\n            vlog(LOG_INFO, \"Fast requesting packet %lu\", incomplete_seq_buf[i]);\n            shm_conn_info->loss_idx++;\n            if (shm_conn_info->loss_idx == LOSS_ARRAY) {\n                shm_conn_info->loss_idx = 0;\n            }\n            shm_conn_info->loss[shm_conn_info->loss_idx].timestamp = info.current_time;\n            shm_conn_info->loss[shm_conn_info->loss_idx].pbl = shm_conn_info->write_sequential;\n            shm_conn_info->loss[shm_conn_info->loss_idx].psl = 1;\n            // TODO: who_lost\n            shm_conn_info->loss[shm_conn_info->loss_idx].who_lost = -1;\n            shm_conn_info->loss[shm_conn_info->loss_idx].sqn = incomplete_seq_buf[i];\n        }\n    }\n}\nint lost_buf_exists(uint32_t seq_num) {\n    for(int i=0;i<LOSS_ARRAY;i++) {\n        if((shm_conn_info->loss[i].sqn == seq_num) || (shm_conn_info->loss[i].sqn == (seq_num + 1))) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\n\n\nint get_cwnd() {\n    int max_gsend_q = 0;\n    int max_gsend_q_chan = -1;\n    int min_gsend_q = INT32_MAX;\n    int min_gsend_q_chan = -1;\n    int gsq;\n    int chamt = 0;\n    int full_cwnd;\n    struct timeval tv_tmp;\n    // 1. in case of no AG - the drop is done by head channel\n    // 2. in case of AG - we should take the most lagging chan+LBL\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if ((shm_conn_info->channels_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && ((i == shm_conn_info->max_chan) || (shm_conn_info->ag_mask & (1 << i)))) {\n            timersub(&info.current_time, &shm_conn_info->stats[i].agon_time, &tv_tmp);\n            if(tv2ms(&tv_tmp) <= 2*shm_conn_info->stats[i].exact_rtt) { // switch immunity time\n                // TODO: calculate real time needed for buffer to be recalculated and received\n                continue; // immunity time for recalculate - wait for buffer to pripagate and to return new value\n            }\n            gsq = shm_conn_info->seq_counter[1] - shm_conn_info->stats[i].la_sqn;\n            if(max_gsend_q < gsq) {\n                max_gsend_q = gsq; \n                max_gsend_q_chan = i;\n            }\n            if(min_gsend_q > gsq) {\n                min_gsend_q = gsq; \n                min_gsend_q_chan = i;\n            }\n            chamt++;\n        }\n    }\n    // TODO: possible problem here: the channel may be in AG mode but head will resend all its packets anyway if it is not in AG itself\n    if(shm_conn_info->msbl_recv > 0) {\n        full_cwnd = min_gsend_q + shm_conn_info->msbl_recv;\n    } else {\n        full_cwnd = max_gsend_q;\n    }\n    return full_cwnd;\n}\n\nint get_cwnd2() {\n    return shm_conn_info->seq_counter[1] - shm_conn_info->write_buf[1].remote_lws;\n}\n\nint compute_max_allowed_rtt() {\n    int full_cwnd = get_cwnd();\n    int spd = shm_conn_info->tpps;\n    shm_conn_info->full_cwnd = full_cwnd;\n    if(spd == 0) return 0;\n    int max_frtt = full_cwnd * 1000 / spd; // in ms\n    return max_frtt;\n}\n\nint is_happiness_reached() {\n    double d_rtt = (double)shm_conn_info->stats[shm_conn_info->max_chan].exact_rtt / 1000.0;\n    if(d_rtt == 0) d_rtt = 1.0;\n    double my_mbits = ((double)(shm_conn_info->tpps) * (double)info.eff_len) / 1000000.0 * 8.0;\n    double happy_mbits = 3.87 + 0.031 / d_rtt - 3.93 * d_rtt;\n    return (my_mbits > happy_mbits);\n}\n\nint mawmar_allowed() {\n    if(info.head_channel) return 1;\n    int BL = (int)shm_conn_info->msbl_recv;\n    /*\n    int sql;\n    // count all RSR/cubics?\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (shm_conn_info->ag_mask & (1 << i))) { // hope this works..\n            sql = \n        }\n    }\n    int MAW = (info.rsr > info.send_q_limit_cubic ? info.rsr : info.send_q_limit_cubic);\n    int MAR = () * shm_conn_info->tpps; \n    */\n    // implementing binary MSWMAR here for two channels only:\n    int cwnd = get_cwnd2();\n    // we are not head here...\n    int max_chan = shm_conn_info->max_chan;\n    //int head_limit = (shm_conn_info->stats[max_chan].rsr < shm_conn_info->stats[max_chan].W_cubic ? shm_conn_info->stats[max_chan].rsr : shm_conn_info->stats[max_chan].W_cubic);\n    //int head_limit = shm_conn_info->stats[max_chan].sqe_mean; \n    int my_limit = (info.rsr < info.send_q_limit_cubic ? info.rsr : info.send_q_limit_cubic);\n    //int MAW = (my_limit + head_limit) / info.eff_len;\n    int MAR = (info.exact_rtt - shm_conn_info->stats[max_chan].exact_rtt) * shm_conn_info->tpps / 1000; // our rtt is greater than head's (usually we suppose)\n    if(MAR < 0) MAR = -MAR; // MAR can not influence MAW as the window required to load both networks has nothing to do with jitter smoothing buffer\n    statb.maw = my_limit / info.eff_len;\n    statb.mar = MAR;\n    if(shm_conn_info->stats[info.process_num].ag_flag_local == R_MODE) {\n        //return (MAW + MAR < cwnd) && (MAR < BL);\n        return (my_limit / info.eff_len < BL) && (MAR < BL); // in theory we need to check MAW+MAR - if, after we push msbl to net, we will still be able to compansate for the jitter\n    } else { // AG_MODE\n        return (MAR < BL); // this will automatically fail if we push all the MSBL to network\n    }\n}\n\n\n/*\n.__   _____   .___    .__  .__        __                     ___  ___    \n|  |_/ ____\\__| _/    |  | |__| ____ |  | __ ___________    /  /  \\  \\   \n|  |\\   __\\/ __ |     |  | |  |/    \\|  |/ // __ \\_  __ \\  /  /    \\  \\  \n|  |_|  | / /_/ |     |  |_|  |   |  \\    <\\  ___/|  | \\/ (  (      )  ) \n|____/__| \\____ |_____|____/__|___|  /__|_ \\\\___  >__|     \\  \\    /  /  \n               \\/_____/            \\/     \\/    \\/          \\__\\  /__/   \n*/\n\nint lfd_linker(void)\n{\n#ifdef PROF\n    int pid = getpid();\n    char pbuf[30];\n    sprintf(pbuf, \"/tmp/vtrunkd_%d\", pid);\n    mkdir(pbuf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);\n    chdir(pbuf);\n#endif\n    int tpps=0;\n    memset((void *)&log_tmp, 0, sizeof(log_tmp));\n    #ifdef TIMEWARP\n        timewarp = malloc(TW_MAX); // 10mb time-warp\n        memset(timewarp, 0, TW_MAX);\n        tw_cur = 0;\n        sprintf(timewarp+tw_cur, \"started\\n\");\n        int fdc = open(\"/tmp/TIMEWARP.log\", O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);\n        close(fdc);\n        int send_q_min = 999999999;\n        int send_q_eff_min = 999999999;\n    #endif\n    \n#ifdef SHM_DEBUG\n    if (!info.process_num) {\n        void *aligned_shm = (void *) (((unsigned long) shm_conn_info->void1) & ~(getpagesize() - 1));\n        static const char ar[] = { 0xfe, 0xed, 0xf0, 0x0d, 0xfa, 0xce };\n        int mprotect_ret = mprotect(aligned_shm, getpagesize(), PROT_NONE);\n        if (mprotect_ret != 0) {\n            vlog(LOG_ERR, \"mprotect %s (%d)\", strerror(errno), errno);\n        }\n        vlog(LOG_ERR, \"void1 address %X aligned to page %X\", shm_conn_info->void2, aligned_shm);\n        aligned_shm = (void *) (((unsigned long) shm_conn_info->void2) & ~(getpagesize() - 1));\n        mprotect_ret = mprotect(aligned_shm, getpagesize(), PROT_NONE);\n        if (mprotect_ret != 0) {\n            vlog(LOG_ERR, \"mprotect %s (%d)\", strerror(errno), errno);\n        }\n        vlog(LOG_ERR, \"void2 address %X aligned to page %X\", shm_conn_info->void2, aligned_shm);\n        aligned_shm = (void *) (((unsigned long) shm_conn_info->void3) & ~(getpagesize() - 1));\n        mprotect_ret = mprotect(aligned_shm, getpagesize(), PROT_NONE);\n        if (mprotect_ret != 0) {\n            vlog(LOG_ERR, \"mprotect %s (%d)\", strerror(errno), errno);\n        }\n        vlog(LOG_ERR, \"void3 address %X aligned to page %X\", shm_conn_info->void3, aligned_shm);\n    }\n#endif\n\n    \n    struct timeval MAX_REORDER_LATENCY = { 0, 50000 };\n\n    int sq_control = 1;\n    int service_channel = lfd_host->rmt_fd; //aka channel 0\n    int len, len1, fl;\n    int err=0;\n    struct timeval tv;\n    char *out, *out2 = NULL;\n    char *buf; // in common for info packet\n    uint32_t seq_num;\n\n    int maxfd;\n    int imf;\n    int fprev = -1;\n    int fold = -1;\n    uint32_t incomplete_seq_buf[FRAME_BUF_SIZE];\n    send_q_limit = START_SQL; // was 55000\n    \n    uint16_t tmp_s;\n    uint32_t tmp_l;\n\n    sem_t *resend_buf_sem = &(shm_conn_info->resend_buf_sem);\n    sem_t *write_buf_sem = &(shm_conn_info->write_buf_sem);\n\n    struct timeval send1; // calculate send delay\n    struct timeval send2;\n    struct timeval old_time = {0, 0};\n    struct timeval ping_req_tv[MAX_TCP_LOGICAL_CHANNELS];\n    for(int i=0; i<MAX_TCP_LOGICAL_CHANNELS; i++) {\n        gettimeofday(&ping_req_tv[i], NULL);\n    }\n    long int last_action = 0; // for ping; TODO: too many vars... this even has clone ->\n\n    struct resent_chk sq_rq_buf[RESENT_MEM]; // for check_sent\n    int sq_rq_pos = 0; // for check_sent\n\n    uint16_t flag_var; // packet struct part\n\n    char succ_flag; // return flag\n\n    int dev_my_cnt = 0; // statistic and watchdog\n    \n    // timing\n    long int last_tick = 0; // important ticking\n    struct timeval last_timing = {0, 0};\n    struct timeval timer_resolution = {0, 0};\n    struct timeval max_latency = {0, 0};\n    struct timeval tv_tmp;\n        // now set up timer resolution\n     max_latency.tv_sec = lfd_host->MAX_LATENCY/1000;\n     max_latency.tv_usec = (lfd_host->MAX_LATENCY - max_latency.tv_sec * 1000) * 1000;\n    \n    if( (lfd_host->TICK_SECS * 1000) > lfd_host->MAX_LATENCY) {\n          timer_resolution.tv_sec = max_latency.tv_sec;\n          timer_resolution.tv_usec = max_latency.tv_usec;\n    } else {\n          timer_resolution.tv_sec = lfd_host->TICK_SECS;\n          timer_resolution.tv_usec = 0;\n    }\n\n#ifdef HAVE_SCHED_H\n    int cpu_numbers = sysconf(_SC_NPROCESSORS_ONLN); /* Get numbers of CPUs */\n    if (cpu_numbers != -1) {\n        cpu_set_t cpu_set;\n        CPU_ZERO(&cpu_set);\n        CPU_SET(info.process_num % cpu_numbers, &cpu_set);\n        if (1) {\n            vlog(LOG_INFO, \"Can't set cpu\");\n        } else {\n            vlog(LOG_INFO, \"Set process %i on cpu %i\", info.process_num, info.process_num % cpu_numbers);\n        }\n    } else {\n        vlog(LOG_INFO, \"sysconf(_SC_NPROCESSORS_ONLN) return error\");\n    }\n#endif\n    int sender_pid; // tmp var for resend detect my own pid\n\n    uint32_t last_last_written_seq[MAX_TCP_LOGICAL_CHANNELS]; // for LWS notification TODO: move this to write_buf!\n\n    // ping stats\n    int ping_rcvd = 1; // flag that ping is rcvd; ok to send next\n    long int last_ping=0;\n\n    //int weight = 1; // defined at top!!!???\n\n    // weight processing in delay algo\n    delay_acc = 0; // accumulated send delay\n    delay_cnt = 0; //\n    int mean_delay = 0; // mean_delay = delay_acc/delay_cnt (arithmetic(al) mean)\n\n    // TCP sepconn vars\n    struct sockaddr_in my_addr, cl_addr, localaddr, rmaddr;\n    socklen_t prio_opt=1, laddrlen, rmaddrlen;\n    int prio_s=-1, fd_tmp=-1;\n\n    char ipstr[INET6_ADDRSTRLEN];\n    int chan_num = 0, chan_num_virt = 0;\n    int i, j, fd0;\n    int break_out = 0;\n\n    if( !(buf = lfd_alloc(VTUN_FRAME_SIZE+VTUN_FRAME_OVERHEAD)) ) {\n        vlog(LOG_ERR,\"Can't allocate buffer for the linker\");\n        return 0;\n    }\n    char *save_buf = buf;\n    if( !(out_buf = lfd_alloc(VTUN_FRAME_SIZE+VTUN_FRAME_OVERHEAD)) ) {\n        vlog(LOG_ERR,\"Can't allocate out buffer for the linker\");\n        return 0;\n    }\n    if( !(buf2 = lfd_alloc(VTUN_FRAME_SIZE2)) ) {\n        vlog(LOG_ERR,\"Can't allocate buffer 2 for the linker\");\n        return 0;\n    }\n    \n    struct timer_obj *recv_n_loss_send_timer = create_timer(); // TODO: create_timer may fail, should be fixed\n    struct timeval recv_n_loss_time = { 0, 100000 }; // this time is crucial to detect send_q dops in case of long hold\n    set_timer(recv_n_loss_send_timer, &recv_n_loss_time);\n\n    struct timer_obj *send_q_limit_change_timer = create_timer();\n    struct timeval send_q_limit_change_time = { 0, 500000 };\n    set_timer(send_q_limit_change_timer, &send_q_limit_change_time);\n\n    struct timer_obj *s_q_lim_drop_timer = create_timer();\n    fast_update_timer(s_q_lim_drop_timer, &info.current_time);\n\n    struct timer_obj *packet_speed_timer = create_timer();\n    struct timeval packet_speed_timer_time = { 0, 500000 };\n    set_timer(packet_speed_timer, &packet_speed_timer_time);\n\n    struct timer_obj *head_channel_switch_timer = create_timer();\n    struct timeval head_channel_switch_timer_time = { 0, 0 };\n    set_timer(head_channel_switch_timer, &head_channel_switch_timer_time);\n\n    char *save_out_buf = out_buf;\n    memset(time_lag_info_arr, 0, sizeof(struct time_lag_info) * MAX_TCP_LOGICAL_CHANNELS);\n    memset(last_last_written_seq, 0, sizeof(uint32_t) * MAX_TCP_LOGICAL_CHANNELS);\n    memset((void *)&statb, 0, sizeof(statb));\n    memset(last_sent_packet_num, 0, sizeof(struct last_sent_packet) * MAX_TCP_LOGICAL_CHANNELS);\n    my_max_speed_chan = 0;\n    dirty_seq_num = 0;\n    for (int i = 0; i < MAX_TCP_LOGICAL_CHANNELS; i++) {\n        last_sent_packet_num[i].seq_num = SEQ_START_VAL;\n    }\n    maxfd = (service_channel > info.tun_device ? service_channel : info.tun_device);\n\n    linker_term = 0;\n    srand((unsigned int) time(NULL ));\n\n    if (setsockopt(service_channel, SOL_SOCKET, SO_RCVTIMEO, (char *) &socket_timeout, sizeof(socket_timeout)) < 0) {\n        vlog(LOG_ERR, \"setsockopt failed\");\n        linker_term = TERM_NONFATAL;\n    }\n    if (setsockopt(service_channel, SOL_SOCKET, SO_SNDTIMEO, (char *) &socket_timeout, sizeof(socket_timeout)) < 0) {\n        vlog(LOG_ERR, \"setsockopt failed\");\n        linker_term = TERM_NONFATAL;\n    }\n    sem_wait(&(shm_conn_info->stats_sem));\n    shm_conn_info->stats[info.process_num].rtt_phys_avg = 1;\n    shm_conn_info->latest_la_sqn = 0;\n    strcpy(shm_conn_info->stats[info.process_num].name, lfd_host->host);\n    // set up hash name\n    shm_conn_info->stats[info.process_num].hsnum = name2hsnum(shm_conn_info->stats[info.process_num].name);\n    sem_post(&(shm_conn_info->stats_sem));    \n#ifdef CLIENTONLY\n    info.srv = 0;\n#endif\n    if(info.srv) {\n//        memset(shm_conn_info->void1,4096,1); //test mprotect\n        /** Server accepted all logical channel here and get and send pid */\n        // now read one single byte\n        vlog(LOG_INFO,\"Waiting for client to request channels...\");\n\t\tread_n(service_channel, buf, sizeof(uint16_t)+sizeof(uint16_t));\n        info.channel_amount = ntohs(*((uint16_t *) buf)); // include info channel\n        info.channel_amount = 2; // WARNING! TODO! HARDCODED 2 hardcoded chan_amt\n        if (info.channel_amount > MAX_TCP_LOGICAL_CHANNELS) {\n            vlog(LOG_ERR, \"Client ask for %i channels. Exit \", info.channel_amount);\n            info.channel_amount = MAX_TCP_LOGICAL_CHANNELS;\n            linker_term = TERM_NONFATAL;\n        }\n        if(info.channel_amount < 1) {\n            vlog(LOG_ERR, \"Client ask for %i channels. Exit \", info.channel_amount);\n            info.channel_amount = 1;\n            linker_term = TERM_NONFATAL;\n        }\n        info.channel = calloc(info.channel_amount, sizeof(*(info.channel)));\n        if (info.channel == NULL) {\n            vlog(LOG_ERR, \"Cannot allocate memory for info.channel, process - %i, pid - %i\",info.process_num, info.pid);\n            return -1;\n        }\n        chan_info = (struct channel_info *) calloc(info.channel_amount, sizeof(struct channel_info));\n        if (chan_info == NULL ) {\n            vlog(LOG_ERR, \"Can't allocate array for struct chan_info for the linker\");\n            goto finish_loop;\n        }\n\t\tsem_wait(&(shm_conn_info->stats_sem));\n        info.channel[0].descriptor = service_channel; // load service channel\n\t\tshm_conn_info->stats[info.process_num].pid_remote = ntohs(*((uint16_t *) (buf + sizeof(uint16_t))));\n\t\ttime_lag_local.pid_remote = shm_conn_info->stats[info.process_num].pid_remote;\n\t\ttime_lag_local.pid = shm_conn_info->stats[info.process_num].pid;\n    \t*((uint16_t *) buf) = htons(shm_conn_info->stats[info.process_num].pid);\n\t\tsem_post(&(shm_conn_info->stats_sem));\n\t\tlen = write_n(service_channel, buf, sizeof(uint16_t));\n \t\tif(len < 0) {\n            vlog(LOG_ERR, \"Error! failed to send pid %s(%d)\", strerror(errno), errno);\n            goto finish_loop;\n \t\t}\n#ifdef DEBUGG\n \t\tvlog(LOG_ERR,\"Remote pid - %d, local pid - %d\", time_lag_local.pid_remote, time_lag_local.pid);\n#endif\n        vlog(LOG_INFO,\"Will create %d channels\", info.channel_amount);\n        uint16_t port_tmp = lfd_host->start_port;\n        if (port_tmp != 0 )\n            vlog(LOG_INFO,\"port range is %\"PRIu16\" - %\"PRIu16\"\", lfd_host->start_port, lfd_host->end_port);\n        for (int i = 1; i < info.channel_amount; i++) {\n            if ((info.channel[i].descriptor = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {\n                vlog(LOG_ERR, \"Can't create Channels socket\");\n                goto finish_loop;\n            }\n\n            // Get buffer size\n            socklen_t optlen = sizeof(sendbuff);\n            if (getsockopt(info.channel[i].descriptor, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen) == -1) {\n                vlog(LOG_ERR, \"Error getsockopt one\");\n            } else {\n                vlog(LOG_INFO, \"send buffer size = %d\\n\", sendbuff);\n            }\n            /*\n            sendbuff = RCVBUF_SIZE;\n            // WARNING! This should be on sysadmin's duty to optimize!\n            if (setsockopt(info.channel[i].descriptor, SOL_SOCKET, SO_RCVBUFFORCE, &sendbuff, sizeof(int)) == -1) {\n                vlog(LOG_ERR, \"WARNING! Can not set rmem (SO_RCVBUF) size. Performance will be poor.\");\n            }\n            */\n\n//            prio_opt = 1;\n//            setsockopt(prio_s, SOL_SOCKET, SO_REUSEADDR, &prio_opt, sizeof(prio_opt));\n            for (; ; ++port_tmp <= lfd_host->end_port) {\n                // try to bind to portnum my_num+smth:\n                memset(&my_addr, 0, sizeof(my_addr));\n                laddrlen = sizeof(localaddr);\n                if (getsockname(service_channel, (struct sockaddr *) (&localaddr), &laddrlen) < 0) {\n                    vlog(LOG_ERR, \"My port socket getsockname error; retry %s(%d)\", strerror(errno), errno);\n                    close(prio_s);\n                    goto finish_loop;\n                }\n                memcpy(&my_addr.sin_addr.s_addr, &localaddr.sin_addr.s_addr, sizeof(localaddr.sin_addr.s_addr));\n                my_addr.sin_port = htons(port_tmp);\n                memset(&rmaddr, 0, sizeof(rmaddr));\n                my_addr.sin_family = AF_INET;\n                if (bind(info.channel[i].descriptor, (struct sockaddr *) &my_addr, sizeof(my_addr)) == -1) {\n                    if ((errno == EADDRINUSE) & (port_tmp < lfd_host->end_port)) {\n                        vlog(LOG_ERR, \"Can't bind port %\"PRIu16\", try next\", port_tmp);\n                    } else if ((errno == EADDRINUSE) & (port_tmp == lfd_host->end_port)) {\n                        vlog(LOG_ERR, \"Can't find free port in range %\"PRIu16\"-%\"PRIu16\"\", lfd_host->start_port, lfd_host->end_port);\n                        goto finish_loop;\n                    } else {\n                        vlog(LOG_ERR, \"Can't bind to the Channels socket reason: %s (%d)\", strerror(errno), errno);\n                        goto finish_loop;\n                    }\n                } else {\n                    break;\n                }\n            }\n            // now get my port number\n            laddrlen = sizeof(localaddr);\n            if (getsockname(info.channel[i].descriptor, (struct sockaddr *) (&localaddr), &laddrlen) < 0) {\n                vlog(LOG_ERR, \"My port socket getsockname error; retry %s(%d)\", strerror(errno), errno);\n                close(prio_s);\n                linker_term = TERM_NONFATAL;\n                goto finish_loop;\n                // break;\n            }\n\n            info.channel[i].lport = ntohs(localaddr.sin_port);\n        }\n        for (int i = 1; i < info.channel_amount; i++) {\n            uint16_t hton_ret = htons(info.channel[i].lport);\n            memcpy(buf + sizeof(uint16_t) * (i - 1), &hton_ret, sizeof(uint16_t));\n            vlog(LOG_INFO, \"Send port to client %u\", info.channel[i].lport);\n        }\n        len = write_n(service_channel, buf, sizeof(uint16_t) * (info.channel_amount - 1));\n \t\tif(len < 0) {\n            vlog(LOG_ERR, \"Error! failed to send chamt %s(%d)\", strerror(errno), errno);\n            goto finish_loop;\n \t\t}\n\n\n        *((uint32_t *) buf) = htonl(0); // already in htons format...\n        *((uint16_t *) (buf + sizeof(uint32_t))) = htons(FRAME_PRIO_PORT_NOTIFY);\n        if (proto_write(service_channel, buf, ((sizeof(uint32_t) + sizeof(flag_var)) | VTUN_BAD_FRAME)) < 0) {\n            vlog(LOG_ERR, \"Could not send FRAME_PRIO_PORT_NOTIFY pkt; exit %s(%d)\", strerror(errno), errno);\n            close(prio_s);\n            linker_term = TERM_NONFATAL;\n            goto finish_loop;\n        }\n\n        // now listen to socket, wait for connection\n\n        vlog(LOG_INFO,\"Entering loop to create %d channels\", info.channel_amount - 1);\n        // TODO: how many TCP CONN AMOUNT allowed for server??\n        for (i = 1; (i < info.channel_amount) && (i < MAX_TCP_LOGICAL_CHANNELS); i++) {\n#ifdef DEBUGG\n            vlog(LOG_INFO,\"Chan %d\", i);\n#endif\n            prio_opt = sizeof(cl_addr);\n            struct timeval accept_time;\n            fd_set rfds;\n            FD_ZERO(&rfds);\n            FD_SET(info.channel[i].descriptor, &rfds);\n\n            accept_time.tv_sec = 5;\n            accept_time.tv_usec = 0;\n\n            if (select(info.channel[i].descriptor + 1, &rfds, (fd_set *) 0, (fd_set *) 0, &accept_time) == 1) {\n                struct sockaddr_in cli_addr;\n                socklen_t slen = sizeof(cli_addr);\n                int ret_len = recvfrom(info.channel[i].descriptor, buf, sizeof(uint16_t), 0, (struct sockaddr*) &cli_addr, &slen);\n                if (ret_len == -1) {\n                    vlog(LOG_ERR, \"Recvfrom err on chan %i %s(%d)\", i, strerror(errno), errno);\n                    break_out = 1;\n                    break;\n                }\n                connect(info.channel[i].descriptor, &cli_addr, sizeof(cli_addr));\n                info.channel[i].rport = ntohs(cli_addr.sin_port);\n            } else {\n                vlog(LOG_ERR, \"Accept timeout on chan %i\", i);\n                break_out = 1;\n                break;\n            }\n            //alarm(0);\n        }\n\n        if(break_out) {\n            close(prio_s);\n            for(; i>=0; i--) {\n                close(info.channel[i].descriptor);\n            }\n            linker_term = TERM_NONFATAL;\n            //alarm(0); // TODO why?\n            goto finish_loop;\n        }\n\n        memset(&rmaddr, 0, sizeof(rmaddr));\n        memset(&localaddr, 0, sizeof(localaddr));\n        rmaddrlen = sizeof(rmaddr);\n        laddrlen = sizeof(localaddr);\n        if (getpeername(info.channel[0].descriptor, (struct sockaddr *) (&rmaddr), &rmaddrlen) < 0) {\n            vlog(LOG_ERR, \"Service channel socket getsockname error; retry %s(%d)\", strerror(errno), errno);\n            linker_term = TERM_NONFATAL;\n            goto finish_loop;\n        }\n        if (getsockname(info.channel[0].descriptor, (struct sockaddr *) (&localaddr), &laddrlen) < 0) {\n            vlog(LOG_ERR, \"Service channel socket getsockname error; retry %s(%d)\", strerror(errno), errno);\n            linker_term = TERM_NONFATAL;\n            goto finish_loop;\n         }\n        info.channel[0].rport = ntohs(rmaddr.sin_port);\n        info.channel[0].lport = ntohs(localaddr.sin_port);\n\n        gettimeofday(&info.current_time, NULL );\n        maxfd = info.tun_device;\n        for (int i = 0; i < info.channel_amount; i++) {\n            vlog(LOG_INFO, \"Server descriptor - %i logical channel - %i lport - %i rport - %i\", info.channel[i].descriptor, i,\n                    info.channel[i].lport, info.channel[i].rport);\n            if (maxfd < info.channel[i].descriptor) {\n                maxfd = info.channel[i].descriptor;\n            }\n            memcpy(&info.channel[i].get_tcp_info_time_old, &info.current_time, sizeof(info.channel[i].get_tcp_info_time_old));\n            memcpy(&info.channel[i].send_q_time, &info.current_time, sizeof(info.channel[i].send_q_time));\n        }\n    } else {\n        /** Send to server information about channel amount and get and send pid */\n        info.channel_amount = 2; // WARNING TODO chan_amt hardcoded here\n    \t*((uint16_t *) buf) = htons(info.channel_amount);\n    \tsem_wait(&(shm_conn_info->stats_sem));\n    \t*((uint16_t *) (buf + sizeof(uint16_t))) = htons(shm_conn_info->stats[info.process_num].pid);\n    \ttime_lag_local.pid = shm_conn_info->stats[info.process_num].pid;\n    \tsem_post(&(shm_conn_info->stats_sem));\n        len = write_n(service_channel, buf, sizeof(uint16_t) + sizeof(uint16_t));\n \t\tif(len < 0) {\n            vlog(LOG_ERR, \"Error! failed to send pid %s(%d)\", strerror(errno), errno);\n            goto finish_loop;\n \t\t}\n\n \t\tlen = read_n(service_channel, buf, sizeof(uint16_t));\n \t\tif(len <= 0) {\n            vlog(LOG_ERR, \"Error! failed to read remote pid %s(%d)\", strerror(errno), errno);\n            goto finish_loop;\n \t\t}\n \t\tsem_wait(&(shm_conn_info->stats_sem));\n \t\tshm_conn_info->stats[info.process_num].pid_remote = ntohs(*((uint16_t *) buf));\n \t\ttime_lag_local.pid_remote = shm_conn_info->stats[info.process_num].pid_remote;\n \t\tsem_post(&(shm_conn_info->stats_sem));\n \t\tvlog(LOG_INFO,\"Remote pid - %d, local pid - %d\", time_lag_local.pid_remote, time_lag_local.pid);\n\n \t\tlen = read_n(service_channel, buf, sizeof(uint16_t) * (info.channel_amount - 1));\n \t\tif(len <= 0) {\n            vlog(LOG_ERR, \"Error! failed to read remote ports %s(%d)\", strerror(errno), errno);\n            goto finish_loop;\n \t\t}\n \t\t    \n        vlog(LOG_INFO, \"remote ports len %d\", len);\n\n        for (int i = 1; i < info.channel_amount; i++) {\n            uint16_t rport_h;\n            memcpy(&rport_h, buf + (i - 1) * sizeof(uint16_t), sizeof(uint16_t));\n            info.channel[i].rport = ntohs(rport_h);\n            vlog(LOG_INFO, \"remote port recived %u\", info.channel[i].rport);\n        }\n \t\tinfo.channel_amount = 1; // now we'll accumulate here established logical channels\n    }\n\n    // we start in a normal mode...\n    if(channel_mode == MODE_NORMAL) {\n        shm_conn_info->normal_senders++;\n        vlog(LOG_INFO, \"normal sender added: now %d\", shm_conn_info->normal_senders);\n    }\n\n    sem_wait(&(shm_conn_info->AG_flags_sem));\n    *((uint32_t *) buf) = htonl(shm_conn_info->session_hash_this);\n    sem_post(&(shm_conn_info->AG_flags_sem));\n    *((uint16_t *) (buf + sizeof(uint32_t))) = htons(FRAME_JUST_STARTED);\n    if (proto_write(service_channel, buf, ((sizeof(uint32_t) + sizeof(flag_var)) | VTUN_BAD_FRAME)) < 0) {\n        vlog(LOG_ERR, \"Could not send init pkt; exit\");\n        linker_term = TERM_NONFATAL;\n        goto finish_loop;\n    }\n#ifdef JSON\n    vlog(LOG_INFO,\"{\\\"name\\\":\\\"%s\\\",\\\"start\\\":1, \\\"build\\\":\\\"%s\\\"}\", lfd_host->host, BUILD_DATE);\n#endif\n\n    shm_conn_info->stats[info.process_num].weight = lfd_host->START_WEIGHT;\n    \n    gettimeofday(&info.current_time, NULL);\n    last_action = info.current_time.tv_sec;\n    long int last_net_read_ds = get_ds_ts(info.current_time); \n    shm_conn_info->lock_time = info.current_time.tv_sec;\n    net_model_start = info.current_time;\n    \n//    alarm(lfd_host->MAX_IDLE_TIMEOUT);\n    struct timeval get_info_time, get_info_time_last, tv_tmp_tmp_tmp;\n    get_info_time.tv_sec = 0;\n    get_info_time.tv_usec = 10000;\n    get_info_time_last.tv_sec = 0;\n    get_info_time_last.tv_usec = 0;\n    timer_resolution.tv_sec = 1;\n    timer_resolution.tv_usec = 0;\n    struct timeval  json_timer;\n    gettimeofday(&json_timer, NULL);\n    info.check_shm = 0; // zeroing check_shm\n\n\n    \n\n    struct timeval t_tv;\n    struct timeval loss_time, loss_immune, loss_tv = { 0, 0 };\n    gettimeofday(&loss_time, NULL);\n    gettimeofday(&loss_immune, NULL);\n    \n    sem_wait(&(shm_conn_info->AG_flags_sem));\n    last_channels_mask = shm_conn_info->channels_mask;\n    sem_post(&(shm_conn_info->AG_flags_sem));\n    drop_packet_flag = 0;\n    info.Cu = CUBIC_C/8.0; // x lower\n    info.C = CUBIC_C/3.0; // x lower\n    //info.C = 0.9; // VERY FAST!\n    info.max_send_q = 0;\n    info.max_send_q_u = 0;\n\n    gettimeofday(&info.cycle_last, NULL); // for info.rsr smooth avg\n    int ag_flag_local = R_MODE;\n    \n    sem_wait(&(shm_conn_info->stats_sem));\n    shm_conn_info->stats[info.process_num].ag_flag_local = ag_flag_local;\n    shm_conn_info->last_head = info.current_time;\n    sem_post(&(shm_conn_info->stats_sem));\n    \n    info.rsr = RSR_TOP;\n    info.send_q_limit = RSR_TOP;\n    info.send_q_limit_cubic_max = RSR_TOP;\n    int agag = 0; // AG_MODE aggressiveness value 0 to 256\n    int ag_flag = R_MODE;\n    int ag_flag_local_prev = R_MODE;\n    struct timeval agon_time; // time at which ag_flag_local bacame 1\n    gettimeofday(&agon_time, NULL);\n    \n    info.max_reorder_latency = MAX_REORDER_LATENCY; // is rtt * 2 actually\n    for (int i = 0; i < info.channel_amount; i++) {\n        info.channel[i].local_seq_num=1; // init to 1 for lossed\n    }\n\n    for (int i = 0; i < MAX_TCP_LOGICAL_CHANNELS; i++) {\n        info.rtt2_lsn[i] = 0;\n        info.rtt2_send_q[i] = 0;\n//        info.channel[i].ACS2 = 0;\n//        info.channel[i].old_packet_seq_num_acked = 0;\n//        info.channel[i].local_seq_num_beforeloss = 0;\n        gettimeofday(&info.rtt2_tv[i], NULL);\n    }\n    info.rtt2 = 0;\n    int was_hold_mode = 0; // TODO: remove, testing only!\n    int send_q_eff_mean = 0;\n    int send_q_eff_var = 0;\n    int channel_dead = 0;\n    int exact_rtt = 0;\n    int t; // time for W\n    //int head_rel = 0;\n    struct timeval drop_time = info.current_time;\n    struct timeval cpulag;\n    gettimeofday(&cpulag, NULL);\n    int super = 0;\n    uint32_t my_max_send_q_prev=0;\n    int buf_len_sent[MAX_TCP_PHYSICAL_CHANNELS];\n    for(i=0; i<MAX_TCP_PHYSICAL_CHANNELS;i++) {\n        buf_len_sent[i]=0;\n    }\n\n    t = (int) t_from_W( RSR_TOP - 10000, info.send_q_limit_cubic_max, info.B, info.C);\n    struct timeval new_lag;\n    ms2tv(&new_lag, t * CUBIC_T_DIV); // multiply to compensate\n    timersub(&info.current_time, &new_lag, &loss_time);\n    sem_wait(&(shm_conn_info->stats_sem));\n    set_W_unsync(t);\n    set_W_to(RSR_TOP, 1, &loss_time); // 1 means immediately!\n    set_Wu_to(RSR_TOP);\n    \n    sem_post(&(shm_conn_info->stats_sem));\n    int ELD_send_q_max = 0;\n    int need_send_FCI = 0;\n    info.max_latency_drop.tv_usec = MAX_LATENCY_DROP_USEC;\n    int PCS = 0;\n    int PCS_aux = 0;\n    int rttvar = 0;\n    info.fast_pcs_ts = info.current_time;\n    int pump_adj = 0;\n    int temp_sql_copy =0;\n    int temp_sql_copy2 =0;\n    int temp_acs_copy =0;\n\n    struct timeval wb_1ms_time = { 0, 1000 };\n    struct timeval wb_1ms_timer = info.current_time;\n    \n    // init pbl\n    shm_conn_info->stats[info.process_num].l_pbl_tmp = INT32_MAX;\n    int cubic_t_max = t_from_W(RSR_TOP, info.send_q_limit_cubic_max, info.B, info.C);\n    vlog(LOG_INFO, \"Cubic Tmax t=%d\", cubic_t_max);\n    memset(shm_conn_info->check, 170, CHECK_SZ);\n    info.head_change_tv = info.current_time;\n    info.head_change_safe = 1;\n\n    //reset FRAME_L_LOSS_INFO sending\n    info.last_sent_FLLI_idx = shm_conn_info->l_loss_idx;\n    //reset FRAME_LOSS_INFO sending\n    info.last_sent_FLI_idx = shm_conn_info->loss_idx;\n    struct timeval select_tv_copy; int alive_physical_channels = 1;\n    info.idle_enter = info.current_time;\n\n    vlog_shm_set(1, &shm_conn_info->syslog.logSem, shm_conn_info->syslog.log, &shm_conn_info->syslog.counter, SHM_SYSLOG);\n    int max_send_q_available = MIN_SEND_Q_BESTGUESS_3G_PKT * info.eff_len;\n    struct conn_stats * my_stats = &shm_conn_info->stats[info.process_num];\n    struct _events * my_events = &my_stats->events;\n\n/**\n *\n *\n    _________                         .__                        \n   /   _____/__ ________   ___________|  |   ____   ____ ______  \n   \\_____  \\|  |  \\____ \\_/ __ \\_  __ \\  |  /  _ \\ /  _ \\\\____ \\ \n   /        \\  |  /  |_> >  ___/|  | \\/  |_(  <_> |  <_> )  |_> >\n  /_______  /____/|   __/ \\___  >__|  |____/\\____/ \\____/|   __/ \n          \\/      |__|        \\/                         |__|                                                            \n *\n *\n * Main program loop\n */\n    while( !linker_term ) {\n        //if((shm_conn_info->hold_mask & shm_conn_info->channels_mask) == 0) {\n        //    vlog(LOG_ERR, \"ASSERT FAILED! all channels in HOLD! %d\", shm_conn_info->hold_mask);\n        //    sig_send1();\n        //}\n        if(shm_conn_info->last_net_read_ds < last_net_read_ds) {\n            shm_conn_info->last_net_read_ds = last_net_read_ds;\n        }\n        if(statb.tokens_max < shm_conn_info->tokens) {\n            statb.tokens_max = shm_conn_info->tokens; // TODO: for debug only - remove!\n        }\n        shm_conn_info->stats[info.process_num].lssqn = last_sent_packet_num[1].seq_num;\n        errno = 0;\n        super++;\n        plp_avg_pbl(info.process_num);\n        \n        gettimeofday(&info.current_time, NULL);\n        // struct timespec ts_f;\n        // clock_gettime(CLOCK_MONOTONIC, &ts_f);\n        // TIMESPEC_TO_TIMEVAL(&info.current_time, &ts_f);\n        \n#ifdef TRACE_BUF_LEN\n        timersub(&info.current_time, &wb_1ms_timer, &tv_tmp);\n        if (timercmp(&tv_tmp, &wb_1ms_time, >)) {\n            wb_1ms_timer = info.current_time;\n            wb_1ms_idx++;\n            if (wb_1ms_idx >= WB_1MS_SIZE) {\n                wb_1ms_idx = 0;\n            }\n            if (start_print == wb_1ms_idx) {\n                start_print++;\n                if (start_print >= WB_1MS_SIZE) {\n                    start_print = 0;\n                }\n            }\n            wb_1ms[wb_1ms_idx] = shm_conn_info->write_buf[1].frames.length;\n        }\n#endif\n\n        // IDLE EXIT >>>\n        if( (send_q_eff_mean > SEND_Q_EFF_WORK) || (shm_conn_info->stats[info.process_num].ACK_speed > ACS_NOT_IDLE) ) {\n            shm_conn_info->idle = 0; // exit IDLE immediately for all chans    \n        }\n        if(info.previous_idle && !shm_conn_info->idle) { // usnig local previos flag to avoid need of syncing this op!\n            // detect IDLE exit and CWR-1S\n            shm_conn_info->cwr_tv = info.current_time; // warning this will race into value\n            //shm_conn_info->slow_start = 1;\n            shm_conn_info->slow_start = 0; // disabled\n            shm_conn_info->slow_start_tv = info.current_time;\n            info.previous_idle = 0;\n        }\n        if(shm_conn_info->idle && !info.previous_idle) {\n            vlog(LOG_INFO, \"Entering IDLE\");\n            info.idle_enter = info.current_time;\n        }\n        info.previous_idle = shm_conn_info->idle;\n        // <<< END IDLE EXIT\n        \n        // EXACT_RTT >>>\n        if(0 && info.rtt2_lsn[1] != 0) { // rtt2 DDS detect\n            timersub(&info.current_time, &info.rtt2_tv[1], &tv_tmp);\n            if(tv2ms(&tv_tmp) > (info.srtt2_10 + info.srtt2var)/10) {\n                info.rtt2 = tv2ms(&tv_tmp);\n                if (info.rtt2 <= 0) info.rtt2 = 1;\n            }\n        }\n\n        // Section to set exact_rtt\n        timersub(&ping_req_tv[1], &info.rtt2_tv[1], &tv_tmp);\n        if (((!shm_conn_info->idle) || timercmp(&tv_tmp, &((struct timeval) {lfd_host->PING_INTERVAL, 0}), <=)) && (info.rtt2 > 3)){ // TODO: threshold depends on phys RTT and speed; investigate that!\n            if(info.rtt2 == 0) {\n                vlog(LOG_INFO, \"WARNING! info.rtt2 == 0!\");\n                info.rtt2 = 1;\n            }\n            exact_rtt = info.rtt2; \n            rttvar = info.srtt2var;\n        } else {\n            // TODO: make sure that we sent PING after high load __before__ this happens!\n            if(info.rtt == 0) {\n                vlog(LOG_INFO, \"WARNING! info.rtt == 0!\");\n                info.rtt = 1;\n            }\n            exact_rtt = info.rtt;\n            rttvar = 0;\n        }\n        info.exact_rtt = exact_rtt;\n        // <<< END EXACT_RTT\n        \n\n        CHKCPU(7);\n\n\n        // SEND_Q_EFF CALC >>>\n        uint32_t my_max_send_q = info.channel[my_max_send_q_chan_num].send_q;\n        int64_t bytes_pass = 0;\n\n        timersub(&info.current_time, &info.channel[my_max_send_q_chan_num].send_q_time, &t_tv);\n        int64_t upload_eff = info.channel[my_max_send_q_chan_num].packet_recv_upload_avg;\n        if(upload_eff < 10) upload_eff = 100000; // 1000kpkts default start speed\n        if((t_tv.tv_sec == 0) && (t_tv.tv_usec < info.exact_rtt * 1000)) {\n            bytes_pass = (((int64_t)t_tv.tv_sec * upload_eff\n                    + (((int64_t)t_tv.tv_usec/10) * upload_eff) / 100000)*3)/10;\n        } else {\n            bytes_pass = 0;\n        }\n\n        uint32_t speed_log = info.channel[my_max_send_q_chan_num].packet_recv_upload_avg;\n        // removed semaphore here: exact value not required\n        info.eff_len = shm_conn_info->eff_len.sum;\n        // end removed sem\n        send_q_eff = //my_max_send_q + info.channel[my_max_send_q_chan_num].bytes_put * 1000;\n            (my_max_send_q + info.channel[my_max_send_q_chan_num].bytes_put * info.eff_len) > bytes_pass ?\n                    my_max_send_q + info.channel[my_max_send_q_chan_num].bytes_put * info.eff_len - bytes_pass : 0;\n#ifdef DEBUGG\n        if(drop_packet_flag) {\n        vlog(LOG_INFO,\"Calc send_q_eff: %d + %d * %d - %d\", my_max_send_q, info.channel[my_max_send_q_chan_num].bytes_put, info.eff_len, bytes_pass);\n        } \n#endif\n        // <<< END SEND_Q_EFF CALC\n        \n        // SLOW START DETECTOR >>>\n        // sem_wait(&(shm_conn_info->write_buf_sem));\n        // struct timeval ss_runtime;\n        // struct timeval ss_immune = SLOW_START_IMMUNE;\n        // struct timeval ss_max_run = SLOW_START_MAX_RUN;\n        // timersub(&info.current_time, &shm_conn_info->slow_start_tv, &ss_runtime);\n        // shm_conn_info->slow_start_allowed = 1;\n        // if(timercmp(&ss_runtime, &ss_max_run, >=)) {\n        //     shm_conn_info->slow_start_allowed = 0;\n        //     if(shm_conn_info->slow_start) {\n        //         shm_conn_info->slow_start = 0;\n        //         // The ONLY slow start EXIT here!\n        //         for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        //             if ((shm_conn_info->channels_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead)) {\n        //                 // leave lossq as unknown\n        //                 //if(shm_conn_info->stats[i].loss_send_q == LOSS_SEND_Q_MAX) {\n        //                     //shm_conn_info->stats[i].loss_send_q = shm_conn_info->stats[i].sqe_mean / info.eff_len;\n        //                 //}\n        //             }\n        //         }\n        //         need_send_FCI = 1;\n        //     }\n        // }\n        // if(timercmp(&ss_runtime, &ss_immune, >=)) {\n        //     shm_conn_info->slow_start_allowed = 1;\n        // }\n        //   /* // this is slow-start -unidle KISS experiment (do a slow start on each new connection?) \n        // if(shm_conn_info->seq_counter[1] - shm_conn_info->ssd_pkts_sent >= 50) {\n        //     int gsq = get_cwnd();\n        //     info.gsend_q_grow = gsq - shm_conn_info->ssd_gsq_old;\n        //     if((shm_conn_info->slow_start_force || (info.gsend_q_grow >= 30 && info.gsend_q_grow < 100)) && shm_conn_info->slow_start_allowed) { // grow > 100 means we have a window restore or some other crazy stuff??\n        //         shm_conn_info->slow_start = 1;\n        //     } else {\n        //         shm_conn_info->slow_start = 0;\n        //         shm_conn_info->slow_start_force = 0;\n        //     }\n        //     if(shm_conn_info->slow_start != shm_conn_info->slow_start_prev) {\n        //         if(shm_conn_info->slow_start) {\n        //             shm_conn_info->slow_start_tv = info.current_time;\n        //         }\n        //         need_send_FCI = 1;\n        //     }\n        //     shm_conn_info->slow_start_prev = shm_conn_info->slow_start;\n        //     shm_conn_info->ssd_pkts_sent = shm_conn_info->seq_counter[1];\n        //     shm_conn_info->ssd_gsq_old = gsq;\n        // }\n        // */\n        // sem_post(&(shm_conn_info->write_buf_sem));\n        // <<< END\n        \n\n                \n        /* Temporarily disabled this due to massive loss :-\\\n        // EXTERNAL LOSS DETECT >>> \n        if(send_q_eff > info.send_q_limit_threshold && (send_q_eff < ELD_send_q_max) && !percent_delta_equal(send_q_eff, ELD_send_q_max, 20)) {\n            vlog(LOG_INFO, \"WARNING: External loss detected! send_q from %d to %d\", ELD_send_q_max, send_q_eff);\n            ELD_send_q_max = send_q_eff;\n        } else if (send_q_eff > ELD_send_q_max) {\n            ELD_send_q_max = send_q_eff;\n        }\n        // <<< END EXTERNAL LOSS DETECT\n        */\n        \n\n\n\n        // calculate on-line RTT: >>>\n        if(ping_rcvd == 0) {\n            timersub(&info.current_time, &ping_req_tv[0], &tv_tmp);\n            int cur_rtt = tv2ms(&tv_tmp);\n            // removed sem here: value not required\n            //for(int i=0; i<info.channel_amount; i++) { // only chan 0 !\n            if(cur_rtt > shm_conn_info->stats[info.process_num].rtt_phys_avg) {\n                shm_conn_info->stats[info.process_num].rtt_phys_avg = cur_rtt;\n                info.rtt = cur_rtt;\n            }\n            //}\n            // TODO: in case of DDS initiate second ping immediately!!??\n        }\n        // <<< END calculate on-line RTT\n\n        \n        // DEAD DETECT and COPY HEAD from SHM >>>\n        // max_chan=-1; // this is bad practice ;-)\n        // removed sem here: value not required\n        uint32_t chan_mask = shm_conn_info->channels_mask;\n        // end sem\n        \n        sem_wait(&(shm_conn_info->stats_sem)); // critical_sem\n        if(info.dropping) { // will ONLY drop if PESO in play. Never as of now...\n            info.dropping = 0;\n            shm_conn_info->drop_time = info.current_time;\n            shm_conn_info->dropping = 1;\n        }\n        if(shm_conn_info->stats[info.process_num].packet_upload_cnt > 50) {\n            timersub(&info.current_time, &shm_conn_info->stats[info.process_num].packet_upload_tv, &tv_tmp_tmp_tmp);\n            int ms_passed = tv2ms(&tv_tmp_tmp_tmp);\n            if(ms_passed > 5) {\n                shm_conn_info->stats[info.process_num].packet_upload_spd = shm_conn_info->stats[info.process_num].packet_upload_cnt * 1000 / ms_passed;\n                shm_conn_info->stats[info.process_num].packet_upload_cnt = 0;\n                shm_conn_info->stats[info.process_num].packet_upload_tv = info.current_time;\n                \n                // int max_pups = 0;\n                // int max_pups_chan = 0;\n                // int min_rtt = INT32_MAX;\n                // int min_rtt_chan = 0;\n                // for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                //     if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead)) { // hope this works..\n                //         if(min_rtt > shm_conn_info->stats[i].exact_rtt) {\n                //             min_rtt = shm_conn_info->stats[i].exact_rtt;\n                //             min_rtt_chan = i;\n                //         }\n                //         if(max_pups < shm_conn_info->stats[info.process_num].packet_upload_spd) {\n                //             max_pups = shm_conn_info->stats[info.process_num].packet_upload_spd;\n                //             max_pups_chan = i;\n                //         }\n                //     }\n                // }\n                // if(shm_conn_info->stats[max_pups_chan].exact_rtt > min_rtt) {\n                //     shm_conn_info->drtt = shm_conn_info->stats[max_pups_chan].exact_rtt - min_rtt;\n                //     vlog(LOG_INFO, \"WARNING Fastest chan Not Lowest RTT delta %d (FnLR) max_pups %d max_pups_chan %d rtt %d min_rtt %d min_rtt_chan %d\", \n                //         shm_conn_info->drtt, max_pups, max_pups_chan, shm_conn_info->stats[max_pups_chan].exact_rtt, min_rtt, min_rtt_chan);\n                //     if(shm_conn_info->drtt > shm_conn_info->forced_rtt) {\n                //         //shm_conn_info->forced_rtt = shm_conn_info->drtt;\n                //         //need_send_FCI = 1;\n                //         //vlog(LOG_INFO, \"WARNING FnLR disabled\");\n                //     }\n                // }\n            }\n        }\n\n        // AVERAGE (MEAN) SEND_Q_EFF calculation --->>>\n        timersub(&info.current_time, &info.tv_sqe_mean_added, &tv_tmp_tmp_tmp);\n        if(timercmp(&tv_tmp_tmp_tmp, &((struct timeval) {0, SELECT_SLEEP_USEC }), >=)) {\n            // FAST TIMER HERE: 20 ticks per second (50ms)\n            \n            \n            // AG DECISION >>>\n            ag_flag_local = ((    //(!info.head_channel) && (info.rsr <= info.send_q_limit_threshold)  \n                (shm_conn_info->stats[info.process_num].ACK_speed < (shm_conn_info->stats[max_chan].ACK_speed / RATE_THRESHOLD_MULTIPLIER))\n                               //|| (send_q_limit_cubic_apply <= info.send_q_limit_threshold) // disabled for #187\n                               //|| (send_q_limit_cubic_apply < info.rsr) // better w/o this one?!? // may re-introduce due to PESO!\n                               || shm_conn_info->slow_start\n                               || ( channel_dead )\n                               || (shm_conn_info->avg_len_out < AVG_LEN_IN_ACK_THRESH) // ACK/telemetry mode\n                               || ( shm_conn_info->idle )\n                               //|| ( info.head_change_safe && !check_rtt_latency_drop() ) // replace by MAWMAR\n                               || ((agag < AGAG_AG_THRESH) && (!mawmar_allowed()))\n                               || (( !shm_conn_info->dropping && !shm_conn_info->head_lossing ) && !is_happiness_reached())\n                               //|| ( shm_conn_info->stats[info.process_num].l_pbl < (shm_conn_info->stats[max_chan].l_pbl / 7) ) // TODO: TCP model => remove\n                               || ( plp_avg_pbl_unrecoverable(info.process_num) < PLP_UNRECOVERABLE_CUTOFF ) // TODO we assume that local unrecoverable PLP is on-par with tflush PBL\n                               //|| ( !shm_conn_info->stats[info.process_num].brl_ag_enabled ) // TODO: for future TCP model\n                               /*|| (shm_conn_info->stats[max_chan].sqe_mean < SEND_Q_AG_ALLOWED_THRESH)*/ // TODO: use mean_send_q\n                               ) ? R_MODE : AG_MODE);\n            // logging part\n            if(info.head_channel && (shm_conn_info->avg_len_out >= AVG_LEN_IN_ACK_THRESH) && !shm_conn_info->idle && !shm_conn_info->slow_start) {// TODO HERE: add RTT/BW decision here\n                ag_flag_local = AG_MODE;\n            }\n            if(ag_flag_local == AG_MODE) {\n                shm_conn_info->ag_mask |= (1 << info.process_num); // set bin mask to 1\n            } else {\n                shm_conn_info->ag_mask &= ~(1 << info.process_num); // set bin mask to zero\n            }\n            if(ag_flag_local_prev != ag_flag_local) {\n                need_send_FCI = 1; // TODO WARNING FCI may be LOST!! need transport\n            }\n            \n            // now calculate AGAG\n            uint32_t dirty_seq = 0;\n            if(ag_flag_local == AG_MODE) {\n                if(ag_flag_local_prev != ag_flag_local) {\n                    if(agag < 10) { // start from zero\n                        agon_time = info.current_time;\n                        shm_conn_info->stats[info.process_num].agon_time = agon_time;\n                    } else {\n                        // recalculate\n                        struct timeval agtime;\n                        timersub(&info.current_time, &agon_time, &agtime);\n                        ms2tv(&agtime, agag * 10);\n                        timersub(&info.current_time, &agtime, &agon_time);\n                        shm_conn_info->stats[info.process_num].agon_time = agon_time;\n                    }\n                    ag_flag_local_prev = ag_flag_local;\n                }\n                // first calculate agag\n                timersub(&info.current_time, &agon_time, &tv_tmp);\n                //agag = (tv2ms(&tv_tmp) - info.exact_rtt * 2)/ 10;\n                agag = tv2ms(&tv_tmp) / 10;\n                if(agag > 0) {\n                    if(agag > AGAG_MAX) agag = AGAG_MAX; // 2555 milliseconds for full AG (~1% not AG)\n                    for(int i=0; i<info.channel_amount; i++) {\n                        dirty_seq += info.channel[i].local_seq_num;\n                    }\n                    if(agag < 127) {\n                        ag_flag = ((dirty_seq % (128 - agag)) == 0) ? AG_MODE : R_MODE;\n                    } else {\n                        ag_flag = ((dirty_seq % (agag - 125)) == 0) ? R_MODE : AG_MODE;\n                    }\n                }\n                // and finally re-set ag_flag_local since send packet part will use it to choose R/AG\n            } else {\n                if(ag_flag_local_prev == AG_MODE) {\n                    vlog(LOG_INFO, \"Dropping AG on Channel %s (head? %d) (idle? %d) (sqe %d) (rsr %d) (ACS %d) (PCS %d)\", lfd_host->host, info.head_channel, shm_conn_info->idle, send_q_eff, info.rsr, shm_conn_info->stats[info.process_num].max_ACS2, shm_conn_info->stats[info.process_num].max_PCS2);\n                    vlog(LOG_INFO, \"       (rsr=%d)<=(THR=%d) || (W=%d)<=(THR=%d) || DEAD=%d || !CLD=%d || dropping=%d\", info.rsr ,info.send_q_limit_threshold, -1/*send_q_limit_cubic_apply*/ ,info.send_q_limit_threshold, channel_dead, ( !check_rtt_latency_drop() ), ( !shm_conn_info->dropping && !shm_conn_info->head_lossing ) );\n                \n                }\n                \n                if(ag_flag_local_prev != ag_flag_local) {\n                    if(agag > 200) { // start from top\n                        agon_time = info.current_time;\n                        shm_conn_info->stats[info.process_num].agon_time = agon_time;\n                    } else {\n                        // recalculate\n                        struct timeval agtime;\n                        timersub(&info.current_time, &agon_time, &agtime);\n                        ms2tv(&agtime, (255 - agag) * 30); \n                        timersub(&info.current_time, &agtime, &agon_time);\n                        shm_conn_info->stats[info.process_num].agon_time = agon_time;\n                    }\n                    ag_flag_local_prev = ag_flag_local;\n                }\n                // first calculate agag\n                timersub(&info.current_time, &agon_time, &tv_tmp);\n                agag = 255 - tv2ms(&tv_tmp) / 30; // WARNING: overflow may happen here // 3x times slower for NVR to be able to collect CWND before loss\n                // TODO: dup code - may be optimized!\n                if(agag > 0) {\n                    if(agag > AGAG_MAX) agag = AGAG_MAX; // 2555 milliseconds for full AG (~1% not AG)\n                    for(int i=0; i<info.channel_amount; i++) {\n                        dirty_seq += info.channel[i].local_seq_num;\n                    }\n                    if(agag < 127) {\n                        ag_flag = ((dirty_seq % (128 - agag)) == 0) ? AG_MODE : R_MODE;\n                    } else {\n                        ag_flag = ((dirty_seq % (agag - 125)) == 0) ? R_MODE : AG_MODE;\n                    }\n                } else {\n                    agag = 0;\n                    ag_flag = R_MODE;\n                }\n            }\n            if(shm_conn_info->stats[info.process_num].channel_dead) {\n                agag = 0; // protect in case we suddenly died\n            }\n            // <<< END AG DECISION\n                \n            // now compute W\n            \n            timersub(&(info.current_time), &loss_time, &t_tv);\n            int t = t_tv.tv_sec * 1000 + t_tv.tv_usec/1000;\n            t = t / CUBIC_T_DIV;\n            t = t > cubic_t_max ? cubic_t_max : t; // 400s limit\n            set_W_unsync(t);\n            t = get_t_loss(&info.u_loss_tv, info.cubic_t_max_u);\n            shm_conn_info->stats[info.process_num].W_cubic_u = cubic_recalculate(t, info.W_u_max, info.Bu, info.Cu);\n            \n            // #define SELECT_SLEEP_USEC 50000 // crucial for mean sqe calculation during idle\n            /* \n            if( (shm_conn_info->stats[info.process_num].sqe_mean > SEND_Q_EFF_WORK) \n                    || (shm_conn_info->stats[info.process_num].ACK_speed > ACS_NOT_IDLE) ) {\n                shm_conn_info->idle = 0; \n            }\n            */\n            // calculate hsqs\n            //info.head_send_q_shift = shm_conn_info->stats[max_chan].loss_send_q * 65 / 100 - shm_conn_info->stats[max_chan].sqe_mean / info.eff_len;\n            timersub(&info.current_time, &shm_conn_info->head_detected_ts, &tv_tmp_tmp_tmp);\n            int headswitch_start_ok = timercmp(&tv_tmp_tmp_tmp, &((struct timeval) HEAD_TRANSITION_DELAY), >=); // protect from immediate dolbejka TODO: need more precise timing\n            if(shm_conn_info->stats[max_chan].loss_send_q != LOSS_SEND_Q_UNKNOWN) {\n                int rsrp = 0, sum_aer; \n                int sqe = get_total_sqe_mean_pkt(&sum_aer, &rsrp, 0);\n                int sqe_above = rsrp * 85 / 100; // above thresh -> push to MBSL\n                int sqe_below = rsrp * 75 / 100; // below thresh -> push to net\n                // int sqe_above = shm_conn_info->stats[max_chan].rsr * 60 / 100 / info.eff_len; // above thresh -> push to MBSL\n                // int sqe_below = shm_conn_info->stats[max_chan].rsr * 40 / 100 / info.eff_len; // below thresh -> push to net\n                // int sqe = shm_conn_info->stats[max_chan].sqe_mean / info.eff_len; // no sync, don't care about actual value +-?\n                // int rsrp = shm_conn_info->stats[max_chan].rsr / info.eff_len;\n                if(sqe > sqe_above && sqe_above != rsrp) {\n                    //info.head_send_q_shift = - calculate_hsqs_percents(MAX_HSQS_EAT, (sqe - sqe_above) * 100 / (rsrp - sqe_above) ) * sqe / 100/ 100; // negative value\n                    if(sqe > rsrp) {\n                        if(info.head_send_q_shift > 0) {\n                            info.head_send_q_shift = -10;\n                        } else {\n                            info.head_send_q_shift -= 5;\n                        }\n                    } else if(sqe < rsrp && percent_delta_equal(sqe, rsrp, 10)) {\n                        if(info.head_send_q_shift > 0) {\n                            info.head_send_q_shift = -5;\n                        } else {\n                            info.head_send_q_shift -= 1;\n                        }\n                    } else if(sqe < rsrp && percent_delta_equal(sqe, rsrp, 20)) {\n                        info.head_send_q_shift = -2;\n                    } else {\n                        info.head_send_q_shift = -1;\n                    }\n                    //need_send_FCI = 1;\n                } else if(sqe < sqe_below && sqe_below > 0) {\n                    //info.head_send_q_shift = calculate_hsqs_percents(MAX_HSQS_PUSH, (sqe_below - sqe) * 100 / sqe_below ) * sqe / 100/100; // positive value\n                    if(percent_delta_equal(sqe, sqe_below, 10)) {\n                        info.head_send_q_shift = 1;\n                    } else if(percent_delta_equal(sqe, sqe_below, 20)) {\n                        info.head_send_q_shift = 3;\n                    } else if(percent_delta_equal(sqe, sqe_below, 40)) {\n                        info.head_send_q_shift = 5;\n                    } else {\n                        info.head_send_q_shift += 3;\n                    }\n                    //need_send_FCI = 1;\n                } else {\n                    info.head_send_q_shift = 0; // this one is actually not required\n                }\n            } else {\n                info.head_send_q_shift = MIN_SEND_Q_BESTGUESS_3G_PKT - shm_conn_info->stats[max_chan].sqe_mean / info.eff_len / MSBL_PUSHUP_K;\n            }\n            if(info.head_send_q_shift != info.head_send_q_shift_old && !shm_conn_info->idle) {\n                info.head_send_q_shift_old = info.head_send_q_shift;\n                info.FCI_send_counter = 0;\n            }\n            if(info.FCI_send_counter < 100) { // send as many times as possible?\n                need_send_FCI = 1;\n                info.FCI_send_counter++;\n            }\n            \n            timersub(&info.current_time, &shm_conn_info->msbl_tick, &tv_tmp_tmp_tmp);\n            if(timercmp(&tv_tmp_tmp_tmp, &((struct timeval) {0, SELECT_SLEEP_USEC }), >=)) {\n                int iK;\n                if(shm_conn_info->head_send_q_shift_recv > 0) {\n                        iK = 1; // push down\n                } else {\n                    // only this seems to work now\n                    if(shm_conn_info->head_send_q_shift_recv < -10000) {\n                        iK = 5; // push up FAST\n                        shm_conn_info->head_send_q_shift_recv += 10000; // fix it back\n                    } else {\n                        iK = 1; // push up\n                    }\n                }\n                int msbl_K;\n                if(timercmp(&info.recv_loss_immune, &info.current_time, <=)) {\n                    msbl_K = shm_conn_info->head_send_q_shift_recv * iK; \n                } else {\n                    msbl_K = 0; // disable any event processing immediately after detected loss since we now have outdated info\n                }\n                    \n                if(!((shm_conn_info->head_send_q_shift_recv == 10000) && (shm_conn_info->slow_start_recv))) {\n                    shm_conn_info->max_stuck_buf_len -= msbl_K;\n                }\n                if(shm_conn_info->max_stuck_buf_len < 0 || shm_conn_info->is_single_channel) { \n                    shm_conn_info->max_stuck_buf_len = 0;\n                }\n                if(shm_conn_info->max_stuck_buf_len > MSBL_LIMIT) {\n                    shm_conn_info->max_stuck_buf_len = MSBL_LIMIT;\n                }\n                // now fix msbl to 0 as an implementation of #77 workaround\n                // warning! this is a temporary workaround and should be removed\n                // int max_rtt = 0;\n                // for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                //     if ((shm_conn_info->channels_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead)) { \n                //         if(max_rtt < shm_conn_info->stats[i].exact_rtt) {\n                //             max_rtt = shm_conn_info->stats[i].exact_rtt;\n                //         }\n                //     }\n                // }\n                // if(max_rtt && ((max_rtt * shm_conn_info->APCS)/1000 < 80)) {\n                //     // if(shm_conn_info->max_stuck_buf_len > 10) shm_conn_info->max_stuck_buf_len -= 10;\n                //     // else\n                //     shm_conn_info->max_stuck_buf_len = 0;\n                //     if(max_rtt < 50) \n                //         statb.web_surf_optimization |= 4;\n                //     else\n                //         statb.web_surf_optimization |= 2;\n                // }\n                // <-- end workaround\n                shm_conn_info->msbl_tick = info.current_time;\n            }\n            \n            timersub(&info.current_time, &shm_conn_info->msrt_tick, &tv_tmp_tmp_tmp);\n            if(timercmp(&tv_tmp_tmp_tmp, &((struct timeval) {0, SELECT_SLEEP_USEC }), >=)) {\n                if(shm_conn_info->idle) {\n                    if(shm_conn_info->max_stuck_rtt > 0) { \n                        shm_conn_info->max_stuck_rtt -= 1; // drop 1 ms at a time\n                    }\n                } else {\n                    //int max_total_rtt = (shm_conn_info->total_max_rtt+shm_conn_info->total_max_rtt_var) - (shm_conn_info->total_min_rtt - shm_conn_info->total_min_rtt_var); \n                    int rhd = shm_conn_info->remote_head_pnum;\n                    int max_total_rtt = shm_conn_info->stats[rhd].exact_rtt * RTT_THRESHOLD_MULTIPLIER;\n                    if(shm_conn_info->max_stuck_rtt < max_total_rtt && shm_conn_info->tokens_in_out > 0) {\n                        shm_conn_info->max_stuck_rtt += 1;\n                    }\n                }\n                    \n                shm_conn_info->msrt_tick = info.current_time;\n            }\n            \n            timersub(&info.current_time, &shm_conn_info->frtt_smooth_tick, &tv_tmp_tmp_tmp);\n            if(timercmp(&tv_tmp_tmp_tmp, &((struct timeval) {0, SELECT_SLEEP_USEC }), >=)) {\n                shm_conn_info->frtt_local_applied = 34 * shm_conn_info->frtt_local_applied / 35 + shm_conn_info->max_rtt_lag / 35;\n                int full_rtt = ((shm_conn_info->forced_rtt_recv > shm_conn_info->frtt_local_applied) ? shm_conn_info->forced_rtt_recv : shm_conn_info->frtt_local_applied);\n                info.max_latency_drop.tv_usec = MAX_LATENCY_DROP_USEC + full_rtt * 1000;\n                shm_conn_info->frtt_smooth_tick = info.current_time;\n            }\n            \n            CHKCPU(8);\n            // FAST speed counter\n            timersub(&info.current_time, &info.fast_pcs_ts, &tv_tmp_tmp_tmp);\n            int time_passed = tv2ms(&tv_tmp_tmp_tmp);\n            if(        ( (PCS-info.fast_pcs_old) > FAST_PCS_PACKETS_CAN_CALC_SPEED) \n                    && (time_passed > FAST_PCS_MINIMAL_INTERVAL)\n                    && (info.fast_pcs_old < PCS) \n              ) {\n                info.channel[1].packet_download = (PCS - info.fast_pcs_old) * 100 / time_passed * 10; // packets/second\n                need_send_FCI = 1;\n                info.fast_pcs_ts = info.current_time;\n                info.fast_pcs_old = PCS;\n            }\n            \n            // FAST-redetect head experiment\n            redetect_head_unsynced(chan_mask, -1);\n            \n            //send_q_eff_mean += (send_q_eff - send_q_eff_mean) / 30; // TODO: choose aggressiveness for smoothed-sqe (50?) // TODO: use correct smoothing algorithm!\n            send_q_eff_mean = 6 * send_q_eff_mean / 7 + send_q_eff / 7;\n            if(send_q_eff < info.max_send_q) {\n                info.max_send_q = 25 * info.max_send_q / 26 + send_q_eff / 26;\n            } else {\n                info.max_send_q = send_q_eff;\n            }\n            int sqe_delta = send_q_eff - send_q_eff_mean;\n            if(sqe_delta > 0) {\n                send_q_eff_var = (6 * send_q_eff_var  +  sqe_delta)/7;\n            } else {\n                send_q_eff_var = (6 * send_q_eff_var  -  sqe_delta)/7;\n            }\n            \n            if(shm_conn_info->stats[info.process_num].sqe_mean_lossq < send_q_eff) {\n                shm_conn_info->stats[info.process_num].sqe_mean_lossq = send_q_eff;\n            } else {\n                //send_q_eff_mean += (send_q_eff - send_q_eff_mean) / 30; // TODO: choose aggressiveness for smoothed-sqe (50?)\n                //shm_conn_info->stats[info.process_num].sqe_mean_lossq = (send_q_eff - shm_conn_info->stats[info.process_num].sqe_mean_lossq) / 30;\n                shm_conn_info->stats[info.process_num].sqe_mean_lossq = 6 * shm_conn_info->stats[info.process_num].sqe_mean_lossq / 7 + send_q_eff / 7;\n            }\n            if (info.max_send_q_u < send_q_eff_mean) {\n                info.max_send_q_u = send_q_eff_mean;\n            }\n            info.tv_sqe_mean_added = info.current_time;\n            \n            timersub(&info.current_time, &info.head_change_tv, &tv_tmp_tmp_tmp);\n            info.head_change_safe = (tv2ms(&tv_tmp_tmp_tmp) > (info.exact_rtt * 2) ? 1 : 0);\n                    \n        }\n        // << END AVERAGE (MEAN) SEND_Q_EFF calculation\n\n\n\n            CHKCPU(81);\n        if(shm_conn_info->idle) {\n            // use rtt\n            if(shm_conn_info->stats[info.process_num].exact_rtt > DEAD_RTT) {\n                channel_dead = 1;\n            } else {\n                channel_dead = 0;\n            }\n        } else {\n            // TODO: what if info.rsr is ~ 0 ??\n            channel_dead = (percent_delta_equal(send_q_eff, info.rsr, DEAD_RSR_USG) && ((shm_conn_info->stats[info.process_num].max_ACS2 == 0) || (shm_conn_info->stats[info.process_num].max_PCS2 == 0)));\n            if((shm_conn_info->last_net_read_ds - last_net_read_ds) > (MAX_NETWORK_STALL_MS / 10 + info.rtt2 + info.srtt2var)) {\n                // vlog(LOG_ERR, \"WARNING! detecting dead channel by last_net_read_ds: %d, %d\", shm_conn_info->last_net_read_ds, last_net_read_ds);\n                channel_dead = 1;\n            }\n        }\n\n        if(channel_dead == 1 && channel_dead != shm_conn_info->stats[info.process_num].channel_dead) {\n            vlog(LOG_INFO, \"Warning! Channel %s suddenly died! (head? %d) (idle? %d) (sqe %d) (rsr %d) (ACS %d) (PCS %d) (exact_rtt %d)\", lfd_host->host, info.head_channel, shm_conn_info->idle, send_q_eff, info.rsr, shm_conn_info->stats[info.process_num].max_ACS2, shm_conn_info->stats[info.process_num].max_PCS2, shm_conn_info->stats[info.process_num].exact_rtt);\n            shm_conn_info->last_switch_time.tv_sec = 0;\n            if(info.head_channel) {\n                vlog(LOG_INFO, \"Warning! %s is head! Re-detecting new HEAD!\", lfd_host->host);\n                redetect_head_unsynced(chan_mask, info.process_num);\n            }\n        }\n        if (channel_dead == 0 && channel_dead != shm_conn_info->stats[info.process_num].channel_dead){\n            vlog(LOG_INFO, \"Channel %s went alive! (head? %d) (idle? %d) (sqe %d) (rsr %d) (ACS %d) (PCS %d) (exact_rtt %d)\", lfd_host->host, info.head_channel, shm_conn_info->idle, send_q_eff, info.rsr, shm_conn_info->stats[info.process_num].max_ACS2, shm_conn_info->stats[info.process_num].max_PCS2, shm_conn_info->stats[info.process_num].exact_rtt);\n        }\n        shm_conn_info->stats[info.process_num].channel_dead = channel_dead;\n        shm_conn_info->stats[info.process_num].sqe_mean = send_q_eff_mean;\n        shm_conn_info->stats[info.process_num].sqe_var = send_q_eff_mean;\n        shm_conn_info->stats[info.process_num].max_send_q = send_q_eff;\n        shm_conn_info->stats[info.process_num].exact_rtt = exact_rtt;\n        shm_conn_info->stats[info.process_num].rttvar = rttvar;\n        max_chan = shm_conn_info->max_chan;\n#ifdef FIX_HEAD_CHAN\n        if(info.process_num == FIX_HEAD_CHAN)  info.head_channel = 1;\n        else info.head_channel = 0;\n#else\n        // head switch block\n            CHKCPU(82);\n        if(max_chan == info.process_num) {\n            if(info.head_channel != 1) {\n                skip++;\n                // info.W_cubic_copy = info.send_q_limit_cubic;\n                // info.Wu_cubic_copy = shm_conn_info->stats[info.process_num].W_cubic_u;\n                vlog(LOG_INFO, \"Switching head to 1 (ON) saving W %d\", info.send_q_limit_cubic);\n                if(shm_conn_info->head_lossing && !shm_conn_info->idle) {\n                    shm_conn_info->stats[info.process_num].real_loss_time = info.current_time; // just to continue AG due to dropping_lossing\n                }\n            }\n            info.head_channel = 1;\n        } else {\n            if(info.head_channel != 0) {\n                skip++;\n                vlog(LOG_INFO, \"Switching head to 0 (OFF) restoring W %d if > than current W %d\", info.W_cubic_copy, info.send_q_limit_cubic);\n                if(info.send_q_limit_cubic < info.W_cubic_copy) {\n                    // here #876\n                    // set_W_to(info.W_cubic_copy, 1, &loss_time);\n                    // set_Wu_to(info.Wu_cubic_copy);\n                }\n                info.head_change_tv = info.current_time;\n                info.head_change_safe = 0;\n            }\n            info.head_channel = 0;\n        }\n#endif\n        // <<< DEAD DETECT and COPY HEAD from SHM\n        \n    \n            CHKCPU(83);\n\n        // RSR section here >>>\n        int rtt_shift;\n        int rsr_top;\n        if (info.head_channel) {\n            //info.rsr = RSR_TOP;\n            info.rsr = info.send_q_limit_cubic;\n            if(shm_conn_info->is_single_channel) {\n                info.send_q_limit_cubic = lfd_host->MAX_WINDOW;\n            }\n            max_send_q_available = info.rsr;\n            shm_conn_info->stats[info.process_num].max_send_q_available = info.rsr;\n            \n            temp_sql_copy = info.send_q_limit; \n            temp_acs_copy = shm_conn_info->stats[info.process_num].ACK_speed ; \n        } else {\n            rsr_top = shm_conn_info->stats[max_chan].rsr;\n            \n            // copy all vars used to their 'double' reprs\n            double d_ACS_h = shm_conn_info->stats[        max_chan].ACK_speed; // bytes/s\n            double d_ACS = shm_conn_info->stats[info.process_num].ACK_speed; // bytes/s\n            double d_rsr_top = shm_conn_info->stats[max_chan].rsr; // bytes\n            double d_rtt_h = shm_conn_info->stats[max_chan].exact_rtt; // ms\n            d_rtt_h = d_rtt_h / 1000.0; // ms->s\n            double d_rtt_h_var = shm_conn_info->stats[max_chan].rttvar;// ms\n            d_rtt_h_var /= 1000.0; // ms->s\n            double d_rtt = shm_conn_info->stats[info.process_num].exact_rtt;// ms\n            d_rtt = d_rtt / 1000.0; // ms->s\n            double d_rtt_var = shm_conn_info->stats[info.process_num].rttvar;// ms\n            d_rtt_var /= 1000.0; // ms->s\n            double d_frtt = shm_conn_info->forced_rtt;// ms\n            d_frtt /= 1000.0; // ms->s\n            double d_rsr = info.rsr; // bytes\n            \n            if(d_ACS_h < 1) {\n                d_ACS_h = 1; // zero-protect\n            }\n            double d_sql = d_rsr_top * ( d_ACS / d_ACS_h );\n            info.send_q_limit = (int) d_sql; // TODO IS IT NEEDED REMOVE\n            \n            temp_sql_copy = info.send_q_limit; \n            temp_acs_copy = shm_conn_info->stats[info.process_num].ACK_speed ; \n            \n            // TODO: rtt_shift and pump_adj are essentially the same - we should join them one day...\n            //double d_rtt_diff = (d_rtt_h - d_rtt_h_var) - (d_rtt + d_rtt_var);\n            double d_rtt_diff = d_rtt_h - d_rtt;\n            \n            //double d_mld_ms = MAX_LATENCY_DROP_USEC / 1000;\n            double d_msbl_overdrive = 50; // packets?\n            /*d_mld_ms /= 1000000.0; \n            if(shm_conn_info->max_allowed_rtt < d_mld_ms) {\n                d_mld_ms = shm_conn_info->max_allowed_rtt;\n            }\n            d_mld_ms /= 1000.0; // to seconds\n            */\n            //d_mld_ms += d_frtt; // ?\n            //double d_pump_adj = d_ACS * ( d_mld_ms + d_rtt_diff );\n            //double d_pump_adj = d_ACS * ( d_mld_ms - d_rtt );\n            //if(d_pump_adj < 0) d_pump_adj = 0;\n            \n            //double d_rtt_shift = ((d_rtt + d_rtt_var) - d_rtt_h) * d_ACS_h;\n            double d_rtt_shift = (d_rtt - d_rtt_h) * d_ACS_h; // rttvar seems to be causing high RSR jitter\n            if(d_rtt_shift < d_sql) {\n                d_sql -= d_rtt_shift;\n            } else {\n                d_sql = SEND_Q_LIMIT_MINIMAL;\n            }\n            \n            //d_sql += d_pump_adj;\n            d_sql += ((double)(shm_conn_info->buf_len_recv / 3) + d_msbl_overdrive) * (double)info.eff_len;\n            temp_sql_copy2 = (int) d_sql; \n            if(d_sql > RSR_TOP) {\n                d_sql = RSR_TOP;\n            }\n            \n            // now calculate max RSR limit in case of CWND deficiency\n            int sum_aer, lim;\n            int total_sq_pkt = get_total_sqe_mean_pkt(&sum_aer, &lim, 1) + shm_conn_info->msbl_recv - MSBL_RESERV;\n            int total_sq_avail = rsr_top > (MIN_SEND_Q_BESTGUESS_3G_PKT * info.eff_len) ? (total_sq_pkt - MIN_SEND_Q_BESTGUESS_3G_PKT) : (total_sq_pkt - rsr_top / info.eff_len);\n            int sqe_pkt = shm_conn_info->stats[info.process_num].sqe_mean / info.eff_len;\n            if(sqe_pkt > 0) {\n                int aer = shm_conn_info->stats[info.process_num].ACK_speed_avg / sqe_pkt;\n                if(aer > 0 && sum_aer > 0) {\n                    max_send_q_available = (total_sq_avail * aer) / sum_aer * info.eff_len;\n                } else {\n                    max_send_q_available = SEND_Q_AG_ALLOWED_THRESH; // what to do if our ACS == 0? we're R_MODE probably..\n                }\n            } else {\n                max_send_q_available = MIN_SEND_Q_BESTGUESS_3G_PKT * info.eff_len; // in case we have zero sqe we just dont care\n            }\n            shm_conn_info->stats[info.process_num].max_send_q_available = max_send_q_available;\n            \n            timersub(&(info.current_time), &info.cycle_last, &t_tv);\n            int32_t ms_passed = tv2ms(&t_tv);\n            if(ms_passed > RSR_SMOOTH_GRAN) { // 10 ms intvl, 500ms full\n                d_rsr = 17.0/18.0 * d_rsr + 1.0/18.0 * d_sql;\n                info.cycle_last = info.current_time;\n            }\n            \n           \n           /*\n            double d_sqlm = d_rtt * (SPEED_MINIMAL - d_ACS);\n            if(d_sqlm > SEND_Q_LIMIT_MINMAX) {\n                d_sqlm = SEND_Q_LIMIT_MINMAX;\n            }\n            */\n            \n            double d_sqlm = 0; // TODO: pump_adj should deal with this problem!\n            if(d_sqlm > SEND_Q_LIMIT_MINIMAL) {\n                if(d_rsr < d_sqlm) {\n                    d_rsr = d_sqlm;\n                }\n            } else {\n                if(d_rsr < SEND_Q_LIMIT_MINIMAL) {\n                    d_rsr = SEND_Q_LIMIT_MINIMAL;\n                    //vlog(LOG_INFO, \"WARNING! d_rsr < SQL_MIMIMAL: %f; setting to MIN\", d_rsr);\n                }\n            }\n                \n            info.rsr = d_rsr;\n            \n            \n            \n            //pump_adj = (int) d_pump_adj;\n            rtt_shift = (int) d_rtt_shift;\n        }\n        shm_conn_info->stats[info.process_num].rsr = info.rsr;\n        \n        \n        \n        CHKCPU(84);\n        //int send_q_limit_cubic_apply = (info.send_q_limit_cubic > shm_conn_info->stats[info.process_num].W_cubic_u ? info.send_q_limit_cubic : shm_conn_info->stats[info.process_num].W_cubic_u);\n        int send_q_limit_cubic_apply = info.send_q_limit_cubic;\n        if (send_q_limit_cubic_apply < SEND_Q_LIMIT_MINIMAL) {\n            send_q_limit_cubic_apply = SEND_Q_LIMIT_MINIMAL-1;\n        }\n\n        // <<< END RSR section here\n\n\n\n\n            CHKCPU(85);\n        // now see if we are actually good enough to kick in AG?\n        // see our RTT diff from head_channel\n        // TODO: use max_ACS thru all chans\n        //if(shm_conn_info->stats[max_chan].exact_rtt > shm_conn_info->stats[info.process_num].exact_rtt) {\n        //    rtt_shift = shm_conn_info->stats[max_chan].exact_rtt - shm_conn_info->stats[info.process_num].exact_rtt;\n        //} else {\n        //    rtt_shift = shm_conn_info->stats[info.process_num].exact_rtt - shm_conn_info->stats[max_chan].exact_rtt;\n        //}\n        // if ( (rtt_shift*(max_speed/1000)) > MAX_BYTE_DELIVERY_DIFF) ag_flag_local = R_MODE; // unneeded check due to check_rtt_latency_drop() above\n        shm_conn_info->stats[info.process_num].ag_flag_local = ag_flag_local;\n        \n        // if(0 && ag_flag_local == AG_MODE) {\n        //     // check our protup against all other chans\n        //     for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        //         if ((chan_mask & (1 << i)) \n        //             && (!shm_conn_info->stats[i].channel_dead)\n        //             && ((shm_conn_info->stats[info.process_num].exact_rtt - shm_conn_info->stats[i].exact_rtt)*1000 > ((int)info.max_latency_drop.tv_usec)) \n        //             && ((shm_conn_info->stats[i].ag_flag_local) || (check_delivery_time_path_unsynced(i, 2)))) { // warning! CLD may\n        //             info.frtt_remote_predicted = get_rttlag(shm_conn_info->ag_mask);\n        //             if( ((shm_conn_info->stats[info.process_num].exact_rtt - shm_conn_info->stats[i].exact_rtt)*1000 > ((int)info.max_latency_drop.tv_usec) + info.frtt_remote_predicted * 1000) ) {\n        //                 if(info.head_channel) {\n        //                     vlog(LOG_ERR, \"WARNING: PROTUP condition detected on our channel: ertt %d - ertt %d > %u and is head frtt_rem %d rtt2-1 %d rtt2-2 %d\", shm_conn_info->stats[info.process_num].exact_rtt, shm_conn_info->stats[i].exact_rtt, ((int)info.max_latency_drop.tv_usec), info.frtt_remote_predicted, shm_conn_info->stats[info.process_num].rtt2, shm_conn_info->stats[i].rtt2);\n        //                     redetect_head_unsynced(chan_mask, info.process_num);\n        //                     // TODO: immediate action required!\n        //                 } else {\n        //                     vlog(LOG_ERR, \"WARNING: PROTUP condition detected on our channel: %d - %d > %u frtt_rem %d\", shm_conn_info->stats[info.process_num].rtt2, shm_conn_info->stats[i].rtt2, ((int)info.max_latency_drop.tv_usec), info.frtt_remote_predicted);\n\n        //                 }\n        //             }\n        //         }\n        //     }\n        // }\n        \n        \n            CHKCPU(86);\n\n\n        CHKCPU(80);\n\n        // HOLD/DROP setup >>>\n        int hold_mode_previous = hold_mode;\n        //if(ag_flag_local == AG_MODE) {\n        if(agag > AGAG_AG_THRESH) {\n            if(info.head_channel) {\n                hold_mode = 0; // no hold whatsoever;\n                // here we decide on whether to hold or not to hold\n                drop_packet_flag = 0;\n                //if (send_q_eff > info.rsr) {\n                if (send_q_eff > send_q_limit_cubic_apply) {\n                        // #876\n                        //if(is_a_hold() && (shm_conn_info->msbl_recv > (MSBL_LIMIT - MSBL_RESERV))) drop_packet_flag = 1;\n                        //else {\n                            hold_mode = 1;\n                        //}\n                }\n                // warning the whole block is not sync\n                if(((shm_conn_info->ag_mask & (~(1 << info.process_num))) & (shm_conn_info->channels_mask)) !=  // hope that ag_mask is consistent with chan_mask\n                        ( (~shm_conn_info->hold_mask) & (~(1 << info.process_num)) & (shm_conn_info->channels_mask) & (shm_conn_info->ag_mask))){ \n                    // exclude current head from comparison (it may not be consistent about flags with mode/hold)\n                    // hold_mask is negative: 1 means send allowed\n                    ///hold_mode = 1; // do not allow to send if the channels are in AG and not in HOLD\n                    ///drop_packet_flag = 0;\n                    // TODO HERE: may have problems in case of \n                    // 1. incorrect detection of chan RSR/W\n                    // 2. channel for some reason can not reach hold (any reasons?)\n                    // 3. possible problems with HEAD detect in case there will be no packets available to send for HEAD to support top speed\n                    // may be implement a 'soft' hold for head (push other chans to top (APTT) - not by going 100% committed to hold if not pushed\n                    shm_conn_info->hold_mask = shm_conn_info->channels_mask;\n                }\n            } else {\n                drop_packet_flag = 0;\n                if ( (send_q_eff > info.rsr) || (send_q_eff > send_q_limit_cubic_apply) || (send_q_eff > max_send_q_available)) {\n                    //vlog(LOG_INFO, \"hold_mode!! send_q_eff=%d, rsr=%d, send_q_limit_cubic_apply=%d\", send_q_eff, rsr, send_q_limit_cubic_apply);\n                    hold_mode = 1;\n                } else {\n                    hold_mode = 0;\n                }\n            }\n        } else { // R_MODE.. no intermediate modes.. yet ;-)\n            hold_mode = 0;\n            drop_packet_flag = 0;\n            if(info.head_channel) {\n                //if(send_q_eff > info.rsr) { // no cubic control on max speed chan!\n                if(shm_conn_info->is_single_channel) {\n                    if (send_q_eff > send_q_limit_cubic_apply) {\n                        hold_mode = 1;\n                    }\n                } else {\n                    if (send_q_eff > send_q_limit_cubic_apply/2) {\n                            // #876\n                        //vlog(LOG_INFO, \"R_MODE DROP HD!!! send_q_eff=%d, rsr=%d, send_q_limit_cubic_apply=%d ( %d )\", send_q_eff, info.rsr, send_q_limit_cubic_apply, info.send_q_limit_cubic);\n                            //drop_packet_flag = 1; // no drop in retransmit? TODO HERE\n                            set_W_to(send_q_eff*2, 1, &loss_time);\n                            set_Wu_to(send_q_eff*2);\n                    } else {\n                        //vlog(LOG_INFO, \"R_MODE NOOP HD!!! send_q_eff=%d, rsr=%d, send_q_limit_cubic_apply=%d ( %d )\", send_q_eff, info.rsr, send_q_limit_cubic_apply, info.send_q_limit_cubic);\n                    }\n                }\n            } else {\n                if((send_q_eff > send_q_limit_cubic_apply) || (send_q_eff > info.rsr)) {\n                    //vlog(LOG_INFO, \"R_MODE DROP!!! send_q_eff=%d, rsr=%d, send_q_limit_cubic_apply=%d ( %d )\", send_q_eff, info.rsr, send_q_limit_cubic_apply, info.send_q_limit_cubic);\n                    hold_mode = 1;\n                } else {\n                    //vlog(LOG_INFO, \"R_MODE NOOP HD!!! send_q_eff=%d, rsr=%d, send_q_limit_cubic_apply=%d ( %d )\", send_q_eff, info.rsr, send_q_limit_cubic_apply, info.send_q_limit_cubic);\n                }\n            }\n        }\n\n        if(hold_mode) {\n            shm_conn_info->hold_mask &= ~(1 << info.process_num); // set bin mask to zero (send not allowed)\n        } else {\n            //shm_conn_info->hold_mask |= (1 << info.process_num); // set bin mask to 1 (free send allowed)\n        }\n        // << END HOLD/DROP setup\n        if(hold_mode) {\n            info.hold_time = info.current_time;\n        }\n        // #ifdef CLIENTONLY\n        // if(!sq_control) {\n        //     hold_mode = 0;\n        //     if(! (dirty_seq_num % 30) ) {\n        //         info.max_latency_drop.tv_usec = 1000;\n        //         shm_conn_info->frtt_local_applied = 1;\n        //         shm_conn_info->rttvar_worst = 1;\n        //         drop_packet_flag = 1;\n        //     } else {\n        //         info.max_latency_drop.tv_usec = 50000;\n        //     }\n        // }\n        // #endif\n        \n        \n        // // fast convergence to underlying encap flow >>> \n        // if(info.head_channel && (drop_packet_flag || hold_mode) && !shm_conn_info->head_lossing ) { \n        //     // if we are head and not lossing -> converge instead of dropping\n        //     drop_packet_flag = 0;\n        //     hold_mode = 0;\n        //     set_W_to(send_q_eff + 2000, 1, &loss_time);\n        //     set_Wu_to(send_q_eff + 2000);\n        // }\n\n        // // Push down envelope\n        // if(info.head_channel && (send_q_eff < (int32_t)info.send_q_limit_cubic)) {\n        //     //set_W_to(send_q_eff, 30, &loss_time);\n        //     // here #876\n        //     // converge only if no losses were detected\n        //     if( !shm_conn_info->dropping && !shm_conn_info->head_lossing ) {\n        //         set_W_to(send_q_eff, 1, &loss_time); // 1 means immediately!\n        //         set_Wu_to(send_q_eff);\n        //     }\n        // }\n        // // <<< END fast convergence to underlying encap flow\n        \n\n#ifdef NOCONTROL\n        hold_mode = 0;\n        drop_packet_flag = 0;\n#endif\n        \n        shm_conn_info->stats[info.process_num].hold = hold_mode;\n        sem_post(&(shm_conn_info->stats_sem)); // critical_sem\n        // if(!info.head_channel) {\n        //     if(hold_mode_previous == 0 && hold_mode == 1) {\n        //         sig_send1(); // notify head (all) about our new condition\n        //     }\n        // }\n        // if(info.head_channel) {\n        //     if(hold_mode_previous == 1 && hold_mode == 0) {\n        //         vlog(LOG_INFO, \"HEAD unhold.\");\n        //     }\n        // }\n        //vlog(LOG_INFO, \"debug0: HOLD_MODE - %i just_started_recv - %i\", hold_mode, info.just_started_recv);\n        if(hold_mode == 1) {\n            was_hold_mode = 1; // for JSON ONLY!\n            info.whm_send_q = send_q_eff;\n            info.whm_cubic = send_q_limit_cubic_apply;\n            info.whm_rsr = info.rsr;\n        }\n        \n        /*\n        if (fast_check_timer(packet_speed_timer, &info.current_time)) { // TODO: Disabled?! Incorrect operation - see code at JSON 0.5s\n            gettimeofday(&info.current_time, NULL );\n            uint32_t tv, max_packets=0;\n            tv = get_difference_timer(packet_speed_timer, &info.current_time)->tv_sec * 1000\n                    + get_difference_timer(packet_speed_timer, &info.current_time)->tv_usec / 1000;\n            if (tv != 0) {\n                for (i = 1; i < info.channel_amount; i++) {\n                    info.channel[i].packet_download = ((info.channel[i].down_packets * 100000) / tv)*10;\n                    //if (info.channel[i].down_packets > 0)\n                        //vlog(LOG_INFO, \"chan %d down packet speed %\"PRIu32\" packets %\"PRIu32\" time %\"PRIu32\" timer %\"PRIu32\"\", i, info.channel[i].packet_download, info.channel[i].down_packets, tv, packet_speed_timer_time.tv_usec/1000);\n                    if (max_packets<info.channel[i].down_packets) max_packets=info.channel[i].down_packets;\n                    info.channel[i].down_packets = 0;\n                }\n                \n                if (packet_speed_timer_time.tv_usec < 800000) packet_speed_timer_time.tv_usec += 20000;\n                if (max_packets<50) {\n                    set_timer(packet_speed_timer, &packet_speed_timer_time);\n                } else if (max_packets>300) {\n                    if (packet_speed_timer_time.tv_usec > 400000) packet_speed_timer_time.tv_usec -= 20000;\n                    set_timer(packet_speed_timer, &packet_speed_timer_time);\n                } else {\n                    fast_update_timer(packet_speed_timer, &info.current_time);\n                }\n            }\n        }\n        */\n        \n       \n        timersub(&info.current_time, &json_timer, &tv_tmp_tmp_tmp);\n        if (timercmp(&tv_tmp_tmp_tmp, &((struct timeval) {0, 500000}), >=)) {\n            int json_ms = tv2ms(&tv_tmp_tmp_tmp);\n            set_rttlag();\n            set_rttlag_total();\n            if(shm_conn_info->max_rtt_lag > shm_conn_info->frtt_local_applied) {\n                //shm_conn_info->frtt_local_applied = shm_conn_info->max_rtt_lag;\n                shm_conn_info->frtt_local_applied = (5 * shm_conn_info->frtt_local_applied + shm_conn_info->max_rtt_lag) / 6;\n                int full_rtt = ((shm_conn_info->forced_rtt_recv > shm_conn_info->frtt_local_applied) ? shm_conn_info->forced_rtt_recv : shm_conn_info->frtt_local_applied);\n                info.max_latency_drop.tv_usec = MAX_LATENCY_DROP_USEC + full_rtt * 1000;\n            }\n            \n            struct timeval min_tv, max_pkt_lag, max_lag = {5, 100000}, since_write_tv;\n            get_wb_oldest_ts_unsync(&min_tv);\n            timersub(&info.current_time, &min_tv, &max_pkt_lag);\n            if(timercmp(&max_pkt_lag, &max_lag, >)) {\n                timersub(&info.current_time, &shm_conn_info->write_buf[1].last_write_time, &since_write_tv);\n                vlog(LOG_ERR, \"ERROR! Max buffer packet lag exceeded: %ld.%06ld s, wlag %ld.%06ld s, buf_len=%d, APCS=%d tks=%d maxstall %ld.%06ld s MLD %d ms. Adding tokens\", max_pkt_lag, since_write_tv, shm_conn_info->write_buf[1].frames.length, shm_conn_info->APCS, shm_conn_info->tokens, shm_conn_info->max_network_stall, get_rto_usec()/1000);\n                //shm_conn_info->tokenbuf+=50;\n                if(shm_conn_info->tokens == 0) {\n                    shm_conn_info->tokens += 10;\n                }\n            }\n            \n            //if( info.head_channel && (max_speed != shm_conn_info->stats[info.process_num].ACK_speed) ) {\n            //    vlog(LOG_ERR, \"WARNING head chan detect may be wrong: max ACS != head ACS\");            \n            //}\n\n            if(shm_conn_info->idle) {\n                shm_conn_info->stats[info.process_num].l_pbl_tmp = INT32_MAX;\n                set_W_to(RSR_TOP / 2, 1, &loss_time); // protect from overflow??\n                set_Wu_to(RSR_TOP/2);\n                shm_conn_info->stats[info.process_num].loss_send_q = LOSS_SEND_Q_UNKNOWN;\n                //info.W_cubic_copy = info.send_q_limit_cubic;\n            }\n            \n            // expensive thing: recalculate minimal rtt channel\n            int min_rtt = INT32_MAX;\n            for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead)) { // hope this works..\n                    if(min_rtt > shm_conn_info->stats[i].exact_rtt) {\n                        min_rtt = shm_conn_info->stats[i].exact_rtt;\n                        info.min_rtt_chan = i;\n                    }\n                }\n            }\n            \n            /*\n            if(shm_conn_info->drtt < shm_conn_info->forced_rtt) { // WTF??\n                shm_conn_info->forced_rtt = shm_conn_info->drtt;\n            }\n            */\n            \n            // compute perceived loss probability\n            if(info.p_lost > 0 && info.r_lost > 0) {\n                info.i_plp += (((info.channel[1].local_seq_num - info.last_loss_lsn) / info.p_lost) - info.i_plp) / 2;\n                info.last_loss_lsn = info.channel[1].local_seq_num; // WRN channel broken here\n                info.p_lost = 0;\n                \n                info.i_rplp += (((info.channel[1].local_seq_num_recv - info.last_rlost_lsn) / info.r_lost) - info.i_rplp) / 2;\n                info.last_rlost_lsn = info.channel[1].local_seq_num_recv;\n                info.r_lost = 0;\n            }\n            \n            int cur_plp = plp_avg_pbl(info.process_num);\n            int cur_plp_unrec = plp_avg_pbl_unrecoverable(info.process_num);\n            \n            sem_wait(&(shm_conn_info->stats_sem));\n            \n            shm_conn_info->rttvar_worst = 0;\n            for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (shm_conn_info->ag_mask_recv & (1 << i))) { // hope this works..\n                    if(shm_conn_info->rttvar_worst < shm_conn_info->stats[i].rttvar) {\n                        shm_conn_info->rttvar_worst = shm_conn_info->stats[i].rttvar;\n                    }\n                }\n            }\n\n            int new_mar = compute_max_allowed_rtt();\n            if(new_mar > shm_conn_info->max_allowed_rtt) {\n                shm_conn_info->max_allowed_rtt = 8 * shm_conn_info->max_allowed_rtt / 9 + new_mar / 9;\n            } else {\n                shm_conn_info->max_allowed_rtt = 5 * shm_conn_info->max_allowed_rtt / 6 + new_mar / 6;\n            }\n            \n            timersub(&info.current_time, &shm_conn_info->APCS_tick_tv, &tv_tmp);\n            if(timercmp(&tv_tmp, &((struct timeval) {1, 350000}), >=) || (shm_conn_info->APCS_cnt > 500)) {\n                int new_APCS = shm_conn_info->APCS_cnt * 1000 / tv2ms(&tv_tmp);\n                shm_conn_info->APCS = 6 * shm_conn_info->APCS / 7 + new_APCS / 7;\n                shm_conn_info->APCS_cnt = 0;\n                shm_conn_info->APCS_tick_tv = info.current_time;\n            }\n            if(shm_conn_info->APCS < MIN_PPS) {\n                shm_conn_info->APCS = MIN_PPS;\n            }\n           \n            shm_conn_info->stats[info.process_num].l_pbl = cur_plp; // absolutely unnessessary (done at loop )\n            //set_xhi_brl_flags_unsync(); // compute xhi from l_pbl\n            shm_conn_info->stats[info.process_num].packet_speed_ag = statb.packet_sent_ag / json_ms;\n            shm_conn_info->stats[info.process_num].packet_speed_rmit = statb.packet_sent_rmit / json_ms;\n\n            timersub(&info.current_time, &shm_conn_info->drop_time, &tv_tmp_tmp_tmp);\n            if (timercmp(&tv_tmp_tmp_tmp, &((struct timeval) {DROPPING_LOSSING_DETECT_SECONDS, 0}), >=)) {\n                if(DL_flag_drop_allowed_unsync_stats(chan_mask)) shm_conn_info->dropping = 0;\n            } else {\n                shm_conn_info->dropping = 1;\n            }\n            \n            if(info.head_channel) {\n                timersub(&(info.current_time), &(shm_conn_info->stats[info.process_num].real_loss_time), &tv_tmp_tmp_tmp);\n                if(timercmp(&tv_tmp_tmp_tmp, &((struct timeval) {DROPPING_LOSSING_DETECT_SECONDS, 0}), >=)) {\n                    if(DL_flag_drop_allowed_unsync_stats(chan_mask)) shm_conn_info->head_lossing = 0;\n                } else {\n                    shm_conn_info->head_lossing = 1;\n                    shm_conn_info->idle = 0;\n                }\n            }\n\n            // calc ACS2 and DDS detect\n            int max_ACS2=0;\n            int Hchan=-1;\n            for(int i=0; i<info.channel_amount; i++) {\n                info.channel[i].ACS2 = (info.channel[i].packet_seq_num_acked - info.channel[i].old_packet_seq_num_acked) * 2 * info.eff_len;\n                info.channel[i].old_packet_seq_num_acked = info.channel[i].packet_seq_num_acked;\n                if(max_ACS2 < info.channel[i].ACS2) { \n                    max_ACS2 = info.channel[i].ACS2;\n                    Hchan = i;\n                }\n            }\n            \n            if(max_ACS2 != info.channel[1].ACS2) {\n                vlog(LOG_ERR,\"ERROR: ACS2 on chan 1 not highest!: %d, ch: %d\", max_ACS2, Hchan);\n                max_ACS2 = info.channel[1].ACS2;\n            }\n            \n            // now put max_ACS2 and PCS2 to SHM:\n            shm_conn_info->stats[info.process_num].max_PCS2 = (PCS + PCS_aux) * 2 * info.eff_len;\n            if(info.pcs_sent_old == info.channel[1].packet_download)  {\n                info.channel[1].packet_download = PCS * 2;\n                info.pcs_sent_old = info.channel[1].packet_download;\n            }\n            timersub(&info.current_time, &info.idle_enter, &tv_tmp);\n            if(timercmp(&tv_tmp, &((struct timeval) {2, 0}), <=)) {\n                need_send_FCI = 1;\n            }\n            //max_ACS2 = (max_ACS2 < (info.PCS2_recv * info.eff_len) ? max_ACS2 : (info.PCS2_recv * info.eff_len)); // disabled for future fix\n            shm_conn_info->stats[info.process_num].max_ACS2 = max_ACS2;\n            shm_conn_info->stats[info.process_num].ACK_speed= max_ACS2; // !\n            shm_conn_info->stats[info.process_num].ACK_speed_avg = 6 * shm_conn_info->stats[info.process_num].ACK_speed_avg / 7 + max_ACS2 / 7;\n            miss_packets_max = shm_conn_info->miss_packets_max;\n             \n            timersub(&info.current_time, &shm_conn_info->tpps_tick_tv, &tv_tmp);\n            if ((timercmp(&tv_tmp, &((struct timeval) {0, 400000}), >=) && ((shm_conn_info->seq_counter[1] - shm_conn_info->tpps_old) > 150))\n                    || (timercmp(&tv_tmp, &((struct timeval) {5, 0}), >=))) {\n                tpps = (shm_conn_info->seq_counter[1] - shm_conn_info->tpps_old) * 1000 / tv2ms(&tv_tmp);\n                shm_conn_info->tpps = tpps;\n                shm_conn_info->tpps_old = shm_conn_info->seq_counter[1];\n                shm_conn_info->tpps_tick_tv = info.current_time;\n            }\n            shm_conn_info->is_single_channel = is_single();\n            \n            sem_post(&(shm_conn_info->stats_sem));\n            statb.packet_sent_ag = 0;\n            statb.packet_sent_rmit = 0;\n            \n            info.psl_per_second = info.psl_count * 2;\n            info.loss_events_per_second = info.loss_event_count * 2;\n            info.psl_count = 0;\n            info.loss_event_count = 0;\n            if(info.loss_events_per_second > 10 && info.psl_per_second > 100) {\n                info.xlm = 1;\n            } else {\n                info.xlm = 0;\n            }\n                \n            \n            //Check time interval and ping if need.\n            if (((info.current_time.tv_sec - last_ping) > lfd_host->PING_INTERVAL) ) {\n    \t\t\t\t// ping ALL channels! this is required due to 120-sec limitation on some NATs\n                for (i = 0; i < info.channel_amount; i++) { // TODO: remove ping DUP code\n                    if(!select_net_write(i)) continue;\n    \t\t\t\tlast_ping = info.current_time.tv_sec;\n    \t\t\t\tping_rcvd = 0;\n                    ping_req_tv[i] = info.current_time;\n                    int len_ret;\n                    if (i == 0) {\n                        len_ret = proto_write(info.channel[i].descriptor, buf, VTUN_ECHO_REQ);\n                        if(debug_trace) {\n                            vlog(LOG_INFO, \"PING2 chan_num %d\", i);\n                        }\n                    } else {\n                        // send ping request - 2\n                        len_ret = udp_write(info.channel[i].descriptor, buf, VTUN_ECHO_REQ);\n                        if(debug_trace) {\n                            vlog(LOG_INFO, \"PING2 chan_num %d\", i);\n                        }\n                    }\n                    if (len_ret < 0) {\n    \t\t\t\t\t\tvlog(LOG_ERR, \"Could not send echo request 2 chan %d reason %s (%d)\", i, strerror(errno), errno);\n    \t\t\t\t\t\tbreak;\n    \t\t\t\t\t}\n    \t\t\t\tshm_conn_info->stats[info.process_num].speed_chan_data[i].up_data_len_amt += len_ret;\n                    shm_conn_info->stats[info.process_num].packet_upload_cnt++;\n    \t\t\t\tinfo.channel[i].up_len += len_ret;\n    \t\t\t}\n    \t\t}\n\n            json_timer = info.current_time;\n            info.max_send_q_max = 0;\n            info.max_send_q_min = 120000;\n            fire_event(&my_events->update);\n            max_chan = shm_conn_info->max_chan;\n        }\n        // <<< END JSON LOGS\n        \n        \n\n        // SEND FCI >>>\n        int timer_result=0;\n        if(shm_conn_info->dropping || shm_conn_info->head_lossing) {\n            timer_result = fast_check_timer(recv_n_loss_send_timer, &info.current_time);\n        } else {\n            // idle timer? // TODO: don't we need to send FCI if not sending on top speed??\n            // TODO: this may or even WILL result in jitter and speed degrade if congestion is e.g. not on the path\n            // TODO: out-of path congestion detection!\n            timersub(&info.current_time, &(recv_n_loss_send_timer->start_time), &(recv_n_loss_send_timer->tmp));\n            timer_result = timercmp(&(recv_n_loss_send_timer->tmp), &((struct timeval) {60, 0}), >=); // send each 60 seconds?\n        }\n        // for (i = 1; i < info.channel_amount; i++) {\n        {\n            i=1;\n            uint32_t tmp32_n;\n            uint16_t tmp16_n;\n            // split LOSS event generation and bytes-in-flight (LLRS)\n\n            // FCI - LLRS: TODO: remove dup code below (FCI packet formation)\n            if( ((info.channel[i].packet_recv_counter > FCI_P_INTERVAL) || timer_result || need_send_FCI) && select_net_write(i) ) {\n                need_send_FCI = 0;\n                fast_update_timer(recv_n_loss_send_timer, &info.current_time);\n                tmp16_n = htons((uint16_t)info.channel[i].packet_recv_counter); // amt of rcvd packets\n                memcpy(buf, &tmp16_n, sizeof(uint16_t)); // amt of rcvd packets\n                tmp16_n = 0; // loss, we're not sending loss now, just general info\n                memcpy(buf + sizeof(uint16_t), &tmp16_n, sizeof(uint16_t)); // loss\n                tmp16_n = htons(FRAME_CHANNEL_INFO);  // flag\n                memcpy(buf + 2 * sizeof(uint16_t), &tmp16_n, sizeof(uint16_t));\n                tmp32_n = htonl(info.channel[i].local_seq_num_recv); // last received local seq_num\n                memcpy(buf + 3 * sizeof(uint16_t), &tmp32_n, sizeof(uint32_t));\n                \n#ifdef CLIENTONLY\n                if(info.head_channel) { \n                    tmp16_n = htons((uint16_t) (100+i)); // chan_num ?? not needed in fact TODO remove\n                } else {\n                    tmp16_n = htons((uint16_t) (i)); // chan_num ?? not needed in fact TODO remove\n                }\n#else\n                if(info.head_channel) { \n                    tmp16_n = htons((uint16_t) (200+i)); // chan_num ?? not needed in fact TODO remove\n                } else {\n                    tmp16_n = htons((uint16_t) (i)); // chan_num ?? not needed in fact TODO remove\n                }\n#endif\n                memcpy(buf + 3 * sizeof(uint16_t) + sizeof(uint32_t), &tmp16_n, sizeof(uint16_t));\n                tmp32_n = htonl(info.channel[1].packet_download);\n                memcpy(buf + 4 * sizeof(uint16_t) + 2 * sizeof(uint32_t), &tmp32_n, sizeof(uint32_t)); // down speed per current chan (PCS send)\n                struct timeval tmp_tv;\n                // local_seq_num\n                tmp32_n = htonl(info.channel[i].local_seq_num);\n                memcpy(buf + 4 * sizeof(uint16_t) + sizeof(uint32_t), &tmp32_n, sizeof(uint32_t)); // local_seq_num\n                /*\n                uint16_t tmp16 = ((uint16_t) (-1));\n                sem_wait(write_buf_sem);\n                if ((unsigned int) shm_conn_info->forced_rtt < ((uint16_t) (-1))) {\n                    tmp16 = shm_conn_info->forced_rtt;\n                }\n                sem_post(write_buf_sem);\n                tmp16_n = htons(tmp16); //forced_rtt here\n                */\n                //tmp16_n = htons(shm_conn_info->frtt_local_applied); //forced_rtt here // replacing this with hsqs\n                tmp16_n = htons(info.head_send_q_shift);\n                memcpy(buf + 4 * sizeof(uint16_t) + 3 * sizeof(uint32_t), &tmp16_n, sizeof(uint16_t)); // hsqs\n                tmp32_n = htonl(ag_mask2hsag_mask(shm_conn_info->ag_mask));\n                memcpy(buf + 5 * sizeof(uint16_t) + 3 * sizeof(uint32_t), &tmp32_n, sizeof(uint32_t)); //ag_mask\n//                vlog(LOG_ERR,\"FRAME_CHANNEL_INFO send buf_len %d counter %d current buf_len %d\", buf_len_real, shm_conn_info->buf_len_send_counter,shm_conn_info->write_buf[1].frames.length);\n                tmp32_n = htons(shm_conn_info->stats[info.process_num].sqe_mean / info.eff_len); // sqe_mean (in pkt)\n                memcpy(buf + 5 * sizeof(uint16_t) + 4 * sizeof(uint32_t), &tmp32_n, sizeof(uint16_t)); // sqe_mean (in pkt)\n                buf_len_real = shm_conn_info->write_buf[1].frames.length;\n                tmp32_n = htons(buf_len_real);\n                memcpy(buf + 6 * sizeof(uint16_t) + 4 * sizeof(uint32_t), &tmp32_n, sizeof(uint16_t)); //buf_len\n                //tmp16_n = htons(get_lbuf_len());\n                tmp16_n = htons(shm_conn_info->max_stuck_buf_len);\n                memcpy(buf + 7 * sizeof(uint16_t) + 4 * sizeof(uint32_t), &tmp16_n, sizeof(uint16_t)); //lbuf_len\n                tmp32_n = htonl(shm_conn_info->write_buf[i].last_received_seq[info.process_num]); // global seq_num\n                memcpy(buf + 8 * sizeof(uint16_t) + 4 * sizeof(uint32_t), &tmp32_n, sizeof(uint32_t)); //global seq_num\n                //tmp32_n = htons(shm_conn_info->slow_start); \n                tmp32_n = htonl(shm_conn_info->seq_counter[1]); \n                //tmp16_n = 0;\n                memcpy(buf + 8 * sizeof(uint16_t) + 5 * sizeof(uint32_t), &tmp32_n, sizeof(uint32_t)); //global seq_num\n                if(debug_trace) {\n                vlog(LOG_ERR,\n                        \"FRAME_CHANNEL_INFO LLRS send chan_num %d packet_recv %\"PRIu16\" packet_loss %\"PRId16\" packet_seq_num_acked %\"PRIu32\" packet_recv_period %\"PRIu32\" \",\n                        i, info.channel[i].packet_recv_counter, info.channel[i].packet_loss_counter,\n                        (int16_t)info.channel[i].local_seq_num_recv, (uint32_t) (tmp_tv.tv_sec * 1000000 + tmp_tv.tv_usec));\n                        }\n                // send FCI-LLRS\n                int len_ret = udp_write(info.channel[i].descriptor, buf, ((8 * sizeof(uint16_t) + 6 * sizeof(uint32_t)) | VTUN_BAD_FRAME));\n                info.channel[i].local_seq_num++;\n                if (len_ret < 0) {\n                    vlog(LOG_ERR, \"Could not send FRAME_CHANNEL_INFO; reason %s (%d)\", strerror(errno), errno);\n                    linker_term = TERM_NONFATAL;\n                    break;\n                }\n                info.channel[i].packet_recv_counter = 0;\n                shm_conn_info->stats[info.process_num].speed_chan_data[0].up_data_len_amt += len_ret; // WTF?? no sync / futex ??\n                shm_conn_info->stats[info.process_num].packet_upload_cnt++;\n                info.channel[0].up_len += len_ret;\n            }\n\n            // now check if we need to fire LOSS event - send and commit locally\n            if(is_loss() || need_send_loss_FCI_flag) { // we are in loss monitoring state..\n                timersub(&info.current_time, &info.channel[i].last_recv_time, &tv_tmp);\n                int timer_result2 = timercmp(&tv_tmp, &info.max_reorder_latency, >=);\n                if ( (need_send_loss_FCI_flag || timer_result2) && select_net_write(i)) {\n                    // now send and zero\n                    int lrs = 0; // TODO: this seems unessessary\n                    if(timer_result2) need_send_loss_FCI_flag = lossed_latency_drop(&lrs);\n                    tmp16_n = htons((uint16_t)info.channel[i].packet_recv_counter); // amt of rcvd packets\n                    memcpy(buf, &tmp16_n, sizeof(uint16_t)); // amt of rcvd packets\n\n                    // TODO: do we use local_seq_num difference or total packets receive count??\n                    info.r_lost++;\n                    //if( (info.channel[i].local_seq_num_recv - info.channel[i].local_seq_num_beforeloss) > MAX_REORDER_PERPATH) {\n                    vlog(LOG_INFO, \"sedning loss %hd lrs %d, llrs %d\", need_send_loss_FCI_flag, shm_conn_info->write_buf[i].last_received_seq[info.process_num], info.channel[i].local_seq_num_recv);\n\n                    if(shm_conn_info->stats[info.process_num].pbl_lossed_cnt < 100) {\n                        tmp16_n = htons(need_send_loss_FCI_flag + 10000); // dumbass method of telling that loss is unrecoverable\n                    } else {\n                        tmp16_n = htons(need_send_loss_FCI_flag); // amt of pkts lost till this moment\n                    }\n\n                    // inform here that we detected loss -->\n                    sem_wait(&(shm_conn_info->write_buf_sem));\n                    shm_conn_info->l_loss_idx++;\n                    if (shm_conn_info->l_loss_idx == LOSS_ARRAY) {\n                        shm_conn_info->l_loss_idx = 0;\n                    }\n                    shm_conn_info->l_loss[shm_conn_info->l_loss_idx].timestamp = info.current_time;\n                    shm_conn_info->l_loss[shm_conn_info->l_loss_idx].psl = need_send_loss_FCI_flag;\n                    shm_conn_info->l_loss[shm_conn_info->l_loss_idx].pbl = shm_conn_info->stats[info.process_num].pbl_lossed_cnt;\n                    shm_conn_info->l_loss[shm_conn_info->l_loss_idx].sqn = info.lossed_local_seq_num_lost_start;\n                    shm_conn_info->l_loss[shm_conn_info->l_loss_idx].who_lost = shm_conn_info->stats[info.process_num].hsnum;\n                    \n                    shm_conn_info->stats[info.process_num].pbl_lossed_saved = shm_conn_info->stats[info.process_num].pbl_lossed;\n                    shm_conn_info->stats[info.process_num].pbl_lossed_cnt_saved = shm_conn_info->stats[info.process_num].pbl_lossed_cnt;\n                    \n                    shm_conn_info->stats[info.process_num].pbl_lossed = shm_conn_info->stats[info.process_num].pbl_lossed_cnt;\n                    shm_conn_info->stats[info.process_num].pbl_lossed_cnt = 0;\n                    memcpy(&shm_conn_info->l_loss[shm_conn_info->l_loss_idx].name, lfd_host->host + strlen(lfd_host->host) - 2, 2);\n                    need_send_loss_FCI_flag = 0;\n                    if(lrs) shm_conn_info->write_buf[i].last_received_seq[info.process_num] = lrs; // TODO: this seems unessessary\n                    shm_conn_info->write_buf[i].possible_seq_lost[info.process_num] = shm_conn_info->write_buf[i].last_received_seq[info.process_num] - 1;\n                    // inform that we lost packet\n                    shm_conn_info->write_buf[i].packet_lost_state[info.process_num] = 1;\n                    \n                    sem_post(&(shm_conn_info->write_buf_sem));\n\n                    memcpy(buf + sizeof(uint16_t), &tmp16_n, sizeof(uint16_t)); // loss\n                    tmp16_n = htons(FRAME_CHANNEL_INFO);  // flag\n                    memcpy(buf + 2 * sizeof(uint16_t), &tmp16_n, sizeof(uint16_t)); // flag\n                    tmp32_n = htonl(info.channel[i].local_seq_num_recv); // last received local seq_num\n                    memcpy(buf + 3 * sizeof(uint16_t), &tmp32_n, sizeof(uint32_t));\n                     \n#ifdef CLIENTONLY\n                if(info.head_channel) { \n                    tmp16_n = htons((uint16_t) (100+i)); // chan_num ?? not needed in fact TODO remove\n                } else {\n                    tmp16_n = htons((uint16_t) (i)); // chan_num ?? not needed in fact TODO remove\n                }\n#else\n                if(info.head_channel) { \n                    tmp16_n = htons((uint16_t) (200+i)); // chan_num ?? not needed in fact TODO remove\n                } else {\n                    tmp16_n = htons((uint16_t) (i)); // chan_num ?? not needed in fact TODO remove\n                }\n#endif\n                    \n                    memcpy(buf + 3 * sizeof(uint16_t) + sizeof(uint32_t), &tmp16_n, sizeof(uint16_t)); //chan_num\n                    tmp32_n = htonl(info.channel[i].local_seq_num); // local_seq_num\n                    memcpy(buf + 4 * sizeof(uint16_t) + sizeof(uint32_t), &tmp32_n, sizeof(uint32_t)); // local_seq_num\n                    tmp32_n = htonl(info.channel[1].packet_download);\n                    memcpy(buf + 4 * sizeof(uint16_t) + 2 * sizeof(uint32_t), &tmp32_n, sizeof(uint32_t)); // down speed per current chan\n                    /*\n                    uint16_t tmp16 = ((uint16_t) (-1));\n                    sem_wait(write_buf_sem);\n                    if ((unsigned int) shm_conn_info->forced_rtt < ((uint16_t) (-1))) {\n                        tmp16 = shm_conn_info->forced_rtt;\n                    }\n                    sem_post(write_buf_sem);\n                    tmp16_n = htons(tmp16); //forced_rtt here\n                    */\n                    //tmp16_n = htons(shm_conn_info->frtt_local_applied); //forced_rtt here\n                    tmp16_n = htons(info.head_send_q_shift);\n                    memcpy(buf + 4 * sizeof(uint16_t) + 3 * sizeof(uint32_t), &tmp16_n, sizeof(uint16_t)); //forced_rtt\n                    tmp32_n = htonl(ag_mask2hsag_mask(shm_conn_info->ag_mask));\n                    memcpy(buf + 5 * sizeof(uint16_t) + 3 * sizeof(uint32_t), &tmp32_n, sizeof(uint32_t)); //forced_rtt\n\n//                    vlog(LOG_ERR,\"FRAME_CHANNEL_INFO send buf_len %d counter %d current buf_len %d\",buf_len_real, shm_conn_info->buf_len_send_counter,shm_conn_info->write_buf[1].frames.length);\n                    memcpy(buf + 5 * sizeof(uint16_t) + 4 * sizeof(uint32_t), &tmp32_n, sizeof(uint16_t)); //buf_len counter\n                    buf_len_real = shm_conn_info->write_buf[1].frames.length;\n                    tmp32_n = htons(buf_len_real);\n                    memcpy(buf + 6 * sizeof(uint16_t) + 4 * sizeof(uint32_t), &tmp32_n, sizeof(uint16_t)); //buf_len\n                    //tmp16_n = htons(get_lbuf_len());\n                    tmp16_n = htons(shm_conn_info->max_stuck_buf_len);\n                    memcpy(buf + 7 * sizeof(uint16_t) + 4 * sizeof(uint32_t), &tmp16_n, sizeof(uint16_t)); //lbuf_len\n                    tmp32_n = htonl(shm_conn_info->write_buf[i].last_received_seq[info.process_num]); // global seq_num\n                    memcpy(buf + 8 * sizeof(uint16_t) + 4 * sizeof(uint32_t), &tmp32_n, sizeof(uint32_t)); //global seq_num\n                    tmp32_n = htonl(shm_conn_info->seq_counter[1]); \n                    //tmp16_n = htons(shm_conn_info->slow_start); \n                    //tmp16_n = 0;\n                    memcpy(buf + 8 * sizeof(uint16_t) + 5 * sizeof(uint32_t), &tmp32_n, sizeof(uint32_t)); //global seq_num\n                        if(debug_trace) {\n                    vlog(LOG_INFO,\n                            \"FRAME_CHANNEL_INFO send chan_num %d packet_recv %\"PRIu16\" packet_loss %\"PRId16\" packet_seq_num_acked %\"PRIu32\" packet_recv_period %\"PRIu32\" \",\n                            i, info.channel[i].packet_recv_counter, info.channel[i].packet_loss_counter,\n                            (int16_t)info.channel[i].local_seq_num_recv, (uint32_t) (tv_tmp.tv_sec * 1000000 + tv_tmp.tv_usec));\n                        }\n                    // send FCI\n                    // TODO: select here ???\n                    int len_ret = udp_write(info.channel[i].descriptor, buf, ((8 * sizeof(uint16_t) + 6 * sizeof(uint32_t)) | VTUN_BAD_FRAME));\n                    info.channel[i].local_seq_num++;\n\n                    if (len_ret < 0) {\n                        vlog(LOG_ERR, \"Could not send FRAME_CHANNEL_INFO; reason %s (%d)\", strerror(errno), errno);\n                        linker_term = TERM_NONFATAL;\n                        break;\n                    }\n                    info.channel[i].packet_recv_counter = 0;\n                    shm_conn_info->stats[info.process_num].speed_chan_data[0].up_data_len_amt += len_ret; // WTF?? no sync / futex ??\n                    shm_conn_info->stats[info.process_num].packet_upload_cnt++;\n                    info.channel[0].up_len += len_ret;                    \n                    infer_lost_seq_num(incomplete_seq_buf);\n                }\n            }\n\n            /* TODO write function for lws sending*/\n            // sem_wait(&(shm_conn_info->write_buf_sem));\n            // uint32_t last_lws_notified_tmp = shm_conn_info->write_buf[i].last_lws_notified;\n            uint32_t last_written_seq_tmp = shm_conn_info->write_buf[i].last_written_seq;\n            // sem_post(&(shm_conn_info->write_buf_sem));\n            if ((last_written_seq_tmp > (last_last_written_seq[i] + LWS_NOTIFY_MAX_SUB_SEQ)) && select_net_write(i) ) {\n                // TODO: DUP code!\n                \n                if(debug_trace) {\n                    vlog(LOG_INFO, \"Sending LWS...\");\n                }\n                sem_wait(&(shm_conn_info->write_buf_sem));\n                *((uint32_t *) buf) = htonl(shm_conn_info->write_buf[i].last_written_seq);\n                last_last_written_seq[i] = shm_conn_info->write_buf[i].last_written_seq;\n                shm_conn_info->write_buf[i].last_lws_notified = info.current_time.tv_sec;\n                sem_post(&(shm_conn_info->write_buf_sem));\n                *((uint16_t *) (buf + sizeof(uint32_t))) = htons(FRAME_LAST_WRITTEN_SEQ);\n                // send LWS. TODO: is it Ever needed?? -> retransmit_send and top_seq_num shifting (why neede too dunno)\n                // TODO: select here!\n                int len_ret = udp_write(info.channel[i].descriptor, buf, ((sizeof(uint32_t) + sizeof(flag_var)) | VTUN_BAD_FRAME));\n                if (len_ret < 0) {\n                    vlog(LOG_ERR, \"Could not send last_written_seq pkt; exit\");\n                    linker_term = TERM_NONFATAL;\n                }\n                shm_conn_info->stats[info.process_num].speed_chan_data[i].up_data_len_amt += len_ret;\n                shm_conn_info->stats[info.process_num].packet_upload_cnt++;\n                info.channel[i].up_len += len_ret;\n            }\n        } // for each chan_num loop end ([i])\n        // <<< END SEND FCI\n\n       CHKCPU(9); \n        \n        // do an expensive thing\n          timersub(&info.current_time, &last_timing, &tv_tmp);\n          /**\n           *\n           *    ___________.__        __     \n           *    \\__    ___/|__| ____ |  | __ \n           *      |    |   |  |/ ___\\|  |/ / \n           *      |    |   |  \\  \\___|    <  \n           *      |____|   |__|\\___  >__|_ \\ \n           *                       \\/     \\/ \n           *                       u\n           * This is the Tick module\n           */\n        if ( timercmp(&tv_tmp, &timer_resolution, >=)) {\n            udp_struct->lport = info.channel[1].lport;\n            udp_struct->rport = info.channel[1].rport;\n            //if (get_udp_stats(udp_struct, 1)) {\n            //    vlog(LOG_INFO, \"udp stat lport %d dport %d tx_q %d rx_q %d drops %d \", udp_struct->lport, udp_struct->rport, udp_struct->tx_q,\n            //            udp_struct->rx_q, udp_struct->drops);\n            //}\n            cubic_t_max = t_from_W(RSR_TOP, info.send_q_limit_cubic_max, info.B, info.C);\n            info.cubic_t_max_u = t_from_W(RSR_TOP, info.W_u_max, info.Bu, info.Cu); // TODO: place it everywhere whenever W_u_max changes??\n            if(shm_conn_info->write_buf[1].possible_seq_lost[info.process_num] > shm_conn_info->write_buf[1].last_received_seq[info.process_num]) {\n                vlog(LOG_INFO, \"WARNING Fixing psl %d > lrs %d to last received seq\", shm_conn_info->write_buf[1].possible_seq_lost[info.process_num], shm_conn_info->write_buf[1].last_received_seq[info.process_num]);\n                shm_conn_info->write_buf[1].possible_seq_lost[info.process_num] = shm_conn_info->write_buf[1].last_received_seq[info.process_num];\n            }\n            if (info.check_shm) { // impossible to work (remove!?)\n                sem_wait(&(shm_conn_info->AG_flags_sem));\n                uint32_t chan_mask = shm_conn_info->channels_mask;\n                if (shm_conn_info->need_to_exit & (1 << info.process_num)) {\n                    linker_term = TERM_NONFATAL;\n                    vlog(LOG_INFO, \"Need to exit by peer\");\n                }\n                sem_post(&(shm_conn_info->AG_flags_sem));\n                for (uint32_t i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                    if (!(chan_mask & (1 << i))) {\n                        if (last_channels_mask & (1 << i)) {\n    #ifdef DEBUGG\n                            vlog(LOG_INFO, \"Sending FRAME_DEAD_CHANNEL for %i\", i);\n    #endif\n                            uint32_t i_n = htonl(i);\n                            uint16_t flag_n = htons(FRAME_DEAD_CHANNEL);\n                            memcpy(buf, &i_n, sizeof(uint32_t));\n                            memcpy(buf, &flag_n, sizeof(uint16_t));\n                            int len_ret = proto_write(info.channel[0].descriptor, buf, ((sizeof(uint32_t) + sizeof(flag_var)) | VTUN_BAD_FRAME));\n                            if (len_ret < 0) {\n                                vlog(LOG_ERR, \"Could not send FRAME_DEAD_CHANNEL; exit\");\n                                linker_term = TERM_NONFATAL;\n                            }\n                        }\n                    }\n                }\n                last_channels_mask = chan_mask;\n                if (shm_conn_info->session_hash_remote != info.session_hash_remote) {\n                    vlog(LOG_INFO, \"Need to exit by hash compare; exit\");\n                    linker_term = TERM_NONFATAL;\n                }\n            }\n\n            if ((get_ds_ts(info.current_time) - last_net_read_ds) > lfd_host->MAX_IDLE_TIMEOUT*100) {\n                vlog(LOG_INFO, \"Session %s network timeout\", lfd_host->host);\n                break;\n            }\n\n            info.encap_streams = NumberOfSetBits(info.encap_streams_bitcnt);\n            info.encap_streams_bitcnt= 0;\n            // int stsum = 0;\n            // int stmax=0;\n            // for(int i=0;i<MAX_TCP_PHYSICAL_CHANNELS;i++) {//   WARN unsync but seems dont care\n            //     stsum+=shm_conn_info->streams[i];\n            //     if(stmax<shm_conn_info->streams[i]) {\n            //         stmax = shm_conn_info->streams[i];\n            //     }\n            //     shm_conn_info->streams[i]=0;\n            // }\n            // if((stsum-stmax) > (stmax/20)) {\n            //     shm_conn_info->single_stream=0;\n            // } else {\n            //     shm_conn_info->single_stream=1;\n            // }\n            \n            set_IDLE();\n\n            // head detect code\n            if (timercmp(&tv_tmp_tmp_tmp, &((struct timeval) SPEED_REDETECT_TV), >=)) {\n                sem_wait(&(shm_conn_info->stats_sem));\n                redetect_head_unsynced(chan_mask, -1);\n                sem_post(&(shm_conn_info->stats_sem));\n            }\n            #ifdef CLIENTONLY\n            timersub(&info.current_time, &shm_conn_info->last_head, &tv_tmp_tmp_tmp);\n            if (timercmp(&tv_tmp_tmp_tmp, &((struct timeval) {800,0}), >=)) {\n                vlog(LOG_ERR, \"WARNING! last_head too high psl %d > lrs %d\", seq_num, info.exact_rtt);\n                sq_control = 0;\n            } else {\n                sq_control = 1;\n            }\n            #endif\n            if (info.just_started_recv == 1) {\n                uint32_t time_passed = tv_tmp.tv_sec * 1000 + tv_tmp.tv_usec / 1000;\n                if (time_passed == 0)\n                    time_passed = 1;\n                info.speed_efficient = info.byte_efficient / time_passed;\n                info.speed_r_mode = info.byte_r_mode / time_passed;\n                info.speed_resend = info.byte_resend / time_passed;\n                info.byte_efficient = 0;\n                info.byte_resend = 0;\n                info.byte_r_mode = 0;\n                for (int i = 0; i < info.channel_amount; i++) {\n                    // speed(kb/s) calculation\n                    sem_wait(&(shm_conn_info->stats_sem));\n                    shm_conn_info->stats[info.process_num].time_lag_remote = time_lag_local.time_lag;\n                    shm_conn_info->stats[info.process_num].speed_chan_data[i].up_current_speed =\n                            shm_conn_info->stats[info.process_num].speed_chan_data[i].up_data_len_amt / time_passed;\n                    sem_post(&(shm_conn_info->stats_sem));\n                    shm_conn_info->stats[info.process_num].speed_chan_data[i].up_data_len_amt = 0;\n                    shm_conn_info->stats[info.process_num].speed_chan_data[i].down_current_speed =\n                            shm_conn_info->stats[info.process_num].speed_chan_data[i].down_data_len_amt / (time_passed);\n                    info.channel[i].download = shm_conn_info->stats[info.process_num].speed_chan_data[i].down_current_speed;\n                    shm_conn_info->stats[info.process_num].speed_chan_data[i].down_data_len_amt = 0;\n#ifdef TRACE\n                    vlog(LOG_INFO, \"upload speed %\"PRIu32\" kb/s physical channel %d logical channel %d\",\n                            shm_conn_info->stats[info.process_num].speed_chan_data[i].up_current_speed, info.process_num, i);\n                    vlog(LOG_INFO, \"download speed %\"PRIu32\" kb/s physical channel %d logical channel %d\",\n                            shm_conn_info->stats[info.process_num].speed_chan_data[i].down_current_speed, info.process_num, i);\n#endif\n                    // speed in packets/sec calculation\n                    shm_conn_info->stats[info.process_num].speed_chan_data[i].down_packet_speed =\n                            (shm_conn_info->stats[info.process_num].speed_chan_data[i].down_packets / tv_tmp.tv_sec);\n                    shm_conn_info->stats[info.process_num].speed_chan_data[i].down_packets = 0;\n#ifdef TRACE\n                    vlog(LOG_INFO, \"download speed %\"PRIu32\" packet/s physical channel %d logical channel %d lport %d rport %d\",\n                            shm_conn_info->stats[info.process_num].speed_chan_data[i].down_packet_speed, info.process_num, i, info.channel[i].lport, info.channel[i].rport);\n#endif\n                }\n                //github.com - Issue #11\n                int time_lag_cnt = 0, time_lag_sum = 0;\n                for (int i = 0; i < MAX_TCP_LOGICAL_CHANNELS; i++) {\n                    if (time_lag_info_arr[i].time_lag_cnt != 0) {\n                        time_lag_cnt++;\n                        time_lag_sum += time_lag_info_arr[i].time_lag_sum / time_lag_info_arr[i].time_lag_cnt;\n                        time_lag_info_arr[i].time_lag_sum = 0;\n                        time_lag_info_arr[i].time_lag_cnt = 0;\n                    }\n                }\n                time_lag_local.time_lag = time_lag_cnt != 0 ? time_lag_sum / time_lag_cnt : 0;\n\n                //todo send time_lag for all process(PHYSICAL CHANNELS)\n                uint32_t time_lag_remote;\n                uint16_t pid_remote;\n                if(send_q_eff_mean > 1000) { // TODO: invent a more neat way to start sending buf_len (>0? changed?)// TODO removeL this was due to bug two lines below. Now fixed\n                    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                        if(buf_len_sent[i] == my_miss_packets_max) continue;\n                        buf_len_sent[i] = my_miss_packets_max;\n                        sem_wait(&(shm_conn_info->stats_sem));\n                        /* If pid is null --> link didn't up --> continue*/\n                        if (shm_conn_info->stats[i].pid == 0) {\n                            sem_post(&(shm_conn_info->stats_sem));\n                            continue;\n                        }\n                        if (debug_trace) {\n                            vlog(LOG_INFO, \"Sending time lag (now buf_len) for %i buf_len %i.\", i, my_miss_packets_max);\n                        }\n                        time_lag_remote = shm_conn_info->stats[i].time_lag_remote;\n                        /* we store my_miss_packet_max value in 12 upper bits 2^12 = 4096 mx is 4095*/\n                        time_lag_remote &= 0xFFFFF; // shrink to 20bit\n                        time_lag_remote = shm_conn_info->stats[i].time_lag_remote | (my_miss_packets_max << 20);\n                        pid_remote = shm_conn_info->stats[i].pid_remote;\n                        uint32_t tmp_host = shm_conn_info->miss_packets_max_send_counter++;\n                        tmp_host &= 0xFFFF;\n    //vlog(LOG_ERR, \"DEBUGG tmp_host %\"PRIu32\"\", tmp_host); //?????\n                        sem_post(&(shm_conn_info->stats_sem));\n                        // sem_wait(write_buf_sem);\n                        tmp_host |= shm_conn_info->tflush_counter << 16;\n                        shm_conn_info->tflush_counter = 0;\n                        // sem_post(write_buf_sem);\n    //                    vlog(LOG_ERR, \"DEBUGG tmp_host packed %\"PRIu32\"\", tmp_host); //?????\n                        uint32_t time_lag_remote_h = htonl(time_lag_remote); // we have two values in time_lag_remote(_h)\n                        memcpy(buf, &time_lag_remote_h, sizeof(uint32_t));\n                        uint16_t FRAME_TIME_LAG_h = htons(FRAME_TIME_LAG);\n                        memcpy(buf + sizeof(uint32_t), &FRAME_TIME_LAG_h, sizeof(uint16_t));\n                        uint16_t pid_remote_h = htons(pid_remote);\n                        memcpy(buf + sizeof(uint32_t) + sizeof(uint16_t), &pid_remote_h, sizeof(uint16_t));\n                        uint32_t miss_packet_counter_h = htonl(tmp_host);\n                        memcpy(buf + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t), &miss_packet_counter_h, sizeof(uint32_t));\n                        int len_ret = proto_write(info.channel[0].descriptor, buf,\n                                ((sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t)) | VTUN_BAD_FRAME));\n                        if (len_ret < 0) {\n                            vlog(LOG_ERR, \"Could not send time_lag + pid pkt; exit\"); //?????\n                            linker_term = TERM_NONFATAL; //?????\n                        }\n                        shm_conn_info->stats[info.process_num].speed_chan_data[0].up_data_len_amt += len_ret;\n                        shm_conn_info->stats[info.process_num].packet_upload_cnt++;\n                        info.channel[0].up_len += len_ret;\n                    }\n                }\n                my_miss_packets_max = 0;\n                if (delay_cnt == 0)\n                    delay_cnt = 1;\n                mean_delay = (delay_acc / delay_cnt);\n#ifdef DEBUGG\n                //vlog(LOG_INFO, \"tick! cn: %s; md: %d, dacq: %d, w: %d, isl: %d, bl: %d, as: %d, bsn: %d, brn: %d, bsx: %d, drop: %d, rrqrx: %d, rxs: %d, ms: %d, rxmntf: %d, rxm_notf: %d, chok: %d, info.rtt: %d, lkdf: %d, msd: %d, ch: %d, chsdev: %d, chrdev: %d, mlh: %d, mrh: %d, mld: %d\", lfd_host->host, channel_mode, dev_my_cnt, weight, incomplete_seq_len, buf_len, shm_conn_info->normal_senders, statb.bytes_sent_norm, statb.bytes_rcvd_norm, statb.bytes_sent_rx, statb.pkts_dropped, statb.rxmit_req_rx, statb.rxmits, statb.mode_switches, statb.rxm_ntf, statb.rxmits_notfound, statb.chok_not, info.info.rtt, (info.current_time.tv_sec - shm_conn_info->lock_time), mean_delay, info.channel_amount, std_dev(statb.bytes_sent_chan, info.channel_amount), std_dev(&statb.bytes_rcvd_chan[1], (info.channel_amount-1)), statb.max_latency_hit, statb.max_reorder_hit, statb.max_latency_drops);\n                //vlog(LOG_INFO, \"ti! s/r %d %d %d %d %d %d / %d %d %d %d %d %d\", statb.bytes_rcvd_chan[0],statb.bytes_rcvd_chan[1],statb.bytes_rcvd_chan[2],statb.bytes_rcvd_chan[3],statb.bytes_rcvd_chan[4],statb.bytes_rcvd_chan[5], statb.bytes_sent_chan[0],statb.bytes_sent_chan[1],statb.bytes_sent_chan[2],statb.bytes_sent_chan[3],statb.bytes_sent_chan[4],statb.bytes_sent_chan[5] );\n#endif\n                dev_my_cnt = 0;\n                last_tick = info.current_time.tv_sec;\n                shm_conn_info->alive = info.current_time.tv_sec;\n                delay_acc = 0;\n                delay_cnt = 0;\n\n                for (i = 1; i < info.channel_amount; i++) {\n                    // sem_wait(&(shm_conn_info->write_buf_sem));\n                    uint32_t last_lws_notified_tmp = shm_conn_info->write_buf[i].last_lws_notified;\n                    uint32_t last_written_seq_tmp = shm_conn_info->write_buf[i].last_written_seq;\n                    // sem_post(&(shm_conn_info->write_buf_sem));\n                    if (((info.current_time.tv_sec - last_lws_notified_tmp) > LWS_NOTIFY_PEROID) && (last_written_seq_tmp > last_last_written_seq[i])) {\n                        if(!select_net_write(i)) continue;\n                        // TODO: DUP code!\n                        if(debug_trace) {\n                            vlog(LOG_INFO, \"Sending LWS...\");\n                        }\n                        sem_wait(&(shm_conn_info->write_buf_sem));\n                        *((uint32_t *) buf) = htonl(shm_conn_info->write_buf[i].last_written_seq);\n                        last_last_written_seq[i] = shm_conn_info->write_buf[i].last_written_seq;\n                        shm_conn_info->write_buf[i].last_lws_notified = info.current_time.tv_sec;\n                        sem_post(&(shm_conn_info->write_buf_sem));\n                        *((uint16_t *) (buf + sizeof(uint32_t))) = htons(FRAME_LAST_WRITTEN_SEQ);\n                        // send LWS\n                        int len_ret = udp_write(info.channel[i].descriptor, buf, ((sizeof(uint32_t) + sizeof(flag_var)) | VTUN_BAD_FRAME));\n                        if (len_ret < 0) {\n                            vlog(LOG_ERR, \"Could not send last_written_seq pkt; exit\");\n                            linker_term = TERM_NONFATAL;\n                        }\n                        shm_conn_info->stats[info.process_num].speed_chan_data[i].up_data_len_amt += len_ret;\n                        shm_conn_info->stats[info.process_num].packet_upload_cnt++;\n                        info.channel[i].up_len += len_ret;\n                    }\n                }\n            \n            \n            \n            \n             // do llist checks\n            \n            alive_physical_channels = 0;\n            int check_result=0;\n            \n            // sem_wait(&(shm_conn_info->AG_flags_sem));\n            uint32_t chan_mask = shm_conn_info->channels_mask;\n            // sem_post(&(shm_conn_info->AG_flags_sem));\n            \n            \n            for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) { \n                if (chan_mask & (1 << i)) {\n                    alive_physical_channels++;\n                }\n            }\n            if (alive_physical_channels == 0) {\n                vlog(LOG_ERR, \"ASSERT All physical channels dead!!!\");\n                alive_physical_channels = 1;\n            }\n            if(shm_conn_info->t_model_rtt100 > MAX_NETWORK_STALL_MS * 100) {\n                ms2tv(&tv_tmp, shm_conn_info->t_model_rtt100 / 100);\n                sem_wait(&(shm_conn_info->write_buf_sem));\n                shm_conn_info->max_network_stall = tv_tmp;\n                sem_post(&(shm_conn_info->write_buf_sem));\n            } else {\n                sem_wait(&(shm_conn_info->write_buf_sem));\n                shm_conn_info->max_network_stall = (struct timeval) MAX_NETWORK_STALL;\n                sem_post(&(shm_conn_info->write_buf_sem));\n            }\n            \n            \n               last_timing.tv_sec = info.current_time.tv_sec;\n               last_timing.tv_usec = info.current_time.tv_usec;\n          }\n#ifdef TESTING\n            //write test case here\n#endif\n            if(shm_conn_info->packet_debug_enabled) {\n                debug_trace = 1;\n            }\n            fire_event(&my_events->tick);\n        }\n        // <<< END TICK\n        \n\n\n        /* Detect that we need to enter retransmit_send as soon as possible \n            (some packets left unsent AND we're not holding) */\n        int need_retransmit = 0;\n        if( (ag_flag == R_MODE) && (hold_mode == 0) ) { // WARNING: if AG_MODE? or of DROP mode?\n            //sem_wait(&(shm_conn_info->common_sem));\n            for (int i = 1; i < info.channel_amount; i++) {\n                if(shm_conn_info->seq_counter[1] > last_sent_packet_num[1].seq_num) {\n                    // WARNING! disabled push-to-top policy!\n                    if( !((!info.head_channel) && PUSH_TO_TOP && ptt_allow_once && (shm_conn_info->dropping || shm_conn_info->head_lossing)) && !check_delivery_time(SKIP_SENDING_CLD_DIV)) {\n                        // noop?\n                    } else {\n                        need_retransmit = 1; \n                    }\n                    break;\n                }\n            }\n            //sem_post(&(shm_conn_info->common_sem));\n        }\n        // gettimeofday(&info.current_time, NULL); // TODO: required??\n        \n        \n\n        //check redundancy code packet's timer\n#ifdef SUM_SEND\n        gettimeofday(&info.current_time, NULL );\n        // for (int i = 1; i <= info.channel_amount; i++) {\n        {\n            int i = 1;\n            for (int selection = 0; selection < SELECTION_NUM; selection++) {\n                int flag = 0, len_sum;\n                //int tmp = shm_conn_info->t_model_rtt100;\n                int tmp = 100000;\n                tv_tmp.tv_sec = tmp / 100000;\n                tv_tmp.tv_usec = (tmp % 100000) * 10;\n                sem_wait(&(shm_conn_info->common_sem)); // critical_sem\n                shm_conn_info->packet_code[selection][i].timer.timer_time = tv_tmp;\n                if (fast_check_timer(&shm_conn_info->packet_code[selection][i].timer, &info.current_time)\n                        && (shm_conn_info->packet_code[selection][i].len_sum > 0)) {\n#ifdef CODE_LOG\n                    vlog(LOG_INFO, \"raise REDUNDANT_CODE_TIMER_TIME add FRAME_REDUNDANCY_CODE to fast resend selection %d seq start %u stop %u  cur %u len %i time passed %u\", selection, shm_conn_info->packet_code[selection][i].start_seq, shm_conn_info->packet_code[selection][i].stop_seq, shm_conn_info->packet_code[selection][i].current_seq, shm_conn_info->packet_code[selection][i].len_sum,tv2ms(&info.current_time) - tv2ms(&shm_conn_info->packet_code[selection][i].timer.start_time));\n#endif\n                    shm_conn_info->packet_code[selection][i].stop_seq = shm_conn_info->packet_code[selection][i].current_seq;\n                    len_sum = pack_redundancy_packet_code(buf2, &shm_conn_info->packet_code[selection][i],\n                            shm_conn_info->packet_code[selection][i].stop_seq, selection, FRAME_REDUNDANCY_CODE);\n                    fast_update_timer(&shm_conn_info->packet_code[selection][i].timer, &info.current_time);\n                    flag = 1;\n\n                }\n\n                sem_post(&(shm_conn_info->common_sem)); // critical_sem\n                if (flag) {\n                    len_sum = pack_packet(i, buf2, len_sum, 0, 0 /*local seq*/, FRAME_REDUNDANCY_CODE);\n                    if (info.channel[i].local_seq_num == (UINT32_MAX - 1)) {\n                        info.channel[i].local_seq_num = 0;\n                    }\n#ifdef CODE_LOG\n                    vlog(LOG_ERR, \"add redund code to fast_resend\");\n#endif\n                    sem_wait(&(shm_conn_info->resend_buf_sem)); // critical_sem\n                    int idx = add_fast_resend_frame(i, buf2, len_sum | VTUN_BAD_FRAME, 0);\n                    sem_post(&(shm_conn_info->resend_buf_sem)); // critical_sem\n                    if (idx == -1) {\n                        vlog(LOG_ERR, \"ERROR: fast_resend_buf is full\");\n                    }\n\n                }\n                if (flag) {\n                    need_retransmit = 1;\n                }\n                flag = 0;\n            }\n        }\n#endif\n                    /*\n                     *\n                        _____         .__                   \n                      /     \\ _____  |__| ____             \n                     /  \\ /  \\\\__  \\ |  |/    \\            \n                    /    Y    \\/ __ \\|  |   |  \\           \n                    \\____|__  (____  /__|___|  /           \n                            \\/     \\/        \\/            \n                                  .__                 __   \n                      ______ ____ |  |   ____   _____/  |_ \n                     /  ___// __ \\|  | _/ __ \\_/ ___\\   __\\\n                     \\___ \\\\  ___/|  |_\\  ___/\\  \\___|  |  \n                    /____  >\\___  >____/\\___  >\\___  >__|  \n                         \\/     \\/          \\/     \\/      \n                     * Now do a select () from all devices and channels\n                     */\n        // removed sem here in a hope of atomic and non-critial sync\n        chan_mask = shm_conn_info->channels_mask;\n        // end removed sem\n        FD_ZERO(&fdset_w);\n        sem_wait(write_buf_sem); // critical_sem\n        for (;;)\n            if (info.last_sent_FLI_idx != shm_conn_info->loss_idx) {\n                info.last_sent_FLI_idx++;\n                if (info.last_sent_FLI_idx == LOSS_ARRAY) {\n                    info.last_sent_FLI_idx = 0;\n                }\n                vlog(LOG_INFO, \"FRAME_LOSS_INFO sending my idx %d shm idx %d time %d %d psl %d pbl %d\", info.last_sent_FLI_idx,\n                        shm_conn_info->loss_idx, shm_conn_info->loss[info.last_sent_FLI_idx].timestamp.tv_sec,\n                        shm_conn_info->loss[info.last_sent_FLI_idx].timestamp.tv_usec, shm_conn_info->loss[info.last_sent_FLI_idx].psl,\n                        shm_conn_info->loss[info.last_sent_FLI_idx].pbl);\n\n                uint32_t tmp_h = htonl(info.last_sent_FLI_idx);\n                memcpy(buf, &tmp_h, sizeof(uint32_t));\n                tmp_h = htons(FRAME_LOSS_INFO);\n                memcpy(buf + sizeof(uint32_t), &tmp_h, sizeof(uint16_t));\n                tmp_h = htonl(shm_conn_info->loss[info.last_sent_FLI_idx].timestamp.tv_sec);\n                memcpy(buf + sizeof(uint16_t) + sizeof(uint32_t), &tmp_h, sizeof(uint32_t));\n                tmp_h = htonl(shm_conn_info->loss[info.last_sent_FLI_idx].timestamp.tv_usec);\n                memcpy(buf + sizeof(uint16_t) + 2 * sizeof(uint32_t), &tmp_h, sizeof(uint32_t));\n                tmp_h = htonl(shm_conn_info->loss[info.last_sent_FLI_idx].psl);\n                memcpy(buf + sizeof(uint16_t) + 3 * sizeof(uint32_t), &tmp_h, sizeof(uint32_t));\n                tmp_h = htonl(shm_conn_info->loss[info.last_sent_FLI_idx].pbl);\n                memcpy(buf + sizeof(uint16_t) + 4 * sizeof(uint32_t), &tmp_h, sizeof(uint32_t));\n                tmp_h = htonl(shm_conn_info->loss[info.last_sent_FLI_idx].sqn);\n                memcpy(buf + sizeof(uint16_t) + 5 * sizeof(uint32_t), &tmp_h, sizeof(uint32_t));\n                uint16_t tmp_s = htons(shm_conn_info->loss[info.last_sent_FLI_idx].who_lost);\n                memcpy(buf + sizeof(uint16_t) + 6 * sizeof(uint32_t), &tmp_s, sizeof(uint16_t));\n\n                fd_set fdset2;\n                tv_tmp.tv_sec = 0;\n                tv_tmp.tv_usec = 0;\n                FD_ZERO(&fdset2);\n                FD_SET(service_channel, &fdset2);\n                if (select(service_channel + 1, NULL, &fdset2, NULL, &tv_tmp) > 0) {\n                    if (proto_write(service_channel, buf, ((6 * sizeof(uint32_t) + 2 * sizeof(uint16_t)) | VTUN_BAD_FRAME)) < 0) {\n                        vlog(LOG_ERR, \"Could not send FLI pkt; exit %s(%d)\", strerror(errno), errno);\n                        close(prio_s);\n                        linker_term = TERM_NONFATAL;\n                        break;\n                    }\n                } else {\n                    info.last_sent_FLI_idx--;\n                    if (info.last_sent_FLI_idx < 0) {\n                        info.last_sent_FLI_idx = LOSS_ARRAY - 1;\n                    }\n                    break;\n                }\n            } else\n                break;\n        for (;;)\n            if (info.last_sent_FLLI_idx != shm_conn_info->l_loss_idx) {\n                info.last_sent_FLLI_idx++;\n                if (info.last_sent_FLLI_idx == LOSS_ARRAY) {\n                    info.last_sent_FLLI_idx = 0;\n                }\n                vlog(LOG_INFO, \"FRAME_L_LOSS_INFO sending sqn %lu ts %ld.%06ld\", shm_conn_info->l_loss[info.last_sent_FLLI_idx].sqn, shm_conn_info->l_loss[info.last_sent_FLLI_idx].timestamp);\n                uint32_t tmp_h = htonl(info.last_sent_FLLI_idx);\n                memcpy(buf, &tmp_h, sizeof(uint32_t));\n                tmp_h = htons(FRAME_L_LOSS_INFO);\n                memcpy(buf + sizeof(uint32_t), &tmp_h, sizeof(uint16_t));\n                tmp_h = htonl(shm_conn_info->l_loss[info.last_sent_FLLI_idx].timestamp.tv_sec);\n                memcpy(buf + sizeof(uint16_t) + sizeof(uint32_t), &tmp_h, sizeof(uint32_t));\n                tmp_h = htonl(shm_conn_info->l_loss[info.last_sent_FLLI_idx].timestamp.tv_usec);\n                memcpy(buf + sizeof(uint16_t) + 2 * sizeof(uint32_t), &tmp_h, sizeof(uint32_t));\n                tmp_h = htonl(shm_conn_info->l_loss[info.last_sent_FLLI_idx].psl);\n                memcpy(buf + sizeof(uint16_t) + 3 * sizeof(uint32_t), &tmp_h, sizeof(uint32_t));\n                tmp_h = htonl(shm_conn_info->l_loss[info.last_sent_FLLI_idx].pbl);\n                memcpy(buf + sizeof(uint16_t) + 4 * sizeof(uint32_t), &tmp_h, sizeof(uint32_t));\n                uint16_t tmp_16_h = htons(shm_conn_info->l_loss[info.last_sent_FLLI_idx].name);\n                memcpy(buf + sizeof(uint16_t) + 5 * sizeof(uint32_t), &tmp_16_h, sizeof(uint16_t));\n                tmp_h = htonl(shm_conn_info->l_loss[info.last_sent_FLLI_idx].sqn);\n                memcpy(buf + sizeof(uint16_t) + 6 * sizeof(uint32_t), &tmp_h, sizeof(uint32_t));\n                uint16_t tmp_s = htons(shm_conn_info->l_loss[info.last_sent_FLLI_idx].who_lost);\n                memcpy(buf + sizeof(uint16_t) + 7 * sizeof(uint32_t), &tmp_s, sizeof(uint16_t));\n                \n                fd_set fdset2;\n                tv_tmp.tv_sec = 0;\n                tv_tmp.tv_usec = 0;\n                FD_ZERO(&fdset2);\n                FD_SET(service_channel, &fdset2);\n                if (select(service_channel + 1, NULL, &fdset2, NULL, &tv_tmp) > 0) {\n                    if (proto_write(service_channel, buf, ((7 * sizeof(uint32_t) + 3 * sizeof(uint16_t)) | VTUN_BAD_FRAME)) < 0) {\n                        vlog(LOG_ERR, \"Could not send FLLI pkt; exit %s(%d)\", strerror(errno), errno);\n                        close(prio_s);\n                        linker_term = TERM_NONFATAL;\n                        break;\n                    }\n                } else {\n                    info.last_sent_FLLI_idx--;\n                    if (info.last_sent_FLLI_idx < 0) {\n                        info.last_sent_FLLI_idx = LOSS_ARRAY - 1;\n                    }\n                    break;\n                }\n            } else\n                break;\n        int next_token_ms;\n        next_token_ms = 0;\n        add_tokens(1, &next_token_ms);\n        if (get_write_buf_wait_data(chan_mask, &next_token_ms) || need_retransmit || check_fast_resend()) { // TODO: need_retransmit here is because we think that it does continue almost immediately on select\n            pfdset_w = &fdset_w;\n            FD_SET(info.tun_device, pfdset_w);\n        } else {\n            pfdset_w = NULL;\n        }\n        sem_post(write_buf_sem); // critical_sem\n        #ifdef FRTTDBG\n            vlog(LOG_INFO, \"next_token_ms %d\", next_token_ms);\n        #endif\n        FD_ZERO(&fdset);\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"debug: HOLD_MODE - %i just_started_recv - %i\", hold_mode, info.just_started_recv);\n#endif\n        struct timespec sel_tv;\n        if (((hold_mode == 0) || (drop_packet_flag == 1)) && (info.just_started_recv == 1)) {\n            FD_SET(info.tun_device, &fdset);\n            sel_tv.tv_sec = 0;\n            if ((next_token_ms == 0) || (next_token_ms > (SELECT_SLEEP_USEC / 1000))) {\n                sel_tv.tv_nsec = SELECT_SLEEP_USEC * 1000;\n            } else {\n                sel_tv.tv_nsec = next_token_ms * 1000 * 1000;\n            }\n        } else {\n            sel_tv.tv_sec = get_info_time.tv_sec;\n            if ((next_token_ms == 0) || (next_token_ms > (get_info_time.tv_usec / 1000))) {\n                sel_tv.tv_nsec = get_info_time.tv_usec * 1000;\n            } else {\n                sel_tv.tv_nsec = next_token_ms * 1000 * 1000;\n            }\n#ifdef DEBUGG\n            vlog(LOG_INFO, \"tun read select skip\");\n            vlog(LOG_INFO, \"debug: HOLD_MODE\");\n#endif\n        }\n        // for (i = 0; i < info.channel_amount; i++) {\n        //     FD_SET(info.channel[i].descriptor, &fdset);\n        // }\n        \n        FD_SET(info.channel[0].descriptor, &fdset);\n        FD_SET(info.channel[1].descriptor, &fdset);\n\n#ifdef DEBUGG\n        struct timeval work_loop1, work_loop2;\n        gettimeofday(&work_loop1, NULL );\n#endif\n#ifdef SYSLOG\n        // CPU LAG >>>\n        gettimeofday(&cpulag, NULL);\n        timersub(&cpulag, &old_time, &tv_tmp_tmp_tmp);\n        if(tv_tmp_tmp_tmp.tv_usec > SUPERLOOP_MAX_LAG_USEC) {\n            vlog(LOG_INFO,\"WARNING! CPU deficiency detected! Cycle lag: %ld.%06ld\", tv_tmp_tmp_tmp.tv_sec, tv_tmp_tmp_tmp.tv_usec);\n        }\n        // <<< END CPU_LAG\n#endif\nmain_select:\n        select_tv_copy = tv;\n        const struct timespec *sel_tvp = &sel_tv;\n        select_check=1;\n        len = pselect(maxfd + 1, &fdset, pfdset_w, NULL, sel_tvp, &unblock_mask);\n        select_check=0;\n#ifdef DEBUGG\nif(drop_packet_flag) {\n        //gettimeofday(&work_loop2, NULL );\n        vlog(LOG_INFO, \"First select time: us descriptors num: %i\", length);\n}\n#endif\n\n        gettimeofday(&old_time, NULL); // cpu-lag..\n\n        if (len < 0) { // selecting from multiple processes does actually work...\n            // errors are OK if signal is received... TODO: do we have any signals left???\n            if( errno != EAGAIN && errno != EINTR ) {\n                vlog(LOG_INFO, \"eagain select err; exit\");\n                break;\n            } else {\n                //vlog(LOG_INFO, \"else select err; continue norm\");\n                continue;\n            }\n        }\n\n        gettimeofday(&info.current_time, NULL); // current time may be ruined by select... TODO: this is expensive call -> optimize by timeradd?\n\n        if( !len ) {\n            /* We are idle, lets check connection */\n#ifdef DEBUGG\n            vlog(LOG_INFO, \"idle...\");\n#endif\n                /* Send ECHO request */\n                if((info.current_time.tv_sec - last_action) > lfd_host->PING_INTERVAL) {\n                    if(ping_rcvd) {\n                         ping_rcvd = 0;\n                         last_ping = info.current_time.tv_sec;\n                         vlog(LOG_INFO, \"PING ...\");\n                         // ping ALL channels! this is required due to 120-sec limitation on some NATs\n                    for (i = 0; i < info.channel_amount; i++) { // TODO: remove ping DUP code\n                        if(!select_net_write(i)) continue;\n                        ping_req_tv[i] = info.current_time;\n                        int len_ret;\n                        if (i == 0) {\n                            len_ret = proto_write(info.channel[i].descriptor, buf, VTUN_ECHO_REQ);\n                        } else {\n                            // send PING request\n                            len_ret = udp_write(info.channel[i].descriptor, buf, VTUN_ECHO_REQ);\n                        }\n                        if (len_ret < 0) {\n                                 vlog(LOG_ERR, \"Could not send echo request chan %d reason %s (%d)\", i, strerror(errno), errno);\n                                 linker_term = TERM_NONFATAL;\n                                 break;\n                             }\n                        shm_conn_info->stats[info.process_num].speed_chan_data[i].up_data_len_amt += len_ret;\n                        shm_conn_info->stats[info.process_num].packet_upload_cnt++;\n                        info.channel[i].up_len += len_ret;\n                         }\n                         last_action = info.current_time.tv_sec; // TODO: clean up last_action/or/last_ping wtf.\n                    }\n                }\n            continue;\n        }\n        CHKCPU(1);\n        /*\n             *\n             *\n\n            _   _  _____ _____ _    _  ___________ _   __\n           | \\ | ||  ___|_   _| |  | ||  _  | ___ \\ | / /\n           |  \\| || |__   | | | |  | || | | | |_/ / |/ / \n           | . ` ||  __|  | | | |/\\| || | | |    /|    \\ \n           | |\\  || |___  | | \\  /\\  /\\ \\_/ / |\\ \\| |\\  \\\n           \\_| \\_/\\____/  \\_/  \\/  \\/  \\___/\\_| \\_\\_| \\_/\n                                                         \n                                                         \n           ______ _____  ___ ______                      \n           | ___ \\  ___|/ _ \\|  _  \\                     \n           | |_/ / |__ / /_\\ \\ | | |                     \n           |    /|  __||  _  | | | |                     \n           | |\\ \\| |___| | | | |/ /                      \n           \\_| \\_\\____/\\_| |_/___/                       \n                                                         \n                                                 \n             *\n             * Read frames from network(service_channel), decode and pass them to\n             * the local device (tun_device)\n             *\n             *\n             *\n             *\n             * */\n        // int alive_physical_channels = 0;\n        // if (FD_ISSET(info.tun_device, &fdset_w)) {\n        //     sem_wait(&(shm_conn_info->AG_flags_sem));\n        //     uint32_t chan_mask = shm_conn_info->channels_mask;\n        //     sem_post(&(shm_conn_info->AG_flags_sem));\n        //     for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        //         if (chan_mask & (1 << i)) {\n        //             alive_physical_channels++;\n        //         }\n        //     }\n        //     if (alive_physical_channels == 0) {\n        //         vlog(LOG_ERR, \"ASSERT All physical channels dead!!!\");\n        //         alive_physical_channels = 1;\n        //     }\n        // }\n        CHKCPU(11);\n        //check all chans for being set..\n        for (chan_num = 0; chan_num < info.channel_amount; chan_num++) {\n            if (FD_ISSET(info.tun_device, &fdset_w)) {\n                sem_wait(write_buf_sem); // critical_sem\n                if (write_buf_check_n_flush(chan_num)) { //double flush if possible\n                    //write_buf_check_n_flush(chan_num); // fix for #509\n                }\n                sem_post(write_buf_sem); // critical_sem\n            }\n        CHKCPU(111);\n            fd0 = -1;\n            if(FD_ISSET(info.channel[chan_num].descriptor, &fdset)) {\n                if(shm_conn_info->write_buf[chan_num_virt].frames.rel_head == -1) { // protect from unnesessary lock in case of high-speed workload (buffer not empty)\n                    sem_wait(write_buf_sem); // critical_sem\n                    fprev = shm_conn_info->write_buf[chan_num_virt].frames.rel_head;\n                    if(fprev == -1) { // don't panic ;-)\n                         shm_conn_info->write_buf[chan_num_virt].last_write_time.tv_sec = info.current_time.tv_sec;\n                         shm_conn_info->write_buf[chan_num_virt].last_write_time.tv_usec = info.current_time.tv_usec;\n                    }\n                    sem_post(write_buf_sem); // critical_sem\n                }\n                fd0=info.channel[chan_num].descriptor; // TODO Why this need????\n\n                //net_counter++; // rxmit mode\n                last_action = info.current_time.tv_sec;\n                if (chan_num == 0) {\n                    len = tcp_read(fd0, buf);\n                } else {\n                    len = udp_read(fd0, buf);\n                }\n\n        CHKCPU(112);\n#ifdef DEBUGG\nif(drop_packet_flag) {\n                vlog(LOG_INFO, \"data on net... chan %d\", chan_num);\n}\n#endif\n                if( len<= 0 ) {\n                    if (len == 0) {\n                        vlog(LOG_INFO, \"proto_read return 0, the peer with %d has performed an orderly shutdown. TERM_NONFATAL\", chan_num);\n                        linker_term = TERM_NONFATAL;\n                        break;\n                    }\n                    if(len < 0) {\n                         vlog(LOG_INFO, \"sem_post! proto read <0; reason %s (%d)\", strerror(errno), errno);\n                         linker_term = TERM_NONFATAL;\n                         break;\n                    }\n                    if(proto_err_cnt > 5) { // TODO XXX whu do we need this?? why doesnt proto_read just return <0???\n                             vlog(LOG_INFO, \"MAX proto read len==0 reached; exit!\");\n                             linker_term = TERM_NONFATAL;\n                             break;\n                    }\n                    proto_err_cnt++;\n                    continue;\n                }\n                proto_err_cnt = 0;\n                /* Handle frame flags module */\n\n                fl = len & ~VTUN_FSIZE_MASK;\n                len = len & VTUN_FSIZE_MASK;\n#ifdef DEBUGG\n                vlog(LOG_INFO, \"data on net... chan %d len %i\", chan_num, length);\n#endif\n                if(debug_trace) {\n                    vlog(LOG_INFO, \"data on net... chan %d len %i\", chan_num, len);\n                }\n        CHKCPU(12);\n                shm_conn_info->stats[info.process_num].speed_chan_data[chan_num].down_data_len_amt += len;\n                if( fl ) { // a packet with flag, relatively rare\n                    if( fl==VTUN_BAD_FRAME ) {\n                        flag_var = ntohs(*((uint16_t *)(buf+(sizeof(uint32_t)))));\n                        if(flag_var == FRAME_MODE_NORM) {\n                            vlog(LOG_ERR, \"ASSERT FAILED! received FRAME_MODE_NORM flag while not in MODE_RETRANSMIT mode!\");\n                            continue;\n                        } else if (flag_var == FRAME_REDUNDANCY_CODE) {\n#ifdef CODE_LOG\n                            vlog(LOG_INFO, \"FRAME_REDUNDANCY_CODE on net... chan %d len %i array index %i start_seq %\"PRIu32\"\", chan_num, len, shm_conn_info->packet_code_bulk_counter,ntohl(*((uint32_t *)(buf))));\n                            print_head_of_packet(buf + sizeof(uint32_t) + sizeof(uint16_t), \"recv redund code\",0, len - (sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint16_t)));\n#endif\n#ifdef SUM_SEND\n                            uint32_t local_seq_num, last_recv_lsn, packet_recv_spd;\n                            uint16_t mini_sum;\n                            len = seqn_break_tail(buf, len, NULL, &flag_var, &local_seq_num, NULL, &last_recv_lsn, &packet_recv_spd);\n                            /*\n                            unsigned int lrs2;\n                            if (lossed_consume(local_seq_num, 0, &lrs2, &info.channel[chan_num].local_seq_num_recv) == 0) { // TODO: lrs?? not updated!\n                                info.channel[chan_num].loss_time = info.current_time;\n                            }\n                            */\n                            info.channel[1].last_recv_time = info.current_time;\n                            sem_wait(write_buf_sem);\n                            int sumIndex = add_redundancy_packet_code(&shm_conn_info->packet_code_recived[chan_num][0],\n                                    &shm_conn_info->packet_code_bulk_counter, buf, len);\n                            uint32_t lostSeq = frame_llist_getLostPacket_byRange(&shm_conn_info->write_buf[chan_num].frames,&shm_conn_info->wb_just_write_frames[chan_num],\n                                    shm_conn_info->frames_buf, &shm_conn_info->packet_code_recived[chan_num][sumIndex]);\n                            vlog(LOG_INFO, \"FRAME_REDUNDANCY_CODE start_seq %\"PRIu32\" stop_seq %\"PRIu32\" LostAmount %d\",\n                                    shm_conn_info->packet_code_recived[chan_num][sumIndex].start_seq,\n                                    shm_conn_info->packet_code_recived[chan_num][sumIndex].stop_seq,\n                                    shm_conn_info->packet_code_recived[chan_num][sumIndex].lostAmount);\n                            if (shm_conn_info->packet_code_recived[chan_num][sumIndex].lostAmount == 1) {\n//#ifdef CODE_LOG\n                                vlog(LOG_INFO, \"Uniq lostSeq %u found lws %lu\", lostSeq, shm_conn_info->write_buf[chan_num].last_written_seq );\n//#endif\n                                int packet_index = check_n_repair_packet_code(&shm_conn_info->packet_code_recived[chan_num][0],\n                                        &shm_conn_info->wb_just_write_frames[chan_num], &shm_conn_info->write_buf[chan_num].frames,\n                                        shm_conn_info->frames_buf, lostSeq);\n                                if (packet_index > -1) {\n                                    shm_conn_info->packet_code_recived[chan_num][sumIndex].lostAmount = 0;\n                                    if (shm_conn_info->packet_code_recived[chan_num][packet_index].sum[0] != 0x45) {\n                                        print_head_of_packet(shm_conn_info->packet_code_recived[chan_num][packet_index].sum,\n                                                \"ASSERT BAD packet repaired \", lostSeq, shm_conn_info->packet_code_recived[chan_num][packet_index].len_sum);\n                                    } else {\n                                        vlog(LOG_INFO, \"{\\\"name\\\":\\\"%s\\\",\\\"repaired_seq_num\\\":%\"PRIu32\", \\\"place\\\": 2}\", lfd_host->host, lostSeq);\n#ifdef CODE_LOG\n                                    print_head_of_packet(shm_conn_info->packet_code_recived[chan_num][packet_index].sum, \"repaired \", lostSeq, shm_conn_info->packet_code_recived[chan_num][packet_index].len_sum);\n#endif\n                                    // TODO: assert here\n                                    write_buf_add(chan_num, shm_conn_info->packet_code_recived[chan_num][packet_index].sum,\n                                            shm_conn_info->packet_code_recived[chan_num][packet_index].len_sum, lostSeq, incomplete_seq_buf, &buf_len,\n                                            info.pid, &succ_flag);\n                                    }\n                                }\n                            }\n                            sem_post(write_buf_sem);\n#endif\n                            continue;\n                        } else if (flag_var == FRAME_MODE_RXMIT) {\n                            // okay\n                        } else if (flag_var == FRAME_JUST_STARTED) {\n                            // the opposite end has zeroed counters; zero mine!\n                            uint32_t session_hash_remote = ntohl(*((uint32_t *) (buf)));\n                            vlog(LOG_INFO, \"received FRAME_JUST_STARTED; receive remote hash - %u\", session_hash_remote);\n                            info.just_started_recv = 1;\n                            sem_wait(&(shm_conn_info->AG_flags_sem));\n                            if (shm_conn_info->session_hash_remote != session_hash_remote) {\n                                shm_conn_info->session_hash_remote = session_hash_remote;\n                                uint32_t chan_mask = shm_conn_info->channels_mask;\n                                vlog(LOG_INFO, \"zeroing counters old - %u new remote hash - %u\",shm_conn_info->session_hash_remote, session_hash_remote );\n                                shm_conn_info->tokens_lastadd_tv = info.current_time;\n                                sem_post(&(shm_conn_info->AG_flags_sem));\n                                info.session_hash_remote = session_hash_remote;\n                                for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                                    if ((i == info.process_num) || (!(chan_mask & (1 << i)))) {\n                                        continue;\n                                    }\n                                    sem_wait(&(shm_conn_info->stats_sem));\n                                    pid_t pid = shm_conn_info->stats[i].pid;\n                                    sem_post(&(shm_conn_info->stats_sem));\n                                }\n                                sem_wait(&(shm_conn_info->write_buf_sem));\n                                for (i = 0; i < info.channel_amount; i++) {\n                                    shm_conn_info->seq_counter[i] = SEQ_START_VAL;\n                                    shm_conn_info->write_buf[i].last_written_seq = SEQ_START_VAL;\n                                    shm_conn_info->write_buf[i].remote_lws = SEQ_START_VAL;\n                                    frame_llist_init(&(shm_conn_info->write_buf[i].frames));\n                                    frame_llist_init(&shm_conn_info->wb_just_write_frames[i]);\n                                    frame_llist_fill(&(shm_conn_info->wb_free_frames), shm_conn_info->frames_buf, FRAME_BUF_SIZE);\n                                }\n                                shm_conn_info->max_network_stall = (struct timeval) MAX_NETWORK_STALL;\n                                memset(shm_conn_info->w_stream_pkts, 0, sizeof(shm_conn_info->w_stream_pkts));\n                                sem_post(&(shm_conn_info->write_buf_sem));\n                                sem_wait(&(shm_conn_info->resend_buf_sem));\n                                for (i = 0; i < RESEND_BUF_SIZE; i++) {\n                                    if (shm_conn_info->resend_frames_buf[i].chan_num == chan_num)\n                                        shm_conn_info->resend_frames_buf[i].seq_num = 0;\n                                }\n                                memset(shm_conn_info->resend_frames_buf, 0, sizeof(struct frame_seq) * RESEND_BUF_SIZE);\n                                memset(shm_conn_info->fast_resend_buf, 0, sizeof(struct frame_seq) * MAX_TCP_PHYSICAL_CHANNELS);\n                                memset(shm_conn_info->write_buf_hashtable, 0, sizeof(shm_conn_info->write_buf_hashtable));\n                                shm_conn_info->resend_buf_idx = 0;\n                                shm_conn_info->fast_resend_buf_idx = 0;\n                                shm_conn_info->latest_la_sqn = 0;\n                                sem_post(&(shm_conn_info->resend_buf_sem));\n                            } else {\n                                sem_post(&(shm_conn_info->AG_flags_sem));\n                            }\n                            continue;\n                        } else if (flag_var == FRAME_PRIO_PORT_NOTIFY) {\n                            /*\n                                \n                    ______     _                     _   _  __       \n                    | ___ \\   (_)                   | | (_)/ _|      \n                    | |_/ / __ _  ___    _ __   ___ | |_ _| |_ _   _ \n                    |  __/ '__| |/ _ \\  | '_ \\ / _ \\| __| |  _| | | |\n                    | |  | |  | | (_) | | | | | (_) | |_| | | | |_| |\n                    \\_|  |_|  |_|\\___/  |_| |_|\\___/ \\__|_|_|  \\__, |\n                                                                __/ |\n                                                               |___/  \n                            */\n                            // connect to port specified\n                            if (server_addr(&rmaddr, lfd_host) < 0) {\n                                vlog(LOG_ERR, \"Could not set server address!\");\n                                linker_term = TERM_FATAL;\n                                break;\n                            }\n                            inet_ntop(AF_INET, &rmaddr.sin_addr, ipstr, sizeof ipstr);\n                            vlog(LOG_INFO, \"Channels connecting to %s to create %d channels\", ipstr, P_TCP_CONN_AMOUNT);\n                            usleep(500000);\n\n                            for (i = 1; i <= P_TCP_CONN_AMOUNT; i++) {\n                                errno = 0;\n                                if ((info.channel[i].descriptor = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {\n                                    vlog(LOG_ERR, \"Can't create CHAN socket. %s(%d) chan %d\", strerror(errno), errno, i);\n                                    linker_term = TERM_FATAL;\n                                    break;\n                                }\n                                if (lfd_host->RT_MARK != -1) {\n                                    if (setsockopt(info.channel[i].descriptor, SOL_SOCKET, SO_MARK, &lfd_host->RT_MARK, sizeof(lfd_host->RT_MARK))) {\n                                        vlog(LOG_ERR, \"Client CHAN socket rt mark error %s(%d)\", strerror(errno), errno);\n                                        break_out = 1;\n                                        break;\n                                    }\n                                }\n                                /*\n                                sendbuff = RCVBUF_SIZE;\n                                // WARNING! This should be on sysadmin's duty to optimize!\n                                if (setsockopt(info.channel[i].descriptor, SOL_SOCKET, SO_RCVBUFFORCE, &sendbuff, sizeof(int)) == -1) {\n                                    vlog(LOG_ERR, \"WARNING! Can not set rmem (SO_RCVBUF) size. Performance will be poor.\");\n                                }\n                                */\n\n\n                                rmaddr.sin_port = htons(info.channel[i].rport);\n                                connect(info.channel[i].descriptor, (struct sockaddr *)&rmaddr, sizeof(rmaddr));\n                                // send PING request\n                                udp_write(info.channel[i].descriptor, buf, VTUN_ECHO_REQ);\n                                usleep(500000);\n                            }\n                            if (i < P_TCP_CONN_AMOUNT) {\n                                vlog(LOG_ERR, \"Could not connect all requested tuns; exit\");\n                                linker_term = TERM_NONFATAL;\n                                break;\n                            }\n                            info.channel_amount = i;\n                            maxfd = info.tun_device;\n                            for (int i = 0; i < info.channel_amount; i++) {\n                                if (maxfd < info.channel[i].descriptor) {\n                                    maxfd = info.channel[i].descriptor;\n                                }\n                            }\n                            //double call for getcockname beacause frst call returned ZERO in addr\n                            laddrlen = sizeof(localaddr);\n                            if (getsockname(info.channel[0].descriptor, (struct sockaddr *) (&localaddr), &laddrlen) < 0) {\n                                vlog(LOG_ERR, \"Channels socket getsockname error; retry %s(%d)\", strerror(errno), errno);\n                                linker_term = TERM_NONFATAL;\n                                break;\n                            }\n                            for (i = 0; i < info.channel_amount; i++) {\n                                memset(&rmaddr, 0, sizeof(rmaddr));\n                                memset(&localaddr, 0, sizeof(localaddr));\n                                rmaddrlen = sizeof(rmaddr);\n                                laddrlen = sizeof(localaddr);\n                                if (getsockname(info.channel[i].descriptor, (struct sockaddr *) (&localaddr), &laddrlen) < 0) {\n                                    vlog(LOG_ERR, \"Channels socket getsockname error; retry %s(%d)\", strerror(errno), errno);\n                                    linker_term = TERM_NONFATAL;\n                                    break;\n                                }\n                                info.channel[i].lport = ntohs(localaddr.sin_port);\n                                if (getpeername(info.channel[i].descriptor, (struct sockaddr *) (&rmaddr), &rmaddrlen) < 0) {\n                                    vlog(LOG_ERR, \"Channels socket getsockname error; retry %s(%d)\", strerror(errno), errno);\n                                    linker_term = TERM_NONFATAL;\n                                    break;\n                                }\n                                info.channel[i].rport = ntohs(rmaddr.sin_port);\n                                vlog(LOG_INFO, \"Client descriptor - %i logical channel - %i lport - %i rport - %i\",info.channel[i].descriptor, i, info.channel[i].lport, info.channel[i].rport);\n                            }\n                            for(i = 1; i < info.channel_amount; i++) {\n                                if (setsockopt(info.channel[i].descriptor, SOL_SOCKET, SO_RCVTIMEO, (char *) &socket_timeout, sizeof(socket_timeout)) < 0) {\n                                    vlog(LOG_ERR, \"setsockopt failed\");\n                                    linker_term = TERM_NONFATAL;\n                                    break;\n                                }\n                                if (setsockopt(info.channel[i].descriptor, SOL_SOCKET, SO_SNDTIMEO, (char *) &socket_timeout, sizeof(socket_timeout)) < 0) {\n                                    vlog(LOG_ERR, \"setsockopt failed\");\n                                    linker_term = TERM_NONFATAL;\n                                    break;\n                                }\n                            }\n                            vlog(LOG_INFO,\"Successfully set up %d connection channels\", info.channel_amount);\n                            continue;\n                        } else if(flag_var == FRAME_LAST_WRITTEN_SEQ) {\n                            PCS_aux++;\n#ifdef DEBUGG\n                            vlog(LOG_INFO, \"received FRAME_LAST_WRITTEN_SEQ lws %\"PRIu32\" chan %d\", ntohl(*((uint32_t *)buf)), chan_num);\n#endif\n                            if(debug_trace) {\n                                vlog(LOG_INFO, \"received FRAME_LAST_WRITTEN_SEQ lws %\"PRIu32\" chan %d\", ntohl(*((uint32_t *)buf)), chan_num);\n                            }\n                            // TODO: no sync here!!?!?!\n                            if( ntohl(*((uint32_t *)buf)) > shm_conn_info->write_buf[chan_num].remote_lws) shm_conn_info->write_buf[chan_num].remote_lws = ntohl(*((uint32_t *)buf));\n                            continue;\n\t\t\t\t\t\t} else if (flag_var == FRAME_TIME_LAG) {\n                            PCS_aux++;\n\t\t\t\t\t\t    int recv_lag = 0;\n\t\t\t\t\t\t\t/* Get time_lag and miss_packet_max for some pid from net here */\n\t\t\t\t\t\t    uint32_t time_lag_and_miss_packets;\n\t\t\t\t\t\t    memcpy(&time_lag_and_miss_packets, buf, sizeof(uint32_t));\n\t\t\t\t\t\t    time_lag_and_miss_packets = ntohl(time_lag_and_miss_packets);\n\t\t\t\t\t\t\tuint16_t miss_packets_max_tmp = time_lag_and_miss_packets >> 20;\n\t\t\t\t\t\t\ttime_lag_local.time_lag = time_lag_and_miss_packets & 0xFFFFF;\n\t\t\t\t\t\t\tmemcpy(&(time_lag_local.pid), buf + sizeof(uint32_t) + sizeof(uint16_t), sizeof(time_lag_local.pid));\n\t\t\t\t\t\t    time_lag_local.pid = ntohs(time_lag_local.pid);\n\t\t\t\t\t\t    uint32_t tmp_n, tmp_h;\n\t\t\t\t\t\t    uint32_t miss_packets_max_recv_counter;\n                            memcpy(&tmp_n, buf + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t), sizeof(uint32_t));\n                            tmp_h = ntohl(tmp_n);\n                            miss_packets_max_recv_counter = tmp_h & 0xFFFF;\n\t\t\t\t\t\t\tsem_wait(&(shm_conn_info->stats_sem));\n                            shm_conn_info->tflush_counter_recv = tmp_h >> 16;\n#ifdef DEBUGG\n                            vlog(LOG_INFO, \"recv pid - %i packet_miss - %\"PRIu32\" tmp_h %\"PRIu32\"\",time_lag_local.pid, miss_packets_max_tmp, tmp_h);\n\t\t\t\t\t\t\tvlog(LOG_INFO, \"Miss packet counter was - %\"PRIu32\" recv - %\"PRIu32\"\",shm_conn_info->miss_packets_max_recv_counter, miss_packets_max_recv_counter);\n#endif\n                            if ((miss_packets_max_recv_counter > shm_conn_info->miss_packets_max_recv_counter)) {\n                                miss_packets_max = miss_packets_max_tmp;\n                                shm_conn_info->miss_packets_max = miss_packets_max;\n                                shm_conn_info->miss_packets_max_recv_counter = miss_packets_max_recv_counter;\n#ifdef DEBUGG\n                                vlog(LOG_INFO, \"Miss packets(buf_len) for counter %u is %u apply\", miss_packets_max_recv_counter, miss_packets_max_tmp);\n#endif\n                            }\n                            for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                                if (time_lag_local.pid == shm_conn_info->stats[i].pid) {\n                                    shm_conn_info->stats[i].time_lag = time_lag_local.time_lag;\n                                    recv_lag = 1;\n                                    break;\n                                }\n                            }\n\n                            if (debug_trace) {\n                                vlog(LOG_INFO, \"Time lag for pid: %i is %u\", time_lag_local.pid, time_lag_local.time_lag);\n                            }\n\n\t\t\t\t\t\t\ttime_lag_local.time_lag = shm_conn_info->stats[info.process_num].time_lag;\n\t\t\t\t\t\t\ttime_lag_local.pid = shm_conn_info->stats[info.process_num].pid;\n\t\t\t\t\t\t\tsem_post(&(shm_conn_info->stats_sem));\n\t\t\t\t\t\t\tcontinue;\n                        } else if (flag_var == FRAME_DEAD_CHANNEL) {\n                            PCS_aux++;\n                            uint32_t chan_mask_h;\n                            memcpy(&chan_mask_h, buf, sizeof(uint32_t));\n                            sem_wait(&(shm_conn_info->AG_flags_sem));\n                            shm_conn_info->channels_mask = ntohl(chan_mask_h);\n                            sem_post(&(shm_conn_info->AG_flags_sem));\n                        } else if ((flag_var == FRAME_LOSS_INFO) || (flag_var == FRAME_L_LOSS_INFO)) {\n                            int psl;\n                            uint32_t tmp_h;\n                            struct timeval tv_tmp;\n                            memcpy(&tmp_h, buf, sizeof(uint32_t));\n                            int idx = ntohl(tmp_h);\n                            //vlog(LOG_INFO, \"FRAME_LOSS_INFO recv idx %d\", idx);\n                            memcpy(&tmp_h, buf + sizeof(uint16_t) + sizeof(uint32_t), sizeof(uint32_t));\n                            tv_tmp.tv_sec = ntohl(tmp_h);\n                            memcpy(&tmp_h, buf + sizeof(uint16_t) + 2 * sizeof(uint32_t), sizeof(uint32_t));\n                            tv_tmp.tv_usec = ntohl(tmp_h);\n                            memcpy(&tmp_h, buf + sizeof(uint16_t) + 3 * sizeof(uint32_t), sizeof(uint32_t));\n                            if (flag_var == FRAME_LOSS_INFO) {\n                                psl = ntohl(tmp_h);\n                            } else {\n                                psl = ntohl(tmp_h);\n                            }\n\n                            memcpy(&tmp_h, buf + sizeof(uint16_t) + 4 * sizeof(uint32_t), sizeof(uint32_t));\n                            if (flag_var == FRAME_LOSS_INFO) {\n                                memcpy(&tmp_h, buf + sizeof(uint16_t) + 5 * sizeof(uint32_t), sizeof(uint32_t));\n                                uint32_t sqn = ntohl(tmp_h);\n                                uint16_t tmp_s;\n                                memcpy(&tmp_s, buf + sizeof(uint16_t) + 6 * sizeof(uint32_t), sizeof(uint16_t));\n                                int hsnum = (int)ntohs(tmp_s);\n                                int who_lost = -1;\n                                if(hsnum == -1) {\n                                    vlog(LOG_INFO, \"WARNING could not detect who lost %lu - sending unconditionally\", sqn);\n                                } else {\n                                    who_lost = hsnum2pnum(hsnum);\n                                }\n                                //if((psl <= 2) && (who_lost != shm_conn_info->max_chan)) { // this is for fairness model #407\n                                struct timeval cwr_diff;\n                                timersub(&info.current_time, &shm_conn_info->cwr_tv, &cwr_diff);\n                                \n                            } else {\n                                memcpy(&tmp_h, buf + sizeof(uint16_t) + 6 * sizeof(uint32_t), sizeof(uint32_t));\n                                uint32_t sqn = ntohl(tmp_h);\n                                uint16_t tmp16_n;\n                                memcpy(&tmp16_n, buf + sizeof(uint16_t) + 5 * sizeof(uint32_t), sizeof(uint16_t));\n                                uint16_t tmp = ntohs(tmp16_n);\n                                char char_tmp[3] = { 0 };\n                                memcpy(char_tmp, &tmp, sizeof(uint16_t));\n                                memcpy(&tmp_s, buf + sizeof(uint16_t) + 7 * sizeof(uint32_t), sizeof(uint16_t));\n                                int hsnum = (int)ntohs(tmp_s);\n                                int who_lost = -1;\n                                if(hsnum == -1) {\n                                    vlog(LOG_INFO, \"WARNING could not detect who lost %lu - not resending\", sqn);\n                                } else {\n                                    who_lost = hsnum2pnum(hsnum);\n                                    if(who_lost == -1) {\n                                        vlog(LOG_ERR, \"WARNING could not resolve who lost %lu - not resending\", sqn);\n                                    }\n                                }\n                                if(who_lost == info.process_num) {\n                                    info.psl_count += psl;\n                                    info.loss_event_count++;\n                                }\n                                sem_wait(&(shm_conn_info->stats_sem));\n                                for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                                    if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead)) { // hope this works..\n                                        if (strncmp(shm_conn_info->stats[i].name + strlen(shm_conn_info->stats[i].name) - 2, char_tmp, 2) == 0) {\n                                            if((shm_conn_info->stats[i].l_pbl_recv != ntohl(tmp_h)) && (timercmp(&shm_conn_info->stats[i].plp_immune, &info.current_time, <=)) \n                                                && ((shm_conn_info->stats[info.process_num].exact_rtt < 800) || (i == info.process_num))) {\n                                                    ms2tv(&loss_tv, shm_conn_info->stats[i].exact_rtt);\n                                                    timeradd(&info.current_time, &loss_tv, &shm_conn_info->stats[i].plp_immune);\n                                                    // TODO: this is totally unsynced and may introduce problems\n                                                    shm_conn_info->stats[i].l_pbl_recv_saved = shm_conn_info->stats[i].l_pbl_recv;\n                                                    shm_conn_info->stats[i].l_pbl_tmp_saved = shm_conn_info->stats[i].l_pbl_tmp;\n                                                    // TODO: because of PLP restore procedure it may rewrite itself again - see FCI handler\n                                                \n                                                shm_conn_info->stats[i].l_pbl_recv = ntohl(tmp_h);\n                                                shm_conn_info->stats[i].l_pbl_tmp = 0; // WARNING it may collide here!\n                                                if(psl > PSL_RECOVERABLE && shm_conn_info->stats[i].l_pbl_recv > L_PBL_JOIN_EVENTS && shm_conn_info->stats[i].l_pbl_tmp_unrec > L_PBL_JOIN_EVENTS) {\n                                                    // unrecoverable loss\n                                                    if(shm_conn_info->stats[i].l_pbl_unrec_avg < INT32_MAX / PBL_SMOOTH_NUMERATOR) {\n                                                        shm_conn_info->stats[i].l_pbl_unrec_avg = PBL_SMOOTH_NUMERATOR * shm_conn_info->stats[i].l_pbl_unrec_avg / PBL_SMOOTH_DENOMINATOR + shm_conn_info->stats[i].l_pbl_tmp_unrec / PBL_SMOOTH_DENOMINATOR;\n                                                    } else {\n                                                        shm_conn_info->stats[i].l_pbl_unrec_avg = INT32_MAX;\n                                                    }\n                                                    shm_conn_info->stats[i].l_pbl_tmp_unrec = 0;\n                                                }\n                                            }\n                                            break;\n                                        }\n\n                                    }\n                                }\n                                sem_post(&(shm_conn_info->stats_sem));\n                                if( psl <= UNRECOVERABLE_LOSS && who_lost > -1 && !shm_conn_info->is_single_channel) {\n                                    if(info.min_rtt_chan == info.process_num) {\n                                        // now do retransmit\n                                        int mypid;\n                                        uint32_t seqn;\n                                        int cnt = 0;\n                                        for(uint32_t sqn_s = sqn; sqn_s < sqn + psl; sqn_s++) {\n                                            if(cnt > UNRECOVERABLE_LOSS) {\n                                                vlog(LOG_ERR, \"ASSERT FAILED!: looping at resend packet > UNRECOVERABLE_LOSS! sqn %lu sqn_s %lu psl %d\", sqn, sqn_s, psl);\n                                                break;\n                                            }\n                                            cnt++;\n                                            sem_wait(&(shm_conn_info->resend_buf_sem));\n                                            int lidx = -1;\n                                            len = get_resend_frame_local_sqn(1, who_lost ,sqn_s, &seqn, &out2, &mypid, &lidx);\n                                            if (len == -1) {\n                                                vlog(LOG_INFO, \"WARNING could not retransmit packet 2 %lu - not found\", sqn_s);\n                                                sem_post(&(shm_conn_info->resend_buf_sem));\n                                            } else {\n                                                memcpy(out_buf, out2, len);\n                                                sem_post(&(shm_conn_info->resend_buf_sem));\n                                                vlog(LOG_INFO, \"resending packet 2 lsn %lu sqn %lu len %d\", sqn_s, seqn, len);\n                                                send_packet(1, out_buf, len);\n                                                shm_conn_info->resend_frames_buf[lidx].local_seq_num[info.process_num] = info.channel[1].local_seq_num - 1; // in case it will be lost again\n                                            }\n                                        }\n                                    }\n                                }\n                            }\n                            \n                            \n                            continue;\n                        } else if (flag_var == FRAME_CHANNEL_INFO) {\n                            PCS_aux++;\n                            uint32_t tmp32_n;\n                            uint16_t tmp16_n;\n                            int chan_num2;\n                            memcpy(&tmp16_n, buf + 3 * sizeof(uint16_t) + sizeof(uint32_t), sizeof(uint16_t));\n                            chan_num2 = (int)ntohs(tmp16_n);\n                            if(chan_num2 >= 100) {\n                                for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                                    shm_conn_info->stats[i].remote_head_channel = 0;\n                                }\n                                shm_conn_info->stats[info.process_num].remote_head_channel = 1;\n                                if(chan_num2 >= 200) {\n                                    shm_conn_info->last_head = info.current_time;\n                                }\n                                shm_conn_info->remote_head_pnum = info.process_num;\n                            }\n                            gettimeofday(&info.current_time, NULL);\n                            memcpy(&info.channel[chan_num].send_q_time, &info.current_time, sizeof(struct timeval));\n                            memcpy(&tmp16_n, buf, sizeof(uint16_t));\n                            info.channel[chan_num].packet_recv = ntohs(tmp16_n); // unused \n                            memcpy(&tmp16_n, buf + sizeof(uint16_t), sizeof(uint16_t));\n                            info.channel[chan_num].packet_loss = ntohs(tmp16_n); // FCI-only data only on loss\n                            memcpy(&tmp32_n, buf + 3 * sizeof(uint16_t), sizeof(uint32_t));\n                            info.channel[chan_num].packet_seq_num_acked = ntohl(tmp32_n); // each packet data here\n                            memcpy(&tmp32_n, buf + 4 * sizeof(uint16_t) + 2 * sizeof(uint32_t), sizeof(uint32_t)); // PCS send\n                            info.PCS2_recv = ntohl(tmp32_n);\n                            //vlog(LOG_ERR, \"local seq %\"PRIu32\" recv seq %\"PRIu32\" chan_num %d \",info.channel[chan_num].local_seq_num, info.channel[chan_num].packet_seq_num_acked, chan_num);\n                            // rtt calculation, TODO: DUP code below!\n                            if( (info.rtt2_lsn[chan_num] != 0) && (info.channel[chan_num].packet_seq_num_acked > info.rtt2_lsn[chan_num])) {\n                                //vlog(LOG_INFO,\"WARNING! rtt2 calculated via FCI receive event!\");\n                                timersub(&info.current_time, &info.rtt2_tv[chan_num], &tv_tmp);\n                                //info.rtt2 = tv2ms(&tv_tmp);\n                                info.rtt2_lsn[chan_num] = 0;\n                                info.srtt2_10 += ((int)tv2ms(&tv_tmp)*10 - info.srtt2_10) / 8;\n                                info.srtt2_100 += ((int)tv2ms(&tv_tmp)*100 - info.srtt2_100) / 50;\n                                info.rtt2 = info.srtt2_10 / 10; // check this!\n                                if (info.rtt2 <= 0) info.rtt2 = 1;\n                                int r_delta = (int)tv2ms(&tv_tmp) - info.srtt2_10 / 10;\n                                if(r_delta > 0) {\n                                    info.srtt2var = (3 * info.srtt2var  +  r_delta)/4;\n                                } else {\n                                    info.srtt2var = (3 * info.srtt2var  -  r_delta)/4;\n                                }\n                            }\n                            \n                            \n                            memcpy(&tmp32_n, buf + 5 * sizeof(uint16_t) + 3 * sizeof(uint32_t), sizeof(uint32_t)); //ag_flag\n                            shm_conn_info->ag_mask_recv = hsag_mask2ag_mask(ntohl(tmp32_n));\n                            // we have received new mask\n                            shm_conn_info->stats[info.process_num].agoff_immunity_tv.tv_sec = 0;\n                            shm_conn_info->stats[info.process_num].agoff_immunity_tv.tv_usec = 0;\n                            if(shm_conn_info->stats[info.process_num].recv_mode != (shm_conn_info->ag_mask_recv & (1 << info.process_num))) {\n                                shm_conn_info->stats[info.process_num].recv_mode = (shm_conn_info->ag_mask_recv & (1 << info.process_num)) ? 1 : 0;\n                            }\n                            // TODO: check WTF is here ^^^vvv ???\n                            for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                                if( (i != info.process_num) && (shm_conn_info->stats[i].recv_mode != (shm_conn_info->ag_mask_recv & (1 << i))) ) { \n                                    // we are setting new mode for another channel\n                                    if(shm_conn_info->stats[i].recv_mode == 1) { // AG_MODE -> R_MODE: set immunity timer\n                                        struct timeval tv_dt;\n                                        ms2tv(&tv_dt, shm_conn_info->stats[i].exact_rtt);\n                                        timeradd(&info.current_time, &tv_dt, &shm_conn_info->stats[i].agoff_immunity_tv);\n                                    }\n                                    shm_conn_info->stats[i].recv_mode = (shm_conn_info->ag_mask_recv & (1 << i)) ? 1 : 0;\n                                }\n                            }\n                                    \n                            set_rttlag();\n                            memcpy(&tmp16_n, buf + 5 * sizeof(uint16_t) + 4 * sizeof(uint32_t), sizeof(uint16_t)); // sqe_mean\n                            shm_conn_info->stats[info.process_num].remote_sqe_mean_pkt = ntohs(tmp16_n);\n                            \n                            memcpy(&tmp16_n, buf + 6 * sizeof(uint16_t) + 4 * sizeof(uint32_t), sizeof(uint16_t)); //buf_len\n                            int buf_len_recv = (int)ntohs(tmp16_n);\n                            \n                            memcpy(&tmp16_n, buf + 7 * sizeof(uint16_t) + 4 * sizeof(uint32_t), sizeof(uint16_t)); \n                            shm_conn_info->msbl_recv = ntohs(tmp16_n);\n                            memcpy(&tmp32_n, buf + 8 * sizeof(uint16_t) + 4 * sizeof(uint32_t), sizeof(uint32_t)); \n                            shm_conn_info->stats[info.process_num].la_sqn = ntohl(tmp32_n);\n                            memcpy(&tmp32_n, buf + 8 * sizeof(uint16_t) + 5 * sizeof(uint32_t), sizeof(uint32_t)); \n                            uint32_t remote_seq = ntohl(tmp32_n);\n                            // vlog(LOG_ERR, \"FRAME_CHANNEL_INFO testing lasqn %ld > %ld \", remote_seq, shm_conn_info->latest_la_sqn);\n                            \n                            if(remote_seq > shm_conn_info->latest_la_sqn) {\n                                memcpy(&tmp16_n, buf + 4 * sizeof(uint16_t) + 3 * sizeof(uint32_t), sizeof(uint16_t)); // hsqs\n                                shm_conn_info->head_send_q_shift_recv = (int16_t) ntohs(tmp16_n); // TODO parse hsqs here\n                                shm_conn_info->buf_len_recv = buf_len_recv;\n                                vlog(LOG_INFO, \"Setting hsqs %d\", (int16_t) ntohs(tmp16_n));\n                                shm_conn_info->latest_la_sqn = remote_seq; \n                            }\n                            \n                            // now recalculate MAR is possible...\n                            info.channel[chan_num].send_q =\n                                    info.channel[chan_num].local_seq_num > info.channel[chan_num].packet_seq_num_acked ?\n                                            1000 * (info.channel[chan_num].local_seq_num - info.channel[chan_num].packet_seq_num_acked) : 0;\n                            //if (info.max_send_q < info.channel[chan_num].send_q) {\n                            //    info.max_send_q = info.channel[chan_num].send_q;\n                            //}\n                            //vlog(LOG_INFO, \"FCI send_q %d\", info.channel[chan_num].send_q);\n                            //if (info.channel[chan_num].send_q > 90000)\n                            //    vlog(LOG_INFO, \"channel %d mad_send_q %\"PRIu32\" local_seq_num %\"PRIu32\" packet_seq_num_acked %\"PRIu32\"\",chan_num, info.channel[chan_num].send_q,info.channel[chan_num].local_seq_num, info.channel[chan_num].packet_seq_num_acked);\n\n                            if(debug_trace) {\n                                vlog(LOG_INFO, \"FCI local seq %\"PRIu32\" recv seq %\"PRIu32\" chan_num %d \",info.channel[chan_num].local_seq_num, info.channel[chan_num].packet_seq_num_acked, chan_num);\n                            }\n                            //vlog(LOG_INFO, \"FRAME_CHANNEL_INFO: Calculated send_q: %d, chan %d, pkt %d, drops: %d\", info.channel[chan_num].send_q, chan_num, info.channel[chan_num].packet_seq_num_acked, drop_counter);\n                            uint32_t my_max_send_q = 0;\n                            for (int i = 1; i < info.channel_amount; i++) {\n                                if (my_max_send_q < info.channel[i].send_q) {\n                                    my_max_send_q = info.channel[i].send_q;\n                                    my_max_send_q_chan_num = i;\n                                }\n                            }\n                            if ((info.channel[chan_num].packet_loss == -1) && (info.Wmax_saved != 0)) { \n                                vlog(LOG_INFO, \"Undoing congestion control: Wmax %d\", info.Wmax_saved);\n                                info.send_q_limit_cubic_max = info.Wmax_saved;\n                                loss_time = info.Wmax_tv;\n                                info.Wmax_saved = 0;\n                            } else if ((info.channel[chan_num].packet_loss == -1) && (info.Wmax_saved == 0)) {\n                                vlog(LOG_INFO, \"Cannot undo congestion: Wmax %d\", info.Wmax_saved);\n                            }\n                            \n                            if((info.channel[chan_num].packet_loss == -1) && (shm_conn_info->stats[info.process_num].l_pbl_tmp_saved != 0)) {\n                                vlog(LOG_INFO, \"Undoing PLP drop: l_pbl_recv %d\", shm_conn_info->stats[info.process_num].l_pbl_recv_saved);\n                                // TODO: unsynced\n                                shm_conn_info->stats[info.process_num].l_pbl_recv = shm_conn_info->stats[info.process_num].l_pbl_recv_saved;\n                                shm_conn_info->stats[info.process_num].l_pbl_tmp = shm_conn_info->stats[info.process_num].l_pbl_tmp_saved; \n                                ms2tv(&loss_tv, 1100); // TODO: a very dumb channel may fail this\n                                timeradd(&info.current_time, &loss_tv, &shm_conn_info->stats[info.process_num].plp_immune);\n                                shm_conn_info->stats[info.process_num].l_pbl_tmp_saved = 0;\n                            } else if ((info.channel[chan_num].packet_loss == -1) && (shm_conn_info->stats[info.process_num].l_pbl_tmp_saved == 0)) {\n                                vlog(LOG_INFO, \"Cannot undo PLP drop: l_pbl_recv %d\", shm_conn_info->stats[info.process_num].l_pbl_recv_saved);\n                            }\n                                \n                                \n                            \n                            //Для чего нужен подсчет значения потерь через info.channel[chan_num].packet_loss ( возможно ложное срабатывание в дальнейшем\n                            if (info.channel[chan_num].packet_loss > 0 && timercmp(&loss_immune, &info.current_time, <=)) { // 2 pkts loss THR is prep for loss recovery\n                                // TODO: need to get L_PBL somehow here - see dumbass method at FCI send\n                                vlog(LOG_INFO, \"RECEIVED approved loss %\"PRId16\" chan_num %d send_q %\"PRIu32\"\", info.channel[chan_num].packet_loss, chan_num,\n                                        info.channel[chan_num].send_q);\n                                loss_time = info.current_time; // received loss event time\n                                info.p_lost++;\n                                sem_wait(&(shm_conn_info->stats_sem));\n                                shm_conn_info->stats[info.process_num].real_loss_time = info.current_time; // received loss event time\n                                if(info.head_channel) {\n                                    if(shm_conn_info->idle) {\n                                        // first check if we are really head\n                                        // find max ACS \n                                        int ch_max_ACS = -1;\n                                        int ch_max_ACS_ch = -1;\n                                        int ch_max_ACS_W = -1;\n                                        for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                                            if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) && (i != info.process_num)) { // hope this works..\n                                                if(shm_conn_info->stats[i].ACK_speed > ch_max_ACS) {\n                                                    ch_max_ACS = shm_conn_info->stats[i].ACK_speed;\n                                                    ch_max_ACS_ch = i;\n                                                    ch_max_ACS_W = shm_conn_info->stats[i].W_cubic;\n                                                }\n                                            }\n                                        }\n                                        if(ch_max_ACS != -1) {\n                                            // check if we are the best from all other\n                                            if(!percent_delta_equal(shm_conn_info->stats[info.process_num].ACK_speed, ch_max_ACS, 10)\n                                                    && (shm_conn_info->stats[info.process_num].ACK_speed < ch_max_ACS)) {\n                                                vlog(LOG_INFO, \"Head changed to %d due to ACS>ACSh: %d > %d\", ch_max_ACS_ch, ch_max_ACS, shm_conn_info->stats[info.process_num].ACK_speed);\n                                                shm_conn_info->max_chan = ch_max_ACS_ch; // we found chan with better ACS (10% corridor)\n                                            } else if ( percent_delta_equal(shm_conn_info->stats[info.process_num].ACK_speed, ch_max_ACS, 10)\n                                                    && (ch_max_ACS_W > shm_conn_info->stats[info.process_num].W_cubic)) {\n                                                // check Wh/Wi here\n                                                // our process has smaller window with same speed; assume we're not the best now\n                                                vlog(LOG_INFO, \"Head changed to %d due to W>Wh: %d > %d\", ch_max_ACS_ch, ch_max_ACS_W, shm_conn_info->stats[info.process_num].W_cubic);\n                                                shm_conn_info->max_chan = ch_max_ACS_ch;\n                                            } else {\n                                                vlog(LOG_INFO, \"Head (real) lossing after idle\");\n                                                shm_conn_info->idle = 0;\n                                                shm_conn_info->head_lossing = 1;\n                                            }\n                                        } else {\n                                            // we are the ONLY channel, drop flags\n                                            vlog(LOG_INFO, \"Head (only) lossing after idle\");\n                                            shm_conn_info->idle = 0;\n                                            shm_conn_info->head_lossing = 1;\n                                        }\n                                    } else {\n                                       // vlog(LOG_INFO, \"Head lossing\");\n                                        shm_conn_info->head_lossing = 1;\n                                    }\n                                }\n                                sem_post(&(shm_conn_info->stats_sem));\n                                ms2tv(&loss_tv, info.exact_rtt);\n                                timeradd(&info.current_time, &loss_tv, &loss_immune);\n                                if(0 && info.head_channel) {\n                                    info.send_q_limit_cubic_max = info.max_send_q; // fast-converge to flow (head now always converges!)\n                                    info.W_u_max = info.max_send_q_u;\n                                    info.cubic_t_max_u = t_from_W(RSR_TOP, info.W_u_max, info.Bu, info.Cu);\n                                } else {\n                                    //if (info.channel[my_max_send_q_chan_num].send_q >= info.send_q_limit_cubic_max) {\n                                    if (!info.xlm && info.max_send_q >= info.send_q_limit_cubic_max) {\n                                    // if (send_q_eff_mean + send_q_eff_var/2 >= info.send_q_limit_cubic_max) {\n                                        info.Wmax_saved = info.send_q_limit_cubic_max;\n                                        info.Wmax_tv = loss_time;\n                                        //info.send_q_limit_cubic_max = info.channel[my_max_send_q_chan_num].send_q;\n                                        // if(info.max_send_q > info.send_q_limit_cubic) {\n                                            info.send_q_limit_cubic_max = info.max_send_q;\n                                            // info.send_q_limit_cubic_max = send_q_eff_mean + send_q_eff_var/2;\n                                        // } else {\n                                        //     info.send_q_limit_cubic_max = info.send_q_limit_cubic;\n                                        // }\n                                        if(info.channel[chan_num].packet_loss > PSL_RECOVERABLE) {\n                                            info.W_u_max = info.max_send_q_u;\n                                            info.cubic_t_max_u = t_from_W(RSR_TOP, info.W_u_max, info.Bu, info.Cu);\n                                        }\n                                    } else {\n                                        //info.send_q_limit_cubic_max = (int) ((double)info.channel[my_max_send_q_chan_num].send_q * (2.0 - info.B) / 2.0);\n                                        // if(info.max_send_q > info.send_q_limit_cubic) {\n                                            if(info.xlm) {\n                                                info.send_q_limit_cubic_max = info.max_send_q / 2;\n                                            } else {\n                                                info.send_q_limit_cubic_max = (int) ((double)info.max_send_q * (2.0 - info.B) / 2.0);\n                                            }\n                                            // info.send_q_limit_cubic_max = (int) ((double)send_q_eff_var * (2.0 - info.B) / 2.0);\n                                        // } else {\n                                        //     info.send_q_limit_cubic_max = (int) ((double)info.send_q_limit_cubic * (2.0 - info.B) / 2.0);\n                                        // }\n                                        if(info.channel[chan_num].packet_loss > PSL_RECOVERABLE) {\n                                            info.W_u_max = (int) ((double)info.max_send_q_u * (2.0 - info.Bu) / 2.0);\n                                            info.cubic_t_max_u = t_from_W(RSR_TOP, info.W_u_max, info.Bu, info.Cu);\n                                        }\n                                    }\n                                }\n                                if(info.send_q_limit_cubic_max / info.eff_len < LOSS_SEND_Q_MAX) {\n                                    //shm_conn_info->stats[info.process_num].loss_send_q = info.send_q_limit_cubic_max / info.eff_len; // packets in network at loss\n                                    shm_conn_info->stats[info.process_num].loss_send_q = shm_conn_info->stats[info.process_num].sqe_mean_lossq / info.eff_len; // SQE expreiment\n                                } else {\n                                    shm_conn_info->stats[info.process_num].loss_send_q = LOSS_SEND_Q_MAX;\n                                } \n                                // now set all the chans that have undefined loss_send_q\n                                for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n                                    if ((chan_mask & (1 << i)) && (!shm_conn_info->stats[i].channel_dead) &&\n                                        (shm_conn_info->stats[i].loss_send_q == LOSS_SEND_Q_UNKNOWN)) {\n                                            shm_conn_info->stats[i].loss_send_q = shm_conn_info->stats[info.process_num].loss_send_q;\n                                    }\n                                }\n                                            \n                                // t = 0;\n                                // info.max_send_q = 0;\n                                // //waste Cubic recalc\n                                // sem_wait(&(shm_conn_info->stats_sem));\n                                // set_W_unsync(t);\n                                // sem_post(&(shm_conn_info->stats_sem));\n                                if(info.channel[chan_num].packet_loss > PSL_RECOVERABLE) {\n                                    info.u_loss_tv = info.current_time;\n                                    info.max_send_q_u = 0;\n                                    shm_conn_info->stats[info.process_num].W_cubic_u = cubic_recalculate(0, info.W_u_max, info.Bu, info.Cu);\n                                }\n                                    \n                                //waste Cubic recalc end\n                            } else {\n                                timersub(&(info.current_time), &loss_time, &t_tv);\n                                t = t_tv.tv_sec * 1000 + t_tv.tv_usec / 1000;\n                                t = t / CUBIC_T_DIV;\n                                t = t > cubic_t_max ? cubic_t_max : t; // 200s limit\n                            }\n                            \n                            info.max_send_q_avg = (uint32_t) ((int32_t) info.max_send_q_avg  // unused\n                                    - ((int32_t) info.max_send_q_avg - (int32_t) my_max_send_q) / 4);\n\n#if !defined(DEBUGG)\n                            info.max_send_q_max = my_max_send_q > info.max_send_q_max ? my_max_send_q : info.max_send_q_max;\n                            info.max_send_q_min = my_max_send_q < info.max_send_q_min ? my_max_send_q : info.max_send_q_min;\n#endif\n                            // local seq_num\n                            memcpy(&tmp32_n, buf + 4 * sizeof(uint16_t) + sizeof(uint32_t), sizeof(uint32_t));\n                            uint32_t local_seq_tmp = ntohl(tmp32_n); \n                            \n                            unsigned int lrs2;\n                            if (lossed_consume(local_seq_tmp, 0, &lrs2, &info.channel[chan_num].local_seq_num_recv) == 0) { // TODO: lrs?? not updated!\n                                info.channel[chan_num].loss_time = info.current_time;\n                            }\n                            info.channel[1].last_recv_time = info.current_time;\n                            \n                            //if (local_seq_tmp > info.channel[chan_num].local_seq_num_recv) {\n                            //    info.channel[chan_num].local_seq_num_recv = local_seq_tmp;\n                            //}\n                            memcpy(&tmp32_n, buf + 4 * sizeof(uint16_t) + 2 * sizeof(uint32_t), sizeof(uint32_t)); // dn speed\n#ifdef DEBUGG\n\n                            int show_speed=0;\n                            if (ntohl(tmp32_n) != info.channel[chan_num].packet_recv_upload) {\n                                show_speed=1;\n                            }\n#endif\n                            info.channel[chan_num].packet_recv_upload = ntohl(tmp32_n); // each packet data\n                            info.channel[chan_num].packet_recv_upload_avg =\n                                    info.channel[chan_num].packet_recv_upload > info.channel[chan_num].packet_recv_upload_avg ?\n                                            (info.channel[chan_num].packet_recv_upload - info.channel[chan_num].packet_recv_upload_avg) / 4\n                                                    + info.channel[chan_num].packet_recv_upload_avg :\n                                            info.channel[chan_num].packet_recv_upload_avg\n                                                    - (info.channel[chan_num].packet_recv_upload_avg - info.channel[chan_num].packet_recv_upload) / 4;\n#ifdef DEBUGG\n                            if(show_speed){\n                                vlog(LOG_INFO, \"channel %d speed %\"PRIu32\" Speed_avg %\"PRIu32\"\",chan_num, info.channel[chan_num].packet_recv_upload, info.channel[chan_num].packet_recv_upload_avg);\n                            }\n#endif\n                            //vlog(LOG_INFO, \"FCI spd %d %d\", info.channel[chan_num].packet_recv_upload, info.channel[chan_num].packet_recv_upload_avg);\n                            sem_wait(&(shm_conn_info->stats_sem));\n                            /* store in shm */\n                            // set_W_unsync(t); // not required to recalculate here; will be more predictable\n                            shm_conn_info->stats[info.process_num].speed_chan_data[chan_num].send_q_loss = info.channel[chan_num].send_q; // never ever used!! TODO remove\n                            //if (my_max_send_q < info.rsr) {\n                            //    drop_packet_flag = 0;\n                            //}\n                            shm_conn_info->stats[info.process_num].my_max_send_q_chan_num = my_max_send_q_chan_num;\n                            shm_conn_info->stats[info.process_num].speed_chan_data[chan_num].up_recv_speed = // TODO: remove! never used\n                                    info.channel[chan_num].packet_recv_upload;\n                            if (my_max_send_q_chan_num == chan_num) {\n                                //shm_conn_info->stats[info.process_num].ACK_speed = info.channel[chan_num].packet_recv_upload_avg == 0 ? 1 : info.channel[chan_num].packet_recv_upload_avg;\n                                info.packet_recv_upload_avg = shm_conn_info->stats[info.process_num].ACK_speed;\n                            }\n                            shm_conn_info->stats[info.process_num].max_send_q = my_max_send_q;\n                            shm_conn_info->stats[info.process_num].max_send_q_avg = info.max_send_q_avg; // unused\n                            sem_post(&(shm_conn_info->stats_sem));\n                            info.channel[chan_num].bytes_put = 0; // bytes_put reset for modeling\n#ifdef DEBUGG\n                            vlog(LOG_INFO,\n                                    \"FRAME_CHANNEL_INFO recv chan_num %d send_q %\"PRIu32\" packet_recv %\"PRIu16\" packet_loss %\"PRId16\" packet_seq_num_acked %\"PRIu32\" packet_recv_period %\"PRIu32\" recv upload %\"PRIu32\" send_q %\"PRIu32\"\",\n                                    chan_num, info.channel[chan_num].send_q, info.channel[chan_num].packet_recv, (int16_t)info.channel[chan_num].packet_loss,\n                                    info.channel[chan_num].packet_seq_num_acked, info.channel[chan_num].packet_recv_period, info.channel[chan_num].packet_recv_upload, info.channel[chan_num].send_q);\n#endif\n\n                            if (info.channel[chan_num].packet_loss != 0) {\n                                fire_event(&my_events->loss);\n                            }\n                            continue;\n                        } else {\n\t\t\t\t\t\t\tvlog(LOG_ERR, \"WARNING! unknown frame mode received: %du, real flag - %u!\", (unsigned int) flag_var, ntohs(*((uint16_t *)(buf+(sizeof(uint32_t)))))) ;\n\t\t\t\t\t}\n                        vlog(LOG_ERR, \"Cannot resend frame %\"PRIu32\"; chan %d coz remomed api\", ntohl(*((uint32_t *)buf)), chan_num);\n                        continue;\n\n                    } // bad frame end\n        CHKCPU(14);\n                    if( fl==VTUN_ECHO_REQ ) {\n                        PCS_aux++;\n                        /* Send ECHO reply */\n                        if(!select_net_write(chan_num)) {\n                            vlog(LOG_ERR, \"Could not send echo reply due to net not selecting\");\n                            continue;\n                        }\n                        last_net_read_ds = get_ds_ts(info.current_time); \n                        if(debug_trace) {\n                            vlog(LOG_INFO, \"sending PONG...\");\n                        }\n                        int len_ret;\n                        if (chan_num == 0) {\n                            len_ret = proto_write(info.channel[chan_num].descriptor, buf, VTUN_ECHO_REP);\n                        } else {\n                            // send pong reply\n                            len_ret = udp_write(info.channel[chan_num].descriptor, buf, VTUN_ECHO_REP);\n                        }\n                        if ( len_ret < 0) {\n                            vlog(LOG_ERR, \"Could not send echo reply\");\n                            linker_term = TERM_NONFATAL;\n                            break;\n                        }\n                        shm_conn_info->stats[info.process_num].speed_chan_data[chan_num].up_data_len_amt += len_ret;\n                        shm_conn_info->stats[info.process_num].packet_upload_cnt++;\n                        info.channel[chan_num].up_len += len_ret;\n                        continue;\n                    }\n                    if( fl==VTUN_ECHO_REP ) {\n                        PCS_aux++;\n                        /* Just ignore ECHO reply */\n                        if(debug_trace) {\n                            vlog(LOG_INFO, \"... was echo reply\");\n                        }\n                        \n                        if(chan_num == 0) ping_rcvd = 1;\n                        last_net_read_ds = get_ds_ts(info.current_time); \n                        gettimeofday(&info.current_time, NULL);\n\n                        if (chan_num == my_max_send_q_chan_num) {\n                            timersub(&info.current_time, &ping_req_tv[chan_num], &tv_tmp);\n                            info.rtt = tv2ms(&tv_tmp);\n                            sem_wait(&(shm_conn_info->stats_sem));\n                            shm_conn_info->stats[info.process_num].rtt_phys_avg += (info.rtt - shm_conn_info->stats[info.process_num].rtt_phys_avg) / 2;\n                            if(shm_conn_info->stats[info.process_num].rtt_phys_avg <= 0) {\n                                shm_conn_info->stats[info.process_num].rtt_phys_avg = 1;\n                            }\n                            info.rtt = shm_conn_info->stats[info.process_num].rtt_phys_avg;\n                            // now update max_reorder_latency\n                            if(info.rtt >= (MAX_REORDER_LATENCY_MAX/1000)) {\n                                info.max_reorder_latency.tv_sec = 0;\n                                info.max_reorder_latency.tv_usec = MAX_REORDER_LATENCY_MAX;\n                            } else if (info.rtt == 1) {\n                                info.max_reorder_latency.tv_sec = 0;\n                                info.max_reorder_latency.tv_usec = MAX_REORDER_LATENCY_MIN; // NOTE possible problem here? \n                            } else {\n                                info.max_reorder_latency.tv_sec = 0;\n                                info.max_reorder_latency.tv_usec = info.rtt * 1000;\n                            }\n                            \n                            sem_post(&(shm_conn_info->stats_sem));\n                        }\n\n                        continue; \n                    }\n                    if( fl==VTUN_CONN_CLOSE ) {\n                        vlog(LOG_INFO,\"Connection close requested by other side daemon\");\n                        linker_term = TERM_NONFATAL;\n                        break;\n                    }\n                } else {\n                    \n        CHKCPU(15);\n                    /*\n\n                    __________               .__                    .___\n                    \\______   \\_____  ___.__.|  |   _________     __| _/\n                     |     ___/\\__  \\<   |  ||  |  /  _ \\__  \\   / __ | \n                     |    |     / __ \\\\___  ||  |_(  <_> ) __ \\_/ /_/ | \n                     |____|    (____  / ____||____/\\____(____  /\\____ | \n                                    \\/\\/                     \\/      \\/ \n                    __________                __           __           \n                    \\______   \\_____    ____ |  | __ _____/  |_         \n                     |     ___/\\__  \\ _/ ___\\|  |/ // __ \\   __\\        \n                     |    |     / __ \\\\  \\___|    <\\  ___/|  |          \n                     |____|    (____  /\\___  >__|_ \\\\___  >__|          \n                                    \\/     \\/     \\/    \\/              \n                    payload packet\n                     */\n                    \n                    gettimeofday(&info.current_time, NULL);\n                    info.channel[chan_num].down_packets++; // accumulate number of packets\n                    PCS++; // TODO: PCS is sent and then becomes ACS. it is calculated above. This is DUP for local use. Need to refine PCS/ACS calcs!\n                    shm_conn_info->stats[info.process_num].pbl_lossed_cnt++;\n                    last_net_read_ds = get_ds_ts(info.current_time); \n                    statb.bytes_rcvd_norm+=len;\n                    statb.bytes_rcvd_chan[chan_num] += len;\n                    out = buf; // wtf?\n                    uint32_t local_seq_tmp;\n                    uint16_t mini_sum;\n                    uint32_t last_recv_lsn;\n                    uint32_t packet_recv_spd;\n                    flag_var = 0;\n                    CHKCPU(2);\n                    len = seqn_break_tail(out, len, &seq_num, &flag_var, &local_seq_tmp, &mini_sum, &last_recv_lsn, &packet_recv_spd);\n#ifdef CODE_LOG\n                    vlog(LOG_INFO, \"PKT local seq num %\"PRIu32\" seq_num %\"PRIu32\"\", local_seq_tmp, seq_num);\n#endif\n                    // rtt calculation\n                    if( (info.rtt2_lsn[chan_num] != 0) && (last_recv_lsn > info.rtt2_lsn[chan_num])) {\n                        timersub(&info.current_time, &info.rtt2_tv[chan_num], &tv_tmp);\n                        //info.rtt2 = tv2ms(&tv_tmp);\n                        info.rtt2_lsn[chan_num] = 0;\n                        info.srtt2_10 += ((int)tv2ms(&tv_tmp)*10 - info.srtt2_10) / 8;\n                        info.srtt2_100 += ((int)tv2ms(&tv_tmp)*100 - info.srtt2_100) / 50;\n                        info.rtt2 = info.srtt2_10 / 10; // check this!\n                        if (info.rtt2 <= 0) info.rtt2 = 1;\n                        int r_delta = (int)tv2ms(&tv_tmp) - info.srtt2_10 / 10;\n                        if(r_delta > 0) {\n                            info.srtt2var = (3 * info.srtt2var  +  r_delta)/4;\n                        } else {\n                            info.srtt2var = (3 * info.srtt2var  -  r_delta)/4;\n                        }\n                    }\n\n                    // if ((start_of_train != 0) && (chan_num == 1)) {\n\n                    //     if (last_recv_lsn >= end_of_train) {\n                    //         uint32_t packet_lag = last_recv_lsn - start_of_train;\n                    //         start_of_train = 0;\n                    //         //if(packet_lag > (TRAIN_PKTS + TRAIN_PKTS/2)) {\n                    //         //    vlog(LOG_ERR, \"WARNING Train calc wrong! packet_lag %d need train restart ASAP\", packet_lag);\n                    //         //    sem_wait(&(shm_conn_info->common_sem));\n                    //         //    shm_conn_info->last_flood_sent.tv_sec = 0;\n                    //         //    sem_post(&(shm_conn_info->common_sem));\n                    //         //} else {\n                    //             timersub(&info.current_time, &flood_start_time, &info.bdp1);\n                    //         //}\n\n                    //         // Now set max_chan -->\n                    //         // sem_wait(&(shm_conn_info->AG_flags_sem));\n                    //         uint32_t chan_mask = shm_conn_info->channels_mask;\n                    //         shm_conn_info->stats[info.process_num].bdp1 = info.bdp1;\n                    //         // sem_post(&(shm_conn_info->AG_flags_sem));\n                    //         sem_wait(&(shm_conn_info->stats_sem));\n                    //         //shm_conn_info->bdp1[info.process_num] = info.bdp1;\n                    //         // now find max_chan\n                    //         set_max_chan(chan_mask);\n                    //         sem_post(&(shm_conn_info->stats_sem));\n                    //         // <-- end max_chan set\n                            \n                    //         vlog(LOG_INFO, \"%s paket_lag %\"PRIu32\" bdp %\"PRIu32\"%\"PRIu32\"us %\"PRIu32\"ms\",  lfd_host->host, packet_lag, info.bdp1.tv_sec,\n                    //                 info.bdp1.tv_usec, tv2ms(&info.bdp1));\n                    //     }\n                    // }\n\n                    CHKCPU(21);\n                    // calculate send_q and speed\n                    // send_q\n                    if(info.channel[chan_num].packet_seq_num_acked != last_recv_lsn) {\n                        info.channel[chan_num].send_q_time = info.current_time;\n                        info.channel[chan_num].bytes_put = 0; // bytes_put reset for modeling\n                    }\n                    info.channel[chan_num].packet_seq_num_acked = last_recv_lsn;\n                    info.channel[chan_num].send_q =\n                                    info.channel[chan_num].local_seq_num > info.channel[chan_num].packet_seq_num_acked ?\n                                            1000 * (info.channel[chan_num].local_seq_num - info.channel[chan_num].packet_seq_num_acked) : 0;\n                    //if(info.max_send_q < info.channel[chan_num].send_q) {\n                    //    info.max_send_q = info.channel[chan_num].send_q;\n                    //}\n\n#ifdef DEBUGG\nif(drop_packet_flag) {\n                    vlog(LOG_INFO, \"PKT send_q %d:.local_seq_num=%d, last_recv_lsn=%d\", info.channel[chan_num].send_q, info.channel[chan_num].local_seq_num, info.channel[chan_num].packet_seq_num_acked);\n}\n#endif\n              //      vlog(LOG_INFO, \"PKT send_q %d\", info.channel[chan_num].send_q);\n                    // the following is to calculate my_max_send_q_chan_num only\n                    uint32_t my_max_send_q = 0;\n                    for (int i = 1; i < info.channel_amount; i++) {\n                        if (my_max_send_q < info.channel[i].send_q) {\n                            my_max_send_q = info.channel[i].send_q;\n                            my_max_send_q_chan_num = i;\n                        }\n                    }\n                    CHKCPU(26);\n\n                    // ACS\n                    info.channel[chan_num].packet_recv_upload = packet_recv_spd; // each packet data\n                    info.channel[chan_num].packet_recv_upload_avg =\n                            info.channel[chan_num].packet_recv_upload > info.channel[chan_num].packet_recv_upload_avg ?\n                                    (info.channel[chan_num].packet_recv_upload - info.channel[chan_num].packet_recv_upload_avg) / 4\n                                            + info.channel[chan_num].packet_recv_upload_avg :\n                                    info.channel[chan_num].packet_recv_upload_avg\n                                            - (info.channel[chan_num].packet_recv_upload_avg - info.channel[chan_num].packet_recv_upload) / 4;\n\n                    sem_wait(&(shm_conn_info->stats_sem)); // critical_sem\n                    if (my_max_send_q_chan_num == chan_num) {\n                        //shm_conn_info->stats[info.process_num].ACK_speed = info.channel[chan_num].packet_recv_upload_avg == 0 ? 1 : info.channel[chan_num].packet_recv_upload_avg;\n                        info.packet_recv_upload_avg = shm_conn_info->stats[info.process_num].ACK_speed;\n                    }\n                    shm_conn_info->stats[info.process_num].max_send_q = my_max_send_q;\n                    shm_conn_info->stats[info.process_num].rtt2 = info.rtt2; // TODO: do this copy only if RTT2 recalculated (does not happen each frame)\n                    shm_conn_info->stats[info.process_num].srtt2_10 = info.srtt2_10; // TODO: do this copy only if RTT2 recalculated (does not happen each frame)\n                    shm_conn_info->stats[info.process_num].srtt2_100 = info.srtt2_100; // TODO: do this copy only if RTT2 recalculated (does not happen each frame)\n                    sem_post(&(shm_conn_info->stats_sem)); // critical_sem\n\n                    //vlog(LOG_INFO, \"PKT spd %d %d\", info.channel[chan_num].packet_recv_upload, info.channel[chan_num].packet_recv_upload_avg);\n\n                    /* Accumulate loss packet*/\n                    uint16_t mini_sum_check = (uint16_t)(seq_num + local_seq_tmp + last_recv_lsn);\n                    \n                    if(mini_sum != mini_sum_check) { // TODO: remove!\n                        vlog(LOG_ERR, \"PACKET CHECKSUM ERROR chan %d, seq_num %lu, %\"PRId16\" != %\"PRId16\"\", chan_num, seq_num, ntohs(mini_sum), mini_sum_check);\n                        continue;\n                    }\n                    \n                    CHKCPU(27);\n                    // this is loss detection -->\n                    if(shm_conn_info->seq_num_unrecoverable_loss == 0 && seq_num != 0) { \n                            // prevent unrecoverable loss from being set to 0 by lossed_consume\n                        vlog(LOG_ERR, \"WARNING! detected unrecoverable loss of 0 packets, fixing to seq %ld\", seq_num);\n                        shm_conn_info->seq_num_unrecoverable_loss = seq_num;\n                    }\n                    unsigned int lrs;\n                    if(lossed_consume(local_seq_tmp, seq_num, &lrs, &info.channel[chan_num].local_seq_num_recv) == 0) {\n                        info.channel[chan_num].loss_time = info.current_time;\n                        shm_conn_info->write_buf[chan_num].packet_lost_state[info.process_num] = 0; // no need to sync\n                    }\n                    sem_wait(write_buf_sem); // critical_sem\n                    shm_conn_info->write_buf[chan_num].last_received_seq[info.process_num] = lrs;\n                    \n                    info.channel[chan_num].packet_recv_counter++;\n#ifdef DEBUGG\nif(drop_packet_flag) {\n                    vlog(LOG_INFO, \"Receive frame ... chan %d local seq %\"PRIu32\" seq_num %\"PRIu32\" recv counter  %\"PRIu16\" len %d loss is %\"PRId16\"\", chan_num, info.channel[chan_num].local_seq_num_recv,seq_num, info.channel[chan_num].packet_recv_counter, length, (int16_t)info.channel[chan_num].packet_loss_counter);\n}\n#endif\n                    if(debug_trace) {\n                        vlog(LOG_INFO, \"Receive frame ... chan %d local seq %\"PRIu32\" seq_num %\"PRIu32\" recv counter  %\"PRIu16\" len %d loss is %\"PRId16\"\", chan_num, info.channel[chan_num].local_seq_num_recv,seq_num, info.channel[chan_num].packet_recv_counter, len, (int16_t)info.channel[chan_num].packet_loss_counter);\n                    }\n                    CHKCPU(28);\n                    // HOLY CRAP! remove this! --->>>\n                    // introduced virtual chan_num to be able to process\n                    //    congestion-avoided priority resend frames\n                    if(chan_num == 0) { // reserved aux channel\n                         if(flag_var == 0) { // this is a workaround for some bug... TODO!!\n                              vlog(LOG_ERR,\"BUG! flag_var == 0 received on chan 0! sqn %\"PRIu32\", len %d. DROPPING\",seq_num, len);\n                              sem_post(write_buf_sem); // critical_sem\n                              continue;\n                         } \n                         chan_num_virt = flag_var - FLAGS_RESERVED;\n                    } else {\n                         chan_num_virt = chan_num;\n                    }\n#ifdef DEBUGG\n                    struct timeval work_loop1, work_loop2;\n                    gettimeofday(&work_loop1, NULL );\n#endif\n                    uint16_t my_miss_packets = 0;\n                    info.channel[chan_num].last_recv_time = info.current_time;\n                    CHKCPU(3);\n\n//                    print_head_of_packet(out, \"recv packet\",seq_num, len);\n\n                    succ_flag = 0;\n                    int newPacket = 0;\n                    if(shm_conn_info->flushed_packet[seq_num % FLUSHED_PACKET_ARRAY_SIZE] != seq_num){\n                        newPacket = 1;\n                    }\n                    incomplete_seq_len = write_buf_add(chan_num_virt, out, len, seq_num, incomplete_seq_buf, &buf_len, info.pid, &succ_flag);\n                    my_miss_packets = buf_len;\n                    my_miss_packets_max = my_miss_packets_max < buf_len ? buf_len : my_miss_packets_max;\n                    if(succ_flag == -2) statb.pkts_dropped++; // TODO: optimize out to wba\n                    if(buf_len == 1) { // to avoid dropping first out-of order packet in sequence\n                         shm_conn_info->write_buf[chan_num_virt].last_write_time.tv_sec = info.current_time.tv_sec;\n                         shm_conn_info->write_buf[chan_num_virt].last_write_time.tv_usec = info.current_time.tv_usec;\n                    }\n#ifdef SUM_SEND\n                    int sumIndex = get_packet_code(&shm_conn_info->packet_code_recived[chan_num][0], &shm_conn_info->packet_code_bulk_counter, seq_num);\n                    if (sumIndex != -1) {\n                        if (newPacket) {\n                            shm_conn_info->packet_code_recived[chan_num][sumIndex].lostAmount--;\n                        }\n#ifdef CODE_LOG\n                        vlog(LOG_INFO, \"LostAmount %d\", shm_conn_info->packet_code_recived[chan_num][sumIndex].lostAmount);\n#endif\n                        if (shm_conn_info->packet_code_recived[chan_num][sumIndex].lostAmount == 1) {\n                            uint32_t lostSeq = frame_llist_getLostPacket_byRange(&shm_conn_info->write_buf[chan_num].frames,\n                                    &shm_conn_info->wb_just_write_frames[chan_num], shm_conn_info->frames_buf,\n                                    &shm_conn_info->packet_code_recived[chan_num][sumIndex]);\n#ifdef CODE_LOG\n                            vlog(LOG_INFO, \"packet after sum Uniq lostSeq %u found\", lostSeq);\n#endif\n                            int packet_index = check_n_repair_packet_code(&shm_conn_info->packet_code_recived[chan_num][0],\n                                    &shm_conn_info->wb_just_write_frames[chan_num], &shm_conn_info->write_buf[chan_num].frames,\n                                    shm_conn_info->frames_buf, lostSeq);\n                            if (packet_index > -1) {\n                                shm_conn_info->packet_code_recived[chan_num][sumIndex].lostAmount = 0;\n                                if (shm_conn_info->packet_code_recived[chan_num][packet_index].sum[0] != 0x45) {\n                                    print_head_of_packet(shm_conn_info->packet_code_recived[chan_num][packet_index].sum, \"ASSERT BAD packet after sum repaired \", lostSeq,\n                                                                            shm_conn_info->packet_code_recived[chan_num][packet_index].len_sum);\n                                } else {\n                                    vlog(LOG_INFO, \"{\\\"name\\\":\\\"%s\\\",\\\"repaired_seq_num\\\":%\"PRIu32\", \\\"place\\\": 1}\", lfd_host->host, lostSeq);\n                                    \n#ifdef CODE_LOG\n                                print_head_of_packet(shm_conn_info->packet_code_recived[chan_num][packet_index].sum, \"packet after sum repaired \", lostSeq,\n                                        shm_conn_info->packet_code_recived[chan_num][packet_index].len_sum);\n#endif\n                                }\n                                write_buf_add(chan_num, shm_conn_info->packet_code_recived[chan_num][packet_index].sum,\n                                        shm_conn_info->packet_code_recived[chan_num][packet_index].len_sum, lostSeq, incomplete_seq_buf, &buf_len,\n                                        info.pid, &succ_flag);\n                            }\n                        }\n                    }\n#endif\n                    struct timeval last_write_time_tmp = shm_conn_info->write_buf[chan_num_virt].last_write_time;\n                    int cond_flag = shm_conn_info->write_buf[chan_num_virt].last_written_seq > (last_last_written_seq[chan_num_virt] + lfd_host->FRAME_COUNT_SEND_LWS) ? 1 : 0;\n                    if(cond_flag) {\n                        if(debug_trace) {\n                            vlog(LOG_INFO, \"sending FRAME_LAST_WRITTEN_SEQ lws %\"PRIu32\" chan %d\", shm_conn_info->write_buf[chan_num_virt].last_written_seq, chan_num_virt);\n                        }\n                        *((uint32_t *)buf) = htonl(shm_conn_info->write_buf[chan_num_virt].last_written_seq);\n                        last_last_written_seq[chan_num_virt] = shm_conn_info->write_buf[chan_num_virt].last_written_seq;\n                        shm_conn_info->write_buf[chan_num_virt].last_lws_notified = info.current_time.tv_sec;\n                    }\n                    sem_post(write_buf_sem); // critical_sem\n#ifdef DEBUGG\n                    gettimeofday(&work_loop2, NULL );\n                    vlog(LOG_INFO, \"write_buf_add time: %\"PRIu32\" us\", (long int) ((work_loop2.tv_sec - work_loop1.tv_sec) * 1000000 + (work_loop2.tv_usec - work_loop1.tv_usec)));\n#endif\n                    if(incomplete_seq_len == -1) {\n                        vlog(LOG_ERR, \"ASSERT FAILED! free write buf assert failed on chan %d\", chan_num_virt);\n                        buf_len = 100000; // flush the sh*t\n                    }\n\n                    CHKCPU(31);\n                    if(buf_len > lfd_host->MAX_ALLOWED_BUF_LEN) {\n                        vlog(LOG_ERR, \"WARNING! MAX_ALLOWED_BUF_LEN reached! Flushing... chan %d\", chan_num_virt);\n                    }\n\n                    // check for initialization\n                    if (!info.just_started_recv) {\n                        continue;\n                    }\n\n                    // if (FD_ISSET(info.tun_device, &fdset_w)) {\n                    //     int write_out_max = buf_len / alive_physical_channels;\n                    //     if(write_out_max > WRITE_OUT_MAX) write_out_max = WRITE_OUT_MAX;\n                    //     if(write_out_max < 2) write_out_max = 2;\n                    //     sem_wait(write_buf_sem); // critical_sem\n                    //     for (int i = 0; i < write_out_max; i++) {\n                    //         if (!write_buf_check_n_flush(chan_num_virt)) {\n                    //             break;\n                    //         }\n                    //     }\n                    //     sem_post(write_buf_sem); // critical_sem\n                    // }\n                    CHKCPU(32);\n                    // send lws(last written sequence number) to remote side\n                    if(cond_flag && select_net_write(chan_num_virt)) { // waste select!\n                        \n                        *((uint16_t *)(buf+sizeof(uint32_t))) = htons(FRAME_LAST_WRITTEN_SEQ);\n                        // send LWS - 2\n                        int len_ret = udp_write(info.channel[chan_num_virt].descriptor, buf, ((sizeof(uint32_t) + sizeof(flag_var)) | VTUN_BAD_FRAME));\n                        if (len_ret < 0) {\n                            vlog(LOG_ERR, \"Could not send last_written_seq pkt; exit\");\n                            linker_term = TERM_NONFATAL;\n                        }\n                        shm_conn_info->stats[info.process_num].speed_chan_data[chan_num_virt].up_data_len_amt += len_ret;\n                        shm_conn_info->stats[info.process_num].packet_upload_cnt++;\n                        info.channel[chan_num_virt].up_len += len_ret;\n                        // TODO: introduce periodic send via each channel. On channel use stop some of resend_buf will remain locked\n                        continue;\n                    }\n\n                    CHKCPU(33);\n                    lfd_host->stat.byte_in += len; // the counter became completely wrong\n\n                } // end load frame processing\n\n            } // if fd0>0\n\n        // if we could not create logical channels YET. We can't send data from tun to net. Hope to create later...\n            if ((info.channel_amount <= 1) || (info.just_started_recv == 0)) { // only service channel available\n#ifdef DEBUGG\n            vlog(LOG_INFO, \"Logical channels have not created. Hope to create later... \");\n#endif\n            if(timercmp(&tv, &select_tv_copy, ==)) { // means select was an immediate return\n                // we either did not connect channels or did not receive FRAME_JUST_STATRTED\n                // FJS is sent by TCP, so we should wait a bit and exit if we fail to get it at last\n                // fill in all structs for immediate read\n                FD_ZERO(&fdset_w);\n                FD_ZERO(&fdset);\n                pfdset_w = NULL;\n                tv.tv_sec = 0;\n                tv.tv_usec = 1000; // one ms to wait\n                for (i = 0; i < info.channel_amount; i++) {\n                    FD_SET(info.channel[i].descriptor, &fdset);\n                }\n                usleep(20000);\n                info.select_immediate++;\n                if(info.select_immediate > 1000) { // wait 20 seconds in total, then exit\n                    vlog(LOG_ERR, \"Timeout waiting for FRAME_JUST_STATRTED or channels to create\");\n                    linker_term = TERM_NONFATAL;\n                    break;\n                } else {\n                    goto main_select;\n                }\n            }\n            continue;\n        }\n        /* Pass data from write_buff to TUN device */\n\n        // I suspect write_buf_sem race condition here... double-check!\n\n\n        CHKCPU(4);\n        } // for chans..\n\n// TODO HERE: do not fall down if network is not selected for writing!\n\n            /* Read data from the local device(tun_device), encode and pass it to\n             * the network (service_channel)\n             *\n\n                .___         _________                  .___\n              __| _/____    /   _____/ ____   ____    __| _/\n             / __ |/  _ \\   \\_____  \\_/ __ \\ /    \\  / __ | \n            / /_/ (  <_> )  /        \\  ___/|   |  \\/ /_/ | \n            \\____ |\\____/  /_______  /\\___  >___|  /\\____ | \n                 \\/                \\/     \\/     \\/      \\/ \n                                 __           __            \n            ___________    ____ |  | __ _____/  |_          \n            \\____ \\__  \\ _/ ___\\|  |/ // __ \\   __\\         \n            |  |_> > __ \\\\  \\___|    <\\  ___/|  |           \n            |   __(____  /\\___  >__|_ \\\\___  >__|           \n            |__|       \\/     \\/     \\/    \\/               \n             *\n             * ****************************************************************************************\n             *\n             *\n             * */\n      //  if (hold_mode) continue;\n        sem_wait(&shm_conn_info->hard_sem); // critical_sem // TODO: REMOVE\n        if (ag_flag == R_MODE) {\n            // int lim = ((info.rsr < info.send_q_limit_cubic) ? info.rsr : info.send_q_limit_cubic);\n            // int n_to_send = (lim - send_q_eff) / 1000;\n            // if(n_to_send < 0) {\n            //     n_to_send = 0;\n            // }\n            len = retransmit_send(out2);\n        CHKCPU(41);\n            if (len == CONTINUE_ERROR) {\n#ifdef DEBUGG\n                vlog(LOG_INFO, \"debug: R_MODE continue err\");\n#endif\n                len = 0;\n            } else if (len == BREAK_ERROR) {\n                vlog(LOG_INFO, \"retransmit_send() BREAK_ERROR\");\n                linker_term = TERM_NONFATAL;\n//            break;\n            } else if ((len == LASTPACKETMY_NOTIFY) | (len == HAVE_FAST_RESEND_FRAME)) { // if this physical channel had sent last packet\n#ifdef DEBUGG\n                    vlog(LOG_INFO, \"debug: R_MODE main send\");\n#endif\n                if( (drop_packet_flag == 1) && (drop_counter > 0) ) {\n                    len = 0; // shittyhold - should never kick in again!    \n                    vlog(LOG_INFO, \"shit! hold!\");\n                } else {\n                len = select_devread_send(buf, out2);\n        CHKCPU(42);\n                }\n                \n                if (len > 0) {\n                } else if (len == BREAK_ERROR) {\n                    vlog(LOG_INFO, \"select_devread_send() R_MODE BREAK_ERROR\");\n                    linker_term = TERM_NONFATAL;\n//                break;\n                } else if (len == CONTINUE_ERROR) {\n                    len = 0;\n                } else if (len == TRYWAIT_NOTIFY) {\n                    len = 0; //todo need to check resend_buf for new packet again ????\n                }\n            }\n        } else { // this is AGGREGATION MODE(AG_MODE) we jump here if all channels ready for aggregation. It very similar to the old MODE_NORMAL ...\n#ifdef DEBUGG\n        vlog(LOG_INFO, \"debug: AG_MODE\");\n#endif\n            if( (drop_packet_flag == 1) && (drop_counter > 0) ) {\n                    len = 0; // shittyhold // never\n                    vlog(LOG_INFO, \"shit! hold!\");\n            } else {\n            len = select_devread_send(buf, out2);\n        CHKCPU(43);\n            }\n            if (len > 0) {\n                dirty_seq_num++;\n#ifdef DEBUGG\n                vlog(LOG_INFO, \"Dirty seq_num - %u\", dirty_seq_num);\n#endif\n            } else if (len == BREAK_ERROR) {\n                vlog(LOG_INFO, \"select_devread_send() AG_MODE BREAK_ERROR\");\n                linker_term = TERM_NONFATAL;\n            } else if (len == CONTINUE_ERROR) {\n#ifdef DEBUGG\n                vlog(LOG_INFO, \"select_devread_send() CONTINUE\");\n#endif\n                len = 0;\n            } else if (len == TRYWAIT_NOTIFY) {\n#ifdef DEBUGG\n                vlog(LOG_INFO, \"select_devread_send() TRYWAIT_NOTIFY\");\n#endif\n                len = 0;\n            } else if (len == NET_WRITE_BUSY_NOTIFY) {\n#ifdef DEBUGG\n                vlog(LOG_INFO, \"select_devread_send() NET_WRITE_BUSY_NOTIFY\");\n#endif\n                len = 0;\n            } else if (len == SEND_Q_NOTIFY) {\n#ifdef DEBUGG\n                vlog(LOG_INFO, \"select_devread_send() SEND_Q_NOTIFY\");\n#endif\n                len = 0;\n            }\n        }\n\n        CHKCPU(5);\n        //todo #flood_code need to move\n//         int flood_flag = 0;\n//         sem_wait(&(shm_conn_info->common_sem));\n//         if (shm_conn_info->flood_flag[info.process_num])\n//             flood_flag = TRAIN_PKTS;\n//         shm_conn_info->flood_flag[info.process_num] = 0;\n//         sem_post(&(shm_conn_info->common_sem));\n//         uint32_t local_seq_num_p;\n//         uint16_t tmp_flag=0, gg1;\n//         uint32_t  gg2, gg3;\n//         if (flood_flag > 0 && linker_term != TERM_NONFATAL) {\n//             gettimeofday(&flood_start_time, NULL );\n//             start_of_train = info.channel[1].local_seq_num;\n//             end_of_train = start_of_train + flood_flag;\n//             sem_wait(&(shm_conn_info->resend_buf_sem));\n//             uint32_t seq_tmp;\n//             get_last_packet_seq_num(1, &seq_tmp);\n//             int sender_pid;\n//             char *out;\n//             int len = get_resend_frame(1, &seq_tmp, &out, &sender_pid );\n//             if (len == -1) {\n//                 len = get_last_packet(1, &last_sent_packet_num[1].seq_num, &out, &sender_pid);\n//             }\n//             if (len == -1) {\n//                 vlog(LOG_ERR, \"WARNING Cannot send train\");\n//             } else {\n//                 memcpy(buf, out, len);\n//             }\n//             if(len < 900) {\n//                 vlog(LOG_ERR, \"WARNING Train car too small to load track!\");\n//             }\n//             sem_post(&(shm_conn_info->resend_buf_sem));\n//             for (; flood_flag > 0; flood_flag--) {\n//                 len = seqn_break_tail(buf, len, &seq_tmp, &tmp_flag, &local_seq_num_p, &gg1, &gg2, &gg3); // last four unused\n//                 len = pack_packet(1, buf, len, seq_tmp, info.channel[1].local_seq_num, 0);\n//                 info.channel[1].packet_recv_counter = 0;\n//                 // send DATA\n//                 int len_ret = udp_write(info.channel[1].descriptor, buf, len);\n// //                vlog(LOG_INFO, \"send train process %i packet num %i local_seq %\"PRIu32\"\", info.process_num, flood_flag,\n// //                        info.channel[1].local_seq_num);\n//                 info.channel[1].local_seq_num++;\n//             }\n//         }\n        sem_post(&shm_conn_info->hard_sem); // critical_sem\n\n\n        gettimeofday(&info.current_time, NULL);\n        last_action = info.current_time.tv_sec;\n        lfd_host->stat.comp_out += len;\n        \n        CHKCPU(6);\n    }\n    \nfinish_loop:\n\n    free_timer(recv_n_loss_send_timer);\n    free_timer(send_q_limit_change_timer);\n    free_timer(s_q_lim_drop_timer);\n    free_timer(packet_speed_timer);\n    free_timer(head_channel_switch_timer);\n\n    sem_wait(&(shm_conn_info->AG_flags_sem));\n    shm_conn_info->channels_mask &= ~(1 << info.process_num); // del channel num from binary mask\n    shm_conn_info->need_to_exit &= ~(1 << info.process_num);\n    shm_conn_info->hold_mask &= ~(1 << info.process_num); // set bin mask to zero (send not allowed)\n    shm_conn_info->ag_mask &= ~(1 << info.process_num); // set bin mask to zero\n    sem_post(&(shm_conn_info->AG_flags_sem));\n#ifdef JSON\n    vlog(LOG_INFO,\"{\\\"name\\\":\\\"%s\\\",\\\"exit\\\":1}\", lfd_host->host);\n#endif\n\n    vlog(LOG_INFO, \"process_name - %s p_chan_num : %i,  exiting linker loop TERM=%i\", lfd_host->host, info.process_num, linker_term);\n    if( !linker_term && errno )\n        vlog(LOG_INFO,\"Reason: %s (%d)\", strerror(errno), errno);\n\n    if (linker_term == VTUN_SIG_TERM) {\n        lfd_host->persist = 0;\n    }\n    if(channel_mode == MODE_NORMAL) { // may quit with different mode\n        shm_conn_info->normal_senders--; // TODO HERE: add all possible checks for sudden deaths!!!\n    }\n\n    sem_wait(&(shm_conn_info->stats_sem));\n    shm_conn_info->stats[info.process_num].pid = 0;\n    shm_conn_info->stats[info.process_num].name[0] = 0;\n    shm_conn_info->stats[info.process_num].weight = 0;\n    shm_conn_info->stats[info.process_num].max_send_q = 0;\n    shm_conn_info->stats[info.process_num].max_send_q_avg = 0;\n    sem_post(&(shm_conn_info->stats_sem));\n\n    /* Notify other end about our close */\n    proto_write(service_channel, buf, VTUN_CONN_CLOSE);\n    for (i = 0; i < info.channel_amount; i++) {\n        close(info.channel[i].descriptor);\n    }\n    close(prio_s);\n\n    if(linker_term == TERM_NONFATAL) linker_term = 0; // drop nonfatal flag\n\n    /*struct sigaction sa;\n    memset(&sa, 0, sizeof(sigaction));\n    sigemptyset(&sa.sa_mask);\n    sa.sa_sigaction = segfault_sigaction;\n    sa.sa_flags   = SA_SIGINFO;\n    sigaction(SIGSEGV, &sa, NULL);\n    */\n    if(buf != save_buf) {\n        vlog(LOG_ERR,\"ERROR: cannot free buf: CORRUPT!\");\n        lfd_free(save_buf);\n    } else {\n        lfd_free(buf);\n    }\n    if(save_out_buf != out_buf) {\n        vlog(LOG_ERR,\"ERROR: cannot free out_buf: CORRUPT!\");\n        lfd_free(save_out_buf);\n    } else {\n        lfd_free(out_buf);\n    }\n\n    /*memset(&sa, 0, sizeof(sigaction));\n    sigemptyset(&sa.sa_mask);\n    sa.sa_sigaction = SIG_DFL;\n    //sa.sa_flags   = SA_SIGINFO;\n    sigaction(SIGSEGV, &sa, NULL);*/\n    \n#ifdef PROF\n    chdir(\"/\");\n#endif\n\n    return 0;\n}\n\n/**\n *\n___________       __                    _____       \n\\_   _____/ _____/  |________ ___.__. _/ ____\\____  \n |    __)_ /    \\   __\\_  __ <   |  | \\   __\\/    \\ \n |        \\   |  \\  |  |  | \\/\\___  |  |  | |   |  \\\n/_______  /___|  /__|  |__|   / ____|  |__| |___|  /\n        \\/     \\/             \\/                 \\/\n\n *  Link remote and local file descriptors.\n *  We should initialize all global variable here if it possible.\n */\nint linkfd(struct vtun_host *host, struct conn_info *ci, int ss, int physical_channel_num)\n{\n    shm_conn_info = ci;\n    memset(last_sent_packet_num, 0, sizeof(struct last_sent_packet) * MAX_TCP_LOGICAL_CHANNELS);\n    memset(&info, 0, sizeof(struct phisical_status));\n    rxmt_mode_request = 0; // flag\n    weight = 0; // bigger weight more time to wait(weight == penalty)\n    weight_cnt = 0;\n    acnt = 0; // assert variable\n\n    vlog_init();\n    // these are for retransmit mode... to be removed\n    retransmit_count = 0;\n    channel_mode = MODE_NORMAL;\n    hold_mode = 0; // 1 - hold 0 - normal\n    force_hold_mode = 1;\n    incomplete_seq_len = 0;\n    my_miss_packets_max = 0; // in ms; calculated here\n    miss_packets_max = 0; // get from another side\n    proto_err_cnt = 0;\n    my_max_send_q_chan_num = 0;\n    my_max_send_q = 0;\n    max_reorder_byte = 0;\n    last_channels_mask = 0;\n    info.B = 0.2;\n    info.Bu = 0.2;\n    /*Variables for the exact way of measuring speed*/\n    send_q_read_timer = (struct timeval) {0, 0};\n    send_q_read_drop_time = (struct timeval) {0, 100000};\n    send_q_mode_switch_time = (struct timeval) {0, 0};\n    ACK_coming_speed_avg = 0;\n    send_q_limit = 7000;\n    magic_rtt_avg = 0;\n\n    /* Host we are working with.\n     * Used by signal handlers that's why it is global.\n     */\n\n    lfd_mod_head = NULL;\n    lfd_mod_tail = NULL;\n    chan_info = NULL;\n    info.max_send_q_max = 0;\n    info.max_send_q_min = 120000;\n    sem_wait(&shm_conn_info->common_sem);\n    if (shm_conn_info->eff_len.sum == 0) {\n        shm_conn_info->eff_len.sum = 1000;\n    }\n    sem_post(&shm_conn_info->common_sem);\n    info.check_shm = 1;\n    struct sigaction sa, sa_oldterm, sa_oldint, sa_oldhup, sa_oldusr1;\n    int old_prio;\n    /** Global initialization section for variable and another things*/\n\n    lfd_host = host;\n    info.srv = ss;\n    info.pid = getpid();\n    info.process_num = physical_channel_num;\n    info.mode = R_MODE;\n    if (info.srv) {\n        info.channel_amount = 0; // first time for server, later server is getting it from client through net\n    } else {\n        info.channel_amount = P_TCP_CONN_AMOUNT + 1; // current here number of channels include service_channel\n        info.channel = calloc(info.channel_amount, sizeof(*(info.channel)));\n        if (info.channel == NULL) {\n            vlog(LOG_ERR, \"Cannot allocate memory for info.channel, process - %i, pid - %i\",info.process_num, info.pid);\n            return 0;\n        }\n        if (info.channel_amount > MAX_TCP_LOGICAL_CHANNELS) {\n            vlog(LOG_ERR, \"ASSERT! channel amount corrupt %i channels. Exit \", info.channel_amount);\n            info.channel_amount = MAX_TCP_LOGICAL_CHANNELS;\n            linker_term = TERM_NONFATAL;\n            return 0;\n        }\n        chan_info = (struct channel_info *) calloc(info.channel_amount, sizeof(struct channel_info));\n        if (chan_info == NULL ) {\n            vlog(LOG_ERR, \"Can't allocate array for struct chan_info for the linker\");\n            return 0;\n        }\n        info.channel[0].descriptor = host->rmt_fd; // service channel\n        gettimeofday(&info.current_time, NULL );\n        for (int i = 0; i < info.channel_amount; i++) {\n            memcpy(&(info.channel[i].get_tcp_info_time_old), &info.current_time, sizeof(info.channel[i].get_tcp_info_time_old));\n            memcpy(&(info.channel[i].send_q_time), &info.current_time, sizeof(info.channel[i].send_q_time));\n        }\n    }\n    info.tun_device = host->loc_fd; // virtual tun device\n    sem_wait(&(shm_conn_info->AG_flags_sem));\n    shm_conn_info->channels_mask |= (1 << info.process_num); // add channel num to binary mask\n    shm_conn_info->hold_mask |= (1 << info.process_num); // set bin mask to 1 (free send allowed)\n    shm_conn_info->need_to_exit &= ~(1 << info.process_num);\n#ifdef DEBUGG\n            vlog(LOG_INFO, \"debug: new channel_mask %xx0 add channel - %u\", shm_conn_info->channels_mask, info.process_num);\n#endif\n    sem_post(&(shm_conn_info->AG_flags_sem));\n\n    /* Create pid directory if need */\n    if (mkdir(LINKFD_PID_DIR, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {\n        if (errno == EEXIST) {\n            vlog(LOG_INFO, \"%s already  exists :)\", LINKFD_PID_DIR);\n        } else {\n            vlog(LOG_ERR, \"Can't create lock directory %s: %s (%d)\", LINKFD_PID_DIR, strerror(errno), errno);\n        }\n    }\n\n    /* Write my pid into file */\n    char pid_file_str[200], pid_str[20];\n    sprintf(pid_file_str, \"%s/%s\", LINKFD_PID_DIR, lfd_host->host);\n    int pid_file_fd = open(pid_file_str, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);\n    if (pid_file_fd < 0) {\n        vlog(LOG_ERR, \"Can't create temp lock file %s\", pid_file_str);\n    }\n    int len = sprintf(pid_str, \"%d\\n\", info.pid);\n    if (write(pid_file_fd, pid_str, len) != len) {\n        vlog(LOG_ERR, \"Can't write PID %d to %s\", info.pid, pid_file_str);\n    }\n    close(pid_file_fd);\n\n    //old_prio=getpriority(PRIO_PROCESS,0);\n    //setpriority(PRIO_PROCESS,0,LINKFD_PRIO);\n    \n    memset(&sa, 0, sizeof(sa));\n    sa.sa_handler=SIG_IGN;\n    sa.sa_flags=SA_NOCLDWAIT;\n    sigaction(SIGCHLD,&sa,NULL);\n    \n    memset(&sa, 0, sizeof(sa));\n    sa.sa_handler=sig_term;\n    sigaction(SIGTERM,&sa,&sa_oldterm);\n    \n    memset(&sa, 0, sizeof(sa));\n    sa.sa_handler=sig_term;\n    sigaction(SIGINT,&sa,&sa_oldint);\n    \n    memset(&sa, 0, sizeof(sa));\n    sa.sa_handler=sig_hup;\n    sigaction(SIGHUP,&sa,&sa_oldhup);\n    \n    memset(&sa, 0, sizeof(sa));\n    sa.sa_handler=sig_usr1;\n    sigaction(SIGUSR1,&sa,&sa_oldusr1);\n\n\n    sigemptyset (&block_mask);\n    // sigemptyset (&unblock_mask);\n    sigaddset (&block_mask, SIGTERM);\n    sigaddset (&block_mask, SIGUSR1);\n    // sigaddset (&block_mask, SIGCONT);\n    sigaddset (&block_mask, SIGHUP);\n    sigaddset (&block_mask, SIGALRM);\n    if (sigprocmask(SIG_BLOCK, &block_mask, &unblock_mask) < 0) {\n        perror (\"sigprocmask\");\n        return 1;\n    }\n\n#ifdef PROF\n    sa.sa_handler=profexit;\n    sigaction(SIGUSR2,&sa,NULL);\n#endif\n\n    /* Initialize statstic dumps */\n    if( host->flags & VTUN_STAT ) {\n        char file[40];\n        sprintf(file,\"%s/%.20s\", VTUN_STAT_DIR, host->host);\n        if( (host->stat.file=fopen(file, \"a\")) ) {\n            setvbuf(host->stat.file, NULL, _IOLBF, 0);\n            //alarm(VTUN_STAT_IVAL);\n        } else\n            vlog(LOG_ERR, \"Can't open stats file %s\", file);\n    }\n\n    io_init();\n\n    lfd_linker();\n\n    io_init();\n\n    vlog_free();\n    remove(pid_file_str); // rm file with my pid\n    free(info.channel);\n    free(chan_info);\n\n    if( host->flags & VTUN_STAT ) {\n        //alarm(0);\n        if (host->stat.file)\n            fclose(host->stat.file);\n    }\n    // I'm saying that I'm dead\n    sem_wait(&(shm_conn_info->AG_flags_sem));\n    uint32_t chan_mask = shm_conn_info->channels_mask;\n    sem_post(&(shm_conn_info->AG_flags_sem));\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if ((i == info.process_num) || (!(chan_mask & (1 << i)))) {\n            continue;\n        }\n        sem_wait(&(shm_conn_info->stats_sem));\n        pid_t pid = shm_conn_info->stats[i].pid;\n        sem_post(&(shm_conn_info->stats_sem));\n    }\n\n    sigaction(SIGTERM,&sa_oldterm,NULL);\n    sigaction(SIGINT,&sa_oldint,NULL);\n    sigaction(SIGHUP,&sa_oldhup,NULL);\n    sigaction(SIGUSR1,&sa_oldusr1,NULL);\n    \n    if (sigprocmask(SIG_SETMASK, &unblock_mask, NULL) < 0) {\n        perror (\"sigprocmask 2\");\n        return 1;\n    }\n\n    //setpriority(PRIO_PROCESS,0,old_prio);\n\n    return linker_term;\n}\n"
  },
  {
    "path": "linkfd.h",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team,\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * linkfd.h,v 1.1.1.2.2.2.2.3 2006/11/16 04:03:26 mtbishop Exp\n */ \n\n#ifndef _LINKFD_H\n#define _LINKFD_H\n\n#define BREAK_ERROR -2\n#define CONTINUE_ERROR -1\n#define TRYWAIT_NOTIFY -3\n#define LASTPACKETMY_NOTIFY -4\n#define RESENDLIMIT_NOTIFY -5\n#define NET_WRITE_BUSY_NOTIFY -5\n#define SEND_Q_NOTIFY -6\n#define HAVE_FAST_RESEND_FRAME -7\n\n#define LINKFD_PID_DIR \"/var/run/vtrunkd\"\n/* Priority of the process in the link_fd function */\n/* Never set the priority to -19 without stating a good reason.\n *#define LINKFD_PRIO -19\n * Since the likely intent was just to give vtun an edge,\n * -1 will do nicely.\n */\n#define LINKFD_PRIO -1\n/* Frame alloc/free */\n//                              len value\n#define LINKFD_FRAME_RESERV sizeof(short)\n//                              seq_num                        flag\n#define LINKFD_FRAME_APPEND sizeof(unsigned long) + sizeof(unsigned short)\n\nstatic inline void * lfd_alloc(size_t size)\n{\n     register char * buf;\n\n     size += LINKFD_FRAME_RESERV + LINKFD_FRAME_APPEND;\n\n     if( !(buf = malloc(size)) )\n        return NULL;\n\n     return buf+LINKFD_FRAME_RESERV; \n}\n\nstatic inline void * lfd_realloc(void *buf, size_t size)\n{\n     unsigned char *ptr = buf;\n\n     ptr  -= LINKFD_FRAME_RESERV;\n     size += LINKFD_FRAME_RESERV;\n\n     if( !(ptr = realloc(ptr, size)) )\n        return NULL;\n\n     return ptr+LINKFD_FRAME_RESERV; \n}\n\nstatic inline void lfd_free(void *buf)\n{\n     unsigned char *ptr = buf;\n\n     free(ptr-LINKFD_FRAME_RESERV);\n}\n\n\nstatic inline int check_force_rtt_max_wait_time(int chan_num, int *next_token_ms);\n\nint linkfd(struct vtun_host *host, struct conn_info *ci, int ss, int conn_num);\n/* Module */\nstruct lfd_mod {\n   char *name;\n   int (*alloc)(struct vtun_host *host);\n   int (*encode)(int len, char *in, char **out);\n   int (*avail_encode)(void);\n   int (*decode)(int len, char *in, char **out);\n   int (*avail_decode)(void);\n   int (*free)(void);\n\n   struct lfd_mod *next;\n   struct lfd_mod *prev;\n};\n\n/* External LINKFD modules */\n\nextern struct lfd_mod lfd_zlib;\nextern struct lfd_mod lfd_lzo;\nextern struct lfd_mod lfd_encrypt;\nextern struct lfd_mod lfd_shaper;\n\n\nunsigned int get_tcp_hash(char *buf, unsigned int *tcp_seq);\n\n#endif\n"
  },
  {
    "path": "linux/tap_dev.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * $Id: tap_dev.c,v 1.4 2006/12/11 10:39:30 mtbishop Exp $\n */ \n\n/*\n    This is an empty file.  All functionality formerly here is moved\n    to the tun_dev.c file.  This file exists to prevent the automangle\n    tools from moving a tap_dev.c from the generic directory - which\n    we can't use - in place of this missing file.\n */\n"
  },
  {
    "path": "linux/tun_dev.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * $Id: tun_dev.c,v 1.4 2006/12/11 10:45:35 mtbishop Exp $\n */ \n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <syslog.h>\n#include <errno.h>\n\n#include <sys/ioctl.h>\n#include <sys/socket.h>\n#include <linux/if.h>\n\n#include \"vtun.h\"\n#include \"lib.h\"\n\n/* \n * Allocate TUN device, returns opened fd. \n * Stores dev name in the first arg(must be large enough).\n */  \nstatic int tun_open_common0(char *dev, int istun)\n{\n    char tunname[14];\n    int i, fd, err;\n\n    if( *dev ) {\n       sprintf(tunname, \"/dev/%s\", dev);\n       return open(tunname, O_RDWR | O_NONBLOCK);\n    }\n\n    sprintf(tunname, \"/dev/%s\", istun ? \"tun\" : \"tap\");\n    err = 0;\n    for(i=0; i < 255; i++){\n       sprintf(tunname + 8, \"%d\", i);\n       /* Open device */\n       if( (fd=open(tunname, O_RDWR)) > 0 ) {\n          strcpy(dev, tunname + 5);\n          return fd;\n       }\n       else if (errno != ENOENT)\n          err = errno;\n       else if (i)\t/* don't try all 256 devices */\n          break;\n    }\n    if (err)\n\terrno = err;\n    return -1;\n}\n\n#ifdef HAVE_LINUX_IF_TUN_H /* New driver support */\n#include <linux/if_tun.h>\n\n#ifndef OTUNSETNOCSUM\n/* pre 2.4.6 compatibility */\n#define OTUNSETNOCSUM  (('T'<< 8) | 200) \n#define OTUNSETDEBUG   (('T'<< 8) | 201) \n#define OTUNSETIFF     (('T'<< 8) | 202) \n#define OTUNSETPERSIST (('T'<< 8) | 203) \n#define OTUNSETOWNER   (('T'<< 8) | 204)\n#endif\n\nstatic int tun_open_common(char *dev, int istun)\n{\n    struct ifreq ifr;\n    int fd;\n\n    if ((fd = open(\"/dev/net/tun\", O_RDWR | O_NONBLOCK)) < 0)\n       return tun_open_common0(dev, istun);\n\n    memset(&ifr, 0, sizeof(ifr));\n    ifr.ifr_flags = (istun ? IFF_TUN : IFF_TAP) | IFF_NO_PI;\n    if (*dev)\n       strncpy(ifr.ifr_name, dev, IFNAMSIZ);\n\n    if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {\n       if (errno == EBADFD) {\n\t  /* Try old ioctl */\n \t  if (ioctl(fd, OTUNSETIFF, (void *) &ifr) < 0) \n\t     goto failed;\n       } else\n          goto failed;\n    } \n\n    strcpy(dev, ifr.ifr_name);\n    return fd;\n\nfailed:\n    close(fd);\n    return -1;\n}\n\n#else\n\n# define tun_open_common(dev, type) tun_open_common0(dev, type)\n\n#endif /* New driver support */\n\nint tun_open(char *dev) { return tun_open_common(dev, 1); }\nint tap_open(char *dev) { return tun_open_common(dev, 0); }\n\nint tun_close(int fd, char *dev) { return close(fd); }\nint tap_close(int fd, char *dev) { return close(fd); }\n\n/* Read/write frames from TUN device */\nint tun_write(int fd, char *buf, int len) { return write(fd, buf, len); }\nint tap_write(int fd, char *buf, int len) { return write(fd, buf, len); }\n\nint tun_read(int fd, char *buf, int len) { return read(fd, buf, len); }\nint tap_read(int fd, char *buf, int len) { return read(fd, buf, len); }\n"
  },
  {
    "path": "llist.c",
    "content": "\n/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * llist.c,v 1.1.1.2.6.1 2006/11/16 04:03:29 mtbishop Exp\n */ \n\n#include <stdlib.h>\n#include \"llist.h\"\n\n/* Function to work with the Linked Lists */\n\nvoid llist_init(llist *l)\n{\n\tl->head = l->tail = NULL;\n} \n\nint llist_empty(llist *l)\n{\n\treturn l->tail == NULL;\n}\n\nint llist_add(llist *l, void * d)\n{\n\tllist_elm *e;\n\n\tif( !(e=malloc(sizeof(llist_elm))) )\n\t   return -1; \t\n\n\tif( !l->head )\n\t   l->head = l->tail = e; \n\telse\n\t   l->tail->next = e;\n\tl->tail = e;\n\n\te->next = NULL;\n\te->data = d;\n\n\treturn 0;\n} \n\n/* Travel list from head to tail */\nvoid * llist_trav(llist *l, int (*f)(void *d, void *u), void *u)\n{\n\tllist_elm *i = l->head;\n\n\twhile( i ){\n\t   if( f(i->data,u) ) return i->data;\n\t   i = i->next;\n\t}\n\treturn NULL;\n}\n\n/* Copy list from (l) to (t) */\nint llist_copy(llist *l, llist *t, void* (*f)(void *d, void *u), void *u)\n{\n\tllist_elm *i = l->head;\n\n\tllist_init(t);\n\t\n\twhile( i ){\n\t   llist_add(t,f(i->data,u));\n\t   i = i->next;\n\t}\n\treturn 0;\n}\n\n/* Travel list from head to tail, deallocate each element */\nvoid * llist_free(llist *l, int (*f)(void *d, void *u), void *u)\n{\n\tllist_elm *i = l->head, *n;\n        void *ff = NULL; \n\n\twhile( i ){\n\t   n = i->next; \t\n\t   if( f(i->data,u) ) \n \t      ff = i->data;\n\t   else\n\t      free(i); \n\t   i = n;\n\t}\n\tl->head = l->tail = NULL;\n\treturn ff;\n}\n\n\n"
  },
  {
    "path": "llist.h",
    "content": "\n/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * llist.h,v 1.1.1.2.6.1 2006/11/16 04:03:32 mtbishop Exp\n */ \n\n#ifndef _VTUN_LLIST_H\n#define _VTUN_LLIST_H\n\nstruct llist_element {\n\tstruct llist_element * next;\n\tvoid * data;\n};\ntypedef struct llist_element llist_elm;\n\ntypedef struct {\n\tllist_elm * head;\n\tllist_elm * tail;\n} llist;\n\n\nvoid llist_init(llist *l);\nint  llist_add(llist *l, void *d);\nint  llist_empty(llist *l);\nvoid * llist_trav(llist *l, int (*f)(void *d, void *u), void *u);\nint llist_copy(llist *l, llist *t, void* (*f)(void *d, void *u), void *u);\nvoid * llist_free(llist *l, int (*f)(void *d, void *u), void *u);\n\n\n#endif /* _VTUN_LLIST_H */\n"
  },
  {
    "path": "lock.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * lock.c,v 1.1.1.1.2.3.2.1 2006/11/16 04:03:35 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/time.h>\n#include <syslog.h>\n#include <sys/types.h>\n#include <signal.h>\n#include <errno.h>\n#include <time.h>\n#include <sys/stat.h>\n\n#include \"vtun.h\"\n#include \"linkfd.h\"\n#include \"lib.h\" \n#include \"lock.h\"\n#include \"log.h\"\n\nint create_lock(char * file)\n{\n  char tmp_file[255], str[20];\n  int  fd, pid, ret;\n   \n  pid = getpid();  \n  ret = 0;\n\n    /* Create lock directory*/\n    if (mkdir(VTUN_LOCK_DIR, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {\n        if (errno == EEXIST) {\n            vlog(LOG_INFO, \"%s already  exists\", VTUN_LOCK_DIR);\n        } else {\n            vlog(LOG_INFO, \"Can't create lock directory %s: %s (%d)\", VTUN_LOCK_DIR, strerror(errno), errno);\n        }\n\n    }\n  /* Create temp file */\n  sprintf(tmp_file, \"%s_%d_tmp\\n\", file, pid);\n  if( (fd = open(tmp_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0 ){\n     vlog(LOG_ERR, \"Can't create temp lock file %s\", file);\n     return -1;\n  }\n\n  pid = sprintf(str, \"%d\\n\", pid);\n  if( write(fd, str, pid) == pid ){\n     /* Create lock file */\n     if( link(tmp_file, file) < 0 ){\n        /* Oops, already locked */\n        ret = -1;\n     }\n  } else { \n     vlog(LOG_ERR, \"Can't write to %s\", tmp_file);\n     ret = -1;\n  }\n  close(fd);\n\n  /* Remove temp file */\n  unlink(tmp_file);\n\n  return ret;\n}\n\npid_t read_lock(char * file)\n{\n  char str[20];\n  int  fd, pid;\n\n  /* Read PID from existing lock */\n  if( (fd = open(file, O_RDONLY)) < 0)\n     return -1;\n\n  pid = read(fd,str,sizeof(str));\n  close(fd);\n  if( pid <= 0 )\n     return -1;\n\n  str[sizeof(str)-1]='\\0';\n  pid = strtol(str, NULL, 10);\n  if( !pid || errno == ERANGE ){\n     /* Broken lock file */\n     if( unlink(file) < 0 )\n        vlog(LOG_ERR, \"Unable to remove broken lock %s\", file);\n     return -1;\n  }\n\n  /* Check if process is still alive */\n  if(kill(pid, 0) < 0 && errno == ESRCH ){\n     /* Process is dead. Remove stale lock. */\n     if( unlink(file) < 0 )\n        vlog(LOG_ERR, \"Unable to remove stale lock %s\", file);\n     return -1;\n  }\n\n  return pid;\n}\n\nint lock_host(struct vtun_host * host)\n{\n  char lock_file[255];\n  struct timespec tm;\n  int pid, i;\n\n  if( host->multi == VTUN_MULTI_ALLOW )\n     return 0;\n\n  sprintf(lock_file, \"%s/%s\", VTUN_LOCK_DIR, host->host);\n\n  /* Check if lock already exists. */\n  if( (pid = read_lock(lock_file)) > 0 ){ \n     /* Old process is alive */\n     switch( host->multi ){\n\tcase VTUN_MULTI_KILL:\n\t    vlog(LOG_INFO, \"We have another process (process %d), connection deny\", pid);\n            return -1; //temporaly, deny if process working\n           vlog(LOG_INFO, \"Killing old connection (process %d)\", pid);\n           if(pid != -1 && kill(pid, SIGTERM) < 0 && errno != ESRCH ){\n              vlog(LOG_ERR, \"Can't kill process %d. %s\",pid,strerror(errno));\n              return -1;\n           }\n           /* Give it a time(up to 5 secs) to terminate */\n\t   for(i=0; i < 10 && !kill(pid, 0); i++ ){\n              tm.tv_sec = 0; tm.tv_nsec = 500000000; \n              nanosleep(&tm, NULL);\n\t   }\n\n\t   /* Make sure it's dead */\t\t \n           if(pid != -1 && !kill(pid, SIGKILL) ){\n              vlog(LOG_ERR, \"Process %d ignored TERM, killed with KILL\", pid);\n   \t      /* Remove lock */\n              if( unlink(lock_file) < 0 )\n                 vlog(LOG_ERR, \"Unable to remove lock %s\", lock_file);\n\t   }\n\n\t   break;\n        case VTUN_MULTI_DENY:\n           return -1;\n     }\n  }\n  return create_lock(lock_file);\n}\n\nvoid unlock_host(struct vtun_host *host)\n{ \n  char lock_file[255];\n\n  if( host->multi == VTUN_MULTI_ALLOW )\n     return;\n\n  sprintf(lock_file, \"%s/%s\", VTUN_LOCK_DIR, host->host);\n\n  if( unlink(lock_file) < 0 )\n     vlog(LOG_ERR, \"Unable to remove lock %s\", lock_file);\n}\n"
  },
  {
    "path": "lock.h",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * lock.h,v 1.1.1.1.6.1 2006/11/16 04:03:38 mtbishop Exp\n */ \n\n#ifndef _VTUN_LOCK_H\n#define _VTUN_LOCK_H\n\npid_t read_lock(char * host);\nint   create_lock(char * host);\nint   lock_host(struct vtun_host * host);\nvoid  unlock_host(struct vtun_host * host);\n\n#endif /* _VTUN_LOCK_H */\n"
  },
  {
    "path": "log.c",
    "content": "#include \"config.h\"\n\n#include \"log.h\"\n\n#include <inttypes.h>\n#include <signal.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n#include <syslog.h>\n#include <sys/time.h>\n\n#include \"lib.h\"\n#include \"vtun.h\"\n\n#define SYSLOG_DUPS 3\nchar *syslog_buf[SYSLOG_DUPS];\nint syslog_buf_counter = 0;\nint syslog_dup_counter = 0;\nint syslog_sequential_counter = 0;\nint syslog_dup_type = 0; //0 - dups no found 1 - single dup 2 - double dup\nint init = 0;\n\n#define SYSLOG_HOST_LEN 256\nchar syslog_host[SYSLOG_HOST_LEN] = { 0x00 };\n\nint shm_log_state = 0; // 0 - regular log 1 - over shm\nstruct {\n    sem_t *logSem;\n    char *log;\n    int *pointer;       // Points after last string-termination zero byte.\n    int size;\n} shm_syslog = { NULL, NULL, NULL, 0 };\n\nvoid vlog_shm_set(int state, sem_t *logSem, char *log, int *counter, int size) {\n    shm_log_state = state;\n    if (state) {\n        shm_syslog.logSem = logSem;\n        shm_syslog.log = log;\n        shm_syslog.pointer = counter;\n        shm_syslog.size = size;\n    } else {\n        shm_syslog.logSem = NULL;\n        shm_syslog.log = NULL;\n        shm_syslog.pointer = NULL;\n        shm_syslog.size = 0;\n    }\n}\n\nvoid vlog_shm_print(int priority, char *format, ...) {\n    va_list ap;\n    va_start(ap, format);\n    if (shm_log_state) {\n        char buf[JS_MAX];\n        int str_len = vsnprintf(buf, sizeof(buf), format, ap);\n        sem_wait(shm_syslog.logSem);\n        if (shm_syslog.size - *(shm_syslog.pointer) < str_len + 1) { // str_len + zero terminate\n            memcpy(shm_syslog.log + * (shm_syslog.pointer), buf, shm_syslog.size - * (shm_syslog.pointer));\n            memcpy(shm_syslog.log, buf + (shm_syslog.size - * (shm_syslog.pointer)), (str_len + 1) - (shm_syslog.size - * (shm_syslog.pointer)));\n            *(shm_syslog.pointer) = (str_len + 1) - (shm_syslog.size - * (shm_syslog.pointer));\n        } else {\n            memcpy(shm_syslog.log + * (shm_syslog.pointer), buf, str_len + 1);\n            *shm_syslog.pointer += str_len + 1;\n        }\n        sem_post(shm_syslog.logSem);\n    } else {\n        vsyslog(priority, format, ap);\n    }\n    va_end(ap);\n}\n\n//\n//  TODO: Handle loglevel.\n//\nvoid vlog_shm_process(struct conn_info *shm_conn_info) {\n    static int logPointer = 0;\n    static char buf[JS_MAX] = { 0x00 };\n\n    /* Log checking */\n    int totalLen = 0; // to prevent race condition total log len no more SHM_SYSLOG\n    while (1) {\n        if (totalLen >= SHM_SYSLOG)\n            break;\n\n        sem_wait(&shm_conn_info->syslog.logSem);\n\n        // Nothing to log.\n        if (logPointer == shm_conn_info->syslog.counter) {\n            sem_post(&shm_conn_info->syslog.logSem);\n            break;\n        }\n\n        ssize_t availLen = (shm_conn_info->syslog.counter - logPointer + SHM_SYSLOG) % SHM_SYSLOG;\n        ssize_t bufLen = sizeof(buf);\n        ssize_t retLen = 0;\n\n        if (availLen < SHM_SYSLOG - logPointer) {\n            retLen = snprintf(buf, bufLen, \"%s\", shm_conn_info->syslog.log + logPointer);\n        } else {\n            ssize_t maxLen = min(bufLen, SHM_SYSLOG - logPointer);\n            retLen = snprintf(buf, maxLen, \"%s\", shm_conn_info->syslog.log + logPointer);\n            // { '\\0', ..., '\\0', 'H', 'e', 'l', 'l', 'o' } -+\n            //    ^                                          |\n            //    +------------------------------------------+\n            if ((retLen == SHM_SYSLOG - logPointer) && (shm_conn_info->syslog.log[0] != 0) && bufLen > retLen + 1) {\n                maxLen = sizeof(buf) - retLen;\n                retLen += snprintf(buf + retLen, maxLen, \"%s\", shm_conn_info->syslog.log);\n            }\n        }\n\n        totalLen += retLen + 1;\n        logPointer = (logPointer+ retLen + 1) % SHM_SYSLOG;\n\n        sem_post(&shm_conn_info->syslog.logSem);\n        // TODO: Why not syslog(buf)?\n        syslog(LOG_INFO, \"%s\", buf);\n    }\n}\n\n\nvoid vlog_init() {\n    for (int i = 0; i < SYSLOG_DUPS; i++) {\n        syslog_buf[i] = malloc(JS_MAX);\n        memset(syslog_buf[i], 0, JS_MAX);\n    }\n    init = 1;\n}\n\nvoid vlog_free() {\n    for (int i = 0; i < SYSLOG_DUPS; i++) {\n        free(syslog_buf[i]);\n    }\n    init = 0;\n}\n\nvoid vlog_open(const char *ident, int option, int facility) {\n    strncpy(syslog_host, ident, SYSLOG_HOST_LEN);\n    openlog(syslog_host, option, facility);\n}\n\nvoid vlog_close() {\n    closelog();\n}\n\nvoid vlog(int priority, char *format, ...) {\n#ifdef SYSLOG\n    if(vtun.quiet && priority != LOG_ERR) return;\n    static volatile sig_atomic_t in_syslog = 0;\n    char buf[JS_MAX];\n    va_list ap;\n    int print = 0;\n\n    if (!in_syslog) {\n        in_syslog = 1;\n\n        va_start(ap, format);\n        vsnprintf(buf, sizeof(buf) - 1, format, ap);\n        va_end(ap);\n        if (init) {\n            if (syslog_dup_type == 0) {\n//                syslog(priority, \"type 1 test counter %d %s new - %s\",syslog_buf_counter,syslog_buf[syslog_buf_counter], buf);\n\n                if (!strcmp(syslog_buf[syslog_buf_counter], buf)) {\n                    syslog_dup_counter++;\n                    syslog_dup_type = 1;\n                    syslog_sequential_counter = 0;\n//                    syslog(priority, \"type %d raise\",syslog_dup_type);\n                } else {\n                    int counter = syslog_buf_counter - 1;\n                    if (counter < 0) {\n                        counter = SYSLOG_DUPS - 1;\n                    }\n//                    syslog(priority, \"type 2 test buf %d counter %d %s new - %s\",syslog_buf_counter,counter,syslog_buf[counter], buf);\n                    if (!strcmp(syslog_buf[counter], buf)) {\n                        syslog_dup_counter++;\n                        syslog_dup_type = 2;\n//                        syslog(priority, \"type %d raise\",syslog_dup_type);\n                        syslog_sequential_counter = 0;\n                    } else {\n                        if (--counter < 0) {\n                            counter = SYSLOG_DUPS - 1;\n                        }\n//                        syslog(priority, \"type 3 test buf %d counter %d %s new - %s\",syslog_buf_counter,counter,syslog_buf[counter], buf);\n\n                        if (!strcmp(syslog_buf[counter], buf)) {\n                            syslog_dup_counter++;\n                            syslog_dup_type = 3;\n                            syslog_sequential_counter = 1;\n//                            syslog(priority, \"type %d raise\",syslog_dup_type);\n                        } else {\n                            if (++syslog_buf_counter == SYSLOG_DUPS) {\n                                syslog_buf_counter = 0;\n                            }\n                            int string_len = strlen(buf);\n                            if (string_len > JS_MAX) {\n                                string_len = JS_MAX - 2;\n                            }\n//                            syslog(priority, \"first save test buf %d %s\",syslog_buf_counter, buf);\n                            memcpy(syslog_buf[syslog_buf_counter], buf, string_len + 1);\n                            print = 1;\n                        }\n                    }\n                }\n            } else if (syslog_dup_type == 1) {\n                if (syslog_sequential_counter < 0) {\n                    syslog_sequential_counter = syslog_dup_type - 1;\n                }\n                int counter = syslog_buf_counter - syslog_sequential_counter;\n                if (counter < 0) {\n                    counter = syslog_buf_counter - syslog_sequential_counter + (SYSLOG_DUPS - 1);\n                }\n//                syslog(priority, \"type %d buf_counter %d sequential_counter %d counter %d log:\\\"%s\\\"\",syslog_dup_type,syslog_buf_counter, syslog_sequential_counter, counter, syslog_buf[counter]);\n\n                if (!strcmp(syslog_buf[counter], buf)) {\n                    syslog_sequential_counter--;\n                    syslog_dup_counter++;\n                } else {\n                    if (++syslog_buf_counter == SYSLOG_DUPS) {\n                        syslog_buf_counter = 0;\n                    }\n                    int string_len = strlen(buf);\n                    if (string_len > JS_MAX) {\n                        string_len = JS_MAX - 2;\n                    }\n                    memcpy(syslog_buf[syslog_buf_counter], buf, string_len + 1);\n                    print = 1;\n                }\n            } else if (syslog_dup_type == 2) {\n                if (syslog_sequential_counter < 0) {\n                    syslog_sequential_counter = syslog_dup_type - 1;\n                }\n                int counter = syslog_buf_counter - syslog_sequential_counter;\n                if (counter < 0) {\n                    counter = syslog_buf_counter - syslog_sequential_counter + (SYSLOG_DUPS );\n                }\n//               syslog(priority, \"type %d buf_counter %d sequential_counter %d counter %d log:\\\"%s\\\"\",syslog_dup_type,syslog_buf_counter, syslog_sequential_counter, counter, syslog_buf[counter]);\n                if (!strcmp(syslog_buf[counter], buf)) {\n                    syslog_sequential_counter--;\n                    syslog_dup_counter++;\n                } else {\n                    if (++syslog_buf_counter == SYSLOG_DUPS) {\n                        syslog_buf_counter = 0;\n                    }\n                    int string_len = strlen(buf);\n                    if (string_len > JS_MAX) {\n                        string_len = JS_MAX - 2;\n                    }\n                    memcpy(syslog_buf[syslog_buf_counter], buf, string_len + 1);\n                    print = 1;\n                }\n            }  else if (syslog_dup_type == 3) {\n                if (syslog_sequential_counter < 0) {\n                    syslog_sequential_counter = syslog_dup_type - 1;\n                }\n                int counter = syslog_buf_counter - syslog_sequential_counter;\n                if (counter < 0) {\n                    counter = syslog_buf_counter - syslog_sequential_counter + (SYSLOG_DUPS );\n                }\n//                syslog(priority, \"type %d buf_counter %d sequential_counter %d counter %d log:\\\"%s\\\"\",syslog_dup_type,syslog_buf_counter, syslog_sequential_counter, counter, syslog_buf[counter]);\n                if (!strcmp(syslog_buf[counter], buf)) {\n                    syslog_sequential_counter--;\n                    syslog_dup_counter++;\n                } else {\n                    if (++syslog_buf_counter == SYSLOG_DUPS) {\n                        syslog_buf_counter = 0;\n                    }\n                    int string_len = strlen(buf);\n                    if (string_len > JS_MAX) {\n                        string_len = JS_MAX - 2;\n                    }\n                    memcpy(syslog_buf[syslog_buf_counter], buf, string_len + 1);\n                    print = 1;\n                }\n            }\n        } else {\n            print = 1;\n        }\n\n        if (print) {\n            struct timeval ts;\n            gettimeofday(&ts, NULL);\n\n            if (syslog_dup_counter) {\n                vlog_shm_print(priority, \"%s [%\" PRIu64 \"]: Last %d message(s) repeat %d times dups %d\", syslog_host, tv2ms(&ts), syslog_dup_type, syslog_dup_counter / syslog_dup_type + 1, syslog_dup_counter);\n                syslog_dup_counter = 0;\n                syslog_dup_type = 0;\n                syslog_sequential_counter = 0;\n                for (int i = 0; i < SYSLOG_DUPS; i++) {\n                    if (i == syslog_buf_counter)\n                        continue;\n                    memset(syslog_buf[i], 0, JS_MAX);\n                }\n\n            }\n\n            vlog_shm_print(priority, \"%s [%\" PRIu64 \"]: %s\", syslog_host, tv2ms(&ts), buf);\n        }\n        in_syslog = 0;\n    }\n#else\n    return;\n#endif\n}"
  },
  {
    "path": "log.h",
    "content": "#ifndef _VTUN_LOG_H\n#define _VTUN_LOG_H\n\n#include \"config.h\"\n\n#include <semaphore.h>\n\n#include \"vtun.h\"\n\n#define\tLOG_EMERG\t0\t/* system is unusable */\n#define\tLOG_ALERT\t1\t/* action must be taken immediately */\n#define\tLOG_CRIT\t2\t/* critical conditions */\n#define\tLOG_ERR\t\t3\t/* error conditions */\n#define\tLOG_WARNING\t4\t/* warning conditions */\n#define\tLOG_NOTICE\t5\t/* normal but significant condition */\n#define\tLOG_INFO\t6\t/* informational */\n#define\tLOG_DEBUG\t7\t/* debug-level messages */\n\nvoid vlog_shm_set(int state, sem_t *logSem, char *log, int *counter, int size);\nvoid vlog_shm_print(int priority, char *format, ...);\nvoid vlog_shm_process(struct conn_info *shm_conn_info);\n\nvoid vlog_init();\nvoid vlog_free();\n\nvoid vlog_open(const char *ident, int option, int facility);\nvoid vlog_close();\n\nvoid vlog (int priority, char *format, ...);\n\n#endif // _VTUN_LOG_H"
  },
  {
    "path": "main.c",
    "content": "/*\n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network.\n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky.\n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * main.c,v 1.1.1.2.2.8.2.4 2006/11/16 04:03:41 mtbishop Exp\n */\n\n#include \"config.h\"\n#include \"version.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <string.h>\n#include <signal.h>\n#include <fcntl.h>\n#include <syslog.h>\n#include <sys/mman.h>\n#include <sys/time.h>\n#include <sys/resource.h>\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\n#ifdef DEBUGG\n#include <sys/types.h>\n#include <sys/gmon.h>\n#endif\n\n#include \"vtun.h\"\n#include \"lib.h\"\n#include \"log.h\"\n#include \"compat.h\"\n\n/* Global options for the server and client */\nstruct vtun_opts vtun;\nstruct vtun_host default_host;\nint debug_trace = 0;\n\nvoid write_pid(void);\nvoid reread_config(int sig);\nvoid usage(void);\nvoid version();\n\nextern int optind, opterr, optopt;\nextern char *optarg;\n\nint main(int argc, char *argv[], char *env[])\n{\n    int svr, daemon, sock, dofork, fd, opt;\n    struct vtun_host *host = NULL;\n    struct sigaction sa;\n    char *hst;\n\n    /* Configure default settings */\n    svr = 0; daemon = 1; sock = 0; dofork = 1;\n\n    vtun.cfg_file = VTUN_CONFIG_FILE;\n    vtun.persist = -1;\n    vtun.timeout = -1;\n\n    vtun.MAX_TUNNELS_NUM = -1; // todo: defaults?\n\n    /* Dup strings because parser will try to free them */\n    vtun.ppp   = strdup(\"/usr/sbin/pppd\");\n    vtun.ifcfg = strdup(\"/sbin/ifconfig\");\n    vtun.route = strdup(\"/sbin/route\");\n    vtun.fwall = strdup(\"/sbin/ipchains\");\n    vtun.iproute = strdup(\"/sbin/ip\");\n\n    vtun.svr_name = NULL;\n    vtun.svr_addr = NULL;\n    vtun.bind_addr.port = -1;\n    vtun.start_port = 0;\n    vtun.end_port = 0;\n    vtun.svr_type = -1;\n    vtun.quiet = 1;\n    vtun.syslog   = LOG_DAEMON;\n    vtun.shm_key = SHM_TUN_KEY;\n\n    /* Initialize default host options */\n    memset(&default_host, 0, sizeof(default_host));\n    default_host.flags   = VTUN_TTY | VTUN_TCP;\n    default_host.multi   = VTUN_MULTI_ALLOW;\n    default_host.timeout = VTUN_CONNECT_TIMEOUT;\n    default_host.ka_interval = 30;\n    default_host.ka_failure  = 4;\n    default_host.loc_fd = default_host.rmt_fd = -1;\n\n    default_host.TICK_SECS = P_TICK_SECS;\n    default_host.RXMIT_CNT_DROP_PERIOD = P_RXMIT_CNT_DROP_PERIOD;\n    default_host.MAX_WEIGHT_NORM = P_MAX_WEIGHT_NORM;\n    default_host.WEIGHT_SCALE = P_WEIGHT_SCALE;\n    default_host.WEIGHT_SMOOTH_DIV = P_WEIGHT_SMOOTH_DIV;\n    default_host.WEIGHT_START_STICKINESS = P_WEIGHT_START_STICKINESS;\n    default_host.WEIGHT_SAW_STEP_UP_DIV = P_WEIGHT_SAW_STEP_UP_DIV;\n    default_host.WEIGHT_SAW_STEP_UP_MIN_STEP = P_WEIGHT_SAW_STEP_UP_MIN_STEP;\n    default_host.WEIGHT_SAW_STEP_DN_DIV = P_WEIGHT_SAW_STEP_DN_DIV;\n    default_host.WEIGHT_MSEC_DELAY = P_WEIGHT_MSEC_DELAY;\n    default_host.MAX_WINDOW = RSR_TOP;\n    default_host.MAX_LATENCY = P_MAX_LATENCY;\n    default_host.MAX_LATENCY_DROP = P_MAX_LATENCY_DROP;\n    default_host.MAX_ALLOWED_BUF_LEN = P_MAX_ALLOWED_BUF_LEN;\n    default_host.MAX_REORDER = P_MAX_REORDER;\n    default_host.MAX_IDLE_TIMEOUT = P_MAX_IDLE_TIMEOUT;\n    default_host.FRAME_COUNT_SEND_LWS = P_FRAME_COUNT_SEND_LWS;\n    default_host.PING_INTERVAL = P_PING_INTERVAL;\n    default_host.TUN_TXQUEUE_LEN = P_TUN_TXQUEUE_LEN;\n    default_host.TCP_CONN_AMOUNT = P_TCP_CONN_AMOUNT;\n    default_host.START_WEIGHT = 0;\n    default_host.RT_MARK = -1;\n    //default_host.MAX_TUNNELS_NUM = P_MAX_TUNNELS_NUM;\n\n    /* Start logging to syslog and stderr */\n    vlog_open(\"vtrunkd\", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);\n\n    while ((opt = getopt(argc, argv, \"S:R:mDisf:P:L:t:M:nQpvh?\")) != EOF) {\n        switch (opt) {\n        case 'S':\n            vtun.shm_key = atoi(optarg);\n            break;\n        case 'R':\n            vtun.start_port = 0;\n            char *start_port = optarg;\n            char *end_port = strchr(start_port, '-');\n            *end_port = '\\0';\n            end_port++;\n            vtun.start_port = atoi(start_port);\n            vtun.end_port = atoi(end_port);\n            break;\n        case 'm':\n            if (mlockall(MCL_CURRENT | MCL_FUTURE) < 0) {\n                perror(\"Unable to mlockall()\");\n                exit(-1);\n            }\n            break;\n        case 'D':\n            // enable debug\n            debug_trace = 1;\n            break;\n        case 'i':\n            vtun.svr_type = VTUN_INETD;\n        case 's':\n            svr = 1;\n            break;\n        case 'L':\n            vtun.svr_addr = strdup(optarg);\n            if (svr) { // WARNING! -s option is required BEFORE -L for server to bind correctly\n                vtun.bind_addr.type = VTUN_ADDR_NAME;\n                vtun.bind_addr.name = strdup(optarg);\n            }\n            break;\n        case 'P':\n            vtun.bind_addr.port = atoi(optarg);\n            break;\n        case 'f':\n            vtun.cfg_file = strdup(optarg);\n            break;\n        case 'n':\n            daemon = 0;\n            break;\n        case 'Q':\n            vtun.quiet = 1;\n            break;\n        case 'V':\n            vtun.quiet = 0;\n            break;\n        case 'p':\n            vtun.persist = 1;\n            break;\n        case 't':\n            vtun.timeout = atoi(optarg);\n            break;\n        case 'M':\n            vtun.MAX_TUNNELS_NUM = atoi(optarg);\n            break;\n        case 'v':\n            version();\n            exit(0);\n            break;\n        case 'h':\n        case '?':\n            usage();\n            exit(0);\n            break;\n        default:\n            usage();\n            exit(1);\n        }\n    }\n    reread_config(0);\n\n    if (vtun.syslog != LOG_DAEMON) {\n        /* Restart logging to syslog using specified facility  */\n        vlog_close();\n        vlog_open(\"vtrunkd\", LOG_PID | LOG_NDELAY | LOG_PERROR, vtun.syslog);\n    }\n\n    if (!svr) {\n        if ( argc - optind < 2 ) {\n            usage();\n            exit(1);\n        }\n        hst = argv[optind++];\n\n        if ( !(host = find_host(hst)) ) {\n            vlog(LOG_ERR, \"Host %s not found in %s\", hst, vtun.cfg_file);\n            exit(1);\n        }\n\n        vtun.svr_name = strdup(argv[optind]);\n    }\n\n    /*\n     * Now fill uninitialized fields of the options structure\n     * with default values.\n     */\n    if (vtun.bind_addr.port == -1)\n        vtun.bind_addr.port = VTUN_PORT;\n    if (vtun.persist == -1)\n        vtun.persist = 0;\n    if (vtun.timeout == -1)\n        vtun.timeout = VTUN_TIMEOUT;\n    if (vtun.MAX_TUNNELS_NUM == -1)\n        vtun.MAX_TUNNELS_NUM = P_MAX_TUNNELS_NUM;\n\n    switch ( vtun.svr_type ) {\n    case -1:\n        vtun.svr_type = VTUN_STAND_ALONE;\n        break;\n    case VTUN_INETD:\n        sock = dup(0);\n        dofork = 0;\n        break;\n    }\n\n    if ( daemon ) {\n        if ( dofork && fork() )\n            exit(0);\n        struct rlimit core_limit;\n        core_limit.rlim_cur = RLIM_INFINITY;\n        core_limit.rlim_max = RLIM_INFINITY;\n\n        if (setrlimit(RLIMIT_CORE, &core_limit) < 0) {\n            vlog(LOG_ERR, \"setrlimit: Warning: core dumps may be truncated or non-existant reason %s (%d)\", strerror(errno), errno);\n        }\n        /* Direct stdin,stdout,stderr to '/dev/null' */\n        fd = open(\"/dev/null\", O_RDWR);\n        close(0); dup(fd);\n        close(1); dup(fd);\n        close(2); dup(fd);\n        close(fd);\n\n        setsid();\n\n        chdir(\"/\");\n#ifdef DEBUGG\n        // now init the profiler; don;t forget to set GMON_OUT_PREFIX\n        extern void _start (void), etext (void);\n        monstartup ((u_long) &_start, (u_long) &etext);\n#endif\n    }\n\n    if (svr) {\n        memset(&sa, 0, sizeof(sa));\n        sa.sa_handler = reread_config;\n        sigaction(SIGHUP, &sa, NULL);\n\n        init_title(argc, argv, env, \"vtrunkd[s]: \");\n\n        if ( vtun.svr_type == VTUN_STAND_ALONE )\n            write_pid();\n\n        server(sock);\n    } else {\n        init_title(argc, argv, env, \"vtrunkd[c]: \");\n        client(host);\n    }\n\n    closelog();\n\n    return 0;\n}\n\n/*\n * Very simple PID file creation function. Used by server.\n * Overrides existing file.\n */\nvoid write_pid(void)\n{\n    FILE *f;\n\n    if ( !(f = fopen(VTUN_PID_FILE, \"w\")) ) {\n        vlog(LOG_ERR, \"Can't write PID file\");\n        return;\n    }\n\n    fprintf(f, \"%d\", (int)getpid());\n    fclose(f);\n}\n\nvoid reread_config(int sig)\n{\n    if ( !read_config(vtun.cfg_file) ) {\n        vlog(LOG_ERR, \"No hosts defined\");\n        exit(1);\n    }\n}\n\nvoid usage(void)\n{\n    printf(\"vtrunkd version %s\\n\", VERSION); // new versioning\n    printf(\"Usage: \\n\");\n    printf(\"  Server:\\n\");\n    printf(\"\\tvtrunkd <-s> [-f file] [-P port] [-L local address] [-S SHM key] [-D (enable packet debug)] [-Q|-V]\\n\");\n    printf(\"  Client:\\n\");\n    /* I don't think these work. I'm disabling the suggestion - bish 20050601*/\n    /* these actually do work. At least given in config file -- grandrew 20110507*/\n    printf(\"\\tvtrunkd [-f file] \" /* [-P port] [-L local address] */\n           \"[-p] [-m] [-t timeout] <host profile> <server address> [-S SHM key] [-D (enable packet debug)] [-Q|-V]\\n\");\n}\n\nvoid version() {\n    printf(\"vtrunkd ver %s\\n\", VERSION);\n}\n"
  },
  {
    "path": "net_structs.h",
    "content": "/*\n * net_structs.h\n *\n *  Created on: 04.07.2012\n *      Author: Vrayo Systems Ltd. team \n */\n\n#ifndef NET_STRUCTS_H_\n#define NET_STRUCTS_H_\n#include <stdint.h>\n\n/**\n * simple info packet\n */\nstruct info_packet {\n\tuint32_t data;\n\tuint16_t flag;\n};\n/**\n * Struct for pack/unpack time lag\n * based on info_packet\n * contain info_packet + uint16_t\n */\nstruct time_lag_packet {\n\tuint32_t time_lag;\n\tuint16_t flag;\n\tuint16_t pid;\n};\n\n#endif /* NET_STRUCTS_H_ */\n"
  },
  {
    "path": "netlib.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * netlib.c,v 1.7.2.4.2.2 2006/11/16 04:03:47 mtbishop Exp\n */ \n\n#include \"config.h\"\n#include \"vtun_socks.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <stdarg.h>\n#include <sys/time.h>\n#include <sys/wait.h>\n#include <syslog.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/ioctl.h>\n#include <net/if.h>\n#include <errno.h>\n\n#ifdef HAVE_SYS_SOCKIO_H\n#include <sys/sockio.h>\n#endif\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\n#ifdef HAVE_NETINET_IN_SYSTM_H\n#include <netinet/in_systm.h>\n#endif\n\n#ifdef HAVE_NETINET_IP_H\n#include <netinet/ip.h>\n#endif\n\n#ifdef HAVE_NETINET_TCP_H\n#include <netinet/tcp.h>\n#endif\n\n#ifdef HAVE_RESOLV_H\n#include <resolv.h>\n#endif\n\n#ifdef HAVE_ARPA_INET_H\n#include <arpa/inet.h>\n#endif\n\n#ifdef HAVE_NETDB_H\n#include <netdb.h>\n#endif\n\n#include \"vtun.h\"\n#include \"lib.h\"\n#include \"log.h\"\n#include \"netlib.h\"\n\n/* Connect with timeout */\nint connect_t(int s, struct sockaddr *svr, time_t timeout) \n{\n#if defined(VTUN_SOCKS) && VTUN_SOCKS == 2\n     /* Some SOCKS implementations don't support\n      * non blocking connect */\n     return connect(s,svr,sizeof(struct sockaddr));\n#else\n     int sock_flags;\n     fd_set fdset;\n     struct timeval tv;\n\n     tv.tv_usec=0; tv.tv_sec=timeout;\n\n     sock_flags=fcntl(s,F_GETFL);\n     if( fcntl(s,F_SETFL,O_NONBLOCK) < 0 )\n        return -1;\n\n     if( connect(s,svr,sizeof(struct sockaddr)) < 0 && errno != EINPROGRESS)\n        return -1;\n\n     FD_ZERO(&fdset);\n     FD_SET(s,&fdset);\n     if( select(s+1,NULL,&fdset,NULL,timeout?&tv:NULL) > 0 ){\n        int l=sizeof(errno);\t \n        errno=0;\n        getsockopt(s,SOL_SOCKET,SO_ERROR,&errno,&l);\n     } else\n        errno=ETIMEDOUT;  \t\n\n     fcntl(s,F_SETFL,sock_flags); \n\n     if( errno )\n        return -1;\n\n     return 0;\n#endif\n}\n\n/* Get interface address */\nunsigned long getifaddr(char * ifname) \n{\n     struct sockaddr_in addr;\n     struct ifreq ifr;\n     int s;\n\n     if( (s = socket(AF_INET, SOCK_DGRAM, 0)) == -1 )\n        return -1;\n\n     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)-1);\n     ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\\0';\n\n     if( ioctl(s, SIOCGIFADDR, &ifr) < 0 ){\n        close(s);\n        return -1;\n     }\n     close(s);\n\n     addr = *((struct sockaddr_in *) &ifr.ifr_addr);\n\n     return addr.sin_addr.s_addr;\n}\n\n/* \n * Establish UDP session with host connected to fd(socket).\n * Returns connected UDP socket or -1 on error.\n */\nint udp_session(struct vtun_host *host) \n{\n     struct sockaddr_in saddr; \n     short port;\n     int s,opt;\n\n     if( (s=socket(AF_INET,SOCK_DGRAM,0))== -1 ){\n        vlog(LOG_ERR,\"Can't create socket\");\n        return -1;\n     }\n\n     opt=1;\n     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); \n    \n     /* Set local address and port */\n     local_addr(&saddr, host, 1);\n     if( bind(s,(struct sockaddr *)&saddr,sizeof(saddr)) ){\n        vlog(LOG_ERR,\"Can't bind to the socket\");\n        return -1;\n     }\n\n     opt = sizeof(saddr);\n     if( getsockname(s,(struct sockaddr *)&saddr,&opt) ){\n        vlog(LOG_ERR,\"Can't get socket name\");\n        return -1;\n     }\n\n     /* Write port of the new UDP socket */\n     port = saddr.sin_port;\n     if( write_n(host->rmt_fd,(char *)&port,sizeof(short)) < 0 ){\n        vlog(LOG_ERR,\"Can't write port number\");\n        return -1;\n     }\n     host->sopt.lport = htons(port);\n\n     /* Read port of the other's end UDP socket */\n     if( readn_t(host->rmt_fd,&port,sizeof(short),host->timeout) < 0 ){\n        vlog(LOG_ERR,\"Can't read port number %s\", strerror(errno));\n        return -1;\n     }\n\n     opt = sizeof(saddr);\n     if( getpeername(host->rmt_fd,(struct sockaddr *)&saddr,&opt) ){\n        vlog(LOG_ERR,\"Can't get peer name\");\n        return -1;\n     }\n\n     saddr.sin_port = port;\n     if( connect(s,(struct sockaddr *)&saddr,sizeof(saddr)) ){\n        vlog(LOG_ERR,\"Can't connect socket\");\n        return -1;\n     }\n     host->sopt.rport = htons(port);\n\n     /* Close TCP socket and replace with UDP socket */\t\n     close(host->rmt_fd); \n     host->rmt_fd = s;\t\n\n     vlog(LOG_INFO,\"UDP connection initialized\");\n     return s;\n}\n\n/* Set local address */\nint local_addr(struct sockaddr_in *addr, struct vtun_host *host, int con)\n{\n     int opt;\n\n     if( con ){\n        /* Use address of the already connected socket. */\n        opt = sizeof(struct sockaddr_in);\n        if( getsockname(host->rmt_fd, (struct sockaddr *)addr, &opt) < 0 ){\n           vlog(LOG_ERR,\"Can't get local socket address\");\n           return -1; \n        }\n     } else {\n        if (generic_addr(addr, &host->src_addr) < 0)\n                 return -1;\n              }\n\n     host->sopt.laddr = strdup(inet_ntoa(addr->sin_addr));\n\n     return 0;\n}\n\nint server_addr(struct sockaddr_in *addr, struct vtun_host *host)\n{\n     struct hostent * hent;\n\n     memset(addr,0,sizeof(struct sockaddr_in));\n     addr->sin_family = AF_INET;\n     addr->sin_port = htons(vtun.bind_addr.port);\n\n     /* Lookup server's IP address.\n      * We do it on every reconnect because server's IP \n      * address can be dynamic.\n      */\n     if( !(hent = gethostbyname(vtun.svr_name)) ){\n        vlog(LOG_ERR, \"Can't resolv server address: %s\", vtun.svr_name);\n        return -1;\n     }\n     addr->sin_addr.s_addr = *(unsigned long *)hent->h_addr; \n\n     host->sopt.raddr = strdup(inet_ntoa(addr->sin_addr));\n     host->sopt.rport = vtun.bind_addr.port;\n\n     return 0; \n}\n\n/* Set address by interface name, ip address or hostname */\nint generic_addr(struct sockaddr_in *addr, struct vtun_addr *vaddr)\n{\n     struct hostent *hent;\n     memset(addr, 0, sizeof(struct sockaddr_in));\n  \n     addr->sin_family = AF_INET;\n  \n     switch (vaddr->type) {\n        case VTUN_ADDR_IFACE:\n\t if (!(addr->sin_addr.s_addr =\n\t       getifaddr(vaddr->name))) {\n\t    vlog(LOG_ERR,\n\t                \"Can't get address of interface %s\",\n\t                vaddr->name);\n\t    return -1;\n\t }\n           break;\n        case VTUN_ADDR_NAME:\n\t if (!(hent = gethostbyname(vaddr->name))) {\n\t    vlog(LOG_ERR,\n\t                \"Can't resolv local address %s\",\n\t                vaddr->name);\n\t    return -1;\n           }\n\t addr->sin_addr.s_addr = *(unsigned long *) hent->h_addr;\n           break;\n        default:\n           addr->sin_addr.s_addr = INADDR_ANY;\n           break;\n     }\n  \n     if (vaddr->port)\n        addr->sin_port = htons(vaddr->port);\n\n     return 0; \n}\n"
  },
  {
    "path": "netlib.h",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * netlib.h,v 1.2.2.1.2.2 2006/11/16 04:03:50 mtbishop Exp\n */ \n\n#ifndef _VTUN_NETDEV_H\n#define _VTUN_NETDEV_H\n\n#include \"config.h\"\n#include <errno.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\nunsigned long getifaddr(char * ifname);\nint connect_t(int s, struct sockaddr *svr, time_t timeout); \nint udp_session(struct vtun_host *host); \n\nint local_addr(struct sockaddr_in *addr, struct vtun_host *host, int con);\nint server_addr(struct sockaddr_in *addr, struct vtun_host *host);\nint generic_addr(struct sockaddr_in *addr, struct vtun_addr *vaddr);\n\n#endif /* _VTUN_NETDEV_H */\n"
  },
  {
    "path": "netlink_socket_info.c",
    "content": "/*\n * netlink_socket_info.c\n\n *\n * According by ss from iproute2 and fss is written by Matt Tierney\n *\n *  Created on: 30.11.2012\n *       Copyright (C) 2011-2016 Vrayo Systems Ltd. team \n */\n\n#include <sys/socket.h>\n#include <linux/inet_diag.h>\n#include <linux/netlink.h>\n#include <linux/rtnetlink.h>\n#include <netinet/in.h>\n#include <netinet/tcp.h>\n#include <alloca.h>\n#include <errno.h>\n#include <syslog.h>\n#include <string.h>\n#include <stdio.h>\n#include \"netlink_socket_info.h\"\n#include \"lib.h\"\n\n#define SSF_DCOND 0\n#define SSF_SCOND 1\n#define SSF_OR    2\n#define SSF_AND   3\n#define SSF_NOT   4\n#define SSF_D_GE  5\n#define SSF_D_LE  6\n#define SSF_S_GE  7\n#define SSF_S_LE  8\n#define SSF_S_AUTO  9\n\nenum {\n    SS_UNKNOWN,\n    SS_ESTABLISHED,\n    SS_SYN_SENT,\n    SS_SYN_RECV,\n    SS_FIN_WAIT1,\n    SS_FIN_WAIT2,\n    SS_TIME_WAIT,\n    SS_CLOSE,\n    SS_CLOSE_WAIT,\n    SS_LAST_ACK,\n    SS_LISTEN,\n    SS_CLOSING,\n    SS_MAX\n};\n\nenum {\n    TCP_DB, DCCP_DB, UDP_DB, RAW_DB, UNIX_DG_DB, UNIX_ST_DB, PACKET_DG_DB, PACKET_R_DB, NETLINK_DB, MAX_DB\n};\n\n#define SS_ALL ((1<<SS_MAX)-1)\n\nstruct ssfilter {\n    int type;\n    struct ssfilter *post;\n    struct ssfilter *pred;\n};\n\nstruct filter {\n    int dbs;\n    int states;\n    int families;\n    struct ssfilter *f;\n};\n\nstruct filter default_filter = {\n    .dbs = (1 << TCP_DB),\n    .states = SS_ALL & ~((1 << SS_LISTEN) | (1 << SS_CLOSE) | (1 << SS_TIME_WAIT) | (1 << SS_SYN_RECV)),\n    .families = (1 << AF_INET) | (1 << AF_INET6),\n};\n\nstruct filter current_filter;\nint conn_counter, channel_amount_ss;\nstruct channel_info* channel_info_ss;\n\nint parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);\nstatic int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f);\nstatic int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype);\nint format_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r);\n\nint parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)\n{\n    memset(tb, 0, sizeof(struct rtattr *) * (max + 1));\n    while (RTA_OK(rta, len)) {\n        if ((rta->rta_type <= max) && (!tb[rta->rta_type]))\n            tb[rta->rta_type] = rta;\n        rta = RTA_NEXT(rta,len);\n    }\n    if (len)\n        vtun_syslog(LOG_ERR, \"Netlink - !!!Deficit %d, rta_len=%d\", len, rta->rta_len);\n    return 0;\n}\n\n/*main parse function*/\nstatic int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f) {\n    struct inet_diag_msg *r = NLMSG_DATA(nlh);\n    // fill channel_info structure\n    if (conn_counter < channel_amount_ss) {\n        for (int i = 0; i < channel_amount_ss; i++) {\n            if ((channel_info_ss[i].lport == ntohs(r->id.idiag_sport)) & (channel_info_ss[i].rport == ntohs(r->id.idiag_dport))) {\n                format_info(nlh, r);\n                channel_info_ss[i].recv_q = r->idiag_rqueue;\n                channel_info_ss[i].send_q = r->idiag_wqueue;\n#ifdef TRACE\n                vtun_syslog(LOG_INFO, \"fss conn_counter - %i channel_amount_ss - %i send_q - %i recv_q - %i lport - %i rport - %i\", i,\n                        channel_amount_ss, channel_info_ss[i].send_q, channel_info_ss[i].recv_q, ntohs(r->id.idiag_sport),\n                        ntohs(r->id.idiag_dport));\n#endif\n                conn_counter++;\n                break;\n            }\n        }\n    }\n\n    return 1;\n}\n\n/**\n * Function for connect to kernel's netlink interface\n * and get info about tcp connections\n *\n * @param f - flags for getting tcp information\n * @param dump_fp - now unused\n * @param socktype\n * @return\n */\nstatic int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype) {\n    int fd;\n    struct sockaddr_nl nladdr;\n    struct {\n        struct nlmsghdr nlh;\n        struct inet_diag_req r;\n    } req;\n    char *bc = NULL;\n    int bclen;\n    struct msghdr msg;\n    struct rtattr rta;\n    char buf[8192];\n    struct iovec iov;\n\n    if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0) {\n        switch (errno) {\n        case EMFILE:\n            vtun_syslog(LOG_ERR, \"Netlink - Too many open files.\");\n            break;\n        default:\n            vtun_syslog(LOG_ERR, \"Netlink - Error: %s (%d)\", strerror(errno), errno);\n            break;\n        }\n        return 0;\n    }\n\n    memset(&nladdr, 0, sizeof(nladdr));\n    nladdr.nl_family = AF_NETLINK;\n\n    req.nlh.nlmsg_len = sizeof(req);\n    req.nlh.nlmsg_type = socktype;\n    req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;\n    req.nlh.nlmsg_pid = 0;\n    req.nlh.nlmsg_seq = 123456;\n    memset(&req.r, 0, sizeof(req.r));\n    req.r.idiag_family = AF_INET;\n    req.r.idiag_states = f->states;\n\n// show_mem - don't use\n//        req.r.idiag_ext |= (1 << (INET_DIAG_MEMINFO - 1));\n\n    //show tcp info such as send_q, cwnd...\n    req.r.idiag_ext |= (1 << (INET_DIAG_INFO - 1));\n    req.r.idiag_ext |= (1 << (INET_DIAG_VEGASINFO - 1));\n    req.r.idiag_ext |= (1 << (INET_DIAG_CONG - 1));\n\n    iov.iov_base = &req;\n    iov.iov_len = sizeof(req);\n\n    msg.msg_name = (void*) &nladdr;\n    msg.msg_namelen = sizeof(nladdr);\n    msg.msg_iov = &iov;\n    msg.msg_iovlen = 1; // iov can be array of structure\n    msg.msg_control = NULL;\n    msg.msg_controllen = 0;\n    msg.msg_flags = 0;\n\n    if (sendmsg(fd, &msg, 0) < 0)\n    {\n        vtun_syslog(LOG_ERR, \"Netlink - Cannot send netlink message: %s (%d)\", strerror(errno), errno);\n        return 0;\n    }\n    iov.iov_base = buf;\n    iov.iov_len = sizeof(buf);\n\n    while (1) {\n        int status;\n        struct nlmsghdr *h;\n\n        msg = (struct msghdr ) { (void*) &nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 };\n\n        status = recvmsg(fd, &msg, 0);\n\n        if (status < 0) {\n            if (errno == EINTR) {\n                vtun_syslog(LOG_ERR, \"Netlink - EINTR, continue...\");\n                continue;\n            }\n            vtun_syslog(LOG_ERR, \"Netlink - OVERRUN: %s (%d)\", strerror(errno), errno);\n            continue;\n        }\n        if (status == 0) {\n            vtun_syslog(LOG_ERR, \"Netlink - EOF on netlink\");\n            return 0;\n        }\n\n        h = (struct nlmsghdr*) buf;\n        while (NLMSG_OK(h, status)) {\n\n            int err;\n            struct inet_diag_msg *r = NLMSG_DATA(h);\n\n            if (/*h->nlmsg_pid != rth->local.nl_pid ||*/\n            h->nlmsg_seq != 123456)\n                goto skip_it;\n\n            if (h->nlmsg_type == NLMSG_DONE) {\n#ifdef DEBUGG\n                vtun_syslog(LOG_INFO, \"Netlink - NLMSG_DONE\");\n#endif\n                close(fd);\n                return 1;\n            }\n            if (h->nlmsg_type == NLMSG_ERROR) {\n                struct nlmsgerr *err = (struct nlmsgerr*) NLMSG_DATA(h);\n                if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {\n                    vtun_syslog(LOG_ERR, \"Netlink - ERROR truncated\");\n                } else {\n                    errno = -err->error;\n                    vtun_syslog(LOG_ERR, \"Netlink - TCPDIAG answers: %s (%d)\", strerror(errno), errno);\n                }\n                return 0;\n            }\n            if (!dump_fp) {\n                if (!(f->families & (1 << r->idiag_family))) {\n                    h = NLMSG_NEXT(h, status);\n                    continue;\n                }\n                if(!tcp_show_sock(h, NULL )){\n                    vtun_syslog(LOG_ERR, \"Netlink - tcp_show_sock return error\");\n                    return 0;\n                }\n\n            }\n\n            skip_it: h = NLMSG_NEXT(h, status);\n        }\n        if (msg.msg_flags & MSG_TRUNC) {\n            vtun_syslog(LOG_ERR, \"Netlink - Message truncated\");\n            continue;\n        }\n        if (status) {\n            vtun_syslog(LOG_ERR, \"Netlink - !!!Remnant of size %d\", status);\n            return 0;\n        }\n    }\n    if (close(fd) == -1) {\n        vtun_syslog(LOG_ERR, \"Netlink - Unable to close socket: %s (%d)\", strerror(errno), errno);\n    }\n    return 1;\n}\n\n/**\n * Function get from **channel_info_vt port's num and fill information about tcp connection\n * @param channel_info_vt\n * @param channel_amount - *channel_info_vt[] array length\n * @return 1 if succes end 0 if error\n */\nint get_format_tcp_info(struct channel_info* channel_info_vt, int channel_amount) {\n    channel_info_ss = channel_info_vt;\n    channel_amount_ss = channel_amount;\n    conn_counter = 0;\n\n    clear_channel_info(channel_info_ss, channel_amount_ss);\n\n    memset(&current_filter, 0, sizeof(current_filter));\n\n    current_filter.states = default_filter.states;\n    current_filter.dbs = default_filter.dbs;\n    current_filter.families = default_filter.families;\n\n    if(!tcp_show_netlink(&current_filter, NULL, TCPDIAG_GETSOCK)) {\n        vtun_syslog(LOG_ERR, \"Netlink - return error\");\n        return 0; // 0 - error 1 - success\n    }\n#ifdef TRACE\n    for (int i = 0; i < channel_amount; i++) {\n        vtun_syslog(LOG_INFO, \"fss channel_info_vt send_q %u lport - %i rport - %i\", channel_info_vt[i].send_q, channel_info_vt[i].lport,\n                channel_info_vt[i].rport);\n        vtun_syslog(LOG_INFO, \"fss channel_info_ss send_q %u lport - %i rport - %i\", channel_info_ss[i].send_q, channel_info_ss[i].lport,\n                channel_info_ss[i].rport);\n    }\n    vtun_syslog(LOG_INFO, \"fss conn_counter is %i\", conn_counter);\n#endif\n    return 1;\n}\n\n/**\n * Parse netlink message to channel_info structure\n *\n * @param nlh\n * @param r\n * @return 0 - error and 1 as success\n */\nint format_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r) {\n\n    struct rtattr * tb[INET_DIAG_MAX + 1];\n    struct tcp_info *info;\n\n    parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr*) (r + 1), nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));\n\n    if (tb[INET_DIAG_INFO]) {\n        int len = RTA_PAYLOAD(tb[INET_DIAG_INFO]);\n\n        /* workaround for older kernels with less fields ???legacy??? */\n        if (len < (int) sizeof(*info)) {\n            info = alloca(sizeof(*info));\n            memset(info, 0, sizeof(*info));\n            memcpy(info, RTA_DATA(tb[INET_DIAG_INFO]), len);\n        } else {\n            info = RTA_DATA(tb[INET_DIAG_INFO]);\n        }\n    } else {\n        return 0;\n    }\n    if (info == 0) {\n        return 0;\n    }\n\n    channel_info_ss[conn_counter].snd_wscale = info->tcpi_snd_wscale;\n    channel_info_ss[conn_counter].rcv_wscale = info->tcpi_rcv_wscale;\n    if (info->tcpi_rto && info->tcpi_rto != 3000000) {\n        channel_info_ss[conn_counter].rto = (double) info->tcpi_rto / 1000;\n    }\n    channel_info_ss[conn_counter].rtt = (double) info->tcpi_rtt / 1000;\n    channel_info_ss[conn_counter].rtt_var = (double) info->tcpi_rttvar / 1000;\n    channel_info_ss[conn_counter].ato = (double) info->tcpi_ato / 1000;\n    if (info->tcpi_snd_cwnd != 2) { // really need?\n        channel_info_ss[conn_counter].cwnd = info->tcpi_snd_cwnd;\n    }\n    if (info->tcpi_snd_ssthresh < 0xFFFF) {\n        channel_info_ss[conn_counter].ssthresh = info->tcpi_snd_ssthresh;\n    }\n    if (channel_info_ss[conn_counter].rtt > 0 && info->tcpi_snd_mss && info->tcpi_snd_cwnd) {\n        channel_info_ss[conn_counter].send = (uint32_t) ((double) info->tcpi_snd_cwnd * (double) info->tcpi_snd_mss * 1000.\n                / channel_info_ss[conn_counter].rtt);\n    }\n    channel_info_ss[conn_counter].mss = info->tcpi_snd_mss;\n    channel_info_ss[conn_counter].rcv_rtt = (double) info->tcpi_rcv_rtt / 1000;\n    channel_info_ss[conn_counter].rcv_space = info->tcpi_rcv_space;\n    return 1;\n}\n\nvoid clear_channel_info(struct channel_info* channel_info, int channel_amount) {\n    int lport, rport;\n    for (int i = 0; i < channel_amount; i++) {\n        lport = channel_info[i].lport;\n        rport = channel_info[i].rport;\n        memset(&(channel_info[i]), 0, sizeof(channel_info));\n        channel_info[i].lport = lport;\n        channel_info[i].rport = rport;\n    }\n}\n"
  },
  {
    "path": "netlink_socket_info.h",
    "content": "/*\n * socket_info.h\n *\n *  Created on: 30.11.2012\n *       Copyright (C) 2011-2016 Vrayo Systems Ltd. team \n */\n\n#ifndef SOCKET_INFO_H_\n#define SOCKET_INFO_H_\n\n#include <stdint.h>\n\nstruct channel_info {\n    uint8_t snd_wscale;\n    uint8_t rcv_wscale;\n    double rto; // TCP retransmit timeout\n    double rtt; // in ms (round trip time)\n    double rtt_var; // in ms (?jitter?)\n    double ato; // ACK timeout\n    uint32_t cwnd; // in mss\n    uint32_t mss;\n    uint32_t ssthresh;\n    uint32_t send; // in kbyte/sec)\n    double rcv_rtt;\n    uint32_t rcv_space;\n    uint32_t send_q;\n    uint32_t recv_q;\n    int lport;\n    int rport;\n};\n\nint get_format_tcp_info(struct channel_info* channel_info_vt, int channel_amount);\n\n#endif /* SOCKET_INFO_H_ */\n"
  },
  {
    "path": "packages/openwrt/Makefile",
    "content": "#\n# Copyright (C) 2011 Andrew Gryaznov <realgrandrew@gmail.com>\n#\n# This is free software, licensed under the GNU General Public License v3 or higher.\n# See /LICENSE for more information.\n#\n# share source in vtrunkd folder\n#\n\ninclude $(TOPDIR)/rules.mk\n\nPKG_NAME:=vtrunkd\nPKG_VERSION:=0.1b\nPKG_RELEASE:=1\n\n#PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz\n#PKG_SOURCE_URL:=@SF/vtrunkd\n#PKG_MD5SUM:=793975b5dbc5525c702dad796ba4a47f\n\ninclude $(INCLUDE_DIR)/package.mk\n\ndefine Package/vtrunkd\n  SECTION:=net\n  CATEGORY:=Network\n  DEPENDS:=+kmod-tun +libpthread +flex +bison +librt\n  TITLE:=Virtual trunking (bonding) daemon\n  URL:=http://mxmit.com/vtrunkd\n  SUBMENU:=VPN\nendef\n\ndefine Package/vtrunkd/conffiles\n/etc/vtrunkd.conf\nendef\n\nCONFIGURE_ARGS += \\\n\t--prefix= \\\n\t--enable-json \\\n\t--disable-o3 \\\n\t--enable-client-only\n#\t--enable-low-mem\n\n# these are reserved for future use\nCONFIGURE_VARS += \\\n\tLIBS=\"$(TARGET_LDFLAGS)\" \\\n\tBLOWFISH_HDR_DIR=\"$(STAGING_DIR)/usr/include/openssl\" \\\n\tLZO_HDR_DIR=\"$(STAGING_DIR)/usr/include/lzo\" \\\n\tSSL_HDR_DIR=\"$(STAGING_DIR)/usr/include/openssl\" \\\n\tCXX=\"mipsel-openwrt-linux-uclibc-g++\"\n\ndefine Build/Prepare\n\tmkdir -p $(PKG_BUILD_DIR)\n\t$(CP) ./vtrunkd-src/* $(PKG_BUILD_DIR)/\nendef\n\ndefine Build/Compile\n\t$(call Build/Compile/Default,vtrunkd)\n\t$(CP) $(PKG_BUILD_DIR)/vtrunkd $(PKG_BUILD_DIR)/../../../\nendef\n\ndefine Package/vtrunkd/install\n\t$(INSTALL_DIR) $(1)/etc\n\t$(INSTALL_CONF) $(PKG_BUILD_DIR)/vtrunkd.conf $(1)/etc/\n\t$(INSTALL_DIR) $(1)/usr/sbin\n\t$(INSTALL_BIN) $(PKG_BUILD_DIR)/vtrunkd $(1)/usr/sbin/\n#\t$(CP) $(PKG_BUILD_DIR)/vtrunkd $(PKG_BUILD_DIR)/../../../\nendef\n\n$(eval $(call BuildPackage,vtrunkd))\n"
  },
  {
    "path": "packages/os-jessie/Dockerfile",
    "content": "FROM debian:jessie\nADD sources.list /etc/apt/\nRUN apt-get update\nRUN apt-get install -y build-essential autotools-dev bison flex build-essential liblzo2-dev  zlib1g-dev libssl-dev devscripts git\nRUN apt-get -y upgrade\n"
  },
  {
    "path": "packages/os-jessie/debian/changelog",
    "content": "vtrunkd2 (0.1-1) unstable; urgency=low\n\n  * Initial release (Closes: #205)\n\n -- David Parunakian <dp@dp.io>  Sat, 16 Jan 2016 00:07:40 +0300\n"
  },
  {
    "path": "packages/os-jessie/debian/compat",
    "content": "9\n"
  },
  {
    "path": "packages/os-jessie/debian/control",
    "content": "Source: vtrunkd2\nSection: net\nPriority: optional\nMaintainer: David Parunakian <dp@dp.io>\nBuild-Depends: debhelper (>= 9), autotools-dev, bison, flex, build-essential, liblzo2-dev,\n zlib1g-dev, libssl-dev\nStandards-Version: 3.9.5\nHomepage: http://vrayo.com\n\nPackage: vtrunkd2\nArchitecture: amd64\nDepends: ${shlibs:Depends}, ${misc:Depends}, udev [linux-any] | makedev [linux-any]\nDescription: Wireless channel trunking daemon\n The first software inverse multiplexing solution for connected automotive,\n live streaming, bonded internet and more.\n"
  },
  {
    "path": "packages/os-jessie/debian/copyright",
    "content": "Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: vtrunkd2\nSource: <http://vrayo.com>\n\nFiles: *\nCopyright: Copyright (C) 2011-2016 Vrayo Systems Ltd. team\n           1998-2003 Maxim Krasnyansky <max_mk@yahoo.com>\n\nLicense: \n\n   This package is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n   .\n   This package is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n   .\n   You should have received a copy of the GNU General Public License\n   along with this package; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA\n   .\n   In addition, as a special exception, the copyright holders give permission\n   to link the code of portions of this program with the OpenSSL library under\n   certain conditions as described in each individual source file, and\n   distribute linked combinations including the two.\n   .\n   You must obey the GNU General Public License in all respects for all of the\n   code used other than OpenSSL. If you modify file(s) with this exception, you\n   may extend this exception to your version of the file(s), but you are not\n   obligated to do so. If you do not wish to do so, delete this exception\n   statement from your version. If you delete this exception statement from all\n   source files in the program, then also delete it here.\n   .\nOn Debian systems, the complete text of the GNU General\nPublic License can be found in `/usr/share/common-licenses/GPL'.\n\nThe Debian packaging is © 2006-2008, Martín Ferrari <martin.ferrari@gmail.com>\nand is licensed under the GPL, see above.\n\nFiles: debian/*\nCopyright: 2016 David Parunakian <dp@dp.io>\nLicense: GPL-2+\n This package is free software; you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation; either version 2 of the License, or\n (at your option) any later version.\n .\n This package is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n .\n You should have received a copy of the GNU General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>\n .\n On Debian systems, the complete text of the GNU General\n Public License version 2 can be found in \"/usr/share/common-licenses/GPL-2\".\n"
  },
  {
    "path": "packages/os-jessie/debian/docs",
    "content": "Credits\nREADME.md\n"
  },
  {
    "path": "packages/os-jessie/debian/files",
    "content": "vtrunkd2_0.1-1_amd64.deb net optional\n"
  },
  {
    "path": "packages/os-jessie/debian/init.d.ex",
    "content": "#!/bin/sh\n### BEGIN INIT INFO\n# Provides:          vtrunkd2\n# Required-Start:    $local_fs $network $remote_fs $syslog\n# Required-Stop:     $local_fs $network $remote_fs $syslog\n# Default-Start:     2 3 4 5\n# Default-Stop:      0 1 6\n# Short-Description: <Enter a short description of the software>\n# Description:       <Enter a long description of the software>\n#                    <...>\n#                    <...>\n### END INIT INFO\n\n# Author: David Parunakian <dp@wotan>\n\n# Do NOT \"set -e\"\n\n# PATH should only include /usr/* if it runs after the mountnfs.sh script\nPATH=/sbin:/usr/sbin:/bin:/usr/bin\nDESC=\"vtrunkd2\"\nNAME=vtrunkd2\nDAEMON=/usr/sbin/vtrunkd2\nDAEMON_ARGS=\"\"\nPIDFILE=/var/run/$NAME.pid\nSCRIPTNAME=/etc/init.d/$NAME\n\n# Exit if the package is not installed\n[ -x \"$DAEMON\" ] || exit 0\n\n# Read configuration variable file if it is present\n[ -r /etc/default/$NAME ] && . /etc/default/$NAME\n\n# Load the VERBOSE setting and other rcS variables\n. /lib/init/vars.sh\n\n# Define LSB log_* functions.\n# Depend on lsb-base (>= 3.2-14) to ensure that this file is present\n# and status_of_proc is working.\n. /lib/lsb/init-functions\n\n#\n# Function that starts the daemon/service\n#\ndo_start()\n{\n\t# Return\n\t#   0 if daemon has been started\n\t#   1 if daemon was already running\n\t#   2 if daemon could not be started\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \\\n\t\t|| return 1\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \\\n\t\t$DAEMON_ARGS \\\n\t\t|| return 2\n\t# The above code will not work for interpreted scripts, use the next\n\t# six lines below instead (Ref: #643337, start-stop-daemon(8) )\n\t#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \\\n\t#\t--name $NAME --test > /dev/null \\\n\t#\t|| return 1\n\t#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \\\n\t#\t--name $NAME -- $DAEMON_ARGS \\\n\t#\t|| return 2\n\n\t# Add code here, if necessary, that waits for the process to be ready\n\t# to handle requests from services started subsequently which depend\n\t# on this one.  As a last resort, sleep for some time.\n}\n\n#\n# Function that stops the daemon/service\n#\ndo_stop()\n{\n\t# Return\n\t#   0 if daemon has been stopped\n\t#   1 if daemon was already stopped\n\t#   2 if daemon could not be stopped\n\t#   other if a failure occurred\n\tstart-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME\n\tRETVAL=\"$?\"\n\t[ \"$RETVAL\" = 2 ] && return 2\n\t# Wait for children to finish too if this is a daemon that forks\n\t# and if the daemon is only ever run from this initscript.\n\t# If the above conditions are not satisfied then add some other code\n\t# that waits for the process to drop all resources that could be\n\t# needed by services started subsequently.  A last resort is to\n\t# sleep for some time.\n\tstart-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON\n\t[ \"$?\" = 2 ] && return 2\n\t# Many daemons don't delete their pidfiles when they exit.\n\trm -f $PIDFILE\n\treturn \"$RETVAL\"\n}\n\n#\n# Function that sends a SIGHUP to the daemon/service\n#\ndo_reload() {\n\t#\n\t# If the daemon can reload its configuration without\n\t# restarting (for example, when it is sent a SIGHUP),\n\t# then implement that here.\n\t#\n\tstart-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME\n\treturn 0\n}\n\ncase \"$1\" in\n  start)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Starting $DESC\" \"$NAME\"\n\tdo_start\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  stop)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Stopping $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  status)\n\tstatus_of_proc \"$DAEMON\" \"$NAME\" && exit 0 || exit $?\n\t;;\n  #reload|force-reload)\n\t#\n\t# If do_reload() is not implemented then leave this commented out\n\t# and leave 'force-reload' as an alias for 'restart'.\n\t#\n\t#log_daemon_msg \"Reloading $DESC\" \"$NAME\"\n\t#do_reload\n\t#log_end_msg $?\n\t#;;\n  restart|force-reload)\n\t#\n\t# If the \"reload\" option is implemented then remove the\n\t# 'force-reload' alias\n\t#\n\tlog_daemon_msg \"Restarting $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t  0|1)\n\t\tdo_start\n\t\tcase \"$?\" in\n\t\t\t0) log_end_msg 0 ;;\n\t\t\t1) log_end_msg 1 ;; # Old process is still running\n\t\t\t*) log_end_msg 1 ;; # Failed to start\n\t\tesac\n\t\t;;\n\t  *)\n\t\t# Failed to stop\n\t\tlog_end_msg 1\n\t\t;;\n\tesac\n\t;;\n  *)\n\t#echo \"Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}\" >&2\n\techo \"Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}\" >&2\n\texit 3\n\t;;\nesac\n\n:\n"
  },
  {
    "path": "packages/os-jessie/debian/logrotate",
    "content": "/var/log/vtrunkd/*.dump {\n  rotate 54\n  daily\n  compress\n  copytruncate\n  missingok\n}\n"
  },
  {
    "path": "packages/os-jessie/debian/postinst.ex",
    "content": "#!/bin/sh\n# postinst script for vtrunkd2\n#\n# see: dh_installdeb(1)\n\nset -e\n\n# summary of how this script can be called:\n#        * <postinst> `configure' <most-recently-configured-version>\n#        * <old-postinst> `abort-upgrade' <new version>\n#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>\n#          <new-version>\n#        * <postinst> `abort-remove'\n#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'\n#          <failed-install-package> <version> `removing'\n#          <conflicting-package> <version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n\n\ncase \"$1\" in\n    configure)\n    ;;\n\n    abort-upgrade|abort-remove|abort-deconfigure)\n    ;;\n\n    *)\n        echo \"postinst called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "packages/os-jessie/debian/postrm.ex",
    "content": "#!/bin/sh\n# postrm script for vtrunkd2\n#\n# see: dh_installdeb(1)\n\nset -e\n\n# summary of how this script can be called:\n#        * <postrm> `remove'\n#        * <postrm> `purge'\n#        * <old-postrm> `upgrade' <new-version>\n#        * <new-postrm> `failed-upgrade' <old-version>\n#        * <new-postrm> `abort-install'\n#        * <new-postrm> `abort-install' <old-version>\n#        * <new-postrm> `abort-upgrade' <old-version>\n#        * <disappearer's-postrm> `disappear' <overwriter>\n#          <overwriter-version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n\n\ncase \"$1\" in\n    purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)\n    ;;\n\n    *)\n        echo \"postrm called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "packages/os-jessie/debian/rules",
    "content": "#!/usr/bin/make -f\n# See debhelper(7) (uncomment to enable)\n# output every command that modifies files on the build system.\n#DH_VERBOSE = 1\n\n# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*\nDPKG_EXPORT_BUILDFLAGS = 1\ninclude /usr/share/dpkg/default.mk\n\n# see FEATURE AREAS in dpkg-buildflags(1)\n#export DEB_BUILD_MAINT_OPTIONS = hardening=+all\n\n# see ENVIRONMENT in dpkg-buildflags(1)\n# package maintainers to append CFLAGS\n#export DEB_CFLAGS_MAINT_APPEND  = -Wall -pedantic\n# package maintainers to append LDFLAGS\n#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed\n\n\n# main packaging script based on dh7 syntax\n%:\n\tdh $@  --with autotools-dev\n\n# debmake generated override targets\n# This is example for Cmake (See http://bugs.debian.org/641051 )\n#override_dh_auto_configure:\n#\tdh_auto_configure -- \\\n#\t-DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)\n\n\n\n\n"
  },
  {
    "path": "packages/os-jessie/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "packages/os-jessie/debian/vtrunkd2.substvars",
    "content": "shlibs:Depends=libc6 (>= 2.15)\nmisc:Depends=\n"
  },
  {
    "path": "packages/os-jessie/sources.list",
    "content": "deb http://security.debian.org/ jessie/updates main\ndeb-src http://security.debian.org/ jessie/updates main\n\ndeb http://ftp.debian.org/debian/ jessie-updates main contrib non-free\ndeb-src http://ftp.debian.org/debian/ jessie-updates main contrib non-free\n\ndeb http://ftp.debian.org/debian/ jessie main contrib non-free\ndeb-src http://ftp.debian.org/debian/ jessie main contrib non-free\n"
  },
  {
    "path": "packages/os-trusty/Dockerfile",
    "content": "FROM ubuntu:trusty\nRUN apt-get update\nRUN apt-get install -y build-essential autotools-dev bison flex build-essential liblzo2-dev  zlib1g-dev libssl-dev devscripts git\nRUN apt-get -y upgrade\n"
  },
  {
    "path": "packages/os-trusty/debian/changelog",
    "content": "vtrunkd2 (0.1-1) unstable; urgency=low\n\n  * Initial release (Closes: #205)\n\n -- David Parunakian <dp@dp.io>  Sat, 16 Jan 2016 00:07:40 +0300\n"
  },
  {
    "path": "packages/os-trusty/debian/compat",
    "content": "9\n"
  },
  {
    "path": "packages/os-trusty/debian/control",
    "content": "Source: vtrunkd2\nSection: net\nPriority: optional\nMaintainer: David Parunakian <dp@dp.io>\nBuild-Depends: debhelper (>= 9), autotools-dev, bison, flex, build-essential, liblzo2-dev,\n zlib1g-dev, libssl-dev\nStandards-Version: 3.9.5\nHomepage: http://vrayo.com\n\nPackage: vtrunkd2\nArchitecture: amd64\nDepends: ${shlibs:Depends}, ${misc:Depends}, udev [linux-any] | makedev [linux-any]\nDescription: Wireless channel trunking daemon\n The first software inverse multiplexing solution for connected automotive,\n live streaming, bonded internet and more.\n"
  },
  {
    "path": "packages/os-trusty/debian/copyright",
    "content": "Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: vtrunkd2\nSource: <http://vrayo.com>\n\nFiles: *\nCopyright: Copyright (C) 2011-2016 Vrayo Systems Ltd. team\n           1998-2003 Maxim Krasnyansky <max_mk@yahoo.com>\n\nLicense: \n\n   This package is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n   .\n   This package is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n   .\n   You should have received a copy of the GNU General Public License\n   along with this package; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA\n   .\n   In addition, as a special exception, the copyright holders give permission\n   to link the code of portions of this program with the OpenSSL library under\n   certain conditions as described in each individual source file, and\n   distribute linked combinations including the two.\n   .\n   You must obey the GNU General Public License in all respects for all of the\n   code used other than OpenSSL. If you modify file(s) with this exception, you\n   may extend this exception to your version of the file(s), but you are not\n   obligated to do so. If you do not wish to do so, delete this exception\n   statement from your version. If you delete this exception statement from all\n   source files in the program, then also delete it here.\n   .\nOn Debian systems, the complete text of the GNU General\nPublic License can be found in `/usr/share/common-licenses/GPL'.\n\nThe Debian packaging is © 2006-2008, Martín Ferrari <martin.ferrari@gmail.com>\nand is licensed under the GPL, see above.\n\nFiles: debian/*\nCopyright: 2016 David Parunakian <dp@dp.io>\nLicense: GPL-2+\n This package is free software; you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation; either version 2 of the License, or\n (at your option) any later version.\n .\n This package is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n .\n You should have received a copy of the GNU General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>\n .\n On Debian systems, the complete text of the GNU General\n Public License version 2 can be found in \"/usr/share/common-licenses/GPL-2\".\n"
  },
  {
    "path": "packages/os-trusty/debian/docs",
    "content": "Credits\nREADME.md\n"
  },
  {
    "path": "packages/os-trusty/debian/files",
    "content": "vtrunkd2_0.1-1_amd64.deb net optional\n"
  },
  {
    "path": "packages/os-trusty/debian/init.d.ex",
    "content": "#!/bin/sh\n### BEGIN INIT INFO\n# Provides:          vtrunkd2\n# Required-Start:    $local_fs $network $remote_fs $syslog\n# Required-Stop:     $local_fs $network $remote_fs $syslog\n# Default-Start:     2 3 4 5\n# Default-Stop:      0 1 6\n# Short-Description: <Enter a short description of the software>\n# Description:       <Enter a long description of the software>\n#                    <...>\n#                    <...>\n### END INIT INFO\n\n# Author: David Parunakian <dp@wotan>\n\n# Do NOT \"set -e\"\n\n# PATH should only include /usr/* if it runs after the mountnfs.sh script\nPATH=/sbin:/usr/sbin:/bin:/usr/bin\nDESC=\"vtrunkd2\"\nNAME=vtrunkd2\nDAEMON=/usr/sbin/vtrunkd2\nDAEMON_ARGS=\"\"\nPIDFILE=/var/run/$NAME.pid\nSCRIPTNAME=/etc/init.d/$NAME\n\n# Exit if the package is not installed\n[ -x \"$DAEMON\" ] || exit 0\n\n# Read configuration variable file if it is present\n[ -r /etc/default/$NAME ] && . /etc/default/$NAME\n\n# Load the VERBOSE setting and other rcS variables\n. /lib/init/vars.sh\n\n# Define LSB log_* functions.\n# Depend on lsb-base (>= 3.2-14) to ensure that this file is present\n# and status_of_proc is working.\n. /lib/lsb/init-functions\n\n#\n# Function that starts the daemon/service\n#\ndo_start()\n{\n\t# Return\n\t#   0 if daemon has been started\n\t#   1 if daemon was already running\n\t#   2 if daemon could not be started\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \\\n\t\t|| return 1\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \\\n\t\t$DAEMON_ARGS \\\n\t\t|| return 2\n\t# The above code will not work for interpreted scripts, use the next\n\t# six lines below instead (Ref: #643337, start-stop-daemon(8) )\n\t#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \\\n\t#\t--name $NAME --test > /dev/null \\\n\t#\t|| return 1\n\t#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \\\n\t#\t--name $NAME -- $DAEMON_ARGS \\\n\t#\t|| return 2\n\n\t# Add code here, if necessary, that waits for the process to be ready\n\t# to handle requests from services started subsequently which depend\n\t# on this one.  As a last resort, sleep for some time.\n}\n\n#\n# Function that stops the daemon/service\n#\ndo_stop()\n{\n\t# Return\n\t#   0 if daemon has been stopped\n\t#   1 if daemon was already stopped\n\t#   2 if daemon could not be stopped\n\t#   other if a failure occurred\n\tstart-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME\n\tRETVAL=\"$?\"\n\t[ \"$RETVAL\" = 2 ] && return 2\n\t# Wait for children to finish too if this is a daemon that forks\n\t# and if the daemon is only ever run from this initscript.\n\t# If the above conditions are not satisfied then add some other code\n\t# that waits for the process to drop all resources that could be\n\t# needed by services started subsequently.  A last resort is to\n\t# sleep for some time.\n\tstart-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON\n\t[ \"$?\" = 2 ] && return 2\n\t# Many daemons don't delete their pidfiles when they exit.\n\trm -f $PIDFILE\n\treturn \"$RETVAL\"\n}\n\n#\n# Function that sends a SIGHUP to the daemon/service\n#\ndo_reload() {\n\t#\n\t# If the daemon can reload its configuration without\n\t# restarting (for example, when it is sent a SIGHUP),\n\t# then implement that here.\n\t#\n\tstart-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME\n\treturn 0\n}\n\ncase \"$1\" in\n  start)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Starting $DESC\" \"$NAME\"\n\tdo_start\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  stop)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Stopping $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  status)\n\tstatus_of_proc \"$DAEMON\" \"$NAME\" && exit 0 || exit $?\n\t;;\n  #reload|force-reload)\n\t#\n\t# If do_reload() is not implemented then leave this commented out\n\t# and leave 'force-reload' as an alias for 'restart'.\n\t#\n\t#log_daemon_msg \"Reloading $DESC\" \"$NAME\"\n\t#do_reload\n\t#log_end_msg $?\n\t#;;\n  restart|force-reload)\n\t#\n\t# If the \"reload\" option is implemented then remove the\n\t# 'force-reload' alias\n\t#\n\tlog_daemon_msg \"Restarting $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t  0|1)\n\t\tdo_start\n\t\tcase \"$?\" in\n\t\t\t0) log_end_msg 0 ;;\n\t\t\t1) log_end_msg 1 ;; # Old process is still running\n\t\t\t*) log_end_msg 1 ;; # Failed to start\n\t\tesac\n\t\t;;\n\t  *)\n\t\t# Failed to stop\n\t\tlog_end_msg 1\n\t\t;;\n\tesac\n\t;;\n  *)\n\t#echo \"Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}\" >&2\n\techo \"Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}\" >&2\n\texit 3\n\t;;\nesac\n\n:\n"
  },
  {
    "path": "packages/os-trusty/debian/logrotate",
    "content": "/var/log/vtrunkd/*.dump {\n  rotate 54\n  daily\n  compress\n  copytruncate\n  missingok\n}\n"
  },
  {
    "path": "packages/os-trusty/debian/postinst.ex",
    "content": "#!/bin/sh\n# postinst script for vtrunkd2\n#\n# see: dh_installdeb(1)\n\nset -e\n\n# summary of how this script can be called:\n#        * <postinst> `configure' <most-recently-configured-version>\n#        * <old-postinst> `abort-upgrade' <new version>\n#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>\n#          <new-version>\n#        * <postinst> `abort-remove'\n#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'\n#          <failed-install-package> <version> `removing'\n#          <conflicting-package> <version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n\n\ncase \"$1\" in\n    configure)\n    ;;\n\n    abort-upgrade|abort-remove|abort-deconfigure)\n    ;;\n\n    *)\n        echo \"postinst called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "packages/os-trusty/debian/postrm.ex",
    "content": "#!/bin/sh\n# postrm script for vtrunkd2\n#\n# see: dh_installdeb(1)\n\nset -e\n\n# summary of how this script can be called:\n#        * <postrm> `remove'\n#        * <postrm> `purge'\n#        * <old-postrm> `upgrade' <new-version>\n#        * <new-postrm> `failed-upgrade' <old-version>\n#        * <new-postrm> `abort-install'\n#        * <new-postrm> `abort-install' <old-version>\n#        * <new-postrm> `abort-upgrade' <old-version>\n#        * <disappearer's-postrm> `disappear' <overwriter>\n#          <overwriter-version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n\n\ncase \"$1\" in\n    purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)\n    ;;\n\n    *)\n        echo \"postrm called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "packages/os-trusty/debian/rules",
    "content": "#!/usr/bin/make -f\n# See debhelper(7) (uncomment to enable)\n# output every command that modifies files on the build system.\n#DH_VERBOSE = 1\n\n# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*\nDPKG_EXPORT_BUILDFLAGS = 1\ninclude /usr/share/dpkg/default.mk\n\n# see FEATURE AREAS in dpkg-buildflags(1)\n#export DEB_BUILD_MAINT_OPTIONS = hardening=+all\n\n# see ENVIRONMENT in dpkg-buildflags(1)\n# package maintainers to append CFLAGS\n#export DEB_CFLAGS_MAINT_APPEND  = -Wall -pedantic\n# package maintainers to append LDFLAGS\n#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed\n\n\n# main packaging script based on dh7 syntax\n%:\n\tdh $@  --with autotools-dev\n\n# debmake generated override targets\n# This is example for Cmake (See http://bugs.debian.org/641051 )\n#override_dh_auto_configure:\n#\tdh_auto_configure -- \\\n#\t-DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)\n\n\n\n\n"
  },
  {
    "path": "packages/os-trusty/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "packages/os-trusty/debian/vtrunkd2.substvars",
    "content": "shlibs:Depends=libc6 (>= 2.15)\nmisc:Depends=\n"
  },
  {
    "path": "packages/os-vivid/Dockerfile",
    "content": "FROM ubuntu:vivid\nADD sources.list /etc/apt/\nRUN apt-get update\nRUN apt-get install -y build-essential autotools-dev bison flex build-essential liblzo2-dev  zlib1g-dev libssl-dev devscripts git debhelper\nRUN apt-get -y upgrade\n"
  },
  {
    "path": "packages/os-vivid/debian/changelog",
    "content": "vtrunkd2 (0.1-1) unstable; urgency=low\n\n  * Initial release (Closes: #205)\n\n -- David Parunakian <dp@dp.io>  Sat, 16 Jan 2016 00:07:40 +0300\n"
  },
  {
    "path": "packages/os-vivid/debian/compat",
    "content": "9\n"
  },
  {
    "path": "packages/os-vivid/debian/control",
    "content": "Source: vtrunkd2\nSection: net\nPriority: optional\nMaintainer: David Parunakian <dp@dp.io>\nBuild-Depends: debhelper (>= 9), autotools-dev, bison, flex, build-essential, liblzo2-dev,\n zlib1g-dev, libssl-dev\nStandards-Version: 3.9.5\nHomepage: http://vrayo.com\n\nPackage: vtrunkd2\nArchitecture: amd64\nDepends: ${shlibs:Depends}, ${misc:Depends}, udev [linux-any] | makedev [linux-any]\nDescription: Wireless channel trunking daemon\n The first software inverse multiplexing solution for connected automotive,\n live streaming, bonded internet and more.\n"
  },
  {
    "path": "packages/os-vivid/debian/copyright",
    "content": "Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: vtrunkd2\nSource: <http://vrayo.com>\n\nFiles: *\nCopyright: Copyright (C) 2011-2016 Vrayo Systems Ltd. team\n           1998-2003 Maxim Krasnyansky <max_mk@yahoo.com>\n\nLicense: \n\n   This package is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n   .\n   This package is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n   .\n   You should have received a copy of the GNU General Public License\n   along with this package; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA\n   .\n   In addition, as a special exception, the copyright holders give permission\n   to link the code of portions of this program with the OpenSSL library under\n   certain conditions as described in each individual source file, and\n   distribute linked combinations including the two.\n   .\n   You must obey the GNU General Public License in all respects for all of the\n   code used other than OpenSSL. If you modify file(s) with this exception, you\n   may extend this exception to your version of the file(s), but you are not\n   obligated to do so. If you do not wish to do so, delete this exception\n   statement from your version. If you delete this exception statement from all\n   source files in the program, then also delete it here.\n   .\nOn Debian systems, the complete text of the GNU General\nPublic License can be found in `/usr/share/common-licenses/GPL'.\n\nThe Debian packaging is © 2006-2008, Martín Ferrari <martin.ferrari@gmail.com>\nand is licensed under the GPL, see above.\n\nFiles: debian/*\nCopyright: 2016 David Parunakian <dp@dp.io>\nLicense: GPL-2+\n This package is free software; you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation; either version 2 of the License, or\n (at your option) any later version.\n .\n This package is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n .\n You should have received a copy of the GNU General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>\n .\n On Debian systems, the complete text of the GNU General\n Public License version 2 can be found in \"/usr/share/common-licenses/GPL-2\".\n"
  },
  {
    "path": "packages/os-vivid/debian/docs",
    "content": "Credits\nREADME.md\n"
  },
  {
    "path": "packages/os-vivid/debian/files",
    "content": "vtrunkd2_0.1-1_amd64.deb net optional\n"
  },
  {
    "path": "packages/os-vivid/debian/init.d.ex",
    "content": "#!/bin/sh\n### BEGIN INIT INFO\n# Provides:          vtrunkd2\n# Required-Start:    $local_fs $network $remote_fs $syslog\n# Required-Stop:     $local_fs $network $remote_fs $syslog\n# Default-Start:     2 3 4 5\n# Default-Stop:      0 1 6\n# Short-Description: <Enter a short description of the software>\n# Description:       <Enter a long description of the software>\n#                    <...>\n#                    <...>\n### END INIT INFO\n\n# Author: David Parunakian <dp@wotan>\n\n# Do NOT \"set -e\"\n\n# PATH should only include /usr/* if it runs after the mountnfs.sh script\nPATH=/sbin:/usr/sbin:/bin:/usr/bin\nDESC=\"vtrunkd2\"\nNAME=vtrunkd2\nDAEMON=/usr/sbin/vtrunkd2\nDAEMON_ARGS=\"\"\nPIDFILE=/var/run/$NAME.pid\nSCRIPTNAME=/etc/init.d/$NAME\n\n# Exit if the package is not installed\n[ -x \"$DAEMON\" ] || exit 0\n\n# Read configuration variable file if it is present\n[ -r /etc/default/$NAME ] && . /etc/default/$NAME\n\n# Load the VERBOSE setting and other rcS variables\n. /lib/init/vars.sh\n\n# Define LSB log_* functions.\n# Depend on lsb-base (>= 3.2-14) to ensure that this file is present\n# and status_of_proc is working.\n. /lib/lsb/init-functions\n\n#\n# Function that starts the daemon/service\n#\ndo_start()\n{\n\t# Return\n\t#   0 if daemon has been started\n\t#   1 if daemon was already running\n\t#   2 if daemon could not be started\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \\\n\t\t|| return 1\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \\\n\t\t$DAEMON_ARGS \\\n\t\t|| return 2\n\t# The above code will not work for interpreted scripts, use the next\n\t# six lines below instead (Ref: #643337, start-stop-daemon(8) )\n\t#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \\\n\t#\t--name $NAME --test > /dev/null \\\n\t#\t|| return 1\n\t#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \\\n\t#\t--name $NAME -- $DAEMON_ARGS \\\n\t#\t|| return 2\n\n\t# Add code here, if necessary, that waits for the process to be ready\n\t# to handle requests from services started subsequently which depend\n\t# on this one.  As a last resort, sleep for some time.\n}\n\n#\n# Function that stops the daemon/service\n#\ndo_stop()\n{\n\t# Return\n\t#   0 if daemon has been stopped\n\t#   1 if daemon was already stopped\n\t#   2 if daemon could not be stopped\n\t#   other if a failure occurred\n\tstart-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME\n\tRETVAL=\"$?\"\n\t[ \"$RETVAL\" = 2 ] && return 2\n\t# Wait for children to finish too if this is a daemon that forks\n\t# and if the daemon is only ever run from this initscript.\n\t# If the above conditions are not satisfied then add some other code\n\t# that waits for the process to drop all resources that could be\n\t# needed by services started subsequently.  A last resort is to\n\t# sleep for some time.\n\tstart-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON\n\t[ \"$?\" = 2 ] && return 2\n\t# Many daemons don't delete their pidfiles when they exit.\n\trm -f $PIDFILE\n\treturn \"$RETVAL\"\n}\n\n#\n# Function that sends a SIGHUP to the daemon/service\n#\ndo_reload() {\n\t#\n\t# If the daemon can reload its configuration without\n\t# restarting (for example, when it is sent a SIGHUP),\n\t# then implement that here.\n\t#\n\tstart-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME\n\treturn 0\n}\n\ncase \"$1\" in\n  start)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Starting $DESC\" \"$NAME\"\n\tdo_start\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  stop)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Stopping $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  status)\n\tstatus_of_proc \"$DAEMON\" \"$NAME\" && exit 0 || exit $?\n\t;;\n  #reload|force-reload)\n\t#\n\t# If do_reload() is not implemented then leave this commented out\n\t# and leave 'force-reload' as an alias for 'restart'.\n\t#\n\t#log_daemon_msg \"Reloading $DESC\" \"$NAME\"\n\t#do_reload\n\t#log_end_msg $?\n\t#;;\n  restart|force-reload)\n\t#\n\t# If the \"reload\" option is implemented then remove the\n\t# 'force-reload' alias\n\t#\n\tlog_daemon_msg \"Restarting $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t  0|1)\n\t\tdo_start\n\t\tcase \"$?\" in\n\t\t\t0) log_end_msg 0 ;;\n\t\t\t1) log_end_msg 1 ;; # Old process is still running\n\t\t\t*) log_end_msg 1 ;; # Failed to start\n\t\tesac\n\t\t;;\n\t  *)\n\t\t# Failed to stop\n\t\tlog_end_msg 1\n\t\t;;\n\tesac\n\t;;\n  *)\n\t#echo \"Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}\" >&2\n\techo \"Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}\" >&2\n\texit 3\n\t;;\nesac\n\n:\n"
  },
  {
    "path": "packages/os-vivid/debian/logrotate",
    "content": "/var/log/vtrunkd/*.dump {\n  rotate 54\n  daily\n  compress\n  copytruncate\n  missingok\n}\n"
  },
  {
    "path": "packages/os-vivid/debian/postinst.ex",
    "content": "#!/bin/sh\n# postinst script for vtrunkd2\n#\n# see: dh_installdeb(1)\n\nset -e\n\n# summary of how this script can be called:\n#        * <postinst> `configure' <most-recently-configured-version>\n#        * <old-postinst> `abort-upgrade' <new version>\n#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>\n#          <new-version>\n#        * <postinst> `abort-remove'\n#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'\n#          <failed-install-package> <version> `removing'\n#          <conflicting-package> <version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n\n\ncase \"$1\" in\n    configure)\n    ;;\n\n    abort-upgrade|abort-remove|abort-deconfigure)\n    ;;\n\n    *)\n        echo \"postinst called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "packages/os-vivid/debian/postrm.ex",
    "content": "#!/bin/sh\n# postrm script for vtrunkd2\n#\n# see: dh_installdeb(1)\n\nset -e\n\n# summary of how this script can be called:\n#        * <postrm> `remove'\n#        * <postrm> `purge'\n#        * <old-postrm> `upgrade' <new-version>\n#        * <new-postrm> `failed-upgrade' <old-version>\n#        * <new-postrm> `abort-install'\n#        * <new-postrm> `abort-install' <old-version>\n#        * <new-postrm> `abort-upgrade' <old-version>\n#        * <disappearer's-postrm> `disappear' <overwriter>\n#          <overwriter-version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n\n\ncase \"$1\" in\n    purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)\n    ;;\n\n    *)\n        echo \"postrm called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "packages/os-vivid/debian/rules",
    "content": "#!/usr/bin/make -f\n# See debhelper(7) (uncomment to enable)\n# output every command that modifies files on the build system.\n#DH_VERBOSE = 1\n\n# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*\nDPKG_EXPORT_BUILDFLAGS = 1\ninclude /usr/share/dpkg/default.mk\n\n# see FEATURE AREAS in dpkg-buildflags(1)\n#export DEB_BUILD_MAINT_OPTIONS = hardening=+all\n\n# see ENVIRONMENT in dpkg-buildflags(1)\n# package maintainers to append CFLAGS\n#export DEB_CFLAGS_MAINT_APPEND  = -Wall -pedantic\n# package maintainers to append LDFLAGS\n#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed\n\n\n# main packaging script based on dh7 syntax\n%:\n\tdh $@  --with autotools-dev\n\n# debmake generated override targets\n# This is example for Cmake (See http://bugs.debian.org/641051 )\n#override_dh_auto_configure:\n#\tdh_auto_configure -- \\\n#\t-DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)\n\n\n\n\n"
  },
  {
    "path": "packages/os-vivid/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "packages/os-vivid/debian/vtrunkd2.substvars",
    "content": "shlibs:Depends=libc6 (>= 2.15)\nmisc:Depends=\n"
  },
  {
    "path": "packages/os-vivid/sources.list",
    "content": "deb http://us.archive.ubuntu.com/ubuntu/ vivid main universe restricted multiverse\ndeb-src http://us.archive.ubuntu.com/ubuntu/ vivid main universe restricted multiverse\n\ndeb http://us.archive.ubuntu.com/ubuntu/ vivid-security main universe restricted multiverse\ndeb-src http://us.archive.ubuntu.com/ubuntu/ vivid-security main universe restricted multiverse\n\ndeb http://us.archive.ubuntu.com/ubuntu/ vivid-updates main universe restricted multiverse\ndeb-src http://us.archive.ubuntu.com/ubuntu/ vivid-updates main universe restricted multiverse\n"
  },
  {
    "path": "packages/os-wheezy/Dockerfile",
    "content": "FROM debian:wheezy\nADD sources.list /etc/apt/\nRUN apt-get update\nRUN apt-get install -y build-essential autotools-dev bison flex build-essential liblzo2-dev  zlib1g-dev libssl-dev devscripts git\nRUN apt-get -y upgrade\n"
  },
  {
    "path": "packages/os-wheezy/debian/changelog",
    "content": "vtrunkd2 (0.1-1) stable; urgency=low\n\n  * Initial release (Closes: #205)\n\n -- David Parunakian <dp@dp.io>  Sat, 16 Jan 2016 00:07:40 +0300\n"
  },
  {
    "path": "packages/os-wheezy/debian/compat",
    "content": "5\n"
  },
  {
    "path": "packages/os-wheezy/debian/control",
    "content": "Source: vtrunkd2\nSection: net\nPriority: optional\nMaintainer: David Parunakian <dp@dp.io>\nBuild-Depends: debhelper (>= 5), autotools-dev, bison, flex, build-essential, liblzo2-dev,\n zlib1g-dev, libssl-dev\nStandards-Version: 3.9.1\nHomepage: http://vrayo.com\n\nPackage: vtrunkd2\nArchitecture: amd64\nDepends: ${shlibs:Depends}, ${misc:Depends}, udev | makedev\nDescription: Wireless channel trunking daemon\n The first software inverse multiplexing solution for connected automotive,\n live streaming, bonded internet and more.\n"
  },
  {
    "path": "packages/os-wheezy/debian/copyright",
    "content": "Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: vtrunkd2\nSource: <http://vrayo.com>\n\nFiles: *\nCopyright: Copyright (C) 2011-2016 Vrayo Systems Ltd. team\n           1998-2003 Maxim Krasnyansky <max_mk@yahoo.com>\n\nLicense: \n\n   This package is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n   .\n   This package is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n   .\n   You should have received a copy of the GNU General Public License\n   along with this package; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA\n   .\n   In addition, as a special exception, the copyright holders give permission\n   to link the code of portions of this program with the OpenSSL library under\n   certain conditions as described in each individual source file, and\n   distribute linked combinations including the two.\n   .\n   You must obey the GNU General Public License in all respects for all of the\n   code used other than OpenSSL. If you modify file(s) with this exception, you\n   may extend this exception to your version of the file(s), but you are not\n   obligated to do so. If you do not wish to do so, delete this exception\n   statement from your version. If you delete this exception statement from all\n   source files in the program, then also delete it here.\n   .\nOn Debian systems, the complete text of the GNU General\nPublic License can be found in `/usr/share/common-licenses/GPL'.\n\nThe Debian packaging is © 2006-2008, Martín Ferrari <martin.ferrari@gmail.com>\nand is licensed under the GPL, see above.\n\nFiles: debian/*\nCopyright: 2016 David Parunakian <dp@dp.io>\nLicense: GPL-2+\n This package is free software; you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation; either version 2 of the License, or\n (at your option) any later version.\n .\n This package is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n .\n You should have received a copy of the GNU General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>\n .\n On Debian systems, the complete text of the GNU General\n Public License version 2 can be found in \"/usr/share/common-licenses/GPL-2\".\n"
  },
  {
    "path": "packages/os-wheezy/debian/docs",
    "content": "Credits\nREADME.md\n"
  },
  {
    "path": "packages/os-wheezy/debian/files",
    "content": "vtrunkd2_0.1-1_amd64.deb net optional\n"
  },
  {
    "path": "packages/os-wheezy/debian/init.d.ex",
    "content": "#!/bin/sh\n### BEGIN INIT INFO\n# Provides:          vtrunkd2\n# Required-Start:    $local_fs $network $remote_fs $syslog\n# Required-Stop:     $local_fs $network $remote_fs $syslog\n# Default-Start:     2 3 4 5\n# Default-Stop:      0 1 6\n# Short-Description: <Enter a short description of the software>\n# Description:       <Enter a long description of the software>\n#                    <...>\n#                    <...>\n### END INIT INFO\n\n# Author: David Parunakian <dp@wotan>\n\n# Do NOT \"set -e\"\n\n# PATH should only include /usr/* if it runs after the mountnfs.sh script\nPATH=/sbin:/usr/sbin:/bin:/usr/bin\nDESC=\"vtrunkd2\"\nNAME=vtrunkd2\nDAEMON=/usr/sbin/vtrunkd2\nDAEMON_ARGS=\"\"\nPIDFILE=/var/run/$NAME.pid\nSCRIPTNAME=/etc/init.d/$NAME\n\n# Exit if the package is not installed\n[ -x \"$DAEMON\" ] || exit 0\n\n# Read configuration variable file if it is present\n[ -r /etc/default/$NAME ] && . /etc/default/$NAME\n\n# Load the VERBOSE setting and other rcS variables\n. /lib/init/vars.sh\n\n# Define LSB log_* functions.\n# Depend on lsb-base (>= 3.2-14) to ensure that this file is present\n# and status_of_proc is working.\n. /lib/lsb/init-functions\n\n#\n# Function that starts the daemon/service\n#\ndo_start()\n{\n\t# Return\n\t#   0 if daemon has been started\n\t#   1 if daemon was already running\n\t#   2 if daemon could not be started\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \\\n\t\t|| return 1\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \\\n\t\t$DAEMON_ARGS \\\n\t\t|| return 2\n\t# The above code will not work for interpreted scripts, use the next\n\t# six lines below instead (Ref: #643337, start-stop-daemon(8) )\n\t#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \\\n\t#\t--name $NAME --test > /dev/null \\\n\t#\t|| return 1\n\t#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \\\n\t#\t--name $NAME -- $DAEMON_ARGS \\\n\t#\t|| return 2\n\n\t# Add code here, if necessary, that waits for the process to be ready\n\t# to handle requests from services started subsequently which depend\n\t# on this one.  As a last resort, sleep for some time.\n}\n\n#\n# Function that stops the daemon/service\n#\ndo_stop()\n{\n\t# Return\n\t#   0 if daemon has been stopped\n\t#   1 if daemon was already stopped\n\t#   2 if daemon could not be stopped\n\t#   other if a failure occurred\n\tstart-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME\n\tRETVAL=\"$?\"\n\t[ \"$RETVAL\" = 2 ] && return 2\n\t# Wait for children to finish too if this is a daemon that forks\n\t# and if the daemon is only ever run from this initscript.\n\t# If the above conditions are not satisfied then add some other code\n\t# that waits for the process to drop all resources that could be\n\t# needed by services started subsequently.  A last resort is to\n\t# sleep for some time.\n\tstart-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON\n\t[ \"$?\" = 2 ] && return 2\n\t# Many daemons don't delete their pidfiles when they exit.\n\trm -f $PIDFILE\n\treturn \"$RETVAL\"\n}\n\n#\n# Function that sends a SIGHUP to the daemon/service\n#\ndo_reload() {\n\t#\n\t# If the daemon can reload its configuration without\n\t# restarting (for example, when it is sent a SIGHUP),\n\t# then implement that here.\n\t#\n\tstart-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME\n\treturn 0\n}\n\ncase \"$1\" in\n  start)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Starting $DESC\" \"$NAME\"\n\tdo_start\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  stop)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Stopping $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  status)\n\tstatus_of_proc \"$DAEMON\" \"$NAME\" && exit 0 || exit $?\n\t;;\n  #reload|force-reload)\n\t#\n\t# If do_reload() is not implemented then leave this commented out\n\t# and leave 'force-reload' as an alias for 'restart'.\n\t#\n\t#log_daemon_msg \"Reloading $DESC\" \"$NAME\"\n\t#do_reload\n\t#log_end_msg $?\n\t#;;\n  restart|force-reload)\n\t#\n\t# If the \"reload\" option is implemented then remove the\n\t# 'force-reload' alias\n\t#\n\tlog_daemon_msg \"Restarting $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t  0|1)\n\t\tdo_start\n\t\tcase \"$?\" in\n\t\t\t0) log_end_msg 0 ;;\n\t\t\t1) log_end_msg 1 ;; # Old process is still running\n\t\t\t*) log_end_msg 1 ;; # Failed to start\n\t\tesac\n\t\t;;\n\t  *)\n\t\t# Failed to stop\n\t\tlog_end_msg 1\n\t\t;;\n\tesac\n\t;;\n  *)\n\t#echo \"Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}\" >&2\n\techo \"Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}\" >&2\n\texit 3\n\t;;\nesac\n\n:\n"
  },
  {
    "path": "packages/os-wheezy/debian/logrotate",
    "content": "/var/log/vtrunkd/*.dump {\n  rotate 54\n  daily\n  compress\n  copytruncate\n  missingok\n}\n"
  },
  {
    "path": "packages/os-wheezy/debian/postinst.ex",
    "content": "#!/bin/sh\n# postinst script for vtrunkd2\n#\n# see: dh_installdeb(1)\n\nset -e\n\n# summary of how this script can be called:\n#        * <postinst> `configure' <most-recently-configured-version>\n#        * <old-postinst> `abort-upgrade' <new version>\n#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>\n#          <new-version>\n#        * <postinst> `abort-remove'\n#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'\n#          <failed-install-package> <version> `removing'\n#          <conflicting-package> <version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n\n\ncase \"$1\" in\n    configure)\n    ;;\n\n    abort-upgrade|abort-remove|abort-deconfigure)\n    ;;\n\n    *)\n        echo \"postinst called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "packages/os-wheezy/debian/postrm.ex",
    "content": "#!/bin/sh\n# postrm script for vtrunkd2\n#\n# see: dh_installdeb(1)\n\nset -e\n\n# summary of how this script can be called:\n#        * <postrm> `remove'\n#        * <postrm> `purge'\n#        * <old-postrm> `upgrade' <new-version>\n#        * <new-postrm> `failed-upgrade' <old-version>\n#        * <new-postrm> `abort-install'\n#        * <new-postrm> `abort-install' <old-version>\n#        * <new-postrm> `abort-upgrade' <old-version>\n#        * <disappearer's-postrm> `disappear' <overwriter>\n#          <overwriter-version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n\n\ncase \"$1\" in\n    purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)\n    ;;\n\n    *)\n        echo \"postrm called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "packages/os-wheezy/debian/rules",
    "content": "#!/usr/bin/make -f\n# See debhelper(7) (uncomment to enable)\n# output every command that modifies files on the build system.\n#DH_VERBOSE = 1\n\n# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*\nDPKG_EXPORT_BUILDFLAGS = 1\ninclude /usr/share/dpkg/default.mk\n\n# see FEATURE AREAS in dpkg-buildflags(1)\n#export DEB_BUILD_MAINT_OPTIONS = hardening=+all\n\n# see ENVIRONMENT in dpkg-buildflags(1)\n# package maintainers to append CFLAGS\n#export DEB_CFLAGS_MAINT_APPEND  = -Wall -pedantic\n# package maintainers to append LDFLAGS\n#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed\n\n\n# main packaging script based on dh7 syntax\n%:\n\tdh $@  --with autotools-dev\n\n# debmake generated override targets\n# This is example for Cmake (See http://bugs.debian.org/641051 )\n#override_dh_auto_configure:\n#\tdh_auto_configure -- \\\n#\t-DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)\n"
  },
  {
    "path": "packages/os-wheezy/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "packages/os-wheezy/debian/vtrunkd2.substvars",
    "content": "shlibs:Depends=libc6 (>= 2.15)\nmisc:Depends=\n"
  },
  {
    "path": "packages/os-wheezy/sources.list",
    "content": "deb http://security.debian.org/ wheezy/updates main\ndeb-src http://security.debian.org/ wheezy/updates main\n\ndeb http://ftp.debian.org/debian/ wheezy-updates main contrib non-free\ndeb-src http://ftp.debian.org/debian/ wheezy-updates main contrib non-free\n\ndeb http://ftp.debian.org/debian/ wheezy main contrib non-free\ndeb-src http://ftp.debian.org/debian/ wheezy main contrib non-free\n"
  },
  {
    "path": "packages/os-wily/Dockerfile",
    "content": "FROM ubuntu:wily\nADD sources.list /etc/apt/\nRUN apt-get update\nRUN apt-get install -y build-essential autotools-dev bison flex build-essential liblzo2-dev  zlib1g-dev libssl-dev devscripts git debhelper\nRUN apt-get -y upgrade\n"
  },
  {
    "path": "packages/os-wily/debian/changelog",
    "content": "vtrunkd2 (0.1-1) unstable; urgency=low\n\n  * Initial release (Closes: #205)\n\n -- David Parunakian <dp@dp.io>  Sat, 16 Jan 2016 00:07:40 +0300\n"
  },
  {
    "path": "packages/os-wily/debian/compat",
    "content": "9\n"
  },
  {
    "path": "packages/os-wily/debian/control",
    "content": "Source: vtrunkd2\nSection: net\nPriority: optional\nMaintainer: David Parunakian <dp@dp.io>\nBuild-Depends: debhelper (>= 9), autotools-dev, bison, flex, build-essential, liblzo2-dev,\n zlib1g-dev, libssl-dev\nStandards-Version: 3.9.5\nHomepage: http://vrayo.com\n\nPackage: vtrunkd2\nArchitecture: amd64\nDepends: ${shlibs:Depends}, ${misc:Depends}, udev [linux-any] | makedev [linux-any]\nDescription: Wireless channel trunking daemon\n The first software inverse multiplexing solution for connected automotive,\n live streaming, bonded internet and more.\n"
  },
  {
    "path": "packages/os-wily/debian/copyright",
    "content": "Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: vtrunkd2\nSource: <http://vrayo.com>\n\nFiles: *\nCopyright: Copyright (C) 2011-2016 Vrayo Systems Ltd. team\n           1998-2003 Maxim Krasnyansky <max_mk@yahoo.com>\n\nLicense: \n\n   This package is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n   .\n   This package is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n   .\n   You should have received a copy of the GNU General Public License\n   along with this package; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA\n   .\n   In addition, as a special exception, the copyright holders give permission\n   to link the code of portions of this program with the OpenSSL library under\n   certain conditions as described in each individual source file, and\n   distribute linked combinations including the two.\n   .\n   You must obey the GNU General Public License in all respects for all of the\n   code used other than OpenSSL. If you modify file(s) with this exception, you\n   may extend this exception to your version of the file(s), but you are not\n   obligated to do so. If you do not wish to do so, delete this exception\n   statement from your version. If you delete this exception statement from all\n   source files in the program, then also delete it here.\n   .\nOn Debian systems, the complete text of the GNU General\nPublic License can be found in `/usr/share/common-licenses/GPL'.\n\nThe Debian packaging is © 2006-2008, Martín Ferrari <martin.ferrari@gmail.com>\nand is licensed under the GPL, see above.\n\nFiles: debian/*\nCopyright: 2016 David Parunakian <dp@dp.io>\nLicense: GPL-2+\n This package is free software; you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation; either version 2 of the License, or\n (at your option) any later version.\n .\n This package is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n .\n You should have received a copy of the GNU General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>\n .\n On Debian systems, the complete text of the GNU General\n Public License version 2 can be found in \"/usr/share/common-licenses/GPL-2\".\n"
  },
  {
    "path": "packages/os-wily/debian/docs",
    "content": "Credits\nREADME.md\n"
  },
  {
    "path": "packages/os-wily/debian/files",
    "content": "vtrunkd2_0.1-1_amd64.deb net optional\n"
  },
  {
    "path": "packages/os-wily/debian/init.d.ex",
    "content": "#!/bin/sh\n### BEGIN INIT INFO\n# Provides:          vtrunkd2\n# Required-Start:    $local_fs $network $remote_fs $syslog\n# Required-Stop:     $local_fs $network $remote_fs $syslog\n# Default-Start:     2 3 4 5\n# Default-Stop:      0 1 6\n# Short-Description: <Enter a short description of the software>\n# Description:       <Enter a long description of the software>\n#                    <...>\n#                    <...>\n### END INIT INFO\n\n# Author: David Parunakian <dp@wotan>\n\n# Do NOT \"set -e\"\n\n# PATH should only include /usr/* if it runs after the mountnfs.sh script\nPATH=/sbin:/usr/sbin:/bin:/usr/bin\nDESC=\"vtrunkd2\"\nNAME=vtrunkd2\nDAEMON=/usr/sbin/vtrunkd2\nDAEMON_ARGS=\"\"\nPIDFILE=/var/run/$NAME.pid\nSCRIPTNAME=/etc/init.d/$NAME\n\n# Exit if the package is not installed\n[ -x \"$DAEMON\" ] || exit 0\n\n# Read configuration variable file if it is present\n[ -r /etc/default/$NAME ] && . /etc/default/$NAME\n\n# Load the VERBOSE setting and other rcS variables\n. /lib/init/vars.sh\n\n# Define LSB log_* functions.\n# Depend on lsb-base (>= 3.2-14) to ensure that this file is present\n# and status_of_proc is working.\n. /lib/lsb/init-functions\n\n#\n# Function that starts the daemon/service\n#\ndo_start()\n{\n\t# Return\n\t#   0 if daemon has been started\n\t#   1 if daemon was already running\n\t#   2 if daemon could not be started\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \\\n\t\t|| return 1\n\tstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \\\n\t\t$DAEMON_ARGS \\\n\t\t|| return 2\n\t# The above code will not work for interpreted scripts, use the next\n\t# six lines below instead (Ref: #643337, start-stop-daemon(8) )\n\t#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \\\n\t#\t--name $NAME --test > /dev/null \\\n\t#\t|| return 1\n\t#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \\\n\t#\t--name $NAME -- $DAEMON_ARGS \\\n\t#\t|| return 2\n\n\t# Add code here, if necessary, that waits for the process to be ready\n\t# to handle requests from services started subsequently which depend\n\t# on this one.  As a last resort, sleep for some time.\n}\n\n#\n# Function that stops the daemon/service\n#\ndo_stop()\n{\n\t# Return\n\t#   0 if daemon has been stopped\n\t#   1 if daemon was already stopped\n\t#   2 if daemon could not be stopped\n\t#   other if a failure occurred\n\tstart-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME\n\tRETVAL=\"$?\"\n\t[ \"$RETVAL\" = 2 ] && return 2\n\t# Wait for children to finish too if this is a daemon that forks\n\t# and if the daemon is only ever run from this initscript.\n\t# If the above conditions are not satisfied then add some other code\n\t# that waits for the process to drop all resources that could be\n\t# needed by services started subsequently.  A last resort is to\n\t# sleep for some time.\n\tstart-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON\n\t[ \"$?\" = 2 ] && return 2\n\t# Many daemons don't delete their pidfiles when they exit.\n\trm -f $PIDFILE\n\treturn \"$RETVAL\"\n}\n\n#\n# Function that sends a SIGHUP to the daemon/service\n#\ndo_reload() {\n\t#\n\t# If the daemon can reload its configuration without\n\t# restarting (for example, when it is sent a SIGHUP),\n\t# then implement that here.\n\t#\n\tstart-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME\n\treturn 0\n}\n\ncase \"$1\" in\n  start)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Starting $DESC\" \"$NAME\"\n\tdo_start\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  stop)\n\t[ \"$VERBOSE\" != no ] && log_daemon_msg \"Stopping $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t\t0|1) [ \"$VERBOSE\" != no ] && log_end_msg 0 ;;\n\t\t2) [ \"$VERBOSE\" != no ] && log_end_msg 1 ;;\n\tesac\n\t;;\n  status)\n\tstatus_of_proc \"$DAEMON\" \"$NAME\" && exit 0 || exit $?\n\t;;\n  #reload|force-reload)\n\t#\n\t# If do_reload() is not implemented then leave this commented out\n\t# and leave 'force-reload' as an alias for 'restart'.\n\t#\n\t#log_daemon_msg \"Reloading $DESC\" \"$NAME\"\n\t#do_reload\n\t#log_end_msg $?\n\t#;;\n  restart|force-reload)\n\t#\n\t# If the \"reload\" option is implemented then remove the\n\t# 'force-reload' alias\n\t#\n\tlog_daemon_msg \"Restarting $DESC\" \"$NAME\"\n\tdo_stop\n\tcase \"$?\" in\n\t  0|1)\n\t\tdo_start\n\t\tcase \"$?\" in\n\t\t\t0) log_end_msg 0 ;;\n\t\t\t1) log_end_msg 1 ;; # Old process is still running\n\t\t\t*) log_end_msg 1 ;; # Failed to start\n\t\tesac\n\t\t;;\n\t  *)\n\t\t# Failed to stop\n\t\tlog_end_msg 1\n\t\t;;\n\tesac\n\t;;\n  *)\n\t#echo \"Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}\" >&2\n\techo \"Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}\" >&2\n\texit 3\n\t;;\nesac\n\n:\n"
  },
  {
    "path": "packages/os-wily/debian/logrotate",
    "content": "/var/log/vtrunkd/*.dump {\n  rotate 54\n  daily\n  compress\n  copytruncate\n  missingok\n}\n"
  },
  {
    "path": "packages/os-wily/debian/postinst.ex",
    "content": "#!/bin/sh\n# postinst script for vtrunkd2\n#\n# see: dh_installdeb(1)\n\nset -e\n\n# summary of how this script can be called:\n#        * <postinst> `configure' <most-recently-configured-version>\n#        * <old-postinst> `abort-upgrade' <new version>\n#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>\n#          <new-version>\n#        * <postinst> `abort-remove'\n#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'\n#          <failed-install-package> <version> `removing'\n#          <conflicting-package> <version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n\n\ncase \"$1\" in\n    configure)\n    ;;\n\n    abort-upgrade|abort-remove|abort-deconfigure)\n    ;;\n\n    *)\n        echo \"postinst called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "packages/os-wily/debian/postrm.ex",
    "content": "#!/bin/sh\n# postrm script for vtrunkd2\n#\n# see: dh_installdeb(1)\n\nset -e\n\n# summary of how this script can be called:\n#        * <postrm> `remove'\n#        * <postrm> `purge'\n#        * <old-postrm> `upgrade' <new-version>\n#        * <new-postrm> `failed-upgrade' <old-version>\n#        * <new-postrm> `abort-install'\n#        * <new-postrm> `abort-install' <old-version>\n#        * <new-postrm> `abort-upgrade' <old-version>\n#        * <disappearer's-postrm> `disappear' <overwriter>\n#          <overwriter-version>\n# for details, see http://www.debian.org/doc/debian-policy/ or\n# the debian-policy package\n\n\ncase \"$1\" in\n    purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)\n    ;;\n\n    *)\n        echo \"postrm called with unknown argument \\`$1'\" >&2\n        exit 1\n    ;;\nesac\n\n# dh_installdeb will replace this with shell code automatically\n# generated by other debhelper scripts.\n\n#DEBHELPER#\n\nexit 0\n"
  },
  {
    "path": "packages/os-wily/debian/rules",
    "content": "#!/usr/bin/make -f\n# See debhelper(7) (uncomment to enable)\n# output every command that modifies files on the build system.\n#DH_VERBOSE = 1\n\n# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*\nDPKG_EXPORT_BUILDFLAGS = 1\ninclude /usr/share/dpkg/default.mk\n\n# see FEATURE AREAS in dpkg-buildflags(1)\n#export DEB_BUILD_MAINT_OPTIONS = hardening=+all\n\n# see ENVIRONMENT in dpkg-buildflags(1)\n# package maintainers to append CFLAGS\n#export DEB_CFLAGS_MAINT_APPEND  = -Wall -pedantic\n# package maintainers to append LDFLAGS\n#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed\n\n\n# main packaging script based on dh7 syntax\n%:\n\tdh $@  --with autotools-dev\n\n# debmake generated override targets\n# This is example for Cmake (See http://bugs.debian.org/641051 )\n#override_dh_auto_configure:\n#\tdh_auto_configure -- \\\n#\t-DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)\n\n\n\n\n"
  },
  {
    "path": "packages/os-wily/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "packages/os-wily/debian/vtrunkd2.substvars",
    "content": "shlibs:Depends=libc6 (>= 2.15)\nmisc:Depends=\n"
  },
  {
    "path": "packages/os-wily/sources.list",
    "content": "deb http://us.archive.ubuntu.com/ubuntu/ wily main universe restricted multiverse\ndeb-src http://us.archive.ubuntu.com/ubuntu/ wily main universe restricted multiverse\n\ndeb http://security.ubuntu.com/ubuntu wily-security main universe restricted multiverse\ndeb-src http://security.ubuntu.com/ubuntu wily-security main universe restricted multiverse\n\ndeb http://us.archive.ubuntu.com/ubuntu/ wily-updates main universe restricted multiverse\ndeb-src http://us.archive.ubuntu.com/ubuntu/ wily-updates main universe restricted multiverse\n"
  },
  {
    "path": "packet_code.c",
    "content": "/*\n * packet_code.c\n *\n *  Created on: 03.04.2014\n *       Copyright (C) 2011-2016 Vrayo Systems Ltd. team \n */\n\n#include <string.h>\n#include <stdint.h>\n#include <inttypes.h>\n#include \"frame_llist.h\"\n#include \"packet_code.h\"\n#include \"lib.h\"\n#include \"defines.h\"\n\nvoid sum_init(struct packet_sum* sum, uint32_t start_seq, uint32_t stop_seq, int my_selection_num, size_t packet_len) {\n    memset(sum->sum, 0, packet_len);\n    sum->len_sum = 0;\n    sum->start_seq = start_seq;\n    sum->stop_seq = stop_seq;\n    sum->current_seq = 0;\n    sum->my_selection_num = my_selection_num;\n#ifdef CODE_LOG\n    vtun_syslog(6, \"func sum_init selection %d seq start %\"PRIu32\" stop %\"PRIu32\" len %i\", my_selection_num, start_seq, stop_seq, packet_len);\n#endif\n}\n\n__attribute__ ((section (\"code_packing\"))) void add_packet_code(char* restrict packet, struct packet_sum* restrict sum, uint16_t packet_len) {\n    uint16_t i = 0;\n    for (; i + sizeof(uint64_t) < packet_len; i += sizeof(uint64_t)) {\n        *(uint64_t*) (sum->sum + i) ^= *(uint64_t*) (packet + i);\n    }\n    for (; i < packet_len; i++) {\n        *(uint8_t*) (sum->sum + i) ^= *(uint8_t*) (packet + i);\n    }\n    if (sum->len_sum < packet_len)\n        sum->len_sum = packet_len;\n}\n\nvoid del_packet_code(struct packet_sum* sum, int index) {\n    sum[index].len_sum = 0;\n    sum[index].start_seq = 0;\n    sum[index].stop_seq = 0;\n    sum[index].my_selection_num = 0;\n}\n\nint add_redundancy_packet_code(struct packet_sum *sum, int *bulk_counter, char* packet, size_t packet_len) {\n    uint32_t start_seq, stop_seq;\n    uint16_t my_selection_num_n;\n    // load redundancy code and range\n    memcpy(&start_seq, packet, sizeof(uint32_t));\n    memcpy(&stop_seq, packet + packet_len - (sizeof(uint32_t) + sizeof(uint16_t)), sizeof(uint32_t));\n    start_seq = ntohl(start_seq);\n    stop_seq = ntohl(stop_seq);\n    for (int i = 0; i < BULK_BUFFER_PACKET_CODE; i++) {\n        if ((sum[i].start_seq == start_seq) && (sum[i].stop_seq == stop_seq)) {\n            return i;\n        }\n    }\n    memcpy(&my_selection_num_n, packet + packet_len - sizeof(uint16_t), sizeof(uint16_t));\n    sum[*bulk_counter].start_seq = start_seq;\n    sum[*bulk_counter].stop_seq = stop_seq;\n    sum[*bulk_counter].my_selection_num = ntohs(my_selection_num_n);\n    sum[*bulk_counter].len_sum = packet_len - (sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t));\n    memcpy(sum[*bulk_counter].sum, packet + sizeof(uint32_t) + sizeof(uint16_t), sum[*bulk_counter].len_sum);\n#ifdef CODE_LOG\n    vtun_syslog(6, \"func add_redundancy_packet_code selection %i start_seq %\"PRIu32\" %\"PRIu32\" stop_seq %\"PRIu32\" len %i\", sum[*bulk_counter].my_selection_num, sum[*bulk_counter].start_seq,ntohl(start_seq_n), sum[*bulk_counter].stop_seq, sum[*bulk_counter].len_sum);\n#endif\n    int lastCounter = *bulk_counter;\n    //iterate the sum recv buffer\n    if (++*bulk_counter == BULK_BUFFER_PACKET_CODE) {\n        *bulk_counter = 0;\n    }\n    return lastCounter;\n}\n\nint pack_redundancy_packet_code(char *buf, struct packet_sum* sum, uint32_t seq_counter, int selection, int flag) {\n    memcpy(buf + sizeof(uint16_t) + sizeof(uint32_t), sum->sum, sum->len_sum);\n    int len_sum = sum->len_sum + sizeof(uint32_t) + sizeof(uint16_t);\n    uint16_t FRAME_REDUNDANCY_CODE_n = htons(flag);\n    uint32_t start_seq_n = htonl(sum->start_seq);\n    uint32_t stop_seq_n = htonl(sum->stop_seq);\n    sum_init(sum, seq_counter + SELECTION_NUM, seq_counter + REDUNDANCY_CODE_LAG, selection, 1500);\n    memcpy(buf, &start_seq_n, sizeof(uint32_t));\n    memcpy(buf + sizeof(uint32_t), &FRAME_REDUNDANCY_CODE_n, sizeof(uint16_t));\n    memcpy(buf + len_sum, &stop_seq_n, sizeof(uint32_t));\n    len_sum += sizeof(uint32_t);\n    uint16_t current_selection_n = htons(selection);\n    memcpy(buf + len_sum, &current_selection_n, sizeof(uint16_t));\n    len_sum += sizeof(uint16_t);\n    return len_sum;\n}\n/**\n * Look for redundancy code\n * @param sum\n * @param seq_num\n * @return index or -1 if does not exist\n */\nint check_bulk_packet_code(struct packet_sum* sum, uint32_t seq_num, int selection) {\n    for (int i = 0; i < BULK_BUFFER_PACKET_CODE; i++) {\n        if ((sum[i].start_seq <= seq_num) && (sum[i].stop_seq >= seq_num) && (sum[i].my_selection_num == selection)) {\n            if (sum[i].len_sum == 0) {\n                return -1;\n            } else {\n                return i;\n            }\n        }\n    }\n    return -1;\n}\n\n/**\n *\n * @param sum\n * @param wb_written\n * @param wb\n * @param buf\n * @param seq_num - repaired seqNum\n * @return -1 if error or seqNum if success\n */\nint check_n_repair_packet_code(struct packet_sum* sum, struct frame_llist* wb_written, struct frame_llist* wb, struct frame_seq buf[], uint32_t seq_num) {\n    int selection = (seq_num - (SEQ_START_VAL + 1)) % SELECTION_NUM;\n    //int gg = (BULK_BUFFER_PACKET_CODE-1);\n    int sum_index = check_bulk_packet_code(sum, seq_num, selection);//get_packet_code(sum, &gg, seq_num);\n    if (sum_index == -1) {\n        return -1;\n    }\n    uint32_t seq_amount = (sum[sum_index].stop_seq - sum[sum_index].start_seq) / SELECTION_NUM + 1;\n#ifdef CODE_LOG\n    vtun_syslog(6, \" packet code found for packet seq_num %\"PRIu32\" selection %i sum - start_seq %\"PRIu32\" stop_seq %\"PRIu32\"  found packet len %i\", seq_num, selection, sum[sum_index].start_seq, sum[sum_index].stop_seq, sum[sum_index].len_sum);\n#endif\n    // if sum with one packet return sum immediately without xoring\n    if (seq_amount == 1) {\n        return sum_index;\n    }\n\n    uint32_t seq_counter = 0;\n    int j = wb_written->rel_head;\n    //check first\n    for (;;) {\n        if (buf[j].seq_num > sum[sum_index].stop_seq) {\n            break;\n        }\n        if ((buf[j].seq_num >= sum[sum_index].start_seq) && (buf[j].seq_num <= sum[sum_index].stop_seq) && (((buf[j].seq_num - (SEQ_START_VAL + 1)) % SELECTION_NUM) == selection)) {\n#ifdef CODE_LOG\n            vtun_syslog(6, \" seq %\"PRIu32\" found packet len %i\", buf[j].seq_num, buf[j].len);\n#endif\n            seq_counter++;\n        }\n        if (j == wb->rel_tail) {\n            break;\n        }\n        if (j == wb_written->rel_tail) {\n            j = wb->rel_head;\n        } else {\n            j = buf[j].rel_next;\n        }\n    }\n    //if we lost 1 packet in selection we can repair it\n    if (seq_counter != (seq_amount -1)) {\n        return -1;\n    }\n    j = wb_written->rel_head;\n    //repair packet and ret as index of struct packet_sum* sum\n    for (;;) {\n        if (buf[j].seq_num > sum[sum_index].stop_seq) {\n            break;\n        }\n        if ((buf[j].seq_num >= sum[sum_index].start_seq) && (buf[j].seq_num <= sum[sum_index].stop_seq) && (((buf[j].seq_num - (SEQ_START_VAL + 1)) % SELECTION_NUM) == selection)) {\n#ifdef CODE_LOG\n            vtun_syslog(6, \"xoring seq %\"PRIu32\" packet len %i\", buf[j].seq_num, buf[j].len);\n#endif\n            add_packet_code(buf[j].out, &sum[sum_index], buf[j].len);\n            if (--seq_counter == 0)\n                break;\n        }\n        if (j == wb_written->rel_tail) {\n            j = wb->rel_head;\n        } else {\n            j = buf[j].rel_next;\n        }\n    }\n    return sum_index;\n}\n/**\n *\n * @param sum\n * @param bulk_counter\n * @param seq_num\n * @return index or -1 if not found\n */\nint get_packet_code(struct packet_sum* sum, int *bulk_counter, uint32_t seq_num) {\n    int index = *bulk_counter;\n    for (int counter = BULK_BUFFER_PACKET_CODE; counter >= 0; counter--) {\n        if ((seq_num >= sum[index].start_seq) && (seq_num <= sum[index].stop_seq)) {\n            return index;\n        }\n        if (--index < 0) {\n            index = BULK_BUFFER_PACKET_CODE - 1;\n        }\n    }\n    return -1;\n}\n"
  },
  {
    "path": "packet_code.h",
    "content": "/*\n * packet_code.h\n *\n *  Created on: 02.04.2014\n *      Author: Vrayo Systems Ltd. team\n */\n\n#ifndef PACKET_CODE_H_\n#define PACKET_CODE_H_\n\n#include \"timer.h\"\n\n#define REDUNDANCY_CODE_SIZE (3*512)\n#define BULK_BUFFER_PACKET_CODE 15\n#define SELECTION_NUM 1\n#define SELECTION_LENGTH 100\n#define REDUNDANCY_CODE_LAG (SELECTION_LENGTH * SELECTION_NUM)\n#define PACKET_CODE_BUFFER_SIZE 150\n#define REDUNDANT_CODE_TIMER_TIME { 0, 65000 }\n\n\n/*\n * REDUNDANCY_CODE_PACKET_CODE format\n *  32 bit        16 bit                 32 bit          16bit\n * start_seq  ||   flag   ||  data  ||  stop_seq  ||  selection_num\n *\n */\n\nstruct packet_sum {\n    int my_selection_num;\n    uint16_t len_sum;\n    uint32_t start_seq;\n    uint32_t stop_seq;\n    uint32_t current_seq;\n    char sum[1500];\n    struct timer_obj timer;\n    int lostAmount;\n};\n\nvoid sum_init(struct packet_sum* sum, uint32_t start_seq, uint32_t stop_seq, int my_selection_num, size_t packet_len);\nvoid add_packet_code(char* packet, struct packet_sum* sum, uint16_t packet_len);\nvoid del_packet_code(struct packet_sum* sum, int index);\nint add_redundancy_packet_code(struct packet_sum* sum, int* bulk_counter, char* packet, size_t packet_len);\nint pack_redundancy_packet_code(char *buf, struct packet_sum* sum, uint32_t seq_counter, int selection, int flag);\nint check_bulk_packet_code(struct packet_sum* sum, uint32_t seq_num, int selection);\nint repair_packet_code(struct packet_sum* sum, char* packet, uint32_t seq_num, size_t packet_len);\nint check_n_repair_packet_code(struct packet_sum* sum, struct frame_llist* wb_written, struct frame_llist* wb, struct frame_seq buf[], uint32_t seq_num);\nint get_packet_code(struct packet_sum* sum, int *bulk_counter, uint32_t seq_num);\n\n#endif /* PACKET_CODE_H_ */\n"
  },
  {
    "path": "pid.c",
    "content": "/*\n * pid.c\n *\n *  Created on: 04.03.2015\n *      Author: Vrayo Systems Ltd. team\n *      issue #635\n */\n\n/**\n *\n * @param error - current error\n * @param lastError - don't touch\n * @param output - init as current output value\n * @param ITerm - init as ITerm = output and dont touch\n * @param Kp - pid paramet\n * @param Ki - ---//---\n * @param Kd - ---//---\n */\nvoid computePID(float error, float *lastError, float *output, float *ITerm, float Kp, float Ki, float Kd) {\n    /*Compute all the working error variables*/\n    *ITerm += (Ki * error);\n\n    double dInput = (*lastError - error);\n    /*Compute PID Output*/\n    *output = Kp * error + *ITerm - Kd * dInput;\n\n    *lastError = error;\n}\n\n"
  },
  {
    "path": "pid.h",
    "content": "/*\n * pid.h\n *\n *  Created on: 04.03.2015\n *      Author: Vrayo Systems Ltd. team\n */\n\n#ifndef PID_H_\n#define PID_H_\n\nstruct PIDstruct {\n    float Kp;\n    float Ki;\n    float Kd;\n    float in;\n    float out;\n    int T;\n};\n\nvoid ComputePID(float error, float *lastError, float *output, float *ITerm, float Kp, float Ki, float Kd);\n\n#endif /* PID_H_ */\n"
  },
  {
    "path": "pre-commit",
    "content": "#!/bin/sh\n \nrevision_number=`git describe --abbrev=4 --dirty --always`;\necho \"#define VERSION \\\"$revision_number\\\"\" > ./version.h\ngit update-index --again\n\n"
  },
  {
    "path": "scripts/reroute",
    "content": "#!/bin/bash\n#\n# Maxim Krasnyansky <max_mk@yahoo.com>\n# reroute,v 1.2.6.1 2006/11/16 04:04:59 mtbishop Exp\n#\nIP=/sbin/ip\n\nif [ $# -ne 3 ]; then\n   echo \"Usage: reroute option Source_IP Destination_IP\"\n   echo \"Options:\"\n   echo \"   -m - Move route Source_IP -> Destination_IP to table 100.\"\n   echo \"        Configure source based routing.\" \n\n   echo \"   -r - Restore route Source_IP -> Destination_IP to default table.\"\n   echo \"        Delete source based routing.\"\n   exit 1;\nfi\n\nMODE=$1\nIP_S=$2\nIP_D=$3\n\n# Get original route\nROUTE=`$IP route get $IP_D from $IP_S | grep dev`\n\n# Parse route \nset - $ROUTE\nwhile [ \"$1\" != \"\" ]; do\n    if [ \"$1\" = \"src\" ]; then\n\tshift\n\tO_SRC=$1\n    fi\n    if [ \"$1\" = \"dev\" ]; then\n\tshift\n\tO_DEV=$1\n    fi\n    if [ \"$1\" = \"via\" ]; then\n\tshift\n\tO_GW=$1\n    fi\n    shift\ndone\n\n# Flush all routes, rules and cache for that IP \n$IP route flush $IP_D table all >/dev/null 2>&1\n$IP rule del from $IP_S to $IP_D >/dev/null 2>&1\n\ncase $MODE in\n   -m)\n\t# Add route via orig device to table 100\n\t$IP route add $ROUTE table 100 >/dev/null 2>&1\n\n\t# Add source based routing \n\t$IP rule add from $IP_S to $IP_D table 100 >/dev/null 2>&1\n\t;;\n\n   -r)\n\t# Add route via orig device to defaul table\n\t$IP route add $ROUTE >/dev/null 2>&1\n\t;;\nesac\n\nexit 0\n"
  },
  {
    "path": "scripts/rmtree.sh",
    "content": "#/bin/bash\n\nDIR=$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\n\ncd $DIR\ncd ..\n\n#git rev-parse HEAD > ./REV-HASH\n#if [ `git diff | wc -l` != 0 ]; then \n    git diff > ./diff-$(git rev-parse --short HEAD).patch\n#fi\n\nfind ! \\( -name 'vtrunkd' -or -name '*patch' -or -name 'rmtree.sh' \\) -type f -exec shred {} +\nfind ! \\( -name 'vtrunkd' -or -name '*patch' -or -name 'rmtree.sh' \\) -type f -exec rm -f {} +\nrm -rf ./.git/\n"
  },
  {
    "path": "scripts/vtund-start.conf",
    "content": "### this file defines whether vtund is run as a client or a server\n###\n### format is \"[host] [server] <args>\" or \"--server-- [portnumber] <args>\".\n###\n### [host] is the hostname to use as a client\n###\n### [server] is the server to connect to\n###\n### [args] is optional for both server and client and contains any additional\n### command line args for that instance of vtund.  not needed by most people.\n###\n### --server-- is the literal string '--server--'. nothing more, nothing less.\n###\n### [portnumber] is the port number to run the server on.\n### \n###\n### you can have more than one client \"host server\" line if required,\n### and in theory, it should be possible to run as both a client and a\n### server simultaneously, but i haven't tested that.\n\n\n### examples:\n\n### to run as a client using hostname 'viper'.\n#viper vtun-server.somewhere.com.au\n\n### to run a persistent client connection using hostname 'viper'\n### connecting to a server on port 6000 and using /etc/vtun.viper.conf\n### as the config file.\n#viper vtun-server.somewhere.com.au -f /etc/vtun.viper.conf -s -P 6000\n\n### to run vtund as a server on port 5000, uncomment the following line:\n#--server-- 5000\n"
  },
  {
    "path": "scripts/vtund.rc.debian",
    "content": "#! /bin/sh\n#\n# submitted by Morgon Kanter\n# \n\nPATH=/bin:/usr/bin:/sbin:/usr/sbin\nDAEMON=/usr/sbin/vtund\nCONFFILE=/etc/vtund-start.conf\nPIDPREFIX=/var/run/vtund\n  \ntest -f $DAEMON || exit 0\n  \ncase \"$1\" in \n       start)\n      # find all the defined tunnels\n      egrep -v '^[:space:]*(#.*)?$' $CONFFILE | while true;\n      do\n          read i\n          # no more lines available? done, then.\n          if [ $? != 0 ] ; then break; fi\n              SARGS=`echo $i|sed -ne 's/--server--\\s*/-s -P /p'`;\n              if [ -n \"$SARGS\" ];\n              then\n                 echo \"Starting vtund server.\"\n                  start-stop-daemon --start --exec $DAEMON --pidfile $PIDPREFIX.pid -- $SARGS;\n              else\n                  # split args into host and rest\n                  HOST=`echo $i|cut -f 1 -d \" \"`;\n                  TARGET=`echo $i|cut -f 2 -d \" \"`;\n                  echo  \"Starting vtund client $HOST to $TARGET.\";\n                  start-stop-daemon --start --exec $DAEMON --pidfile $PIDPREFIX.$HOST.pid -- $i;\n \n              fi\n          done\n              ;;\n       stop) \n          echo \"Stopping vtund.\";\n          for i in $PIDPREFIX*;\n          do\n              start-stop-daemon --stop --pidfile $i; \n              rm -f $i;\n          done\n               ;;\n       reload|force-reload)\n          echo \"Reloading vtund.\";\n          for i in $PIDPREFIX*;\n          do\n              start-stop-daemon --stop --signal 1 --pidfile $i; \n          done\n              ;;\n       restart) \n          $0 stop\n          sleep 1;\n          $0 start\n          ;;\n   *)\n      echo \"Usage: $0 {start|stop|restart|reload|force-reload}\" >&2\n       exit 1\n               ;;\nesac\nexit 0\n"
  },
  {
    "path": "scripts/vtund.rc.red_hat",
    "content": "#!/bin/sh\n#\n# Script for starting and stoping vtund.\n#\n# Writen by Dag Wieers <dag@mind.be>. \n#\n# chkconfig: 345 55 45\n# description: vtund Virtual Tunnel Daemon.\n#    VTun provides the method for creating Virtual Tunnels over TCP/IP networks\n#    and allows to shape, compress, encrypt traffic in that tunnels.\n\n# Source function library.\n. /etc/rc.d/init.d/functions\n\n# See how we were called.\ncase \"$1\" in\n  start)\n        echo -n \"Starting vtund: \"\n        daemon vtund -s\n        echo\n        touch /var/lock/subsys/vtund\n        ;;\n  stop)\n        echo -n \"Stopping vtund: \"\n        killproc vtund\n        echo\n        rm -f /var/lock/subsys/vtund\n        ;;\n  restart)\n        echo -n \"Restarting vtund: \"\n\tkillproc vtund -HUP\n        echo\n        ;;\n  status)\n        status vtund\n        ;;\n  *)\n        echo \"Usage: vtund {start|stop|restart|status}\"\n        exit 1\nesac\n\nexit 0\n\n\n"
  },
  {
    "path": "scripts/vtund.rc.suse",
    "content": "#!/bin/sh\n#\n# Script for starting and stoping vtund.\n#\n# Writen by Dag Wieers <dag@mind.be>.\n# Updated by willems luc <willems.luc@pandora.be> 02-10-2002\n#\n### BEGIN INIT INFO\n# Provides: vtunnel\n# Required-Start: $remote_fs $syslog $network\n# Required-Stop:  $remote_fs $syslog $network\n# Default-Start:  3 5\n# Default-Stop:   0 1 2 6\n# Description:    Start vtunnel.\n### END INIT INFO\n\n# Source SuSE config\n. /etc/rc.config\n\n# Determine the base and follow a runlevel link name.\nbase=${0##*/}\nlink=${base#*[SK][0-9][0-9]}\n\n# Force execution if not called by a runlevel directory.\ntest $link = $base && START_VTUNNEL=yes\ntest \"$START_VTUNNEL\" = yes || exit 0\n\nVTUND_BIN=/usr/sbin/vtund\ntest -x $VTUND_BIN || exit 5\n\n# Shell functions sourced from /etc/rc.status:\n#      rc_check         check and set local and overall rc status\n#      rc_status        check and set local and overall rc status\n#      rc_status -v     ditto but be verbose in local rc status\n#      rc_status -v -r  ditto and clear the local rc status\n#      rc_failed        set local and overall rc status to failed\n#      rc_failed <num>  set local and overall rc status to <num><num>\n#      rc_reset         clear local rc status (overall remains)\n#      rc_exit          exit appropriate to overall rc status\n. /etc/rc.status\n\n# First reset status of this service\nrc_reset\n\n# Return values acc. to LSB for all commands but status:\n# 0 - success\n# 1 - generic or unspecified error\n# 2 - invalid or excess argument(s)\n# 3 - unimplemented feature (e.g. \"reload\")\n# 4 - insufficient privilege\n# 5 - program is not installed\n# 6 - program is not configured\n# 7 - program is not running\n# \n# Note that starting an already running service, stopping\n# or restarting a not-running service as well as the restart\n# with force-reload (in case signalling is not supported) are\n# considered a success.\n\n# chkconfig: 345 55 45\n# description: vtund Virtual Tunnel Daemon.\n#    VTun provides the method for creating Virtual Tunnels \n#    over TCP/IP networks and allows to shape, compress, encrypt \n#    traffic in that tunnels.\n\n\n# See how we were called.\ncase \"$1\" in\n  start)\n        echo -n \"Starting service vtund\"\n        startproc /usr/sbin/vtund -s\n        touch /var/lock/subsys/vtund\n\trc_status -v\t\n        ;;\n  stop)\n        echo -n \"Shutting down service vtund\"\n        killproc -TERM /usr/sbin/vtund || return=$rc_failed\n        rm -f /var/lock/subsys/vtund\n\trc_status -v\t\n        ;;\n  try-restart)\n\t## Stop the service and if this succeeds (i.e. the\n\t## service was running before), start it again.\n\t$0 stop  &&  $0 start\n\n\t# Remember status and be quiet\n\trc_status\n\t;;\n  reload|restart)\n\t## Stop the service and regardless of whether it was\n\t## running or not, start it again.\n\t$0 stop\n\t$0 start\n\n\t# Remember status and be quiet\n\trc_status\n\t;;\n  status)\n        echo -n \"Checking for service vtund: \"\n        checkproc /usr/sbin/vtund && echo OK || echo No process\n        ;;\n  *)\n        echo \"Usage: vtund {start|stop|reload|try-restart|restart|status}\"\n        exit 1\nesac\n\nrc_exit\n\n"
  },
  {
    "path": "scripts/vtund.rc.suse.config",
    "content": "#\n# Start VTunnel daemon ? (yes/no)\n#\nSTART_VTUNNEL=no\n"
  },
  {
    "path": "scripts/vtund.xinetd",
    "content": "service unlisted\n{\n        type                    = UNLISTED\n        port                    = 5000\n        socket_type             = stream\n        protocol                = tcp\n        wait                    = no\n        user                    = root\n        server                  = /usr/local/sbin/vtund\n        server_args             = -i\n        disable                 = yes\n#\tbind\t\t\t= aa.bb.cc.dd\n}\n"
  },
  {
    "path": "server.c",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * server.c,v 1.4.2.5.2.4 2006/11/16 04:03:53 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <signal.h>\n#include <fcntl.h>\n#include <syslog.h>\n#include <sys/socket.h>\n#include <sys/time.h>\n#include <sys/resource.h>\n\n#ifdef DEBUGG\n#include <sys/types.h>\n#include <sys/gmon.h>\n#endif\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\n#ifdef HAVE_NETINET_TCP_H\n#include <netinet/tcp.h>\n#endif\n\n#ifdef HAVE_ARPA_INET_H\n#include <arpa/inet.h>\n#endif\n\n#include \"vtun.h\"\n#include \"lib.h\"\n#include \"log.h\"\n#include \"lock.h\"\n#include \"auth.h\"\n#include \"netlib.h\"\n\n#include \"compat.h\"\n\nchar process_string[100] = { 0 };\nstruct conn_info* shm_conn_info = NULL;\nint shmid = 0;\n\nstatic volatile sig_atomic_t server_term;\nstatic void sig_term(int sig) {\n    if (shmid != 0) {\n        if (shmctl(shmid, IPC_RMID, NULL ) == -1) {\n            vlog(LOG_INFO, \"shm destroy fail; reason %s (%d)\", strerror(errno), errno);\n        } else {\n            vlog(LOG_INFO, \"shm destroy mark\");\n        }\n    } else {\n        if ((shmid = shmget(vtun.shm_key, sizeof(struct conn_info) * vtun.MAX_TUNNELS_NUM, 0666)) < 0) {\n            vlog(LOG_ERR, \"SHM buffer for key %d not found\", vtun.shm_key);\n        } else {\n            if (shmctl(shmid, IPC_RMID, NULL ) == -1) {\n                vlog(LOG_INFO, \"shm destroy fail; reason %s (%d)\", strerror(errno), errno);\n            }\n        }\n    }\n    if (shm_conn_info != NULL ) {\n\n        if (shmdt(shm_conn_info) == -1) {\n            vlog(LOG_INFO, \"Detach shm fail; reason %s (%d)\", strerror(errno), errno);\n        } else {\n            vlog(LOG_INFO, \"shm detached\");\n        }\n\n    }\n    vlog(LOG_INFO, \"Terminated\");\n    server_term = VTUN_SIG_TERM;\n}\n\nvoid connection(int sock, sem_t *shm_sem)\n{\n#ifndef CLIENTONLY\n    struct sockaddr_in my_addr, cl_addr;\n    struct vtun_host *host;\n    struct sigaction sa;\n    char *ip;\n    int opt;\n    int reason = 0;\n\n    opt = sizeof(struct sockaddr_in);\n    if ( getpeername(sock, (struct sockaddr *) &cl_addr, &opt) ) {\n        vlog(LOG_ERR, \"Can't get peer name\");\n        exit(1);\n    }\n    opt = sizeof(struct sockaddr_in);\n    if ( getsockname(sock, (struct sockaddr *) &my_addr, &opt) < 0 ) {\n        vlog(LOG_ERR, \"Can't get local socket address\");\n        exit(1);\n    }\n\n    ip = strdup(inet_ntoa(cl_addr.sin_addr));\n\n    io_init();\n\n    if ( (host = auth_server(sock, &reason)) ) {\n        sa.sa_handler = SIG_IGN;\n        sa.sa_flags = SA_NOCLDWAIT;;\n        sigaction(SIGHUP, &sa, NULL);\n\n        sprintf(process_string, \"vtrunkd %s\", host->host);\n        vlog(LOG_INFO, \"Change title with: %s\", process_string);\n        vlog_close();\n\n        vlog_open(host->host, LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);\n        vlog(LOG_ERR, \"Session %s[%s:%d] opened (build %s)\", host->host, ip, ntohs(cl_addr.sin_port), BUILD_DATE);\n\n        host->rmt_fd = sock;\n\n        host->sopt.laddr = strdup(inet_ntoa(my_addr.sin_addr));\n        host->sopt.lport = vtun.bind_addr.port;\n        host->sopt.raddr = strdup(ip);\n        host->sopt.rport = ntohs(cl_addr.sin_port);\n        host->start_port = vtun.start_port;\n        host->end_port = vtun.end_port;\n        /* Start tunnel */\n        tunnel(host, 1, shm_sem);\n\n        vlog(LOG_ERR, \"Session %s closed\", host->host);\n\n        /* Unlock host. (locked in auth_server) */\n        unlock_host(host);\n    } else {\n        vlog(LOG_INFO, \"Denied connection from %s:%d, reason: %d\", ip,\n                    ntohs(cl_addr.sin_port), reason );\n    }\n    close(sock);\n#endif\n    exit(0);\n}\n\nvoid listener(void)\n{\n    struct sigaction sa;\n    struct sockaddr_in my_addr, cl_addr;\n    int s, s1, opt;\n\n    memset(&my_addr, 0, sizeof(my_addr));\n    my_addr.sin_family = AF_INET;\n\n    /* Set listen address */\n    if ( generic_addr(&my_addr, &vtun.bind_addr) < 0)\n    {\n        vlog(LOG_ERR, \"Can't fill in listen socket\");\n        exit(1);\n    }\n\n    if ( (s = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {\n        vlog(LOG_ERR, \"Can't create socket\");\n        exit(1);\n    }\n\n    opt = 1;\n    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));\n\n    if ( bind(s, (struct sockaddr *)&my_addr, sizeof(my_addr)) ) {\n        vlog(LOG_ERR, \"Can't bind to the socket\");\n        exit(1);\n    }\n\n    if ( listen(s, 10) ) {\n        vlog(LOG_ERR, \"Can't listen on the socket\");\n        exit(1);\n    }\n\n    memset(&sa, 0, sizeof(sa));\n    sa.sa_flags = SA_NOCLDWAIT;\n    sa.sa_handler = sig_term;\n    sigaction(SIGTERM, &sa, NULL);\n    sigaction(SIGINT, &sa, NULL);\n    // WARNING: signals should be re-checked before using!\n    server_term = 0;\n\n    set_title(\"waiting for connections on port %d\", vtun.bind_addr.port);\n\n    // now init everything...\n    key_t key;\n    /*\n    * We'll name our shared memory segment\n    * defaul is 567888\n    */\n    key = vtun.shm_key;\n\n    /*\n    * Create the segment.\n    */\n    // TODO: do not allocate all memory at once!!!!\n    if ((shmid = shmget(key, sizeof(struct conn_info) * vtun.MAX_TUNNELS_NUM, IPC_CREAT | 0666)) < 0) {\n        vlog(LOG_ERR, \"Can not allocate SHM buffer of size %d. Please check your system shmmax or use 'ipcrm' to remove stale SHMs\", sizeof(struct conn_info) * vtun.MAX_TUNNELS_NUM);\n        exit(1);\n    }\n\n    /*\n    * Now we attach the segment to our data space.\n    */\n    if ((shm_conn_info = shmat(shmid, NULL, 0)) == (struct conn_info *) - 1) {\n        vlog(LOG_ERR, \"shmat 1\");\n        exit(1);\n    }\n\n    memset(shm_conn_info, 0, sizeof(struct conn_info) * vtun.MAX_TUNNELS_NUM);\n    \n    char semname[255];\n    sprintf(semname, \"/vtrunkd_%d\", vtun.shm_key);\n    sem_t *shm_sem;\n    if ((shm_sem = sem_open(semname, O_CREAT, 0644, 1)) == SEM_FAILED) {\n        perror(\"shm semaphore initilization\");\n        exit(1);\n    }\n    sem_init(&shm_sem, 1, 1);\n\n    while ( (!server_term) || (server_term == VTUN_SIG_HUP) ) {\n        opt = sizeof(cl_addr);\n        if ( (s1 = accept(s, (struct sockaddr *)&cl_addr, &opt)) < 0 )\n            continue;\n\n        switch ( fork() ) {\n        case 0:\n            close(s);\n#ifdef DEBUGG\n            // now init the profiler; don;t forget to set GMON_OUT_PREFIX\n            extern void _start (void), etext (void);\n            monstartup ((u_long) &_start, (u_long) &etext);\n#endif\n            struct rlimit core_limit;\n            core_limit.rlim_cur = RLIM_INFINITY;\n            core_limit.rlim_max = RLIM_INFINITY;\n\n            if (setrlimit(RLIMIT_CORE, &core_limit) < 0) {\n                vlog(LOG_ERR, \"setrlimit: Warning: core dumps may be truncated or non-existant reason %s (%d)\", strerror(errno), errno);\n            }\n            connection(s1, shm_sem);\n            break;\n        case -1:\n            vlog(LOG_ERR, \"Couldn't fork()\");\n        default:\n            close(s1);\n            // normal cont\n            break;\n        }\n    }\n\n    shmctl(key, IPC_RMID, NULL);\n\n    vlog(LOG_INFO, \"SERVER QUIT %d\", server_term);\n}\n\nvoid server(int sock)\n{\n    struct sigaction sa;\n\n    sa.sa_handler = SIG_IGN;\n    sa.sa_flags = SA_NOCLDWAIT;;\n    sigaction(SIGINT, &sa, NULL);\n    sigaction(SIGQUIT, &sa, NULL);\n    sigaction(SIGCHLD, &sa, NULL);\n    sigaction(SIGPIPE, &sa, NULL);\n    sigaction(SIGUSR1, &sa, NULL);\n    sigaction(SIGUSR2, &sa, NULL);\n\n    vlog(LOG_INFO, \"vtrunkd server ver %s %s (%s)\", VTUN_VER, BUILD_DATE,\n                vtun.svr_type == VTUN_INETD ? \"inetd\" : \"stand\" );\n\n    switch ( vtun.svr_type ) {\n    case VTUN_STAND_ALONE:\n        listener();\n        break;\n    case VTUN_INETD:\n        connection(sock, NULL);\n        break;\n    }\n}\n"
  },
  {
    "path": "speed_algo.c",
    "content": "/*\n * speed_algo.c\n *\n *  Created on: 22.01.2013\n *      Author: Vrayo Systems Ltd. team\n */\n\n#include <sys/time.h>\n#include <syslog.h>\n#include <stdint.h>\n#include \"speed_algo.h\"\n#include \"lib.h\"\n\n/**\n * Function for ACK_coming_speed = bytes_acked/time.\n * Idea - was + more = now + acked --> acked = was + more - now\n *\n * @param time_start\n * @param time_stop\n * @param byte_was\n * @param byte_now\n * @param byte_more\n * @return speed or error -1 - byte_more overflow, -2 - bad measure or speed --> 0, -3 - high speed, need wait one more time\n */\nint speed_algo_ack_speed(struct timeval *time_start, struct timeval *time_stop, int byte_was, int byte_now, int byte_more, int min_time_usec) {\n    int speed = 0;\n    struct timeval time_passed;\n    timersub(time_stop, time_start, &time_passed);\n#ifdef DEBUGG\n    vtun_syslog(LOG_INFO,\"was %i + more %i == acked %i + now %i  / time_passed - %ul s %ul us, min_time_usec = %i\", byte_was, byte_more,byte_was + byte_more - byte_now, byte_now, time_passed.tv_sec, time_passed.tv_usec, min_time_usec);\n#endif\n    if (byte_more < 0) {\n        return SPEED_ALGO_OVERFLOW;\n    }\n    int byte_acked = byte_was + byte_more - byte_now;\n    if (byte_acked <= 1000) {\n        if (timercmp(&time_passed, &((struct timeval) {SPEED_ALGO_EPIC_TIME_S, SPEED_ALGO_EPIC_TIME_US}), <)) {\n            return SPEED_ALGO_SLOW_SPEED;\n        } else {\n            return SPEED_ALGO_EPIC_SLOW;\n        }\n    }\n    if (timercmp(&time_passed, &((struct timeval) {0, min_time_usec}), <)) {\n        return SPEED_ALGO_HIGH_SPEED;\n    }\n    int time_passed_ms = time_passed.tv_sec * (1000000/100); // in ms*10\n    time_passed_ms += time_passed.tv_usec / 100;\n    speed = (byte_acked * 10) / time_passed_ms;\n#ifdef TRACE\n    vtun_syslog(LOG_INFO,\"speed_moment - %i\", speed);\n#endif\n    return speed;\n}\n\n/**\n * Function for ACK_coming_speed averaging\n * @param arr\n * @param arr_size - size of *arr\n * @param new_speed - new value which will be add\n * @param counter - current pointer in *arr\n * @return speed average\n */\nint speed_algo_avg_speed(int32_t *arr, int arr_size, int new_speed, int *counter) {\n    int speed_avg = 0;\n#ifdef TRACE\n    vtun_syslog(LOG_INFO,\"new_speed - %i counter - %i\",new_speed, *counter);\n#endif\n    (*counter)++;\n    *counter = *counter == arr_size ? 0 : *counter;\n    arr[*counter] = new_speed;\n    for (int i = 0; i < arr_size; i++) {\n#ifdef TRACE\n        vtun_syslog(LOG_INFO,\"speed[%i] - %i\",i, arr[i] );\n#endif\n        speed_avg += arr[i] * 100 / arr_size;\n    }\n    return speed_avg / 100;\n}\n\n"
  },
  {
    "path": "speed_algo.h",
    "content": "/*\n * speed_algo.h\n *\n *  Created on: 22.01.2013\n *      Author: Vrayo Systems Ltd. team\n */\n\n#ifndef SPEED_ALGO_H_\n#define SPEED_ALGO_H_\n\n#include <sys/time.h>\n#include <stdint.h>\n\n#define SPEED_ALGO_SLOW_SPEED -1\n#define SPEED_ALGO_OVERFLOW -2\n#define SPEED_ALGO_HIGH_SPEED -3\n#define SPEED_ALGO_EPIC_SLOW -4\n\n#define SPEED_ALGO_EPIC_TIME_S 2\n#define SPEED_ALGO_EPIC_TIME_US 0\n\nstruct speed_algo_rtt_speed {\n    int rtt;\n    int speed;\n};\n\nint speed_algo_ack_speed(struct timeval *time_start, struct timeval *time_stop, int byte_was, int byte_now, int byte_more, int min_time_usec);\nint speed_algo_avg_speed(int32_t *arr, int arr_size, int new_speed, int *counter);\n\n#endif /* SPEED_ALGO_H_ */\n"
  },
  {
    "path": "svr4/tap_dev.c",
    "content": "/*  \n    VTun - Virtual Tunnel over TCP/IP network.\n\n    Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n    VTun has been derived from VPPP package by Maxim Krasnyansky. \n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n */\n\n/*\n * tap_dev.c,v 1.1.1.1.2.2.2.1 2006/11/16 04:05:08 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <stdarg.h>\n#include <sys/time.h>\n#include <sys/wait.h>\n#include <syslog.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/ioctl.h>\n#include <errno.h>\n#include <signal.h>\n#include <stropts.h>\n#include <net/if.h>\n#include <net/if_tun.h>\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\n#ifdef HAVE_NETINET_IN_SYSTM_H\n#include <netinet/in_systm.h>\n#endif\n\n#ifdef HAVE_NETINET_IP_H\n#include <netinet/ip.h>\n#endif\n\n#ifdef HAVE_NETINET_TCP_H\n#include <netinet/tcp.h>\n#endif\n\n#include \"vtun.h\"\n#include \"lib.h\"\n\n/* \n * Allocate Ether TAP device, returns opened fd. \n * Stores dev name in the first arg(must be large enough).\n */ \nint tap_open(char *dev)\n{\n    int tap_fd, if_fd, ppa = -1;\n    static int ip_fd = 0;\n    char *ptr;\n\n    if( *dev ){\n       ptr = dev;\t\n       while( *ptr && !isdigit((int)*ptr) ) ptr++; \n       ppa = atoi(ptr);\n    }\n\n    /* Check if IP device was opened */\n    if( ip_fd )\n       close(ip_fd);\n\n    if( (ip_fd = open(\"/dev/ip\", O_RDWR, 0)) < 0){\n       syslog(LOG_ERR, \"Can't open /dev/ip\");\n       return -1;\n    }\n\n    if( (tap_fd = open(\"/dev/tap\", O_RDWR, 0)) < 0){\n       syslog(LOG_ERR, \"Can't open /dev/tap\");\n       return -1;\n    }\n\n    /* Assign a new PPA and get its unit number. */\n    if( (ppa = ioctl(tap_fd, TUNNEWPPA, ppa)) < 0){\n       syslog(LOG_ERR, \"Can't assign new interface\");\n       return -1;\n    }\n\n    if( (if_fd = open(\"/dev/tap\", O_RDWR, 0)) < 0){\n       syslog(LOG_ERR, \"Can't open /dev/tap (2)\");\n       return -1;\n    }\n    if(ioctl(if_fd, I_PUSH, \"ip\") < 0){\n       syslog(LOG_ERR, \"Can't push IP module\");\n       return -1;\n    }\n\n    /* Assign ppa according to the unit number returned by tap device */\n    if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0){\n       syslog(LOG_ERR, \"Can't set PPA %d\", ppa);\n       return -1;\n    }\n    if(ioctl(ip_fd, I_LINK, if_fd) < 0){\n       syslog(LOG_ERR, \"Can't link TAP device to IP\");\n       return -1;\n    }\n\n    sprintf(dev, \"tap%d\", ppa);\n    return tap_fd;\n}\n\nint tap_close(int fd, char *dev)\n{\n    return close(fd);\n}\n\nint tap_write(int fd, char *buf, int len)\n{\n    struct strbuf sbuf;\n    sbuf.len = len;      \n    sbuf.buf = buf;      \n    return putmsg(fd, NULL, &sbuf, 0) >= 0 ? sbuf.len : -1;\n}\n\nint tap_read(int fd, char *buf, int len)\n{\n    struct strbuf sbuf;\n    int f = 0;\n\n    sbuf.maxlen = len;      \n    sbuf.buf = buf;      \n    return getmsg(fd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1;\n}\n"
  },
  {
    "path": "svr4/tun_dev.c",
    "content": "/*  \n    VTun - Virtual Tunnel over TCP/IP network.\n\n    Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n    VTun has been derived from VPPP package by Maxim Krasnyansky. \n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n */\n\n/*\n * tun_dev.c,v 1.2.2.2.2.1 2006/11/16 04:05:18 mtbishop Exp\n */ \n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <stdarg.h>\n#include <sys/time.h>\n#include <sys/wait.h>\n#include <syslog.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/sockio.h>\n#include <sys/ioctl.h>\n#include <errno.h>\n#include <signal.h>\n#include <stropts.h>\n#include <net/if.h>\n#include <net/if_tun.h>\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\n#ifdef HAVE_NETINET_IN_SYSTM_H\n#include <netinet/in_systm.h>\n#endif\n\n#ifdef HAVE_NETINET_IP_H\n#include <netinet/ip.h>\n#endif\n\n#ifdef HAVE_NETINET_TCP_H\n#include <netinet/tcp.h>\n#endif\n\n#include \"vtun.h\"\n#include \"lib.h\"\n\nstatic int ip_fd = -1;\n\n/* \n * Allocate TUN device, returns opened fd. \n * Stores dev name in the first arg(must be large enough).\n */  \nint tun_open(char *dev)\n{\n    int tun_fd, if_fd, muxid, ppa = -1;\n    struct ifreq ifr;\n    char *ptr;\n\n    if( *dev ){\n       ptr = dev;\t\n       while( *ptr && !isdigit((int)*ptr) ) ptr++; \n       ppa = atoi(ptr);\n    }\n\n    if( (ip_fd = open(\"/dev/udp\", O_RDWR, 0)) < 0){\n       syslog(LOG_ERR, \"Can't open /dev/ip\");\n       return -1;\n    }\n\n    if( (tun_fd = open(\"/dev/tun\", O_RDWR, 0)) < 0){\n       syslog(LOG_ERR, \"Can't open /dev/tun\");\n       return -1;\n    }\n\n    /* Assign a new PPA and get its unit number. */\n    if( (ppa = ioctl(tun_fd, TUNNEWPPA, ppa)) < 0){\n       syslog(LOG_ERR, \"Can't assign new interface\");\n       return -1;\n    }\n\n    if( (if_fd = open(\"/dev/tun\", O_RDWR, 0)) < 0){\n       syslog(LOG_ERR, \"Can't open /dev/tun (2)\");\n       return -1;\n    }\n    if(ioctl(if_fd, I_PUSH, \"ip\") < 0){\n       syslog(LOG_ERR, \"Can't push IP module\");\n       return -1;\n    }\n\n    /* Assign ppa according to the unit number returned by tun device */\n    if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0){\n       syslog(LOG_ERR, \"Can't set PPA %d\", ppa);\n       return -1;\n    }\n    if( (muxid = ioctl(ip_fd, I_PLINK, if_fd)) < 0){\n       syslog(LOG_ERR, \"Can't link TUN device to IP\");\n       return -1;\n    }\n    close(if_fd);    \n\n    sprintf(dev, \"tun%d\", ppa);\n\n    memset(&ifr, 0, sizeof(ifr));\n    strcpy(ifr.ifr_name, dev);\n    ifr.ifr_ip_muxid = muxid;\n\n    if( ioctl(ip_fd, SIOCSIFMUXID, &ifr) < 0 ){\n       ioctl(ip_fd, I_PUNLINK, muxid);\n       syslog(LOG_ERR, \"Can't set multiplexor id\");\n       return -1;\n    }\n\n    return tun_fd;\n}\n\n/* \n * Close TUN device. \n */  \nint tun_close(int fd, char *dev)\n{\n    struct ifreq ifr;\n\n    memset(&ifr, 0, sizeof(ifr));\n    strcpy(ifr.ifr_name, dev);\n    if( ioctl(ip_fd, SIOCGIFFLAGS, &ifr) < 0 ){\n       syslog(LOG_ERR, \"Can't get iface flags\");\n       return 0;\n    }\n\n    if( ioctl(ip_fd, SIOCGIFMUXID, &ifr) < 0 ){\n       syslog(LOG_ERR, \"Can't get multiplexor id\");\n       return 0;\n    }\n\n    if( ioctl(ip_fd, I_PUNLINK, ifr.ifr_ip_muxid) < 0 ){\n       syslog(LOG_ERR, \"Can't unlink interface\");\n       return 0;\n    }\n\n    close(ip_fd); close(fd);\n    return 0;\n}\n\nint tun_write(int fd, char *buf, int len)\n{\n    struct strbuf sbuf;\n    sbuf.len = len;      \n    sbuf.buf = buf;      \n    return putmsg(fd, NULL, &sbuf, 0) >=0 ? sbuf.len : -1;\n}\n\nint tun_read(int fd, char *buf, int len)\n{\n    struct strbuf sbuf;\n    int f = 0;\n\n    sbuf.maxlen = len;      \n    sbuf.buf = buf;      \n    return getmsg(fd, NULL, &sbuf, &f) >=0 ? sbuf.len : -1;\n}\n"
  },
  {
    "path": "test/lossed.c",
    "content": "/*\n Detected loss +-1 by REORDER lsn: 6495; last lsn: 6489, sqn: 1\n2884, lsq before loss 6489\n lossed buffer: complete: 15 lsn 6495, last: 15 lsn 6495\n > 0 lsn 6480, sn 12869\n > 1 lsn 6481, sn 12870\n > 2 lsn 6482, sn 12871\n > 3 lsn 6483, sn 12872\n > 4 lsn 6484, sn 12873\n > 5 lsn 6485, sn 12874\n > 6 lsn 6486, sn 12875\n > 7 lsn 6487, sn 12876\n > 8 lsn 6488, sn 12877\n > 9 lsn 6489, sn 12878\n > 10 lsn 6470, sn 12859\n > 11 lsn 6471, sn 12860\n > 12 lsn 6472, sn 12861\n > 13 lsn 6473, sn 12862\n > 14 lsn 6474, sn 12863\n > 15 lsn 6495, sn 12884                                       \n > 16 lsn 6476, sn 12865                                       \n > 17 lsn 6477, sn 12866                                       \n > 18 lsn 6478, sn 12867                                       \n > 19 lsn 6479, sn 12868                                       \n sedning loss -1 lrs 12884, llrs 6495         \n\n*/\n\n#include <stdio.h>\n\nstruct {\n    int lossed_complete_received;\n    int lossed_last_received;\n    struct {\n        int local_seq_num;\n        int seq_num;\n    } lossed_loop_data[10];\n} info;\n\nint lossed_count() {\n    int cnt = 0;\n    int idx_prev = info.lossed_complete_received;\n    int idx = idx_prev;\n    unsigned int old_lsn = info.lossed_loop_data[idx].local_seq_num;\n    int pkt_shift = 1;\n    while(idx != info.lossed_last_received) {\n        idx++;\n        if(idx >= LOSSED_BACKLOG_SIZE) idx = 0;\n        if((info.lossed_loop_data[info.lossed_complete_received].local_seq_num + pkt_shift) == info.lossed_loop_data[idx].local_seq_num) {\n            // ok\n        } else {\n            cnt++;\n        }\n        idx_prev = idx;\n        pkt_shift++;\n    }\n    return cnt - 1; // last one is for vendetta!\n}\n\n\nint is_loss() {\n    if(info.lossed_last_received != info.lossed_complete_received) {\n        return 1;\n    }\n    return 0;\n}\n\nint main(int argc, char **argv) {\n    info.lossed_complete_received = 4;\n    info.lossed_last_received = 8;\n    info.lossed_loop_data = { \n        { 6480, 12869 },\n        { 6481, 12870 },\n        { 6482, 12871 },\n        { 6483, 12872 },\n        { 6484, 12873 },\n        { 6470, 12859 },\n        { 6471, 12860 },\n        { 6472, 12861 },\n        { 6485, 12869 },\n        { 6465, 12869 }\n    };\n    printf(\"count %d\", lossed_count());\n    return 0;\n}\n"
  },
  {
    "path": "timer.c",
    "content": "/*\n * timer.c\n *\n *  Created on: 11.12.2013\n *      Author: Vrayo Systems Ltd. team\n */\n\n#include <sys/time.h>\n#include <string.h>\n#include <stdlib.h>\n#include \"timer.h\"\n\nstruct timer_obj* create_timer() {\n    return malloc(sizeof(struct timer_obj));\n}\n\nvoid free_timer(struct timer_obj *timer) {\n    free(timer);\n}\n\nvoid set_timer(struct timer_obj *timer, struct timeval *timer_time) {\n    memset(timer, 0, sizeof(struct timer_obj));\n    gettimeofday(&(timer->start_time), NULL );\n    memcpy(&(timer->timer_time), timer_time, sizeof(struct timeval));\n}\n\nvoid update_timer(struct timer_obj *timer){\n    gettimeofday(&(timer->start_time), NULL );\n}\n\nvoid fast_update_timer(struct timer_obj *timer, struct timeval *cur_time){\n    timer->start_time.tv_sec = cur_time->tv_sec;\n    timer->start_time.tv_usec = cur_time->tv_usec;\n}\n\nint check_timer(struct timer_obj *timer) {\n    gettimeofday(&timer->cur_time, NULL );\n    timersub(&(timer->cur_time), &(timer->start_time), &(timer->tmp));\n    return timercmp(&(timer->timer_time), &(timer->tmp), <=);\n}\n\nint fast_check_timer(struct timer_obj *timer, struct timeval *cur_time){\n    timersub(cur_time, &(timer->start_time), &(timer->tmp));\n    return timercmp(&(timer->timer_time), &(timer->tmp), <=);\n}\n\nstruct timeval* get_difference_timer(struct timer_obj *timer, struct timeval *cur_time) {\n    timersub(cur_time, &(timer->start_time), &(timer->tmp));\n    return &(timer->tmp);\n}\n\n"
  },
  {
    "path": "timer.h",
    "content": "/*\n * timer.h\n *\n *  Created on: 11.12.2013\n *      Author: Vrayo Systems Ltd. team\n */\n\n#ifndef TIMER_H_\n#define TIMER_H_\n\n#include <sys/time.h>\n\nstruct timer_obj {\n    struct timeval start_time;\n    struct timeval timer_time;\n    struct timeval cur_time;\n    struct timeval tmp;\n};\n\nstruct timer_obj* create_timer();\nvoid free_timer(struct timer_obj *timer);\n\nvoid set_timer(struct timer_obj *timer, struct timeval *timer_time);\nvoid update_timer(struct timer_obj *timer);\nvoid fast_update_timer(struct timer_obj *timer, struct timeval *cur_time);\nint check_timer(struct timer_obj *timer);\nint fast_check_timer(struct timer_obj *timer, struct timeval *cur_time);\nstruct timeval* get_difference_timer(struct timer_obj *timer, struct timeval *cur_time);\n\n#endif /* TIMER_H_ */\n"
  },
  {
    "path": "tunnel.c",
    "content": "/*\n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network.\n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky.\n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * tunnel.c,v 1.5.2.8.2.2 2006/11/16 04:03:56 mtbishop Exp\n */\n\n#include \"config.h\"\n\n#include <unistd.h>\n#include <fcntl.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <stdarg.h>\n#include <sys/time.h>\n#include <sys/wait.h>\n#include <syslog.h>\n#include <signal.h>\n#include <sys/resource.h>\n\n#include <sys/types.h>   /* basic system data types */\n#include <sys/socket.h>  /* basic socket definitions */\n#include <sys/time.h>    /* timeval{} for select() */\n#include <time.h>                /* timespec{} for pselect() */\n#include <netinet/in.h>  /* sockaddr_in{} and other Internet defns */\n#include <arpa/inet.h>   /* inet(3) functions */\n#include <errno.h>\n#include <fcntl.h>               /* for nonblocking */\n#include <netdb.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>    /* for S_xxx file mode constants */\n#include <sys/uio.h>             /* for iovec{} and readv/writev */\n#include <unistd.h>\n#include <sys/wait.h>\n#include <sys/un.h>              /* for Unix domain sockets */\n\n#include <sys/ioctl.h>\n#include <net/if.h>\n\n#include <semaphore.h>\n\n#ifdef HAVE_NETINET_IN_H\n#include <netinet/in.h>\n#endif\n\n#ifdef HAVE_NETINET_IN_SYSTM_H\n#include <netinet/in_systm.h>\n#endif\n\n#ifdef HAVE_NETINET_IP_H\n#include <netinet/ip.h>\n#endif\n\n#ifdef HAVE_NETINET_TCP_H\n#include <netinet/tcp.h>\n#endif\n\n#include \"vtun.h\"\n#include \"linkfd.h\"\n#include \"lib.h\"\n#include \"log.h\"\n#include \"netlib.h\"\n#include \"driver.h\"\n\nint (*dev_write)(int fd, char *buf, int len);\nint (*dev_read)(int fd, char *buf, int len);\n\nint (*proto_write)(int fd, char *buf, int len);\nint (*proto_read)(int fd, char *buf);\n\nint fdserver_term = 0;\n\nssize_t\nread_fd(int fd, void *ptr, size_t nbytes, int *recvfd)\n{\n    struct msghdr   msg;\n    struct iovec    iov[1];\n    ssize_t         n;\n    int             newfd;\n\n#ifdef  HAVE_MSGHDR_MSG_CONTROL\n    union {\n        struct cmsghdr    cm;\n        char              control[CMSG_SPACE(sizeof(int))];\n    } control_un;\n    struct cmsghdr  *cmptr;\n\n    msg.msg_control = control_un.control;\n    msg.msg_controllen = sizeof(control_un.control);\n#else\n    msg.msg_accrights = (caddr_t) &newfd;\n    msg.msg_accrightslen = sizeof(int);\n#endif\n\n    msg.msg_name = NULL;\n    msg.msg_namelen = 0;\n\n    iov[0].iov_base = ptr;\n    iov[0].iov_len = nbytes;\n    msg.msg_iov = iov;\n    msg.msg_iovlen = 1;\n\n    if ( (n = recvmsg(fd, &msg, 0)) <= 0)\n        return (n);\n\n#ifdef  HAVE_MSGHDR_MSG_CONTROL\n    if ( (cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&\n            cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {\n        if (cmptr->cmsg_level != SOL_SOCKET) {\n            vlog(LOG_ERR, \"control level != SOL_SOCKET\");\n            return -1;\n        }\n        if (cmptr->cmsg_type != SCM_RIGHTS) {\n            vlog(LOG_ERR, \"control type != SCM_RIGHTS\");\n            return -1;\n        }\n        *recvfd = *((int *) CMSG_DATA(cmptr));\n    } else\n        *recvfd = -1;       /* descriptor was not passed */\n#else\n/* *INDENT-OFF* */\n    if (msg.msg_accrightslen == sizeof(int))\n        *recvfd = newfd;\n    else\n        *recvfd = -1;       /* descriptor was not passed */\n/* *INDENT-ON* */\n#endif\n\n    return (n);\n}\n/* end read_fd */\n\nssize_t\nwrite_fd(int fd, void *ptr, size_t nbytes, int sendfd)\n{\n    struct msghdr   msg;\n    struct iovec    iov[1];\n\n#ifdef  HAVE_MSGHDR_MSG_CONTROL\n    union {\n        struct cmsghdr    cm;\n        char              control[CMSG_SPACE(sizeof(int))];\n    } control_un;\n    struct cmsghdr  *cmptr;\n\n    msg.msg_control = control_un.control;\n    msg.msg_controllen = sizeof(control_un.control);\n\n    cmptr = CMSG_FIRSTHDR(&msg);\n    cmptr->cmsg_len = CMSG_LEN(sizeof(int));\n    cmptr->cmsg_level = SOL_SOCKET;\n    cmptr->cmsg_type = SCM_RIGHTS;\n    *((int *) CMSG_DATA(cmptr)) = sendfd;\n#else\n    msg.msg_accrights = (caddr_t) &sendfd;\n    msg.msg_accrightslen = sizeof(int);\n#endif\n\n    msg.msg_name = NULL;\n    msg.msg_namelen = 0;\n\n    iov[0].iov_base = ptr;\n    iov[0].iov_len = nbytes;\n    msg.msg_iov = iov;\n    msg.msg_iovlen = 1;\n\n    return (sendmsg(fd, &msg, 0));\n}\n/* end write_fd */\n\nstatic void fd_server_term(int sig) {\n    fdserver_term = 1;\n    vlog(LOG_ERR, \"Received a SIGTERM! No connections possible after this message!\");\n}\n\nint run_fd_server(int fd, char * dev, struct conn_info *shm_conn_info, int srv, sem_t *shm_sem) {\n    int s, s2, t, len;\n    struct sockaddr_un local, remote;\n    char ptr;\n    int ptr_len = 1;\n    char str[100];\n    fd_set fdset;\n    struct timeval tv, cur_time;\n\n    struct sigaction sa;\n\n    memset(&sa, 0, sizeof(sa));\n    sa.sa_handler = fd_server_term;\n    sigaction(SIGTERM, &sa, NULL);\n\n    sa.sa_handler = SIG_DFL;\n    sa.sa_flags = SA_NOCLDWAIT;\n    sigaction(SIGINT, &sa, NULL);\n    sigaction(SIGQUIT, &sa, NULL);\n    sigaction(SIGKILL, &sa, NULL);\n    sigaction(SIGCHLD, &sa, NULL);\n\n    sigaction(SIGUSR1, &sa, NULL);\n    sigaction(SIGUSR2, &sa, NULL);\n\n// SIGPIPE is OK\n    sa.sa_handler = SIG_IGN;\n    sigaction(SIGPIPE, &sa, NULL);\n\n    openlog(\"vtrunkd\", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON);\n\n\n    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {\n        vlog(LOG_ERR, \"srv socket\");\n        return -1;\n    }\n\n    local.sun_family = AF_UNIX;\n    sprintf(local.sun_path, \"/tmp/vtrunkd_%s.socket\", dev);\n    unlink(local.sun_path);\n    len = strlen(local.sun_path) + sizeof(local.sun_family);\n    if (bind(s, (struct sockaddr *)&local, len) == -1) {\n        vlog(LOG_ERR, \"srv bind\");\n        return -1;\n    }\n\n    if (listen(s, 5) == -1) {\n        vlog(LOG_ERR, \"listen\");\n        return -1;\n    }\n\n    gettimeofday(&cur_time, NULL);\n\n    vlog(LOG_INFO, \"fd_server waiting for a connection...\\n\");\n    int select_counter = 0;\n    while (!fdserver_term) {\n        int done, n = 0, i;\n\n        FD_ZERO(&fdset);\n        FD_SET(s, &fdset);\n        tv.tv_sec  = 0;\n        tv.tv_usec = 500000;\n\n\n        shm_conn_info->rdy = 1;\n        if ( (len = select(s + 1, &fdset, NULL, NULL, &tv)) < 0 ) { // selecting from multiple processes does actually work...\n// errors are OK if signal is received... TODO: do we have any signals left???\n            if ( errno != EAGAIN && errno != EINTR ) {\n                vlog(LOG_INFO, \"fd_server eagain select err; exit\");\n                break;\n            } else {\n//vlog(LOG_INFO, \"fd_server else select err; continue norm\");\n                continue;\n            }\n        }\n        if (select_counter <= 10000) {\n            select_counter += 1;\n        }\n        if (FD_ISSET(s, &fdset)) {\n\n            t = sizeof(remote);\n\n            if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {\n                vlog(LOG_ERR, \"srv accept\");\n                return -1;\n            }\n\n            vlog(LOG_INFO, \"fd_server connected.\\n\");\n\n            done = 0;\n            do {\n\n                if (!done)\n                    if (write_fd(s2, &ptr, ptr_len, fd) < 0) {\n                        vlog(LOG_ERR, \"fd_srv send error\");\n                        done = 1;\n                    }\n                done = 1;\n            } while (!done);\n\n            close(s2);\n        } else if (select_counter > PROCESS_FD_SHM_TIMEOUT) {\n            gettimeofday(&cur_time, NULL);\n            if ( srv && ( (cur_time.tv_sec - shm_conn_info->alive) > PROCESS_FD_SHM_TIMEOUT )) {\n                sem_wait(shm_sem);\n                if(shm_conn_info->usecount == 0) {\n                    break;\n                } else {\n                    vlog(LOG_ERR, \"Process %s dead but usecount = %d, continuing\", dev, shm_conn_info->usecount);\n                }\n                sem_post(shm_sem);\n            }\n        }\n\n#ifdef SYSLOG\n        vlog_shm_process(shm_conn_info);\n#endif\n    }\n    \n    vlog(LOG_INFO, \"Killing old connections\");\n    /* Make sure it's dead */\n    for (int i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if (!(shm_conn_info->channels_mask & (1 << i))) {\n            continue;\n        }\n        if ((shm_conn_info->stats[i].pid > 0) && (kill(shm_conn_info->stats[i].pid, SIGKILL) == 0)) {\n            // if we do not kill - then zeroing SHM will cause deadlock\n            vlog(LOG_ERR, \"fd_server %s exiting; killed %d with SIGKILL\", dev, shm_conn_info->stats[i].pid);\n        }\n    }\n    // clean up\n    vlog(LOG_INFO, \"fd_server zeroing shm & exiting.\\n\");\n    memset(shm_conn_info, 0, sizeof(struct conn_info));\n    sem_post(shm_sem);\n    vlog(LOG_ERR, \"fd_server exit\");\n    exit(0);\n\n    return 0;\n}\n\nint read_fd_full(int *fd, char *dev) {\n    int s, len;\n    char ptr;\n    size_t ptr_len = 1;\n    struct sockaddr_un local, remote;\n\n    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {\n        vlog(LOG_ERR, \"cannot create socket for fd_server connection\");\n        return -1;\n    }\n    remote.sun_family = AF_UNIX;\n    sprintf(remote.sun_path, \"/tmp/vtrunkd_%s.socket\", dev);\n    len = strlen(remote.sun_path) + sizeof(remote.sun_family);\n    if (connect(s, (struct sockaddr *)&remote, len) == -1) {\n        vlog(LOG_ERR, \"can not connect to fd_server UNIX SOCKET %s \", remote.sun_path);\n        close(s); // dunno why this couls happen but anyways...\n        return -1;\n    }\n    read_fd(s, &ptr, ptr_len, fd);\n    close(s);\n}\n\n/* Initialize and start the tunnel.\n   Returns:\n      -1 - critical error\n      0  - normal close or noncritical error \n*/\n\nvoid release_shm(struct conn_info *shm_conn_info, sem_t *shm_sem, int connid) {\n    sem_wait(shm_sem);\n    shm_conn_info[connid].usecount--;\n    sem_post(shm_sem);\n}\n\nint tunnel(struct vtun_host *host, int srv, sem_t *shm_sem_unused)\n{\n    int null_fd, pid, opt, pid2;\n    int fd[2] = { -1, -1};\n    char dev[VTUN_DEV_LEN] = \"\";\n    int interface_already_open = 0;\n    int shmid, i;\n    struct sockaddr_un remote;\n    int connid = -1;\n    struct conn_info *shm_conn_info;\n    int my_conn_num = -1;\n    int s, s2, t, len;\n\n    char str[100];\n    \n    char semname[255];\n    sprintf(semname, \"/vtrunkd_%d\", vtun.shm_key);\n    sem_t *shm_sem;\n    if ((shm_sem = sem_open(semname, O_CREAT, 0644, 1)) == SEM_FAILED) {\n        vlog(LOG_ERR, \"shm semaphore initilization\");\n        exit(1);\n    }\n\n\n    if (host->persist == VTUN_PERSIST_KEEPIF) {\n        vlog(LOG_INFO, \"PERSIST enabled\");\n    } else {\n        vlog(LOG_INFO, \"PERSIST DIS-abled\");\n    }\n\n\n    if ( (host->persist == VTUN_PERSIST_KEEPIF) &&\n            (host->loc_fd >= 0) ) {\n        interface_already_open = 0; // always try to reopen interface since shm is always required to get!!\n        vlog(LOG_INFO, \"Reusing open fd(NOT:-)!\");\n    } else {\n        vlog(LOG_INFO, \"New fd required (%d) \", host->loc_fd);\n    }\n\n    /* Initialize device. */\n    if ( host->dev ) {\n        strncpy(dev, host->dev, VTUN_DEV_LEN);\n        dev[VTUN_DEV_LEN - 1] = '\\0';\n    }\n    if ( ! interface_already_open ) {\n        switch ( host->flags & VTUN_TYPE_MASK ) {\n        case VTUN_TTY:\n            if ( (fd[0] = pty_open(dev)) < 0 ) {\n                vlog(LOG_ERR, \"Can't allocate pseudo tty. %s(%d)\", strerror(errno), errno);\n                return -1;\n            }\n            break;\n\n        case VTUN_PIPE:\n            if ( pipe_open(fd) < 0 ) {\n                vlog(LOG_ERR, \"Can't create pipe. %s(%d)\", strerror(errno), errno);\n                return -1;\n            }\n            break;\n\n        case VTUN_ETHER:\n            if ( (fd[0] = tap_open(dev)) < 0 ) {\n                vlog(LOG_ERR, \"Can't allocate tap device %s. %s(%d)\", dev, strerror(errno), errno);\n                return -1;\n            }\n            break;\n\n        case VTUN_TUN:\n            if ( (fd[0] = tun_open(dev)) < 0 ) { //\n                int while_end = 1;\n                for (int i = 0; while_end; i++) {\n                    if (srv) {\n                        vlog(LOG_INFO, \"vtrunkd SERVER: trying to attach to running server\");\n                        if ((shmid = shmget(vtun.shm_key, sizeof(struct conn_info) * vtun.MAX_TUNNELS_NUM, 0666)) < 0) {\n                            vlog(LOG_ERR, \"shmget 3\");\n                            return -1;\n                        }\n                        if ((shm_conn_info = shmat(shmid, NULL, 0)) == ((struct conn_info *) - 1)) {\n                            vlog(LOG_ERR, \"shmat 3\");\n                            return -1;\n                        }\n// now scan for names, only fail if no found\n                        sem_wait(shm_sem);\n                        for (int i2 = 0; i2 < vtun.MAX_TUNNELS_NUM; i2++) {\n                            if (shm_conn_info[i2].usecount > 0 && strcmp(shm_conn_info[i2].devname, dev) == 0) {\n                                connid = i2;\n                                break;\n                            }\n                            if (shm_conn_info[i2].usecount < 0) {\n                                vlog(LOG_ERR, \"ASSERT FAILED! usecount < 0!\");\n                            }\n                            if (shm_conn_info[i2].usecount != 0 && shm_conn_info[i2].devname[0] == 0) {\n                                vlog(LOG_ERR, \"ASSERT FAILED! usecount != 0 and devname = 0!\");\n                            }\n                        }\n                        if (connid < 0) {\n                            vlog(LOG_ERR, \"Can't allocate tun device %s. %s(%d) - did not find master server shm\", dev, strerror(errno),\n                                        errno);\n                            sem_post(shm_sem);\n                            return 0;\n                        }\n                        if (!shm_conn_info[connid].rdy) {\n                            if (i == 20) {\n                                vlog(LOG_ERR, \"SHM not ready EXIT\");\n                                sem_post(shm_sem);\n                                return 0;\n                            }\n                            vlog(LOG_WARNING, \"SHM not ready yet; I'll try again\");\n                            sem_post(shm_sem);\n                            usleep(200000);\n                            continue;\n                        }\n                        shm_conn_info[connid].usecount++;\n                        sem_post(shm_sem);\n                    } else {\n                        vlog(LOG_INFO, \"vtrunkd CLIENT: trying to attach to running buddy\");\n// match only first conn...\n// here comes the play. !. detect whether we are server or client??\n                        if ((shmid = shmget(vtun.shm_key, sizeof(struct conn_info), 0666)) < 0) {\n                            vlog(LOG_ERR, \"shmget 4\");\n                            return -1;\n                        }\n                        if ((shm_conn_info = shmat(shmid, NULL, 0)) == (struct conn_info *) - 1) {\n                            vlog(LOG_ERR, \"shmat 4 - %s(%d)\",\n                                        strerror(errno), errno); // FAULT HERE\n                            return -1;\n                        }\n\n// now see if it is available.. only exit if not available\n// never reaches here if not available...\n                        if (strcmp(shm_conn_info[0].devname, dev) == 0) {\n// ok\n                            connid = 0;\n                        } else {\n                            vlog(LOG_ERR, \"Can't allocate tun device %s. %s(%d) - did not find running buddy shm %s != %s\", dev,\n                                        strerror(errno), errno, shm_conn_info[0].devname, dev);\n                            return 0;\n                        }\n                        if (!shm_conn_info[connid].rdy) {\n                            if (i == 20) {\n                                vlog(LOG_ERR, \"SHM not ready EXIT\");\n                                return 0;\n                            }\n                            vlog(LOG_WARNING, \"SHM not ready yet; I'll try again\");\n                            usleep(200000);\n                            continue;\n                        }\n\n                    }\n                    break;\n                }\n\n\n// in either case, try to read\n\n                if (read_fd_full(&fd[0], dev) < 0) {\n//vlog(LOG_ERR,\"Cannot read fd tun device %s. %s(%d); failed to get from server\", dev, strerror(errno), errno);\n// wtf is going on here?? always <0! ?!?\n//return -1;\n                }\n\n\n\n\n                if (fd[0] < 0) { // still...\n                    vlog(LOG_ERR, \"CRITICAL ERROR Can't allocate tun device %s. %s(%d); failed to get from server\", dev, strerror(errno), errno);\n                    if(srv) release_shm(shm_conn_info, shm_sem, connid);\n                    return 0;\n                } else {char semname[255];\n    sprintf(semname, \"/vtrunkd_%d\", vtun.shm_key);\n    sem_t *shm_sem;\n    if ((shm_sem = sem_open(semname, O_CREAT, 0644, 1)) == SEM_FAILED) {\n        perror(\"shm semaphore initilization\");\n        exit(1);\n    }\n// now we are forked, and have everything set up (?)\n                }\n\n            } else {\n// We were able to open device => we are new connection. connect shm, set devname in conn_info\n                if (srv) {\n                    vlog(LOG_INFO, \"vtrunkd SERVER: setting up fresh connection\");\n                    if ((shmid = shmget(vtun.shm_key, sizeof(struct conn_info) * vtun.MAX_TUNNELS_NUM, 0666)) < 0) {\n                        vlog(LOG_ERR, \"CRITICAL ERROR shmget 5\");\n                        return -1;\n                    }\n                    if ((shm_conn_info = shmat(shmid, NULL, 0)) == (struct conn_info *) - 1) {\n                        vlog(LOG_ERR, \"CRITICAL ERROR shmat 5\");\n                        return -1;\n                    }\n// now scan for free names\n                    sem_wait(shm_sem);\n                    for (i = 0; i < vtun.MAX_TUNNELS_NUM; i++) {\n                        if (shm_conn_info[i].usecount == 0 && shm_conn_info[i].devname[0] == 0) {\n                            strcpy(shm_conn_info[i].devname, dev);\n                            connid = i;\n                            break;\n                        }\n                    }\n                    if (i >= vtun.MAX_TUNNELS_NUM - 1) {\n                        vlog(LOG_ERR, \"Can't allocate tun device %s. %s(%d) - did not find free slots master server shm\", dev, strerror(errno), errno);\n                        sem_post(shm_sem);\n                        return -1;\n                    }\n                    shm_conn_info[connid].usecount++;\n                    sem_post(shm_sem);\n                } else {\n                    vlog(LOG_INFO, \"vtrunkd CLIENT: setting up fresh connection\");\n\n                    if ((shmid = shmget(vtun.shm_key, sizeof(struct conn_info), 0666)) < 0) {\n                        vlog(LOG_ERR, \"CRITICAL ERROR shmget 6\");\n                        return -1;\n                    }\n                    if ((shm_conn_info = shmat(shmid, NULL, 0)) == (struct conn_info *) - 1) {\n                        vlog(LOG_ERR, \"CRITICAL ERROR shmat 6\");\n                        return -1;\n                    }\n\n// TODO: make sure this check is nesessary! we already suppose that we're the only client on this host\n//   so that in case we have an initialized shm but fd_server not running we will fail here (e.g. race?)\n                    if (shm_conn_info[0].devname[0] == 0) {\n// ok\n                        strcpy(shm_conn_info[0].devname, dev);\n                        vlog(LOG_INFO, \"copied tun name to shm_conn_info: %s\", shm_conn_info[0].devname);\n                        connid = 0;\n                    } else {\n                        vlog(LOG_ERR, \"CRITICAL ERROR Can't allocate tun device %s. %s(%d) - did not find freeslot at running buddy shm\", dev, strerror(errno), errno);\n                        return -1;\n                    }\n                }\n\n// okay, now init if tx queue size! we dont want it too big on slow links! (what we're likely to have here)\n                struct ifreq ifr_queue;\n                int ctl_sock;\n\n                if ((ctl_sock = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {\n                    memset(&ifr_queue, 0, sizeof(ifr_queue));\n                    strcpy(ifr_queue.ifr_name, dev);\n                    ifr_queue.ifr_qlen = host->TUN_TXQUEUE_LEN;\n                    if (ioctl(ctl_sock, SIOCSIFTXQLEN, (void *) &ifr_queue) < 0) {\n                        if(srv) release_shm(shm_conn_info, shm_sem, connid);\n                        vlog(LOG_ERR, \"ioctl SIOCGIFTXQLEN\");\n                        return -1;\n                    }\n                    close(ctl_sock);\n                }\n                else {\n                    vlog(LOG_ERR, \"error open control socket\");\n                    if(srv) release_shm(shm_conn_info, shm_sem, connid);\n                    return -1;\n                }\n\n// init all semaphores, etc...\n                vlog(LOG_INFO, \"init vars sem %s\", shm_conn_info[connid].devname);\n\n                sem_init(&shm_conn_info[connid].tun_device_sem, 1, 1);\n                sem_init(&shm_conn_info[connid].write_buf_sem, 1, 1);\n                sem_init(&shm_conn_info[connid].resend_buf_sem, 1, 1);\n                sem_init(&shm_conn_info[connid].stats_sem, 1, 1);\n                sem_init(&shm_conn_info[connid].AG_flags_sem, 1, 1);\n                sem_init(&shm_conn_info[connid].common_sem, 1, 1);\n                sem_init(&shm_conn_info[connid].hard_sem, 1, 1);\n                sem_init(&shm_conn_info[connid].recv_loss_sem, 1, 1);\n                sem_init(&shm_conn_info[connid].syslog.logSem, 1, 1);\n                sem_init(&shm_conn_info[connid].event_sem, 1, 1);\n\n                struct timeval session_hash_time;\n                gettimeofday(&session_hash_time, NULL );\n                shm_conn_info[connid].session_hash_this = (uint32_t)session_hash_time.tv_usec;\n\n                for (i = 0; i < MAX_TCP_LOGICAL_CHANNELS; i++) {\n                    shm_conn_info[connid].seq_counter[i] = SEQ_START_VAL; // start with 10!! 0-9 are reserved as flags\n                    shm_conn_info[connid].write_buf[i].last_written_seq = SEQ_START_VAL;\n                    shm_conn_info[connid].resend_buf[i].last_written_seq = SEQ_START_VAL; // not needed...\n                    frame_llist_init(&shm_conn_info[connid].write_buf[i].frames);\n                    frame_llist_init(&shm_conn_info[connid].wb_just_write_frames[i]);\n                    frame_llist_init(&shm_conn_info[connid].resend_buf[i].frames);\n                }\n\n                frame_llist_init(&shm_conn_info[connid].wb_free_frames);\n                frame_llist_fill(&shm_conn_info[connid].wb_free_frames, shm_conn_info[connid].frames_buf, FRAME_BUF_SIZE);\n\n\n                frame_llist_init(&shm_conn_info[connid].rb_free_frames);\n                frame_llist_fill(&shm_conn_info[connid].rb_free_frames, shm_conn_info[connid].resend_frames_buf, RESEND_BUF_SIZE);\n\n                vlog(LOG_INFO, \"Starting fd_server\");\n                if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {\n                    vlog(LOG_ERR, \"socket 4\");\n                    if(srv) release_shm(shm_conn_info, shm_sem, connid);\n                    return -1;\n                }\n                remote.sun_family = AF_UNIX;\n                sprintf(remote.sun_path, \"/tmp/vtrunkd_%s.socket\", dev);\n                len = strlen(remote.sun_path) + sizeof(remote.sun_family);\n                if (connect(s, (struct sockaddr *)&remote, len) == -1) {\n                    pid2 = fork();\n                    if (pid2 < 0) {\n                        if(srv) release_shm(shm_conn_info, shm_sem, connid);\n                        vlog(LOG_ERR, \"Couldn't fork() on fd server\");\n                        return 0;\n                    }\n                    if (pid2 != 0) {\n// now run server\n// TODO: how to stop server??\n//chdir(\"/var\"); // chdir to protect gprof\n                        signal(SIGCHLD, SIG_IGN);\n                        set_title(\"fd server %s\", host->host);\n                        run_fd_server(fd[0], dev, &shm_conn_info[connid], srv, shm_sem);\n                    }\n                }\n                close(s);\n\n            }\n            break;\n        }\n        vlog(LOG_INFO, \"Setting loc_fd to %d\", fd[0]);\n        host->loc_fd = fd[0];\n    }\n    host->sopt.dev = strdup(dev);\n\n    /* Initialize protocol. */\n    switch ( host->flags & VTUN_PROT_MASK ) {\n    case VTUN_TCP:\n        opt = 1;\n        setsockopt(host->rmt_fd, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt) );\n\n        opt = 1;\n        setsockopt(host->rmt_fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt) );\n\n        proto_write = tcp_write;\n        proto_read  = tcp_read;\n\n        break;\n\n    case VTUN_UDP:\n        if ( (opt = udp_session(host)) == -1) {\n            vlog(LOG_ERR, \"Can't establish UDP session\");\n            if(srv) release_shm(shm_conn_info, shm_sem, connid);\n            close(fd[1]);\n            if ( ! ( host->persist == VTUN_PERSIST_KEEPIF ) )\n                close(fd[0]);\n            return 0;\n        }\n\n        proto_write = udp_write;\n        proto_read = udp_read;\n\n        break;\n    }\n\n\n    pid = fork();\n    struct rlimit core_limit;\n    core_limit.rlim_cur = RLIM_INFINITY;\n    core_limit.rlim_max = RLIM_INFINITY;\n\n    if (setrlimit(RLIMIT_CORE, &core_limit) < 0) {\n        vlog(LOG_ERR, \"setrlimit: Warning: core dumps may be truncated or non-existant reason %s (%d)\", strerror(errno), errno);\n    }\n    if ( pid < 0 ) {\n        vlog(LOG_ERR, \"Couldn't fork()\");\n        if ( ! ( host->persist == VTUN_PERSIST_KEEPIF ) )\n            close(fd[0]);\n        close(fd[1]);\n        if(srv) release_shm(shm_conn_info, shm_sem, connid);\n        return 0;\n    }\n    if (pid != 0) { // use parent to run commands, child to go further\n        /* do this only the first time when in persist = keep mode */\n//chdir(\"/var\"); // gprof\n        if ( ! interface_already_open ) {\n            switch ( host->flags & VTUN_TYPE_MASK ) {\n            case VTUN_TTY:\n                /* Open pty slave (becomes controlling terminal) */\n                if ( (fd[1] = open(dev, O_RDWR)) < 0) {\n                    vlog(LOG_ERR, \"Couldn't open slave pty\");\n                    exit(0);\n                }\n            /* Fall through */\n            case VTUN_PIPE:\n                null_fd = open(\"/dev/null\", O_RDWR);\n                close(fd[0]);\n                close(0); dup(fd[1]);\n                close(1); dup(fd[1]);\n                close(fd[1]);\n\n                /* Route stderr to /dev/null */\n                close(2); dup(null_fd);\n                close(null_fd);\n                break;\n            case VTUN_ETHER:\n            case VTUN_TUN:\n                break;\n            }\n        }\n        /* Run list of up commands */\n        set_title(\"%s running up commands\", host->host);\n        llist_trav(&host->up, run_cmd, &host->sopt);\n\n        exit(0);\n    }\n\n\n    switch ( host->flags & VTUN_TYPE_MASK ) {\n    case VTUN_TTY:\n        set_title(\"%s tty\", host->host);\n\n        dev_read  = pty_read;\n        dev_write = pty_write;\n        break;\n\n    case VTUN_PIPE:\n        /* Close second end of the pipe */\n        close(fd[1]);\n        set_title(\"%s pipe\", host->host);\n\n        dev_read  = pipe_read;\n        dev_write = pipe_write;\n        break;\n\n    case VTUN_ETHER:\n        set_title(\"%s ether %s\", host->host, dev);\n\n        dev_read  = tap_read;\n        dev_write = tap_write;\n        break;\n\n    case VTUN_TUN:\n        set_title(\"%s tun %s\", host->host, dev);\n\n        dev_read  = tun_read;\n        dev_write = tun_write;\n        break;\n    }\n\n    struct timeval cur_time;\n// finally, choose my conn number in stats block\n    \n    \n    sem_wait(&(shm_conn_info[connid].stats_sem));\n    for (i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if (strcmp(shm_conn_info[connid].stats[i].name, host->host) == 0) {\n            vlog(LOG_ERR, \"Warning! Race error - can not continue: Chan %s pid %d exists. Lock file malfunction.\", host->host, shm_conn_info[connid].stats[i].pid);\n            if ( kill(shm_conn_info[connid].stats[i].pid, 0) < 0 ) {\n                vlog(LOG_ERR, \"ASSERT FAILED! detected dead process by nonexistent pid %d\", shm_conn_info[connid].stats[i].pid);\n            }\n            sem_post(&(shm_conn_info[connid].stats_sem));\n            if(srv) release_shm(shm_conn_info, shm_sem, connid);\n            return -1;\n        }\n    }\n    \n    for (i = 0; i < MAX_TCP_PHYSICAL_CHANNELS; i++) {\n        if (shm_conn_info[connid].stats[i].pid == 0) {\n            if (my_conn_num == -1) my_conn_num = i;\n        } else {\n            gettimeofday(&cur_time, NULL);\n            if ( kill(shm_conn_info[connid].stats[i].pid, 0) < 0 ) {\n// okay no proc found, use it\n                vlog(LOG_ERR, \"ASSERT FAILED! detected dead process by nonexistent pid %d\", shm_conn_info[connid].stats[i].pid);\n                // we may only check vtrunkd by PID if we are sure that this particular PID is vtrunkd and it is using this one SHM\n                if (my_conn_num == -1) my_conn_num = i;\n                shm_conn_info[connid].stats[i].pid = 0;\n                shm_conn_info[connid].stats[i].weight = 0;\n            }\n        }\n    }\n    if (my_conn_num == -1) {\n        // this may only happen if either amount of processes > MAX_TCP_PHYSICAL_CHANNELS or a bug in cleanup code at linkfd\n        sem_post(&(shm_conn_info[connid].stats_sem));\n        vlog(LOG_ERR, \"could not find free conn_num for stats, exit. (%d)\", connid); \n        if(srv) release_shm(shm_conn_info, shm_sem, connid);\n        return -1;\n    }\n    shm_conn_info[connid].stats[my_conn_num].pid = getpid();\n    sem_post(&(shm_conn_info[connid].stats_sem));\n\n    opt = linkfd(host, &(shm_conn_info[connid]), srv, my_conn_num);\n    \n    if(srv) release_shm(shm_conn_info, shm_sem, connid);\n    \n    set_title(\"%s running down commands\", host->host);\n\n    if (srv) {\n        if (shm_conn_info[connid].usecount <= 0) { // AND we're going to quit the process...?\n// if we do \"free\" here, we need to kill fd server, free the local fd tun device - otherwise it will try shm_find+fd_read and fail\n// now check the lock.. if left locked - release!\n            if (sem_trywait(&(shm_conn_info[connid].tun_device_sem)) == -1) {\n                vlog(LOG_ERR, \"ASSERT: usecount == 0 && sem left unclosed!\");\n            } else {\n                sem_post(&(shm_conn_info[connid].tun_device_sem));\n            }\n        }\n        if (shm_conn_info[connid].usecount < 0) {\n            vlog(LOG_ERR, \"ASSERT: usecount < 0 !!!\");\n        }\n    } else {\n// noop\n    }\n\n    if (! ( host->persist == VTUN_PERSIST_KEEPIF ) ) {\n        set_title(\"%s closing\", host->host);\n\n        /* Gracefully destroy interface */\n        switch ( host->flags & VTUN_TYPE_MASK ) {\n        case VTUN_TUN:\n            tun_close(fd[0], dev); // or even nerver close???\n            break;\n\n        case VTUN_ETHER:\n            tap_close(fd[0], dev);\n            break;\n        }\n\n//close(host->loc_fd); // never close too\n    }\n\n    /* Close all other fds */\n    close(host->rmt_fd);\n\n    return opt;\n}\n"
  },
  {
    "path": "udp_states.c",
    "content": "/*\n * udp_states.c\n *\n *  Created on: 15.10.2014\n *      Author: Vrayo Systems Ltd. team\n *\n *\n */\n\n#include <errno.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/syslog.h>\n\n#include \"udp_states.h\"\n#include \"lib.h\"\n#include \"log.h\"\n\nconst char udp_stat_path[] = \"/proc/net/udp\";\n\nint add_line(char* line, struct udp_stats* udp_struct, int conn_amount);\n\nint get_udp_stats(struct udp_stats* udp_struct, int conn_amount) {\n    char line[256];\n    int line_counter = 0;\n    FILE * f = fopen(udp_stat_path, \"r\");\n    if (f == NULL ) {\n        vlog(LOG_ERR, \"udp_stats %s open fail reason %s (%d)\", udp_stat_path, strerror(errno), errno);\n        return 0;\n    }\n    //skip title\n    if (fgets(line, sizeof(line), f) == (char *) EOF) {\n        vlog(LOG_ERR, \"udp_stats fgets EOF title reason %s (%d)\", strerror(errno), errno);\n        if (fclose(f) == EOF) {\n            vlog(LOG_ERR, \"udp_stats file close err %s (%d)\", strerror(errno), errno);\n        }\n        return 0;\n    }\n    while (fgets(line, sizeof(line), f)) {\n        int n = strlen(line);\n        if (n == 0 || line[n - 1] != '\\n') {\n            errno = -EINVAL;\n            if (fclose(f) == EOF) {\n                vlog(LOG_ERR, \"udp_stats file close err %s (%d)\", strerror(errno), errno);\n            }\n            return 0;\n        }\n        line[n - 1] = 0;\n        // line handling\n        line_counter += add_line(line, udp_struct, conn_amount);\n        if (line_counter == conn_amount) {\n            if (fclose(f) == EOF) {\n                vlog(LOG_ERR, \"udp_stats file close err %s (%d)\", strerror(errno), errno);\n            }\n            return 1;\n        }\n    }\n    vlog(LOG_ERR, \"udp connection not found reason %s (%d)\", strerror(errno), errno);\n    if (fclose(f) == EOF) {\n        vlog(LOG_ERR, \"udp_stats file close err %s (%d)\", strerror(errno), errno);\n    }\n    return 0;\n}\n\nint add_line(char* line, struct udp_stats* udp_struct, int conn_amount) {\n    int lport = 0, rport = 0;\n    char *loc, *rem, *data;\n    char opt[256];\n    int n, ret = 0;\n    char *p;\n\n    if ((p = strchr(line, ':')) == NULL )\n        return -1;\n    loc = p + 2;\n\n    if ((p = strchr(loc, ':')) == NULL )\n        return -1;\n    p[5] = 0;\n    rem = p + 6;\n\n    if ((p = strchr(rem, ':')) == NULL )\n        return -1;\n    p[5] = 0;\n    data = p + 6;\n\n    sscanf(loc, \"%*x:%x\", (unsigned*) &lport);\n    sscanf(rem, \"%*x:%x\", (unsigned*) &rport);\n\n    for (int i = 0; i < conn_amount; i++) {\n        if ((lport == udp_struct[i].lport) && (rport == udp_struct[i].rport)) {\n            udp_struct[i].drops = 0;\n            n = sscanf(data, \"%x %x:%x %*x:%*x %*x %d %*d %u %d %llx %d\", &udp_struct[i].state, &udp_struct[i].tx_q, &udp_struct[i].rx_q,\n                    &udp_struct[i].uid, &udp_struct[i].ino, &udp_struct[i].refcnt, &udp_struct[i].sk, &udp_struct[i].drops);\n            if (n < 9)\n                udp_struct[i].drops = 0;\n            ret = 1;\n            break;\n        }\n    }\n    return ret;\n}\n"
  },
  {
    "path": "udp_states.h",
    "content": "/*\n * udp_states.h\n *\n *  Created on: 15.10.2014\n *      Author: Vrayo Systems Ltd. team\n */\n\n#ifndef UDP_STATES_H_\n#define UDP_STATES_H_\n\n#include <asm/types.h>\n\nstruct udp_stats {\n    __u32 rdata[8];\n    int rport;\n    __u32 ldata[8];\n    int lport;\n    int rx_q;\n    int tx_q;\n    int drops, state, refcnt, wq, rq;\n    unsigned uid, ino;\n    unsigned long long sk;\n};\n\nint get_udp_stats(struct udp_stats* udp_struct, int conn_amount);\n\n#endif /* UDP_STATES_H_ */\n"
  },
  {
    "path": "v_struct.h",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016 Vrayo Systems Ltd. team \n   This file is dual-licensed to be compatible with \n   Vrayo Systems vtrunkd_helper, part of Vrayo Internet Combiner package\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n \n#define SHM_SYSLOG 100000\n\nstruct frame_hash {\n    unsigned int seq;\n    int n;\n};\n\nstruct timed_loss {\n    struct timeval timestamp;\n    uint16_t name;\n    int pbl;\n    int psl;\n    uint32_t sqn;\n    int16_t who_lost;\n};\n\n\nstruct _write_buf {\n    struct frame_llist frames;\n    //struct frame_llist free_frames; /* init all elements here */\n    struct frame_llist now; // maybe unused\n    unsigned long last_written_seq; // last pack number has written into device\n    unsigned long wr_lws; // last pack number has written into device\n    unsigned long last_received_seq[MAX_TCP_PHYSICAL_CHANNELS]; // max of 30 physical channels\n    unsigned long last_received_seq_shadow[MAX_TCP_PHYSICAL_CHANNELS]; // used for max_reorder\n    unsigned long possible_seq_lost[MAX_TCP_PHYSICAL_CHANNELS]; // used for max_reorder\n    unsigned long packet_lost_state[MAX_TCP_PHYSICAL_CHANNELS]; // used for max_reorder\n\n    struct timeval last_write_time; // into device\n    int buf_len;\n    unsigned long remote_lws; // last written packet into device on remote side\n    unsigned long last_lws_notified;\n    uint16_t complete_seq_quantity;\n    int top_packet_physical_channel_num;\n};\n\n/**\n * local structure\n * per channel\n */\nstruct time_lag_info {\n\tuint64_t time_lag_sum;\n\tuint16_t time_lag_cnt;\n\tuint32_t packet_lag_sum; // lag in packets\n\tuint16_t packet_lag_cnt;\n\tuint8_t once_flag:1;\n};\n\n/**\n * local structure\n * for local pid\n */\nstruct time_lag {\n\tuint32_t time_lag_remote; // calculater here\n\tuint32_t time_lag; // get from another side\n\tint pid_remote; // pid from another side\n\tint pid; // our pid\n};\n\nstruct _events {\n    int update;\n    int tick;\n    int loss;\n};\n\nstruct speed_chan_data_struct {\n    uint32_t up_current_speed; // current physical channel's speed(kbyte/s) = up_data_len_amt / time\n    uint32_t up_recv_speed;\n    uint32_t up_data_len_amt; // in byte\n    uint32_t down_current_speed; // current physical channel's speed(kbyte/s) = down_data_len_amt / time\n    uint32_t down_data_len_amt; // in byte\n\n    uint32_t down_packets; // per last_tick. need for speed calculation\n    uint32_t down_packet_speed;\n    uint32_t send_q_loss;\n\n};\n\n/**\n * global structure\n */\nstruct conn_stats {\n    char name[SESSION_NAME_SIZE];\n    int lssqn; // TODO: remove this after tests\n    int hsnum; /* session name hash - identical between prodesses */\n    int pid; /* current pid */\n    int pid_remote; // pid from another side\n    long int weight; /* bandwith-delay product */\n    long int last_tick; // watch dog timer\n    // time_lag = old last written time - new written time (in millisecond)\n    // and get from another side\n    uint32_t time_lag_remote;// calculated here\n    uint32_t time_lag; // get from another side\n    struct speed_chan_data_struct speed_chan_data[MAX_TCP_LOGICAL_CHANNELS];\n    uint32_t max_upload_speed;\n    uint32_t max_send_q;\n    uint32_t max_send_q_avg;\n    int32_t send_q_limit; // remove this; replaced by rsr\n    uint16_t miss_packets_max; // get from another side\n    int32_t ACK_speed;\n    int32_t max_ACS2;\n    int32_t max_PCS2;\n    int32_t max_sqspd;\n    int32_t W_cubic;\n    int max_send_q_available;\n    int32_t W_cubic_u;\n    int32_t rsr; // sync on stats_sem\n    int rtt_phys_avg; // accurate on idling\n    int rtt2; // RTT based on per-packet ACK delivery watch; very accurate on high speeds; does not work while idling\n    int srtt2_10; // COPIED from info RTT based on per-packet ACK delivery watch; very accurate on high speeds; does not work while idling\n    int srtt2_100; // COPIED from info RTT based on per-packet ACK delivery watch; very accurate on high speeds; does not work while idling\n    int sqe_mean;\n    int sqe_var;\n    int sqe_mean_lossq;\n    int my_max_send_q_chan_num;\n    int ag_flag_local;\n    int hold;\n    int channel_dead;\n    int exact_rtt;\n    int rttvar; // pure ms\n    int head_in;\n    int head_use;\n    struct timeval bdp1;\n    struct timeval real_loss_time;\n    int packet_speed_ag;\n    int packet_speed_rmit;\n    int local_seq_num_beforeloss;\n    int packet_recv_counter_afterloss;\n    int l_pbl;\n    int l_pbl_recv;\n    int brl_ag_enabled;\n    int l_pbl_tmp; \n    int l_pbl_unrec_avg;\n    int l_pbl_tmp_unrec; \n    int pbl_lossed;\n    int pbl_lossed_cnt;\n    int packet_upload_cnt;\n    int packet_upload_spd;\n    struct timeval packet_upload_tv;\n    struct timeval agon_time;\n    struct timeval agoff_immunity_tv;\n    int recv_mode;\n    struct timeval plp_immune;\n    int l_pbl_recv_saved;\n    int l_pbl_tmp_saved;\n    int pbl_lossed_saved;\n    int pbl_lossed_cnt_saved;\n    int remote_head_channel;\n    uint32_t la_sqn; // last received global seq_num ACK\n    int loss_send_q;\n    int32_t ACK_speed_avg;  /**< Moving average of @see ACK_speed */\n    int remote_sqe_mean_pkt; /** remote sqe_mean sent by FCI, in packets */\n    struct _events events;\n};\n/**\n * Structure for garbage statistic and information\n * about logical channels. Include service channel[0]\n */\nstruct logical_status {\n    /** Information about tcp connection */\n    uint16_t rport;  /**< remote(dst) tcp port */\n    uint16_t lport;  /**< local(src) tcp port */\n    int descriptor; /** file descriptor associated with this connection*/\n\n    /** AVG measuring speed */\n    uint32_t upload;    /**< upload speed */\n    uint32_t up_len;    /**< how much bytes are uploaded */\n    uint32_t up_packets; /**< how much packets are uploaded */\n    uint32_t download;  /**< download speed */\n    uint32_t down_len;    /**< how much bytes are downloaded */\n    uint32_t packet_download;\n    uint32_t down_packets;\n    uint32_t rtt;       /**< rtt is measured by vtrunkd */\n    uint32_t tcp_rtt;   /**< rtt is said by @see get_format_tcp_info() */\n    uint32_t magic_rtt;   /**< rtt based on @see ACK_speed_avg */\n\n    /** Net buffer control information */\n    uint32_t send_q;    /**< current send_q value */\n    struct timeval send_q_time;\n    uint32_t send_q_old;    /**< previous send_q value */\n    int32_t send_q_limit;  /**< current send_q_limit value */\n    int32_t ACK_speed[SPEED_AVG_ARR];      /**< Speed based on how fast ACK packets come back. Last 10 measurements @see avg_count */\n    int avg_count;         /**< Counter for @see ACK_speed_avg calculate*/\n    uint32_t local_seq_num;\n    uint32_t local_seq_num_recv;\n    uint32_t local_seq_num_beforeloss; /** used for max_reorder support */\n    struct timeval loss_time; /** time from last detected packet loss on this chan_num (incoming stream) */\n    struct timeval last_recv_time;\n    struct timeval last_info_send_time;\n    int16_t packet_loss_counter;\n    uint16_t packet_recv_counter;\n    uint16_t packet_recv_counter_afterloss;\n    struct timeval packet_recv_time;\n    int16_t packet_loss;\n    uint16_t packet_recv;\n    uint32_t packet_seq_num_acked;\n    uint32_t packet_recv_period;\n    uint32_t packet_recv_upload;\n    uint32_t packet_recv_upload_avg;\n    struct timeval get_tcp_info_time_old; /**< Previous value of @see get_tcp_info_time.*/\n    int32_t ACS2;\n    uint32_t old_packet_seq_num_acked;\n    uint32_t bytes_put;\n};\n\n/**\n * Structure for storing all information about\n * physical channel\n */\nstruct phisical_status { // A.K.A. \"info\"\n    /** Common information */\n    int process_num;    /**< Current physical channel's number */\n    int pid; /**< Our pid is got on this side by getpid()  */\n    int remote_pid; /**< Pid is got from another side by net */\n    int tun_device; /**< /dev/tun descriptor */\n    int srv; /**< 1 - if I'm server and 0 - if I'm client */\n    int head_channel;\n    int min_rtt_chan;\n    struct {\n        unsigned int seq_num;\n        unsigned int local_seq_num;\n    } lossed_loop_data[LOSSED_BACKLOG_SIZE]; // array of seq_nums for lossed detect\n    uint32_t lossed_local_seq_num_lost_start; /** start seq_num of lost packet */\n    int lossed_complete_received;\n    int lossed_last_received;\n    /** Collect statistic*/\n    int mode;   /**< local aggregation flag, can be AG_MODE and R_MODE */\n    struct timeval current_time;    /**< Is last got time.*/\n    struct timeval current_time_old; /**< Previous value of @see current_time. Need for for the Tick module */\n    uint32_t max_send_q_avg;\n    uint32_t max_send_q_avg_arr[SPEED_AVG_ARR];\n    uint32_t max_send_q_min;\n    uint32_t max_send_q_max;\n    uint32_t max_send_q_calc; // = cwnd * mss\n    int max_send_q_counter;\n    unsigned int speed_efficient;\n    unsigned int speed_resend;\n    unsigned int speed_r_mode;\n    unsigned int byte_efficient;\n    unsigned int byte_resend;\n    unsigned int byte_r_mode;\n    int rtt;\n    uint32_t packet_recv_upload_avg;\n    struct timeval bdp1;\n\n    /** Calculated values*/\n    int32_t send_q_limit_cubic;\n    int32_t send_q_limit;\n    int32_t send_q_limit_cubic_max;\n    int32_t rsr;\n    struct timeval cycle_last;\n    double C;\n    double Cu;\n    double B;\n    double Bu;\n    int W_u_max;\n    int cubic_t_max_u;\n    struct timeval u_loss_tv;\n    int max_send_q;\n    int max_send_q_u;\n    struct timeval tv_sqe_mean_added;\n    /** Logical channels information and statistic*/\n    int channel_amount;   /**< Number elements in @see channel array AKA Number of logical channels already established(created)*/\n    struct logical_status *channel; /**< Array for all logical channels */\n    uint32_t session_hash_this; /**< Session hash for this machine */\n    uint32_t session_hash_remote; /**< Session hash for remote machine */\n    /** Events */\n    int just_started_recv; /**< 0 - when @see FRAME_JUST_STARTED hasn't received yet and 1 - already */\n    int check_shm; /**< 1 - need to check some shm values */\n    uint32_t least_rx_seq[MAX_TCP_LOGICAL_CHANNELS]; // local store of least received seq_num across all phy\n\n    uint32_t rtt2_lsn[MAX_TCP_LOGICAL_CHANNELS];\n    int32_t max_sqspd;\n    int32_t rtt2_send_q[MAX_TCP_LOGICAL_CHANNELS];\n    struct timeval rtt2_tv[MAX_TCP_LOGICAL_CHANNELS]; \n    int rtt2; // max..?\n    int srtt2_10; // max..?\n    int srtt2_100; // max..?\n    int srtt2var; \n    int dropping;\n    struct timeval max_reorder_latency;\n    struct timeval max_latency_drop;\n    int eff_len;\n    int send_q_limit_threshold;\n    int exact_rtt;\n    int flush_sequential; // PSL\n    int ploss_event_flag; /** flag to detect PLOSS at tflush */\n    int mean_latency_us;\n    int max_latency_us;\n    int frtt_us_applied;\n    int PCS2_recv; // through FRAME_CHANNEL_INFO\n    \n    int i_plp; /** inverse packet loss probability (sent) */\n    int p_lost;\n    int last_loss_lsn;\n    int i_rplp; /** inverse packet loss probability (received) */\n    int r_lost;\n    int last_rlost_lsn;\n\n    int l_pbl;\n    int pbl_cnt;\n    struct {\n        int pbl;\n        struct timeval ts;\n    } plp_buf[PLP_BUF_SIZE];\n    \n    int fast_pcs_old;\n    int pcs_sent_old;\n    struct timeval fast_pcs_ts;\n    struct timeval last_sent_FLI;\n    int last_sent_FLI_idx;\n    int last_sent_FLLI_idx;\n    int32_t encap_streams_bitcnt;\n    int encap_streams;\n    int W_cubic_copy;\n    int Wu_cubic_copy;\n    struct timeval hold_time;\n    struct timeval head_change_tv;\n    int head_change_safe; // enough time passed since head change\n    int frtt_remote_predicted;\n    int select_immediate; /** immediate select times counter */\n    int Wmax_saved;\n    struct timeval Wmax_tv;\n    int gsend_q_grow;\n    int whm_cubic;\n    int whm_rsr;\n    int whm_send_q;\n    int previous_idle;\n    int head_send_q_shift;\n    int head_send_q_shift_old;\n    int FCI_send_counter;\n    struct timeval recv_loss_immune;\n    struct timeval idle_enter;\n    int loss_event_count; // EXT\n    int psl_count; // EXT\n    int psl_per_second; // EXT\n    int loss_events_per_second; // EXT\n    int xlm;\n};\n\n/** @struct conn_info\n *  @brief Common shm struct.\n *\n *  Description\n */\nstruct conn_info {\n#ifdef SHM_DEBUG\n    volatile char void11[4096];\n    char void1[4096];\n#endif\n    int usecount;\n    int rdy; /* ready flag */\n    // char sockname[100], /* remember to init to \"/tmp/\" and strcpy from byte *(sockname+5) or &sockname[5]*/ // not needed due to devname\n    char devname[VTUN_DEV_LEN];\n    sem_t hard_sem;\n    //sem_t frtt; // for frtt calculations and tokens\n    sem_t tun_device_sem;\n    int packet_debug_enabled;\n    int is_single_channel;\n    struct frame_seq frames_buf[FRAME_BUF_SIZE];\t\t\t// memory for write_buf\n    struct frame_seq resend_frames_buf[RESEND_BUF_SIZE];\t// memory for resend_buf\n    int resend_buf_idx;\n    struct frame_seq fast_resend_buf[FAST_RESEND_BUF_SIZE];\n    int fast_resend_buf_idx; // how many packets in fast_resend_buf\n    struct _write_buf write_buf[MAX_TCP_LOGICAL_CHANNELS]; // input todo need to synchronize\n    struct frame_hash write_buf_hashtable[WBUF_HASH_SIZE];\n    int write_sequential; // PBL sync by write_buf_sem\n    int prev_flushed; // PBL/PSL flagsync by write_buf_sem\n    struct frame_llist wb_just_write_frames[MAX_TCP_LOGICAL_CHANNELS];\n    struct frame_llist wb_free_frames; /* init all elements here */ // input (to device)\n    sem_t write_buf_sem; //for write buf, seq_counter\n    struct _write_buf resend_buf[MAX_TCP_LOGICAL_CHANNELS]; // output\n    struct frame_llist rb_free_frames; /* init all elements here */ // output (to net)\n    sem_t resend_buf_sem; //for resend buf,  (ever between write_buf_sem if need double blocking)\n    sem_t common_sem; // for seq_counter\n    unsigned long seq_counter[MAX_TCP_LOGICAL_CHANNELS];\t// packet sequense counter\n    uint32_t flushed_packet[FLUSHED_PACKET_ARRAY_SIZE]; //sync by write_buf_sem\n    uint32_t seq_num_unrecoverable_loss; /** seq_num of unrecoverable loss - just flush up to this one since we're going to retransmit anyways */\n    short lock_pid;\t// who has locked shm\n    char normal_senders;\n    int rxmt_mode_pid; // unused?\n    sem_t stats_sem;\n    sem_t event_sem;\n    long int event_mask;\n    uint16_t miss_packets_max; // get from another side sync on stats_sem\n    int buf_len_recv,buf_len;\n    struct conn_stats stats[MAX_TCP_PHYSICAL_CHANNELS]; // need to synchronize because can acces few proccees\n    uint32_t miss_packets_max_recv_counter; // sync on stats_sem\n    uint32_t miss_packets_max_send_counter; // sync on stats_sem\n#ifdef SHM_DEBUG\n    char void12[4096];\n    char void2[4096];\n#endif\n    long int lock_time;\n    long int alive;\n    sem_t AG_flags_sem; // semaphore for AG_ready_flags and channels_mask\n    uint32_t AG_ready_flag; // contain global flags for aggregation possible 0 - enable 1 - disable sync by AG_flags_sem\n    uint32_t channels_mask; // 1 - channel is working 0 - channel is dead sync by AG_flags_sem\n    uint32_t hold_mask; // 0 - channel is on hold, 1 = send allowed\n    uint32_t need_to_exit; // sync by AG_flags_sem\n    uint32_t session_hash_this; /**< Session hash for this machine sync by @see AG_flags_sem*/\n    uint32_t session_hash_remote; /**< Session hash for remote machine sync by @see AG_flags_sem*/\n    unsigned char check[CHECK_SZ]; // check-buf. TODO: fill with pattern \"170\" aka 10101010\n    int head_process;\n    int tflush_counter, tflush_counter_recv;\n    struct timeval chanel_info_time;\n    int flood_flag[MAX_TCP_PHYSICAL_CHANNELS];\n    struct timeval last_flood_sent;\n    struct timeval last_switch_time;\n    int head_all;\n    int max_chan;\n    int dropping;\n    int head_lossing;\n    struct timeval forced_rtt_start_grow;\n    int forced_rtt;\n    int forced_rtt_recv; //in ms\n    int idle;\n    struct timeval drop_time; // time that we DROPPED by fact!\n    struct timed_loss loss[LOSS_ARRAY]; // sync by write_buf_sem\n    struct timed_loss loss_recv[LOSS_ARRAY]; // sync by recv_loss_sem\n    struct timed_loss l_loss[LOSS_ARRAY]; // sync by write_buf_sem\n    struct timed_loss l_loss_recv[LOSS_ARRAY]; // sync by recv_loss_sem\n    sem_t recv_loss_sem;\n    int loss_idx; // sync by write_buf_sem\n    int l_loss_idx; // sync by write_buf_sem\n    struct {\n#define EFF_LEN_BUFF 15\n        int warming_up;\n        int counter;\n        int len_num[EFF_LEN_BUFF];\n        int sum;\n    } eff_len; /**< Session hash for remote machine sync by @see common_sem*/\n    int t_model_rtt100; // RTT multiplied by 100, in ms, for tcp model, calculated as toata avg rtt\n    unsigned char streams[32];\n    int single_stream;\n    struct packet_sum packet_code[SELECTION_NUM][MAX_TCP_LOGICAL_CHANNELS];// sync by common_sem\n    struct packet_sum packet_code_recived[MAX_TCP_LOGICAL_CHANNELS][BULK_BUFFER_PACKET_CODE];// sync by common_sem\n    int packet_code_bulk_counter;\n    struct packet_sum test_packet_code[MAX_TCP_LOGICAL_CHANNELS];\n    struct timeval last_written_recv_ts;\n    struct timeval last_head;\n    int frtt_ms;\n    int drtt;\n    int frtt_local_applied;\n    struct timeval frtt_smooth_tick;\n    uint32_t ag_mask; // unsynced\n    uint32_t ag_mask_recv; // unsynced\n    int max_rtt_lag;\n    int APCS_cnt; // counter for coming packets with AG mode\n    int APCS; // speed for packets per seconf in AG mode coming to WB\n    struct timeval APCS_tick_tv;\n    struct timeval tpps_tick_tv;\n    int tokens;\n    struct timeval tokens_lastadd_tv;\n    int max_chan_new;\n    struct timeval head_detected_ts;\n    int max_allowed_rtt; // MAR calculated against current speed and send_q\n    int tpps; // transfer packets per second\n    int forced_rtt_remote;\n    int rttvar_worst;\n    uint32_t latest_la_sqn; /** latest SQN used to identify HSQS event update age */\n    int remote_head_pnum; // remote head local pnum (for TPC)\n    int write_speed_avg;\n    int write_speed;\n    int write_speed_b;\n    int min_rtt_pnum_checkonly;\n    int max_rtt_pnum_checkonly;\n    int max_stuck_buf_len;\n    int max_stuck_rtt;\n    int msbl_recv;\n    int total_max_rtt;\n    int total_max_rtt_var;\n    int total_min_rtt;\n    int total_min_rtt_var;\n    int full_cwnd;\n    struct timeval msbl_tick;\n    struct timeval msrt_tick;\n    int tokens_in_out;\n    int ssd_gsq_old;\n    int tpps_old; /** holding old global seq_coutner[1] value */\n    int ssd_pkts_sent;\n    int slow_start;\n    int slow_start_recv;\n    int slow_start_prev;\n    int slow_start_allowed;\n    int slow_start_force;\n    int avg_len_in;\n    int avg_len_out;\n    struct timeval slow_start_tv;\n    // struct streams_seq w_streams[W_STREAMS_AMT];\n    int w_stream_pkts[W_STREAMS_AMT]; /** packets for this stream currently in wb */\n    struct timeval cwr_tv; // for CWND Reserve 1s\n    struct timeval max_network_stall; /** drop packets if this value is exceeded */\n    int head_send_q_shift_recv; \n    struct timeval head_change_htime_tv;\n    int head_change_htime;\n    int tokenbuf;\n    int last_net_read_ds; /** last network read in deciseconds */\n#ifdef SHM_DEBUG\n    char void13[4096];\n    char void3[4096];\n#endif\n    struct {\n        sem_t logSem;\n        char log[SHM_SYSLOG];\n        int counter;\n    } syslog;\n};\n"
  },
  {
    "path": "version.h",
    "content": "#define VERSION \"v0.1601-10-g82e93-dirty\"\n"
  },
  {
    "path": "vtrunkd.8",
    "content": ".\\\" Manual page for vtrunkd\n.\\\" vtrunkd.8,v 1.4.2.3.2.2 2011/05/08 04:03:59 realgrandrew\n.\\\" SH section heading\n.\\\" SS subsection heading\n.\\\" LP paragraph\n.\\\" IP indented paragraph\n.\\\" TP hanging label\n.TH VTRUNKD 8\n.SH NAME\nvtrunkd \\- Virtual Tunnel Trunking (Aggregation, Bonding) daemon.\n.SH SYNOPSIS\n.B vtrunkd \n<\n.I -s  \n>\n[ \n.I -i \n] \n[ \n.I -n \n] \n[ \n.I -f file \n] \n[ \n.I -S SHM_ID\n] \n[ \n.I -P port \n]\n.LP\n.B vtrunkd \n[ \n.I -f file \n]\n[ \n.I -S SHM_ID\n]\n[ \n.I -P port \n]\n[ \n.I -p \n]\n[ \n.I -m \n]\n[ \n.I -t timeout \n]\n[ \n.I -n \n] \n<\n.I session \n>\n<\n.I server address \n>\n\n.SH DESCRIPTION\n.LP\nvtrunkd provides the method for creating Virtual Tunnels over IP networks\nand allows to bond available bandwidth in created virtual tunnels. It \nincludes network congestion avoidance algorithms and aggressive failover and \nis suitable even for highly-unstable uplinks aggregation e.g. for fast-moving \nmobile.\n.LP\nSupported type of tunnels is: IP packet based.\n.LP\nvtrunkd is easily and highly configurable, it can be used for various network\ntask like VPN, Mobile IP, IP address saving, etc.\n.LP\nIt is completely user space implementation and does not require modification\nto any kernel parts. \n.LP\nThe dynamic aggregation algorithm invented and implemented by Andrew Gryaznov\nhas over 20 tunable input parameters but comes with good defaults. Please \nrefer to algorithm manual for fine-tuning the aggregation to your needs, like\npreferencing lower latency and failover over higher bandwidth, or vice versa.\nAlgorithm manual can be found on the online wiki on project web homepage.\nPlease note that vtrunkd is in a state of active development and everything\nlisted here is subject to change.\n.LP\nSome setups may require advanced knowledge in TCP/IP networking and linux\nnetwork stack, advanced tools like iproute2 and iptables. Please see the\nexamples given in the project wiki. \n.LP\nPlease note that client mode vtrunkd does not free up SHM upon exit. You \nshould do it manually by calling \\fBipcrm -M 567888\\fR or the SHM_ID you used.\n.LP\nAlso note that server-mode vtrunkd allocates all memory required to hold \n\\fBmax_tunnels_num\\fR connections at start. This may be more than your system\nis configured to allow by default. You may change the SHM size defaults at\n\\fB/proc/sys/kernel/shmmax\\fR and \\fB/proc/sys/kernel/shmall\\fR.\n.LP\nIn order to mix server/client modes and run several servers on single host\nyou must provide different SHM_ID and server ports for each instance group\nand/or bind (-L) to different IP addresses explicitly.\n\n.SH OPTIONS\n.TP\n.I -f file \nRead config information from the\n.I file\n(full path required). By default vtrunkd uses /etc/vtrunkd.conf\n.TP\n.I -n \nDo not become daemon.\n.SS Server mode: \n.TP\n.I -s\nRun as the server.\n.TP\n.I -i\nRun as the inetd server.\n.TP\n.I -P port\nListen for connection on the specified\n.I port\nBy default vtrunkd listens on TCP port 5000. This options is equivalent to \nthe 'port' option of config file.\n.SS Client mode:\n.TP\n.I -P port\nConnect to the server on the specified\n.I port\nBy default vtrunkd connects to TCP port 5000. This options is equivalent to \nthe 'port' option of config file.\n.TP\n.I -p\nReconnect to the server after connection termination. By default vtrunkd will\nexit if connection has been terminated. This options is equivalent to \nthe 'persist' option of config file.\n.TP\n.I -m\nForce memory pages to be locked memory-resident to prevent potential VM deadlock.  Useful with NFS traffic.  This option has no config file equivalent.\n.TP\n.I -t timeout\nConnect \n.I timeout\nDefault is 30 seconds. This options is equivalent to the 'timeout' option of\nconfig file.\n.TP\n.I session \nSession name from the config file.\n.TP\n.I server \nAddress of the server to connect to. Either IP address or domain name can be \nspecified.\n.SH FILES\n.TP\n.B /etc/vtrunkd.conf\nMain configuration file with sessions and other information. \nSee vtrunkd.conf example provided with distribution and vtrunkd.conf(5) \nfor more information.\n.TP\n.B /var/lock/vtrunkd/\nSession lock files. \n.TP\n.B /var/log/vtrunkd/\nConnection statistic log files.\n.br\nFormat:\n   Date Uncomp_In Uncomp_Out Comp_In Comp_Out\n.SH SIGNALS\n.TP\n.B SIGHUP\nServer mode: Causes vtrunkd to reread the config file.\n.br\nClient mode: Causes vtrunkd to reestablish the connection.\n.TP\n.B SIGUSR1\nThis signal causes vtrunkd to reset statistic counters. \n.SH SEE ALSO\n.TP\nvtrunkd.conf(5)\n.SH NOTES \n.LP\nThis product includes software developed by the OpenSSL Project\nfor use in the OpenSSL Toolkit. (http://www.openssl.org/)\n.SH AUTHORS\nVrayo Systems (http://vrayo.com/), Maxim Krasnyansky <max_mk@yahoo.com>\n"
  },
  {
    "path": "vtrunkd.conf",
    "content": "#\n# vtrunkd - Virtual link Trunking daemon\n# (C) 2015-2016 Vrayo Systems Ltd. team (http://vrayo.com/)\n# Copyright (C) 2011 Andrew Gryaznov\n# based on \n# VTun - Virtual Tunnel over TCP/IP network.\n# Copyright (C) 1998-2001  Maxim Krasnyansky <max_mk@yahoo.com>\n#\n# Cleanup of English and spelling by \n#   Ted Rolle <ted@acacia.datacomm.com>\n#\n# Configuration file example\n#\n# \n# Lines which begin with '#' are comments\n#\n# File format:\n#\n# XXXXX {\n#   option param; option param;\n#   option param;\n#   ......\n# }  \n# Where XXXXX:\n#   options - General options.\n#   default - default session options.\n#   session - Session options.     \n# \n# Options _must_ be grouped by curly braces '{' '}'.\n# Each option _must_ end with ';' \n#\n# -----------\n# General options: \n#\n# -----------\n#   port - Server TCP port number.\n#\n# -----------\n#   bindaddr - Server listen address. Used to force vtund to bind\n# \tto the specific address and port in server mode.\n#    Format:\t  \n#       bindaddr {\n#         option .....;\n#       };\n#\n#    'bindaddr' options:\n#\n#    iface - Use interface address as the listen address.\n#    Format:\n#       iface if_name;\n#\n#    addr - Listen address.\n#    Format:\n#       addr ip_address;\n#       addr host_name;\n#\n# -----------\n#   syslog - Syslog facility.\n#\n# -----------\n#   timeout - General timeout. \n#\n# -----------\n#   ifconfig - Program for the net interface initialization.\n#\n# -----------\n#   route  - Program for the routing table manipulation. \n#\n# -----------\n#   firewall - Program for the firewall setup. \n#\n# -----------\n#  \n# Session options: \n#\n#    passwd - Password for authentication.\n#\n# -----------\n#    type - Tunnel type.\n#       'tun'   - IP tunnel (No PPP,Ether,.. headers).\n#       Must be set. No other types currently supported.\n#\n# -----------\n#    device - Network device.\n#       'tunXX' - for 'tun'\n#       Must be set. Vtrunkd uses this value to distinguish\n#         process groups.\n#\n# -----------\n#    proto - Protocol.\n#       ignored\n#  \n#       'tcp' is default for all tunnel types.\n#\n# -----------\n#    persist - Persist mode. \n#       'yes' - Reconnect to the server after connection \n#\t      termination. \n#\t'no' - Exit after connection termination (default).\n#       Used only by the client.\n#\n# -----------\n#    keepalive - Enable 'yes' or disable 'no' connection\n#\tkeep-alive. Ignored by the client.\n#\n# -----------\n#    timeout - Connect timeout. \n#\n# ---------------------------------------\n#   compression and encryption is not yet supported by vtruunkd\n# -----------\n#    compress - Enable 'yes' or disable 'no' compression. \n#\tIt is also possible to specify method:\n#\t   'zlib' - ZLIB compression\n#\t   'lzo'  - LZO compression\n#\tand level: \n#\t   from 1(best speed) to 9(best compression)\n#\tseparated by ':'. Default method is 'zlib:1'.  \n#       Ignored by the client. \n#\n# -----------\n#    encrypt - Enable 'yes' or disable 'no' encryption.\n#\tIt is also possible to specify a method:\n#\t   'blowfish128ecb' - Blowfish cipher, 128 bit key, mode ECB\n#\t   'blowfish128cbc' - Blowfish cipher, 128 bit key, mode CBC\n#\t   'blowfish128cfb' - Blowfish cipher, 128 bit key, mode CFB\n#\t   'blowfish128ofb' - Blowfish cipher, 128 bit key, mode OFB\n#\t   'blowfish256ecb' - Blowfish cipher, 256 bit key, mode ECB\n#\t   'blowfish256cbc' - Blowfish cipher, 256 bit key, mode CBC\n#\t   'blowfish256cfb' - Blowfish cipher, 256 bit key, mode CFB\n#\t   'blowfish256ofb' - Blowfish cipher, 256 bit key, mode OFB\n#\t   'aes128ecb'      - AES cipher, 128 bit key, mode ECB\n#\t   'aes128cbc'      - AES cipher, 128 bit key, mode CBC\n#\t   'aes128cfb'      - AES cipher, 128 bit key, mode CFB\n#\t   'aes128ofb'      - AES cipher, 128 bit key, mode OFB\n#\t   'aes256ecb'      - AES cipher, 256 bit key, mode ECB\n#\t   'aes256cbc'      - AES cipher, 256 bit key, mode CBC\n#\t   'aes256cfb'      - AES cipher, 256 bit key, mode CFB\n#\t   'aes256ofb'      - AES cipher, 256 bit key, mode OFB\n#\tDefault method is 'blowfish128ecb'.\n#       Ignored by the client.\n#\n# -----------\n#    stats are not supported by vtrunkd yet; separate module on the way\n# -----------\n#    stat - Enable 'yes' or disable 'no' statistics.\n#       If enabled vtund will log statistic counters every\n#\t5 minutes.\n#\n# -----------\n#    up - List of programs to run after connection has been \n#\testablished. Used to initialize protocols, devices, \n#\trouting and firewall.\n#    Format:\t  \n#       up {\n#         option .....;\n#         option .....;\n#       };\n#\n#    down - List of programs to run after connection has been \n#\tterminated. Used to reset protocols, devices, routing \n#\tand firewall.\n#    Format:\t  \n#       down {\n#         option .....;\n#         option .....;\n#       };\n#\n#    'up' and 'down' options:\n#\n#    program - Run specified program.\n#    Format:\n#       program path arguments wait;\n#\n#       path - Full path to the program. \n#\t   '/bin/sh' will be used if path was omitted.\n#\n#       arguments - Arguments to pass to the program. \n#\t   Must be enclosed in double quotes. \n#\t   Special characters and expansions: \n#\t      ' (single quotes) -  group arguments\n#\t      \\ (back slash) - escape character \n#\t      %%(double percent) - same as %d\n#\t      %d - TUN or TAP device or TTY port name \n#\t      %A - Local IP address\n#\t      %P - Local TCP or UDP port  \n#\t      %a - Remote IP address\n#\t      %p - Remote TCP or UDP port\n#\n#       wait - Wait for the program termination. \n#\n#    ifconfig - Run program specified by 'ifconfig' statement in \n#\t   'options' section.\n#    Format:\n#       ifconfig arguments;\n#\n#    route - Run program specified by 'route' statement in \n#\t   'options' section.\n#    Format:\n#       route arguments;\n#\n#    firewall - Run program specified by 'firewall' statement in \n#\t   'options' section.\n#    Format:\n#       firewall arguments;\n#\n# -----------\n#    srcaddr - Local (source) address. Used to force vtund to bind\n# \tto the specific address and port in client mode.\n#    Format:\t  \n#       srcaddr {\n#         option .....;\n#         option .....;\n#       };\n#\n#    'srcaddr' options:\n#\n#    iface - Use interface address as the Source address.\n#    Format:\n#       iface if_name;\n#\n#    addr - Source address.\n#    Format:\n#       addr ip_address;\n#       addr host_name;\n#\n#    port - Source port.\n#    Format:\n#       port port_no;\n#\n# -----------\n#    multi - Multiple connections.\n#\t'yes' or 'allow' - allow multiple connections.\n#\t'no' or 'deny' - deny multiple connections.\n#\t'killold' - allow new connection and kill old one.\n#       Ignored by the client.\n#\n# -----------\n# Notes:\n#   Options 'Ignored by the client' are provided by server \n#   at the connection initialization. \n#\n#   Option names cannot be abbreviated.\n#\n# ----- CUT HERE  --- Server config --- CUT HERE -----\n#\n\noptions {\n  port 5000;\t\t# Listen on this port.\n  timeout 5;\n\n  max_tunnels_num 10;\n  # Syslog facility\n  syslog \tdaemon;\n\n  # Path to various programs\n  ppp \t\t/usr/sbin/pppd;            \n  ifconfig \t/sbin/ifconfig;\n  route \t/sbin/route;\n  firewall \t/sbin/iptables;\n  ip\t\t/sbin/ip;\n}\n\n# Default session options \ndefault {\n  compress no;  \t# Compression is off by default\n  speed 0;\t\t# By default maximum speed, NO shaping\n  proto tcp;   \t\t# UDP|TCP protocol\n  encrypt  no;\t\t# Encryption\n  keepalive yes;\t# Keep connection alive\n  multi killold;  # has no effect now\n  stat yes;\n\ttick_secs 3;\n\tmax_latency 2000;\n\tmax_latency_drop 50;\n\tmax_idle_timeout 20;\n\tping_interval 2;\n\ttun_txqueue_len 4000;\n\ttcp_conn_amount 1;\n  type tun;\n}\n\n000000_1 { # name is required to have a distinguishing last 2 characters like _1,_2,_3,_4 ... or AA,AB, etc. for a group\n  passwd  testpasswd;\n  device tun10;\n  up {\n    ifconfig \"%% 10.0.0.1 pointopoint 10.0.0.2  mtu 1350 up\";\n  };\n  down {\n        ifconfig \"%% down\";\n  };\n}\n000000_2 {\n  passwd  testpasswd;\n  device tun10;\n  up {\n    ifconfig \"%% 10.0.0.1 pointopoint 10.0.0.2  mtu 1350 up\";\n  };\n  down {\n        ifconfig \"%% down\";\n  };\n}\n000000_3 {\n  passwd  testpasswd;\n  device tun10;\n  up {\n    ifconfig \"%% 10.0.0.1 pointopoint 10.0.0.2  mtu 1350 up\";\n  };\n  down {\n        ifconfig \"%% down\";\n  };\n}\n000000_4 {\n  passwd  testpasswd;\n  device tun10;\n  up {\n    ifconfig \"%% 10.0.0.1 pointopoint 10.0.0.2  mtu 1350 up\";\n  };\n  down {\n        ifconfig \"%% down\";\n  };\n}\n\n # see vtrunkd_client.conf file for client config example\n "
  },
  {
    "path": "vtrunkd.conf.5",
    "content": ".\\\" Manual page for vtrunkd.conf\n.\\\" vtrunkd.conf.5,v 1.1.2.6.2.3 2011/05/08 04:04:12 realgrandrew Exp\n.TH VTRUNKD.CONF 5\n\n.SH NAME\nvtrunkd.conf \\- Virtual Tunnel Trunking daemon configuration file.\n\n.SH DESCRIPTION\n\nConfiguration file for\n.BR vtrunkd (8)\nvirtual trunking daemon.\n.LP\nFile consists of sections in the form:\n.IP\n.nf\n.IR name \" {\"\n.IR \"  keyword value\" ;\n.IR \"  keyword value\" ;\n  ..\n}\n.fi\n\n.LP\nSemicolon at the end of each keyword-value pair is required,\nas well as grouping curly braces {}.\nLines which begin with '#' characters are comments.\n.LP\nName of section (\\fIname\\fR) can be one of:\n.IP \\fBoptions\\fR\nthis section specifies general options for vtrunkd\n.IP \\fBdefault\\fR\nspecifies default options for all sessions\n.IP \\fIsession\\fR\n(any other word except \"options\" and \"default\")\nintroduces new session and specifies options for it.\n.LP\nAll keyword names can be abbreviated to a minimum of 4 characters.\n.LP\n\n.SH \"GENERAL OPTIONS\"\n\n.LP\nThis section, named\n.BR options ,\nspecifies general options to use by\n.BR vtrunkd (8).\nPossible \\fIkeyword\\fRs are:\n\n.IP \\fBport\\ \\fIportnumber\\fR\nserver port number to listen on or connect to.\nBy default, \\fBvtrunkd\\fR(8) uses port 5000.\n\n.IP \\fBbindaddr\\ \\fIlist\\fR\nserver listen address. Used to force vtrunkd to bind to the specific\naddress and port in server mode.  Format:\n.nf\n  \\fBbindaddr\\fR {\n   \\fIoption \\fIvalue\\fR;\n  };\n.fi\n.IP\n\\fBbindaddr\\fR options:\n.RS\n.IP \\fBiface\\ \\fIif_name\\fR\nuse interface address \\fIif_name\\fR as the bind address.\n.IP \\fBaddr\\ \\fIaddr\\fR\nbind address.  Can be either IP address or host name.\n.RE\n\n.IP \\fBtimeout\\ \\fIseconds\\fR\nGeneral timeout.\n\n.IP \\fBpersist\\fR\\ \\fByes\\fR|\\fBkeep\\fR|\\fBno\\fR\npersist mode.  If \\fByes\\fR, the client will try to reconnect to the server\nafter connection termination.  If \\fBkeep\\fR, the client will not remove\nand re-add the \\fBtun\\fIXX\\fR device when reconnecting.\nIf \\fBno\\fR, the client will exit (default).\nThis option is ignored by the server.\n\n.IP \\fBsyslog\\fR\\ \\fBnumber\\fR|\\fBname\\fR\nsyslog facility specification, either numeric or name (from syslog (3)).\n\n.IP \\fBifconfig\\ \\fIpath\\fR\npath to \\fBifconfig\\fR(8) program.  Can be used in session sections.\n\n.IP \\fBroute\\ \\fIpath\\fR\npath to \\fBroute\\fR(8) program.  Can be used in session sections.\n\n.IP \\fBip\\ \\fIpath\\fR\npath to \\fBiproute\\fR(8) program.  Can be used in session sections.\n\n.IP \\fBfirewall\\ \\fIpath\\fR\nprogram for the firewall setup.\n\n.IP \\fBmax_tunnels_num\\ \\fIsecounds\\fR\nmaximum VPNs allocated at server side (affects SHM memory). Used by server.\n\n.LP\nAll the \\fBifconfig\\fR, \\fBroute\\fR and \\fBfirewall\\fR\nparameters can specify a filename for corresponding program or\nequivalent (or shell script).  This parameters are used in session sections\nto setup network interfaces.\n\n.SH \"SESSION OPTIONS\"\n\n.LP\nSession options can be specified inside session section or\ninside \\fBdefault\\fR section.  Default parameters apply\nto any session section but can be overwritten there.\nParameters are:\n\n.IP \\fBpasswd\\ \\fIsecret\\fR\npassword for authentication.  This should be the same in\nclient and server.\n\n.IP \\fBtype\\ \\fItype\\fR\ntype of tunnel.  Possible tunnel types are:\n.RS\n.IP \\fBtun\\fR\nIP tunnel (no PPP, Ether etc headers)\n.RE\n.IP\nThis option is ignored by client.\n\n.IP \\fBdevice\\ \\fIdev\\fR\nnetwork device to use.  You can choose\n\\fBtun\\fIXX\\fR for \\fBtun\\fR tunnel.\nBy default \\fBvtrunkd\\fR(8) will automatically select available device.\n\n.IP \\fBproto\\ \\fBtcp\\fR|\\fBudp\\fR\nprotocol to use.  By default, \\fBvtrunkd\\fR(8) will use TCP protocol.\nUDP is recommended for \\fBether\\fR and \\fBtun\\fR tunnels only.\nThis option is ignored by the client. Current UDP implementation is untested.\n\n.IP \\fBtimeout\\ \\fIseconds\\fR\nConnect timeout.\n\n.IP \\fBcompress\\ \\fImethod\\fR[\\fB:\\fIlevel\\fR]\nspecifies compression method to use. Compression and encryption are not yet supported by vtrunkd.  Compression \\fImethod\\fRs include:\n.RS\n.IP \\fBno\\fR\nno compression\n.IP \\fByes\\fR\ndefault compression method\n.IP \\fBzlib\\fR\nZLIB compression\n.IP \\fBlzo\\fR\nLZO compression (if compiled in)\n.RE\n.IP\nYou can also specify \\fIlevel\\fR of compression using one\ndigit (1 is best speed, 9 is best compression ratio).\nThis option ignored by the client.\n.IP \\fBencrypt\\ \\fByes\\fR|\\fBno\\fR\nenable or disable encryption.  This option ignored by the client.\n.IP \\fBkeepalive\\ \\fByes\\fR|\\fBno\\fR\nenable or disable connection keep-alive.\nThis option is ignored by the client.\n.IP \\fBstat\\ \\fByes\\fR|\\fBno\\fR\nenable or disable statistics.  If enabled \\fBvtrunkd\\fR(8) will log\nstatistic counters to /var/log/vtrunkd/session_X every 5 minutes.\n.IP \\fBspeed\\ \\fIkbps\\fR\nspecifies speed of the connection in kilobits/second.\nValid values for \\fIkbps\\fR are 8,16,32,64,128,256,etc.\n0 (the default) means maximum possible speed without shaping.\nYou can specify speed in form \\fIin\\fB:\\fIout\\fR, where\n\\fIin\\fR is speed to client, \\fIout\\fR - from the client.\nSingle number means the same speed for in and out.\nThis option ignored by the client.\n.IP \\fBsrcaddr\\ \\fIlist\\fR\nlocal (source) address. Used to force vtrunkd to bind to the specific\naddress and port.  Format:\n.nf\n  \\fBsrcaddr\\fR {\n   \\fIoption \\fIvalue\\fR;\n   \\fIoption \\fIvalue\\fR;\n   ..\n  };\n.fi\n.IP\n\\fBsrcaddr\\fR options:\n.RS\n.IP \\fBiface\\ \\fIif_name\\fR\nuse interface address \\fIif_name\\fR as the source address.\n.IP \\fBaddr\\ \\fIaddr\\fR\nsource address.  Can be either IP address or host name.\n.IP \\fBport\\ \\fIportnumber\\fR\nsource port.\n.RE\n.IP \\fBmulti\\ \\fIvalue\\fR\ncontrol multiple connections.  \\fIvalue\\fR can be\n\\fByes\\fR or \\fBallow\\fR to allow multiple connections,\n\\fBno\\fR or \\fBdeny\\fR to deny them or\n\\fBkillold\\fR to allow new connection and kill old one.\nIgnored by the client.\n.IP \\fBup\\ \\fIlist\\fR\nlist of programs to run after connection has been established.\nUsed to initialize protocols, devices, routing and firewall.\nThis option looks like whole section inside of session section.\nFormat:\n.nf\n \\fBup\\fR {\n   \\fIoption \\fIvalue\\fR;\n   \\fIoption \\fIvalue\\fR;\n   ..\n };\n\n.fi\n.IP\nOptions inside \\fBup\\fR (and \\fBdown\\fR) blocks:\n.RS\n.IP \\fBprogram\\ \\fIpath\\ arguments\\fR\\ [\\fBwait\\fR]\nrun specified program.  \\fIpath\\fR is the full path to the program,\n\\fIarguments\\fR is all arguments to pass to it (enclosed in double quotes).\nIf \\fIwait\\fR specified, \\fBvtrunkd\\fR will wait program termination.\nSpecial characters that can be used inside \\fIarguments\\fR parameter:\n.IP\n\\fB\\'\\fR (single quotes) - group arguments\n.br\n\\fB\\\\\\fR (back slash) - escape character\n.br\n\\fB%d\\fR - TUN or TAP device or TTY port name \n.br\n\\fB%%\\fR (double percent) - same as %d\n.br\n\\fB%A\\fR - Local IP address\n.br\n\\fB%P\\fR - Local TCP or UDP port\n.br\n\\fB%a\\fR - Remote IP address\n.br\n\\fB%p\\fR - Remote TCP or UDP port\n.IP \\fBppp\\ \\fIarguments\\fR\nrun program specified by \\fBppp\\fR statement in \\fBoptions\\fR section.\nAll special character described above are valid in \\fIarguments\\fR here.\n.IP \\fBifconfig\\ \\fIarguments\\fR\nrun program specified by \\fBifconfig\\fR statement in \\fBoptions\\fR section.\n.IP \\fBroute\\ \\fIarguments\\fR\nrun program specified by \\fBroute\\fR statement in \\fBoptions\\fR section.\n.IP \\fBip\\ \\fIarguments\\fR\nrun program specified by \\fBip\\fR statement in \\fBoptions\\fR section.\n.IP \\fBfirewall\\ \\fIarguments\\fR\nrun program specified by \\fBfirewall\\fR statement in \\fBoptions\\fR section.\n.RE\n.IP \\fBdown\\ \\fIlist\\fR\nlist of programs to run after connection has been terminated.\nIt is similar to \\fBup\\fR parameter above.\nFormat:\n.nf\n \\fBdown\\fR {\n   \\fIoption \\fIvalue\\fR;\n   \\fIoption \\fIvalue\\fR;\n   ..\n };\n\n.SH \"AG ALGORITHM PARAMETERS\"\n\n.LP\nAlgorithm parameters control various aspects of channel bonding behaviour. All algorithm parameters are integer numbers. Please see the example config files and project online documentation on how to use them.\n\n.IP \\fBrt_mark\\ \\fInumber\\fR\nMarker to use for packet routing. This actually allows to route virtual connections through different interfaces. Defaults to not set any mark, thus requiring to use separate IP addresses per virtual link on server-side.\n\n.IP \\fBping_interval\\ \\fIseconds\\fR\n seconds to ping. must be less than MAX_IDLE_TIMEOUT, set to higher to reduce idle traffic\n\n.IP \\fBtun_txqueue_len\\ \\fIpackets\\fR\nthis controls jitter and congestion on tun device (set to higher on faster links, lower on slower). Setting it t\n\n\n.fi\n\n.SH NOTES\nOptions ignored by the client are supplied by the server at the run\ntime or are used only on the server side.\n\n.SH \"SEE ALSO\"\n.BR vtrunkd (8),\n.BR ifconfig (8),\n.BR route (8),\n.BR pppd (8),\n.BR syslog (3),\n.BR zlib (3).\n\n.SH AUTHOR\nVtrunkd algorithm written by Andrew Gryaznov <realgrandrew@gmail.com>.\nOriginal vtund written by Maxim Krasnyansky <max_mk@yahoo.com>.\nThis manual page was derived from comments in config file by\nMichael Tokarev <mjt@tls.msk.ru>\n"
  },
  {
    "path": "vtrunkd_client.conf",
    "content": "options {\n    port 5000;\n    timeout 2;\n    ppp /usr/sbin/pppd;\n    ifconfig /sbin/ifconfig;\n    route /sbin/route;\n    firewall /sbin/iptables;\n    ip /usr/sbin/tc;\n}\ndefault {\n    tick_secs 3;\n    max_latency 2000;\n    max_idle_timeout 20;\n    ping_interval 2;\n    tun_txqueue_len 1000;\n}\n000000_1 {\n    passwd testpasswd;\n    device tun1;\n    timeout 2;\n    rt_mark 1; # remember to set up policy mark-based routing \"ip rule\" and \"ip table\" using IPROUTE2\n    persist keep;\n    encrypt no;\n    up {\n        ifconfig \"%% 10.0.0.2 pointopoint 10.0.0.1  mtu 1350 up\";\n    };\n    down {\n        ifconfig \"%% down\";\n    };\n}\n000000_2 {\n    passwd testpasswd;\n    device tun1;\n    timeout 2;\n    rt_mark 2;\n    persist keep;\n    encrypt no;\n    up {\n        ifconfig \"%% 10.0.0.2 pointopoint 10.0.0.1  mtu 1350 up\";\n    };\n    down {\n        ifconfig \"%% down\";\n    };\n}\n000000_3 {\n    passwd testpasswd;\n    device tun1;\n    timeout 2;\n    rt_mark 3;\n    persist keep;\n    encrypt no;\n    up {\n        ifconfig \"%% 10.0.0.2 pointopoint 10.0.0.1  mtu 1350 up\";\n    };\n    down {\n        ifconfig \"%% down\";\n    };\n}\n000000_4 {\n    passwd testpasswd;\n    device tun1;\n    timeout 2;\n    rt_mark 4;\n    persist keep;\n    encrypt no;\n    up {\n        ifconfig \"%% 10.0.0.2 pointopoint 10.0.0.1  mtu 1350 up\";\n    };\n    down {\n        ifconfig \"%% down\";\n    };\n}\n"
  },
  {
    "path": "vtun.drivers",
    "content": "tun_dev.c\ntap_dev.c\npty_dev.c\npipe_dev.c\ntcp_proto.c\nudp_proto.c\n"
  },
  {
    "path": "vtun.h",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016 Vrayo Systems Ltd. team \n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * vtun.h,v 1.7.2.6.2.6 2006/11/16 04:04:17 mtbishop Exp\n */ \n\n#ifndef _VTUN_H\n#define _VTUN_H\n#include \"llist.h\"\n#include \"frame_llist.h\"\n#include \"const.h\"\n#include \"version.h\"\n#include <semaphore.h>\n#include <sys/types.h>\n#include <sys/ipc.h>\n#include <sys/shm.h>\n#include <stdio.h>\n#include <stdint.h>\n#include <time.h>\n#include \"speed_algo.h\"\n#include \"packet_code.h\"\n\n/* Default VTUN port */\n#define VTUN_PORT 5000\n\n/* Default VTUN connect timeout in sec */\n#define VTUN_CONNECT_TIMEOUT 30\n\n/* General VTUN timeout for several operations, in sec */\n#define VTUN_TIMEOUT 30\n\n/* Number of seconds for delay after pppd startup*/\n#define VTUN_DELAY_SEC  10 \n\n/* Statistic interval in seconds */\n#define VTUN_STAT_IVAL  60  /* 1 min */ /* this will also trigger timeout for socket read */\n\n\n// these are tunable algorithm parameters...\n\n/* Algorithm configurable runtime defaults */\n// general system resolution and stats output period\n#define P_TICK_SECS 3 // seconds\n// timed weight division \n#define P_RXMIT_CNT_DROP_PERIOD 1 // seconds\n// peak weight cut\n#define P_MAX_WEIGHT_NORM  19000 // unit*scale\n// scaling\n#define P_WEIGHT_SCALE 100 // 1/unit; [e.g. 100: 100/100 = 1.00 ]\n// how much to approximate weight to \"start_weight\" each RXMIT_CNT_DROP_PERIOD seconds\n#define P_WEIGHT_SMOOTH_DIV  000 // (1/s)*scale\n// TODO: DIV_PROPORTIONAL - drop weight proportional to data sent amount; for links with mostly static \n// how much to tend to approximate to start_weight.\n#define P_WEIGHT_START_STICKINESS  0 // (1/s)*scale\n// nonlinear saw-like weight function step-up smoothness (the higher value the lower is step up and smoother penalty)\n#define P_WEIGHT_SAW_STEP_UP_DIV 60 // (1/s)\n// minimal step up on weight. With channels with most likely high-difference in speeds 'smooth closeup'\n// may be too smooth to quickly reach optimum but setting lower smoothness results in system resonanse\n// this threshold helps to reach optimum more quickly with some loss of precision\n#define P_WEIGHT_SAW_STEP_UP_MIN_STEP 0 // 1/ms -> in P_WEIGHT_MSEC_DELAY units\n// nonlinear step down smoothness; the higher the smoother and less aggressive return to uncontrolled send\n#define P_WEIGHT_SAW_STEP_DN_DIV 5 // (1/s)\n// sets control delay (and granularity)\n#define P_WEIGHT_MSEC_DELAY 2000 // micro(!!)seconds\n\n// this actually affects how much resends will occur, milliseconds\n#define P_MAX_LATENCY 2000 // milliseconds\n// DROP shall not be reached! if reached - it indicates problems\n#define P_MAX_LATENCY_DROP 5 // seconds\n// this is hardly dependent on MAX_REORDER (e.g. MR90/MABL350)\n#define P_MAX_ALLOWED_BUF_LEN 1800 // int // WARNING: need large buffer for rtt tweaking on fast chans! (500ms * 2MB/s = at least 1MB!\n// very sensitive parameter - setting it huge will stuck into MAX_LATENCY* product always\n#define P_MAX_REORDER 90 // int\n// seconds to timeout. set to 10 for mostly-stable links, to 30 for very-unstable and jitterish\n#define P_MAX_IDLE_TIMEOUT 20 // seconds\n// notify each N frames of successful writedown with all misses and reordering resolved\n// should be < FRAME_BUF_SIZE/TCP_CONN_AMOUNT\n#define P_FRAME_COUNT_SEND_LWS 50 // int frames\n// seconds to ping. must be less than MAX_IDLE_TIMEOUT, set to higher to reduce idle traffic\n#define P_PING_INTERVAL 1 // seconds\n// this controls jitter and congestion on tun device (set to higher on faster links, lower on slower)\n// setting it to low value will result in packet loss on full load; setting too high will result in significant tx delay\n#define P_TUN_TXQUEUE_LEN 1000 // int\n// maximum VPNs allocated at server side (aaffects SHM memory)\n#define P_MAX_TUNNELS_NUM 20\n// amount of tcp channels per process (vpn link) requested by CLIENT mode\n#define P_TCP_CONN_AMOUNT 1 // without service channel\n// big jitter\n#define ABSOLUTE_MAX_JITTER 2500 // in ms\n// ag switch compare parameter always less than 1 but higher than 0\n#define AG_FLOW_FACTOR 0.2\n\n\n/* Compiled-in values */\n// defines period of LWS notification; helps reduce resend_buf outage probability\n// uses TICK_SECS as base interval\n#define LWS_NOTIFY_PEROID 3 // seconds; TODO: make this configurable\n#define LWS_NOTIFY_MAX_SUB_SEQ 30\n\n// 10 seconds to start accepting tcp channels; otherwise timeout\n#define CHAN_START_ACCEPT_TIMEOUT 10\n\n#define TCP_MAX_REORDER 3 // general knowledge\n/* End of configurable part */\n\nstruct vtun_sopt {\n    char *dev;\n    char *laddr;\n    int  lport;\n    char *raddr;\n    int  rport;\n};\n\nstruct vtun_stat {\n   unsigned long byte_in;\n   unsigned long byte_out;\n   unsigned long comp_in;\n   unsigned long comp_out;\n   FILE *file;\n};\n\nstruct vtun_cmd {\n   char *prog;\n   char *args;\n   int  flags;\n};\n/* Command flags */\n#define VTUN_CMD_WAIT\t0x01 \n#define VTUN_CMD_DELAY  0x02\n#define VTUN_CMD_SHELL  0x04\n\nstruct vtun_addr {\n   char *name;\n   char *ip;\n   int port;\n   int type;\n};\n/* Address types */\n#define VTUN_ADDR_IFACE\t0x01 \n#define VTUN_ADDR_NAME  0x02\n\nstruct vtun_host {\n   char *host;\n   char *passwd;\n   char *dev;\n\n   llist up;\n   llist down;\n\n   int  flags;\n   int  timeout;\n   int  spd_in;\n   int  spd_out;\n   int  zlevel;\n   int  cipher;\n\n   int  rmt_fd;\n   int  loc_fd;\n\n   uint16_t start_port;\n   uint16_t end_port;\n\n   /* Persist mode */\n   int  persist;\n\n   /* Multiple connections */\n   int  multi;\n\n   /* Keep Alive */\n   int ka_interval;\n   int ka_failure;\n\n   /* Source address */\n   struct vtun_addr src_addr;\n\n   struct vtun_stat stat;\n\n   struct vtun_sopt sopt;\n   \n   /* Algorithm parameters */\n   \n   int TICK_SECS;\n   int RXMIT_CNT_DROP_PERIOD;\n   int MAX_WEIGHT_NORM;\n   int WEIGHT_SCALE;\n   int WEIGHT_SMOOTH_DIV;\n   int WEIGHT_START_STICKINESS;\n   int WEIGHT_SAW_STEP_UP_DIV;\n   int WEIGHT_SAW_STEP_UP_MIN_STEP;\n   int WEIGHT_SAW_STEP_DN_DIV;\n   int WEIGHT_MSEC_DELAY;\n   int MAX_WINDOW;\n   int MAX_LATENCY;\n   int MAX_LATENCY_DROP;\n   int MAX_ALLOWED_BUF_LEN;\n   int MAX_REORDER;\n   int MAX_IDLE_TIMEOUT;\n   int FRAME_COUNT_SEND_LWS;\n   int PING_INTERVAL;\n   int TUN_TXQUEUE_LEN;\n   int TCP_CONN_AMOUNT;\n   int START_WEIGHT;\n   int RT_MARK;\n   \n};\n\n\n\n//\n// -= these are not tunable... =-\n//\n\n// absolutly minimal weight\n#define MIN_WEIGHT 100000000\n\n// asserts of frame seq_num difference \n#define STRANGE_SEQ_FUTURE 1000 // unsigned long int frames\n#define STRANGE_SEQ_PAST 50000 // unsigned long int frames\n\n// SHM key\n#define SHM_TUN_KEY 567888\n\n// these are static ...\n\n// RMODE (rxmit mode) tunes % stickiness; mostly unused\n#define MAX_RETRANSMIT_RMODE 1\n\n// when to timeout fd_server process and free shm memory and tun device\n#define PROCESS_FD_SHM_TIMEOUT 30 // seconds\n\n// statics\n#define MODE_NORMAL 0\n#define MODE_RETRANSMIT 1\n\n// start val\n#define SEQ_START_VAL 10\n#define SUP_TCP_CONN_TIMEOUT_SECS 15\n\n// more frame flags\n#define FLAGS_RESERVED 200 // 0-200 is reserved for flags\n#define FRAME_MODE_NORM 0\n#define FRAME_MODE_RXMIT 1\n#define FRAME_JUST_STARTED 2\n#define FRAME_PRIO_PORT_NOTIFY 3\n#define FRAME_LAST_WRITTEN_SEQ 4\n#define FRAME_TIME_LAG 5 // time lag from favorite CONN - Issue #11\n#define FRAME_DEAD_CHANNEL 6\n#define FRAME_CHANNEL_INFO 7\n#define FRAME_LOSS_INFO 8\n#define FRAME_L_LOSS_INFO 9\n#define FRAME_REDUNDANCY_CODE 10\n\n#define HAVE_MSGHDR_MSG_CONTROL\n\n#define TERM_NONFATAL 1000\n#define TERM_FATAL 1001\n\n#define CUBIC_C 0.2\n\n#define AG_MODE 1\n#define R_MODE 0\n\n\n#define PLP_BUF_TIMEOUT_MS 5000 // timeout for PLP buffer values\n\n\nstruct streams_seq {\n    unsigned int seq;\n    struct timeval ts;\n    int packets;\n};\n\n\n#include \"v_struct.h\"\n\nstruct resent_chk {\n    unsigned long seq_num;\n    int chan_num;\n};\n\n#define MAX_NUM_RESEND 1 //max number of resend in retransmit mode\n\nstruct last_sent_packet {\n    uint32_t seq_num;\n    unsigned long num_resend; //how many time resend\n};\n\n#define SEM_KEY 567000\n#define FD_SEM 0\n#define WB_SEM 1\n#define RB_SEM 2\n\nextern llist host_list;\n\n/* Flags definitions */\n#define VTUN_TTY        0x0100\n#define VTUN_PIPE       0x0200\n#define VTUN_ETHER      0x0400\n#define VTUN_TUN        0x0800\n#define VTUN_TYPE_MASK  (VTUN_TTY | VTUN_PIPE | VTUN_ETHER | VTUN_TUN) \n\n#define VTUN_TCP        0x0010  \n#define VTUN_UDP        0x0020  \n#define VTUN_PROT_MASK  (VTUN_TCP | VTUN_UDP) \n#define VTUN_KEEP_ALIVE 0x0040\t\n\n#define VTUN_ZLIB       0x0001\n#define VTUN_LZO        0x0002\n#define VTUN_SHAPE      0x0004\n#define VTUN_ENCRYPT    0x0008\n\n/* Cipher options */\n#define VTUN_ENC_BF128ECB\t1\n#define VTUN_ENC_BF128CBC\t2\n#define VTUN_ENC_BF128CFB\t3\n#define VTUN_ENC_BF128OFB\t4\n#define VTUN_ENC_BF256ECB\t5\n#define VTUN_ENC_BF256CBC\t6\n#define VTUN_ENC_BF256CFB\t7\n#define VTUN_ENC_BF256OFB\t8\n\n#define VTUN_ENC_AES128ECB\t9\n#define VTUN_ENC_AES128CBC\t10\n#define VTUN_ENC_AES128CFB\t11\n#define VTUN_ENC_AES128OFB\t12\n#define VTUN_ENC_AES256ECB\t13\n#define VTUN_ENC_AES256CBC\t14\n#define VTUN_ENC_AES256CFB\t15\n#define VTUN_ENC_AES256OFB\t16\n\n/* Mask to drop the flags which will be supplied by the server */\n#define VTUN_CLNT_MASK  0xf000\n\n#define VTUN_STAT\t0x1000\n#define VTUN_PERSIST    0x2000\n\n/* Constants and flags for VTun protocol */\n#define VTUN_FRAME_SIZE     2048\n#define VTUN_FRAME_OVERHEAD 100\n#define VTUN_FSIZE_MASK 0x0fff\n\n#define VTUN_CONN_CLOSE 0x1000\n#define VTUN_ECHO_REQ\t0x2000\n#define VTUN_ECHO_REP\t0x4000\n#define VTUN_BAD_FRAME  0x8000\n\n#define RESENT_MEM 1000 // very heavy load on this\n\n/* Authentication message size */\n#define VTUN_MESG_SIZE\t50\n\n/* Support for multiple connections */\n#define VTUN_MULTI_DENY\t\t0  /* no */ \n#define VTUN_MULTI_ALLOW\t1  /* yes */\n#define VTUN_MULTI_KILL\t\t2\n\n/* keep interface in persistant mode */\n#define VTUN_PERSIST_KEEPIF     2\n\n/* Values for the signal flag */\n\n#define VTUN_SIG_TERM 1\n#define VTUN_SIG_HUP  2\n\n/* Authentication errors */\n#define D_NOSHAKE1 1\n#define D_NOSHAKE2 2\n#define D_ST_CHAL 3\n#define D_CHAL 4\n#define D_NOHOST 5\n#define D_NOMULT 6\n#define D_GREET 7\n#define D_PWD 8\n#define D_NOREAD 9\n#define D_OTHER 10\n\n\n/* Global options */\nstruct vtun_opts {\n   int  timeout;\n   int  persist;\n   int quiet;\n   int MAX_TUNNELS_NUM;\n\n   char *cfg_file;\n\n   char *shell; \t /* Shell */\n   char *ppp;\t\t /* Command to configure ppp devices */\n   char *ifcfg;\t\t /* Command to configure net devices */\n   char *route;\t\t /* Command to configure routing */\n   char *fwall; \t /* Command to configure FireWall */\n   char *iproute;\t /* iproute command */\n\n   char *svr_name;       /* Server's host name */\n   char *svr_addr;       /* Server's address (string) */\n   struct vtun_addr bind_addr;\t /* Server should listen on this address */\n   uint16_t start_port;\n   uint16_t end_port;\n   int  svr_type;\t /* Server mode */\n   int  syslog; \t /* Facility to log messages to syslog under */\n   key_t shm_key;\n};\n#define VTUN_STAND_ALONE\t0 \n#define VTUN_INETD\t\t1\t\n\n#ifndef BUILD_DATE\n  #define BUILD_DATE VERSION\n#endif\n\nextern struct vtun_opts vtun;\nextern int debug_trace;\n\nvoid server(int sock);\nvoid client(struct vtun_host *host);\nint  tunnel(struct vtun_host *host, int srv, sem_t * shm_sem);\nint  read_config(char *file);\nstruct vtun_host * find_host(char *host);\n\nint read_fd_full(int *fd, char *dev);\n\n#endif\n"
  },
  {
    "path": "vtun_socks.h",
    "content": "/*  \n   vtrunkd - Virtual Tunnel Trunking over TCP/IP network. \n\n   Copyright (C) 2011-2016  Vrayo Systems Ltd. team\n\n   Vtrunkd has been derived from VTUN package by Maxim Krasnyansky. \n   vtun Copyright (C) 1998-2000  Maxim Krasnyansky <max_mk@yahoo.com>\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n */\n\n/*\n * vtun_socks.h,v 1.1.1.1.6.1 2006/11/16 04:04:20 mtbishop Exp\n */ \n\n#ifndef _VTUN_SOCKS_H\n#define _VTUN_SOCKS_H\n\n#if defined(VTUN_SOCKS)\n   /* Syscalls to SOCKS calls */\n   #if VTUN_SOCKS == 1\n      #define connect \t\tSOCKSconnect\n      #define bind \t\tSOCKSbind\n      #define select\t\tSOCKSselect\n      #define getsockname \tSOCKSgetsockname\n      #define getpeername \tSOCKSgetpeername\n      #define gethostbyname \tSOCKSgethostbyname\n   #else\n      #define connect \t\tRconnect\n      #define bind \t\tRbind\n      #define select\t\tRselect\n      #define getsockname \tRgetsockname\n      #define getpeername \tRgetpeername\n      #define gethostbyname \tRgethostbyname\n   #endif\n#endif\n\n\n#endif /* _VTUN_SOCKS_H */\n"
  }
]