From 91c4ef665aef24ae95ceea83cb68764bad39bfa5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 8 Dec 2010 13:14:04 -0800 Subject: [PATCH 001/330] More renaming --- libguac/AUTHORS | 1 + libguac/COPYING | 661 +++++++++++++++ libguac/ChangeLog | 0 libguac/Doxyfile | 1551 ++++++++++++++++++++++++++++++++++++ libguac/INSTALL | 0 libguac/Makefile.am | 14 + libguac/NEWS | 0 libguac/README | 0 libguac/configure.in | 29 + libguac/include/client.h | 242 ++++++ libguac/include/guacio.h | 179 +++++ libguac/include/protocol.h | 203 +++++ libguac/src/client.c | 296 +++++++ libguac/src/guacio.c | 297 +++++++ libguac/src/protocol.c | 464 +++++++++++ 15 files changed, 3937 insertions(+) create mode 100644 libguac/AUTHORS create mode 100644 libguac/COPYING create mode 100644 libguac/ChangeLog create mode 100644 libguac/Doxyfile create mode 100644 libguac/INSTALL create mode 100644 libguac/Makefile.am create mode 100644 libguac/NEWS create mode 100644 libguac/README create mode 100644 libguac/configure.in create mode 100644 libguac/include/client.h create mode 100644 libguac/include/guacio.h create mode 100644 libguac/include/protocol.h create mode 100644 libguac/src/client.c create mode 100644 libguac/src/guacio.c create mode 100644 libguac/src/protocol.c diff --git a/libguac/AUTHORS b/libguac/AUTHORS new file mode 100644 index 00000000..517d7a79 --- /dev/null +++ b/libguac/AUTHORS @@ -0,0 +1 @@ +Michael Jumper diff --git a/libguac/COPYING b/libguac/COPYING new file mode 100644 index 00000000..dba13ed2 --- /dev/null +++ b/libguac/COPYING @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/libguac/ChangeLog b/libguac/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/libguac/Doxyfile b/libguac/Doxyfile new file mode 100644 index 00000000..b8a2290e --- /dev/null +++ b/libguac/Doxyfile @@ -0,0 +1,1551 @@ +# Doxyfile 1.6.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = libguac + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = include + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it parses. +# With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this tag. +# The format is ext=language, where ext is a file extension, and language is one of +# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, +# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = YES + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. +# For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's +# filter section matches. +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/libguac/INSTALL b/libguac/INSTALL new file mode 100644 index 00000000..e69de29b diff --git a/libguac/Makefile.am b/libguac/Makefile.am new file mode 100644 index 00000000..f20371cc --- /dev/null +++ b/libguac/Makefile.am @@ -0,0 +1,14 @@ +AUTOMAKE_OPTIONS = gnu + +ACLOCAL_AMFLAGS = -I m4 +AM_CFLAGS = -Werror -Wall -Iinclude + +libguacincdir = $(includedir)/guacamole +libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h + +lib_LTLIBRARIES = libguac.la + +libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c + +libguac_la_LDFLAGS = -version-info 0:0:0 + diff --git a/libguac/NEWS b/libguac/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/libguac/README b/libguac/README new file mode 100644 index 00000000..e69de29b diff --git a/libguac/configure.in b/libguac/configure.in new file mode 100644 index 00000000..622be0ef --- /dev/null +++ b/libguac/configure.in @@ -0,0 +1,29 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_INIT(src/client.c) +AM_INIT_AUTOMAKE(libguac, 0.0.1) +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +AC_PROG_CC +AC_PROG_LIBTOOL + +# Checks for libraries. +AC_CHECK_LIB([dl], [dlopen],, AC_MSG_ERROR("libdl is required for loading client plugins")) +AC_CHECK_LIB([png], [png_write_png]) + +# Checks for header files. +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T + +# Checks for library functions. +AC_FUNC_MALLOC +AC_FUNC_REALLOC +AC_CHECK_FUNCS([gettimeofday memmove memset select strdup]) + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/libguac/include/client.h b/libguac/include/client.h new file mode 100644 index 00000000..7ece35b7 --- /dev/null +++ b/libguac/include/client.h @@ -0,0 +1,242 @@ + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _CLIENT_H +#define _CLIENT_H + +#include + +#include "guacio.h" + +/** + * Provides functions and structures required for defining (and handling) a proxy client. + * + * @file client.h + */ + +typedef struct guac_client guac_client; + +/** + * Handler for server messages (where "server" refers to the server that + * the proxy client is connected to). + */ +typedef int guac_client_handle_messages(guac_client* client); + +/** + * Handler for Guacamole mouse events. + */ +typedef int guac_client_mouse_handler(guac_client* client, int x, int y, int button_mask); + +/** + * Handler for Guacamole key events. + */ +typedef int guac_client_key_handler(guac_client* client, int keysym, int pressed); + +/** + * Handler for Guacamole clipboard events. + */ +typedef int guac_client_clipboard_handler(guac_client* client, char* copied); + +/** + * Handler for freeing up any extra data allocated by the client + * implementation. + */ +typedef int guac_client_free_handler(void* client); + +/** + * Guacamole proxy client. + * + * Represents a Guacamole proxy client (the client which communicates to + * a server on behalf of Guacamole, on behalf of the web-client). + */ +struct guac_client { + + /** + * The GUACIO structure to be used to communicate with the web-client. It is + * expected that the implementor of any Guacamole proxy client will provide + * their own mechanism of I/O for their protocol. The GUACIO structure is + * used only to communicate conveniently with the Guacamole web-client. + */ + GUACIO* io; + + /** + * Reference to dlopen'd client plugin. + */ + void* client_plugin_handle; + + /** + * Arbitrary reference to proxy client-specific data. Implementors of a + * Guacamole proxy client can store any data they want here, which can then + * be retrieved as necessary in the message handlers. + */ + void* data; + + /** + * Handler for server messages. If set, this function will be called + * occasionally by the Guacamole proxy to give the client a chance to + * handle messages from whichever server it is connected to. + * + * Example: + * @code + * void handle_messages(guac_client* client); + * + * int guac_client_init(guac_client* client, int argc, char** argv) { + * client->handle_messages = handle_messages; + * } + * @endcode + */ + guac_client_handle_messages* handle_messages; + + /** + * Handler for mouse events sent by the Gaucamole web-client. + * + * The handler takes the integer mouse X and Y coordinates, as well as + * a button mask containing the bitwise OR of all button values currently + * being pressed. Those values are: + * + * + * + * + * + * + * + * + *
Button Value
Left 1
Middle 2
Right 4
Scrollwheel Up 8
Scrollwheel Down16
+ + * Example: + * @code + * void mouse_handler(guac_client* client, int x, int y, int button_mask); + * + * int guac_client_init(guac_client* client, int argc, char** argv) { + * client->mouse_handler = mouse_handler; + * } + * @endcode + */ + guac_client_mouse_handler* mouse_handler; + + /** + * Handler for key events sent by the Guacamole web-client. + * + * The handler takes the integer X11 keysym associated with the key + * being pressed/released, and an integer representing whether the key + * is being pressed (1) or released (0). + * + * Example: + * @code + * void key_handler(guac_client* client, int keysym, int pressed); + * + * int guac_client_init(guac_client* client, int argc, char** argv) { + * client->key_handler = key_handler; + * } + * @endcode + */ + guac_client_key_handler* key_handler; + + /** + * Handler for clipboard events sent by the Guacamole web-client. This + * handler will be called whenever the web-client sets the data of the + * clipboard. + * + * This handler takes a single string which contains the text which + * has been set in the clipboard. This text is already unescaped from + * the Guacamole escaped version sent within the clipboard message + * in the protocol. + * + * Example: + * @code + * void clipboard_handler(guac_client* client, char* copied); + * + * int guac_client_init(guac_client* client, int argc, char** argv) { + * client->clipboard_handler = clipboard_handler; + * } + * @endcode + */ + guac_client_clipboard_handler* clipboard_handler; + + /** + * Handler for freeing data when the client is being unloaded. + * + * This handler will be called when the client needs to be unloaded + * by the proxy, and any data allocated by the proxy client should be + * freed. + * + * Implement this handler if you store data inside the client. + * + * Example: + * @code + * void free_handler(guac_client* client); + * + * int guac_client_init(guac_client* client, int argc, char** argv) { + * client->free_handler = free_handler; + * } + * @endcode + */ + guac_client_free_handler* free_handler; + +}; + +/** + * Handler which should initialize the given guac_client. + */ +typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); + +/** + * Initialize and return a new guac_client. The pluggable client will be chosen based on + * the first connect message received on the given file descriptor. + * + * @param client_fd The file descriptor associated with the socket associated with the connection to the + * web-client tunnel. + * @return A pointer to the newly initialized client. + */ +guac_client* guac_get_client(int client_fd); + +/** + * Enter the main network message handling loop for the given client. + * + * @param client The proxy client to start handling messages of/for. + */ +void guac_start_client(guac_client* client); + +/** + * Free all resources associated with the given client. + * + * @param client The proxy client to free all reasources of. + */ +void guac_free_client(guac_client* client); + +/** + * Allocate a libpng-compatible buffer to hold raw image data. + * + * @param w The width of the buffer to allocate, in pixels. + * @param h The height of the buffer to allocate, in pixels. + * @param bpp The number of bytes per pixel (3 for RGB images, 4 for RGBA). + * @return A pointer to the newly allocated buffer. + */ +png_byte** guac_alloc_png_buffer(int w, int h, int bpp); + +/** + * Free all memory associated with the given libpng-compatible buffer + * as allocated by guac_alloc_png_buffer. + * + * @param png_buffer The buffer to free. + * @param h The height of the buffer to free. + */ +void guac_free_png_buffer(png_byte** png_buffer, int h); + +#endif diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h new file mode 100644 index 00000000..8499ea3e --- /dev/null +++ b/libguac/include/guacio.h @@ -0,0 +1,179 @@ + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _GUACIO_H +#define _GUACIO_H + +#include + +/** + * Defines the GUACIO object and functionss for using and manipulating it. + * + * @file guacio.h + */ + + +/** + * The core I/O object of Guacamole. GUACIO provides buffered input and output + * as well as convenience methods for efficiently writing base64 data. + */ +typedef struct GUACIO { + + /** + * The file descriptor to be read from / written to. + */ + int fd; + + /** + * The number of bytes present in the base64 "ready" buffer. + */ + int ready; + + /** + * The base64 "ready" buffer. Once this buffer is filled, base64 data is + * flushed to the main write buffer. + */ + int ready_buf[3]; + + /** + * The number of bytes currently in the main write buffer. + */ + int written; + + /** + * The main write buffer. Bytes written go here before being flushed + * to the open file descriptor. + */ + char out_buf[8192]; + + /** + * The current size of the instruction buffer. + */ + int instructionbuf_size; + + /** + * The number of bytes currently in the instruction buffer. + */ + int instructionbuf_used_length; + + /** + * The instruction buffer. This is essentially the input buffer, + * provided as a convenience to be used to buffer instructions until + * those instructions are complete and ready to be parsed. + */ + char* instructionbuf; + + /** + * The transfer limit, in kilobytes per second. If 0, there is no + * transfer limit. If non-zero, sleep calls are used at the end of + * a write to ensure output never exceeds the specified limit. + */ + unsigned int transfer_limit; /* KB/sec */ + +} GUACIO; + +/** + * Allocates and initializes a new GUACIO object with the given open + * file descriptor. + * + * @param fd An open file descriptor that this GUACIO object should manage. + * @return A newly allocated GUACIO object associated with the given + * file descriptor. + */ +GUACIO* guac_open(int fd); + +/** + * Writes the given unsigned int to the given GUACIO object. The data + * written may be buffered until the buffer is flushed automatically or + * manually. + * + * @param io The GUACIO object to write to. + * @param i The unsigned int to write. + * @return Zero on success, or non-zero if an error occurs while writing. + */ +ssize_t guac_write_int(GUACIO* io, unsigned int i); + +/** + * Writes the given string to the given GUACIO object. The data + * written may be buffered until the buffer is flushed automatically or + * manually. Note that if the string can contain characters used + * internally by the Guacamole protocol (commas, semicolons, or + * backslashes) it will need to be escaped. + * + * @param io The GUACIO object to write to. + * @param str The string to write. + * @return Zero on success, or non-zero if an error occurs while writing. +*/ +ssize_t guac_write_string(GUACIO* io, const char* str); + +/** + * Writes the given binary data to the given GUACIO object as base64-encoded + * data. The data written may be buffered until the buffer is flushed + * automatically or manually. Beware that because base64 data is buffered + * on top of the write buffer already used, a call to guac_flush_base64() must + * be made before non-base64 writes (or writes of an independent block of + * base64 data) can be made. + * + * @param io The GUACIO object to write to. + * @param buf A buffer containing the data to write. + * @param count The number of bytes to write. + * @return Zero on success, or non-zero if an error occurs while writing. + */ +ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count); + +/** + * Flushes the base64 buffer, writing padding characters as necessary. + * + * @param io The GUACIO object to flush + * @return Zero on success, or non-zero if an error occurs during flush. + */ +ssize_t guac_flush_base64(GUACIO* io); + +/** + * Flushes the write buffer. + * + * @param io The GUACIO object to flush + * @return Zero on success, or non-zero if an error occurs during flush. + */ +ssize_t guac_flush(GUACIO* io); + + +/** + * Waits for input to be available on the given GUACIO object until the + * specified timeout elapses. + * + * @param io The GUACIO object to wait for. + * @param usec_timeout The maximum number of microseconds to wait for data, or + * -1 to potentially wait forever. + * @return Positive on success, zero if the timeout elapsed and no data is + * available, negative on error. + */ +int guac_select(GUACIO* io, int usec_timeout); + +/** + * Frees resources allocated to the given GUACIO object. Note that this + * implicitly flush all buffers, but will NOT close the associated file + * descriptor. + * + * @param io The GUACIO object to close. + */ +void guac_close(GUACIO* io); + +#endif + diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h new file mode 100644 index 00000000..685a112b --- /dev/null +++ b/libguac/include/protocol.h @@ -0,0 +1,203 @@ + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef __PROTOCOL_H +#define __PROTOCOL_H + +#include + +#include "guacio.h" + +/** + * Provides functions and structures required for communicating using the + * Guacamole protocol over a GUACIO connection, such as that provided by + * guac_client objects. + * + * @file protocol.h + */ + + +/** + * Represents a single instruction within the Guacamole protocol. + */ +typedef struct guac_instruction { + + /** + * The opcode of the instruction. + */ + char* opcode; + + /** + * The number of arguments passed to this instruction. + */ + int argc; + + /** + * Array of all arguments passed to this instruction. Strings + * are not already unescaped. + */ + char** argv; + +} guac_instruction; + + +/** + * Frees all memory allocated to the given instruction opcode + * and arguments. The instruction structure itself will not + * be freed. + * + * @param instruction The instruction to free. + */ +void guac_free_instruction_data(guac_instruction* instruction); + + +/** + * Frees all memory allocated to the given instruction. This + * includes freeing memory allocated for the structure + * itself. + * + * @param instruction The instruction to free. + */ +void guac_free_instruction(guac_instruction* instruction); + +/** + * Escapes the given string as necessary to be passed within + * a Guacamole instruction. The returned string must later be + * released with a call to free(). + * + * @param str The string to escape. + * @return A new escaped string, which must be freed with free(). + */ +char* guac_escape_string(const char* str); + +/** + * Unescapes the given string in-place, as an unescaped string + * is always the same length or shorter than the original. + * + * @param str The string to unescape. + * @return A pointer to the original string, which is now unescaped. + */ +char* guac_unescape_string_inplace(char* str); + +/** + * Sends a name instruction over the given GUACIO connection. The + * name given will be automatically escaped for transmission. + * + * @param io The GUACIO connection to use. + * @param name The name to send within the name instruction. + */ +void guac_send_name(GUACIO* io, const char* name); + +/** + * Sends an error instruction over the given GUACIO connection. The + * error description given will be automatically escaped for + * transmission. + * + * @param io The GUACIO connection to use. + * @param error The description associated with the error. + */ +void guac_send_error(GUACIO* io, const char* error); + +/** + * Sends a clipboard instruction over the given GUACIO connection. The + * clipboard data given will be automatically escaped for transmission. + * + * @param io The GUACIO connection to use. + * @param data The clipboard data to send. + */ +void guac_send_clipboard(GUACIO* io, const char* data); + +/** + * Sends a size instruction over the given GUACIO connection. + * + * @param io The GUACIO connection to use. + * @param w The width of the display. + * @param h The height of the display. + */ +void guac_send_size(GUACIO* io, int w, int h); + +/** + * Sends a copy instruction over the given GUACIO connection. + * + * @param io The GUACIO connection to use. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. + * @param dstx The X coordinate of the destination, where the source rectangle + * should be copied. + * @param dsty The Y coordinate of the destination, where the source rectangle + * should be copied. + */ +void guac_send_copy(GUACIO* io, int srcx, int srcy, int w, int h, int dstx, int dsty); + +/** + * Sends a png instruction over the given GUACIO connection. The PNG image data + * given will be automatically base64-encoded for transmission. + * + * @param io The GUACIO connection to use. + * @param x The destination X coordinate. + * @param y The destination Y coordinate. + * @param png_rows A libpng-compatible PNG image buffer containing the image + * data to send. + * @param w The width of the image in the image buffer. + * @param h The height of the image in the image buffer. + */ +void guac_send_png(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h); + +/** + * Sends a cursor instruction over the given GUACIO connection. The PNG image + * data given will be automatically base64-encoded for transmission. + * + * @param io The GUACIO connection to use. + * @param x The destination X coordinate. + * @param y The destination Y coordinate. + * @param png_rows A libpng-compatible PNG image buffer containing the image + * data to send. + * @param w The width of the image in the image buffer. + * @param h The height of the image in the image buffer. + */ +void guac_send_cursor(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h); + +/** + * Returns whether new instruction data is available on the given GUACIO + * connection for parsing. + * + * @param io The GUACIO connection to use. + * @return A positive value if data is available, negative on error, or + * zero if no data is currently available. + */ +int guac_instructions_waiting(GUACIO* io); + +/** + * Reads a single instruction from the given GUACIO connection. + * + * @param io The GUACIO connection to use. + * @param parsed_instruction A pointer to a guac_instruction structure which + * will be populated with data read from the given + * GUACIO connection. + * @return A positive value if data was successfully read, negative on + * error, or zero if the instrucion could not be read completely, + * in which case, subsequent calls to guac_read_instruction() will + * return the parsed instruction once enough data is available. + */ +int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction); + +#endif + diff --git a/libguac/src/client.c b/libguac/src/client.c new file mode 100644 index 00000000..7ac1bd45 --- /dev/null +++ b/libguac/src/client.c @@ -0,0 +1,296 @@ + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include + +#include + +#include "guacio.h" +#include "protocol.h" +#include "client.h" + + +png_byte** guac_alloc_png_buffer(int w, int h, int bpp) { + + png_byte** png_buffer; + png_byte* row; + int y; + + /* Allocate rows for PNG */ + png_buffer = (png_byte**) malloc(h * sizeof(png_byte*)); + for (y=0; yio = io; + + return client; +} + + +guac_client* guac_get_client(int client_fd) { + + guac_client* client; + GUACIO* io = guac_open(client_fd); + + /* Pluggable client */ + char protocol_lib[256] = "libguac_client_"; + + union { + guac_client_init_handler* client_init; + void* obj; + } alias; + + char* error; + + /* Client arguments */ + int argc; + char** argv; + + /* Connect instruction */ + guac_instruction instruction; + + /* Wait for connect instruction */ + for (;;) { + + int result = guac_read_instruction(io, &instruction); + if (result < 0) { + syslog(LOG_ERR, "Error reading instruction while waiting for connect"); + return NULL; + } + + /* Connect instruction read */ + if (result > 0) { + + if (strcmp(instruction.opcode, "connect") == 0) { + + /* Get protocol from message */ + char* protocol = instruction.argv[0]; + + strcat(protocol_lib, protocol); + strcat(protocol_lib, ".so"); + + /* Create new client */ + client = __guac_alloc_client(io); + + /* Load client plugin */ + client->client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); + if (!(client->client_plugin_handle)) { + syslog(LOG_ERR, "Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); + guac_send_error(io, "Could not load server-side client plugin."); + guac_flush(io); + guac_free_instruction_data(&instruction); + return NULL; + } + + dlerror(); /* Clear errors */ + + /* Get init function */ + alias.obj = dlsym(client->client_plugin_handle, "guac_client_init"); + + if ((error = dlerror()) != NULL) { + syslog(LOG_ERR, "Could not get guac_client_init in plugin: %s\n", error); + guac_send_error(io, "Invalid server-side client plugin."); + guac_flush(io); + guac_free_instruction_data(&instruction); + return NULL; + } + + /* Initialize client arguments */ + argc = instruction.argc; + argv = instruction.argv; + + if (alias.client_init(client, argc, argv) != 0) { + /* NOTE: On error, proxy client will send appropriate error message */ + guac_free_instruction_data(&instruction); + return NULL; + } + + guac_free_instruction_data(&instruction); + return client; + + } /* end if connect */ + + guac_free_instruction_data(&instruction); + } + + } + +} + + +void guac_free_client(guac_client* client) { + + if (client->free_handler) { + if (client->free_handler(client)) + syslog(LOG_ERR, "Error calling client free handler"); + } + + guac_close(client->io); + + /* Unload client plugin */ + if (dlclose(client->client_plugin_handle)) { + syslog(LOG_ERR, "Could not close client plugin while unloading client: %s", dlerror()); + } + + free(client); +} + + +void guac_start_client(guac_client* client) { + + GUACIO* io = client->io; + guac_instruction instruction; + int wait_result; + + /* VNC Client Loop */ + for (;;) { + + /* Handle server messages */ + if (client->handle_messages) { + + int retval = client->handle_messages(client); + if (retval) { + syslog(LOG_ERR, "Error handling server messages"); + return; + } + + guac_flush(io); + } + + wait_result = guac_instructions_waiting(io); + if (wait_result > 0) { + + int retval; + retval = guac_read_instruction(io, &instruction); /* 0 if no instructions finished yet, <0 if error or EOF */ + + if (retval > 0) { + + do { + + if (strcmp(instruction.opcode, "mouse") == 0) { + if (client->mouse_handler) + if ( + client->mouse_handler( + client, + atoi(instruction.argv[0]), /* x */ + atoi(instruction.argv[1]), /* y */ + atoi(instruction.argv[2]) /* mask */ + ) + ) { + + syslog(LOG_ERR, "Error handling mouse instruction"); + guac_free_instruction_data(&instruction); + return; + + } + } + + else if (strcmp(instruction.opcode, "key") == 0) { + if (client->key_handler) + if ( + client->key_handler( + client, + atoi(instruction.argv[0]), /* keysym */ + atoi(instruction.argv[1]) /* pressed */ + ) + ) { + + syslog(LOG_ERR, "Error handling key instruction"); + guac_free_instruction_data(&instruction); + return; + + } + } + + else if (strcmp(instruction.opcode, "clipboard") == 0) { + if (client->clipboard_handler) + if ( + client->clipboard_handler( + client, + guac_unescape_string_inplace(instruction.argv[0]) /* data */ + ) + ) { + + syslog(LOG_ERR, "Error handling clipboard instruction"); + guac_free_instruction_data(&instruction); + return; + + } + } + + else if (strcmp(instruction.opcode, "disconnect") == 0) { + syslog(LOG_INFO, "Client requested disconnect"); + guac_free_instruction_data(&instruction); + return; + } + + guac_free_instruction_data(&instruction); + + } while ((retval = guac_read_instruction(io, &instruction)) > 0); + + if (retval < 0) { + syslog(LOG_ERR, "Error reading instruction from stream"); + return; + } + } + + if (retval < 0) { + syslog(LOG_ERR, "Error or end of stream"); + return; /* EOF or error */ + } + + /* Otherwise, retval == 0 implies unfinished instruction */ + + } + else if (wait_result < 0) { + syslog(LOG_ERR, "Error waiting for next instruction"); + return; + } + + } + +} + diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c new file mode 100644 index 00000000..b6a8a368 --- /dev/null +++ b/libguac/src/guacio.c @@ -0,0 +1,297 @@ + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "guacio.h" + +char __GUACIO_BASE64_CHARACTERS[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', +}; + +GUACIO* guac_open(int fd) { + + GUACIO* io = malloc(sizeof(GUACIO)); + io->ready = 0; + io->written = 0; + io->fd = fd; + + /* Allocate instruction buffer */ + io->instructionbuf_size = 1024; + io->instructionbuf = malloc(io->instructionbuf_size); + io->instructionbuf_used_length = 0; + + /* Set limit */ + io->transfer_limit = 0; + + return io; + +} + +void guac_close(GUACIO* io) { + guac_flush(io); + free(io); +} + +/* Write bytes, limit rate */ +ssize_t __guac_write(GUACIO* io, const char* buf, int count) { + + struct timeval start, end; + int retval; + + /* Write and time how long the write takes (microseconds) */ + gettimeofday(&start, NULL); + retval = write(io->fd, buf, count); + gettimeofday(&end, NULL); + + if (retval < 0) + return retval; + + if (io->transfer_limit > 0) { + + suseconds_t elapsed; + suseconds_t required_usecs; + + /* Get elapsed time */ + elapsed = (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec; + + /* Calculate how much time we must sleep */ + required_usecs = retval * 1000 / io->transfer_limit - elapsed; /* useconds at transfer_limit KB/s*/ + + /* Sleep as necessary */ + if (required_usecs > 0) { + + struct timespec required_sleep; + + required_sleep.tv_sec = required_usecs / 1000000; + required_sleep.tv_nsec = (required_usecs % 1000000) * 1000; + + nanosleep(&required_sleep, NULL); + + } + + } + + return retval; +} + +ssize_t guac_write_int(GUACIO* io, unsigned int i) { + + char buffer[128]; + char* ptr = &(buffer[127]); + + *ptr = 0; + + do { + + ptr--; + *ptr = '0' + (i % 10); + + i /= 10; + + } while (i > 0 && ptr >= buffer); + + return guac_write_string(io, ptr); + +} + +ssize_t guac_write_string(GUACIO* io, const char* str) { + + char* out_buf = io->out_buf; + + int retval; + + for (; *str != '\0'; str++) { + + out_buf[io->written++] = *str; + + /* Flush when necessary, return on error */ + if (io->written > 8188 /* sizeof(out_buf) - 4 */) { + + struct timeval start, end; + suseconds_t elapsed; + + gettimeofday(&start, NULL); + retval = __guac_write(io, out_buf, io->written); + gettimeofday(&end, NULL); + + if (retval < 0) + return retval; + + /* Get elapsed time */ + elapsed = (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec; + + io->written = 0; + } + + } + + return 0; + +} + +ssize_t __guac_write_base64_triplet(GUACIO* io, int a, int b, int c) { + + char* out_buf = io->out_buf; + + int retval; + + /* Byte 1 */ + out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[(a & 0xFC) >> 2]; /* [AAAAAA]AABBBB BBBBCC CCCCCC */ + + if (b >= 0) { + out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4) | ((b & 0xF0) >> 4)]; /* AAAAAA[AABBBB]BBBBCC CCCCCC */ + + if (c >= 0) { + out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)]; /* AAAAAA AABBBB[BBBBCC]CCCCCC */ + out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[c & 0x3F]; /* AAAAAA AABBBB BBBBCC[CCCCCC] */ + } + else { + out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2)]; /* AAAAAA AABBBB[BBBB--]------ */ + out_buf[io->written++] = '='; /* AAAAAA AABBBB BBBB--[------] */ + } + } + else { + out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4)]; /* AAAAAA[AA----]------ ------ */ + out_buf[io->written++] = '='; /* AAAAAA AA----[------]------ */ + out_buf[io->written++] = '='; /* AAAAAA AA---- ------[------] */ + } + + /* At this point, 4 bytes have been io->written */ + + /* Flush when necessary, return on error */ + if (io->written > 8188 /* sizeof(out_buf) - 4 */) { + retval = __guac_write(io, out_buf, io->written); + if (retval < 0) + return retval; + + io->written = 0; + } + + if (b < 0) + return 1; + + if (c < 0) + return 2; + + return 3; + +} + +ssize_t __guac_write_base64_byte(GUACIO* io, char buf) { + + int* ready_buf = io->ready_buf; + + int retval; + + ready_buf[io->ready++] = buf & 0xFF; + + /* Flush triplet */ + if (io->ready == 3) { + retval = __guac_write_base64_triplet(io, ready_buf[0], ready_buf[1], ready_buf[2]); + if (retval < 0) + return retval; + + io->ready = 0; + } + + return 1; +} + +ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count) { + + int retval; + + const char* char_buf = (const char*) buf; + const char* end = char_buf + count; + + while (char_buf < end) { + + retval = __guac_write_base64_byte(io, *(char_buf++)); + if (retval < 0) + return retval; + + } + + return count; + +} + +ssize_t guac_flush(GUACIO* io) { + + int retval; + + /* Flush remaining bytes in buffer */ + if (io->written > 0) { + retval = __guac_write(io, io->out_buf, io->written); + if (retval < 0) + return retval; + + io->written = 0; + } + + return 0; + +} + +ssize_t guac_flush_base64(GUACIO* io) { + + int retval; + + /* Flush triplet to output buffer */ + while (io->ready > 0) { + retval = __guac_write_base64_byte(io, -1); + if (retval < 0) + return retval; + } + + return 0; + +} + + +int guac_select(GUACIO* io, int usec_timeout) { + + fd_set fds; + struct timeval timeout; + + if (usec_timeout < 0) + return select(io->fd + 1, &fds, NULL, NULL, NULL); + + timeout.tv_sec = usec_timeout/1000000; + timeout.tv_usec = usec_timeout%1000000; + + FD_ZERO(&fds); + FD_SET(io->fd, &fds); + + return select(io->fd + 1, &fds, NULL, NULL, &timeout); + +} + diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c new file mode 100644 index 00000000..a084d7b7 --- /dev/null +++ b/libguac/src/protocol.c @@ -0,0 +1,464 @@ + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "guacio.h" +#include "protocol.h" + +char* guac_escape_string(const char* str) { + + char* escaped; + char* current; + + int i; + int length = 0; + + /* Determine length */ + for (i=0; str[i] != '\0'; i++) { + switch (str[i]) { + + case ';': + case ',': + case '\\': + length += 2; + break; + + default: + length++; + + } + } + + /* Allocate new */ + escaped = malloc(length+1); + + current = escaped; + for (i=0; str[i] != '\0'; i++) { + switch (str[i]) { + + case ';': + *(current++) = '\\'; + *(current++) = 's'; + break; + + case ',': + *(current++) = '\\'; + *(current++) = 'c'; + break; + + case '\\': + *(current++) = '\\'; + *(current++) = '\\'; + break; + + default: + *(current++) = str[i]; + } + + } + + *current = '\0'; + + return escaped; + +} + +char* guac_unescape_string_inplace(char* str) { + + char* from; + char* to; + + from = to = str; + for (;;) { + + char c = *(from++); + + if (c == '\\') { + + c = *(from++); + if (c == 's') + *(to++) = ';'; + + else if (c == 'c') + *(to++) = ','; + + else if (c == '\\') + *(to++) = '\\'; + + else if (c == '\0') { + *(to++) = '\\'; + break; + } + + else { + *(to++) = '\\'; + *(to++) = c; + } + } + + else if (c == '\0') + break; + + else + *(to++) = c; + + } + + *to = '\0'; + + return str; + +} + +void guac_send_name(GUACIO* io, const char* name) { + + char* escaped = guac_escape_string(name); + + guac_write_string(io, "name:"); + guac_write_string(io, escaped); + guac_write_string(io, ";"); + + free(escaped); + +} + +void guac_send_size(GUACIO* io, int w, int h) { + guac_write_string(io, "size:"); + guac_write_int(io, w); + guac_write_string(io, ","); + guac_write_int(io, h); + guac_write_string(io, ";"); +} + +void guac_send_clipboard(GUACIO* io, const char* data) { + + char* escaped = guac_escape_string(data); + + guac_write_string(io, "clipboard:"); + guac_write_string(io, escaped); + guac_write_string(io, ";"); + + free(escaped); + +} + +void guac_send_error(GUACIO* io, const char* error) { + + char* escaped = guac_escape_string(error); + + guac_write_string(io, "error:"); + guac_write_string(io, escaped); + guac_write_string(io, ";"); + + free(escaped); + +} + +void guac_send_copy(GUACIO* io, int srcx, int srcy, int w, int h, int dstx, int dsty) { + guac_write_string(io, "copy:"); + guac_write_int(io, srcx); + guac_write_string(io, ","); + guac_write_int(io, srcy); + guac_write_string(io, ","); + guac_write_int(io, w); + guac_write_string(io, ","); + guac_write_int(io, h); + guac_write_string(io, ","); + guac_write_int(io, dstx); + guac_write_string(io, ","); + guac_write_int(io, dsty); + guac_write_string(io, ";"); +} + +void __guac_write_png(png_structp png, png_bytep data, png_size_t length) { + + if (guac_write_base64((GUACIO*) png->io_ptr, data, length) < 0) { + perror("Error writing PNG"); + png_error(png, "Error writing PNG"); + return; + } + +} + +void __guac_write_flush(png_structp png) { +} + +void guac_send_png(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h) { + + png_structp png; + png_infop png_info; + + /* Write image */ + + /* Set up PNG writer */ + png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png) { + perror("Error initializing libpng write structure"); + return; + } + + png_info = png_create_info_struct(png); + if (!png_info) { + perror("Error initializing libpng info structure"); + png_destroy_write_struct(&png, NULL); + return; + } + + /* Set error handler */ + if (setjmp(png_jmpbuf(png))) { + perror("Error setting handler"); + png_destroy_write_struct(&png, &png_info); + return; + } + + png_set_write_fn(png, io, __guac_write_png, __guac_write_flush); + + /* Set PNG IHDR */ + png_set_IHDR( + png, + png_info, + w, + h, + 8, + PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT + ); + + guac_write_string(io, "png:"); + guac_write_int(io, x); + guac_write_string(io, ","); + guac_write_int(io, y); + guac_write_string(io, ","); + png_set_rows(png, png_info, png_rows); + png_write_png(png, png_info, PNG_TRANSFORM_IDENTITY, NULL); + + if (guac_flush_base64(io) < 0) { + perror("Error flushing PNG"); + png_error(png, "Error flushing PNG"); + return; + } + + png_destroy_write_struct(&png, &png_info); + + guac_write_string(io, ";"); + +} + + +void guac_send_cursor(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h) { + + png_structp png; + png_infop png_info; + + /* Write image */ + + /* Set up PNG writer */ + png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png) { + perror("Error initializing libpng write structure"); + return; + } + + png_info = png_create_info_struct(png); + if (!png_info) { + perror("Error initializing libpng info structure"); + png_destroy_write_struct(&png, NULL); + return; + } + + /* Set error handler */ + if (setjmp(png_jmpbuf(png))) { + perror("Error setting handler"); + png_destroy_write_struct(&png, &png_info); + return; + } + + png_set_write_fn(png, io, __guac_write_png, __guac_write_flush); + + /* Set PNG IHDR */ + png_set_IHDR( + png, + png_info, + w, + h, + 8, + PNG_COLOR_TYPE_RGBA, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT + ); + + guac_write_string(io, "cursor:"); + guac_write_int(io, x); + guac_write_string(io, ","); + guac_write_int(io, y); + guac_write_string(io, ","); + png_set_rows(png, png_info, png_rows); + png_write_png(png, png_info, PNG_TRANSFORM_IDENTITY, NULL); + + if (guac_flush_base64(io) < 0) { + perror("Error flushing PNG"); + png_error(png, "Error flushing PNG"); + return; + } + + png_destroy_write_struct(&png, &png_info); + + guac_write_string(io, ";"); + +} + + +int __guac_fill_instructionbuf(GUACIO* io) { + + int retval; + + /* Attempt to fill buffer */ + retval = recv( + io->fd, + io->instructionbuf + io->instructionbuf_used_length, + io->instructionbuf_size - io->instructionbuf_used_length, + 0 + ); + + if (retval < 0) + return retval; + + io->instructionbuf_used_length += retval; + + /* Expand buffer if necessary */ + if (io->instructionbuf_used_length > io->instructionbuf_size / 2) { + io->instructionbuf_size *= 2; + io->instructionbuf = realloc(io->instructionbuf, io->instructionbuf_size); + } + + return retval; + +} + +/* Returns new instruction if one exists, or NULL if no more instructions. */ +int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction) { + + int retval; + int i = 0; + int argcount = 0; + int j; + int current_arg = 0; + + /* Loop until a instruction is read */ + for (;;) { + + /* Search for end of instruction */ + for (; i < io->instructionbuf_used_length; i++) { + + /* Count arguments as we look for the end */ + if (io->instructionbuf[i] == ',') + argcount++; + else if (io->instructionbuf[i] == ':' && argcount == 0) + argcount++; + + /* End found ... */ + else if (io->instructionbuf[i] == ';') { + + /* Parse new instruction */ + char* instruction = malloc(i+1); + memcpy(instruction, io->instructionbuf, i+1); + instruction[i] = '\0'; /* Replace semicolon with null terminator. */ + + parsed_instruction->opcode = NULL; + + parsed_instruction->argc = argcount; + parsed_instruction->argv = malloc(sizeof(char*) * argcount); + + for (j=0; jopcode == NULL) { + instruction[j] = '\0'; + parsed_instruction->argv[current_arg++] = &(instruction[j+1]); + parsed_instruction->opcode = instruction; + } + + /* If encountered a comma, set following argument */ + else if (instruction[j] == ',') { + instruction[j] = '\0'; + parsed_instruction->argv[current_arg++] = &(instruction[j+1]); + } + } + + /* If no arguments, set opcode to entire instruction */ + if (parsed_instruction->opcode == NULL) + parsed_instruction->opcode = instruction; + + /* Found. Reset buffer */ + memmove(io->instructionbuf, io->instructionbuf + i + 1, io->instructionbuf_used_length - i - 1); + io->instructionbuf_used_length -= i + 1; + + /* Done */ + return 1; + } + + } + + /* No instruction yet? Get more data ... */ + retval = guac_select(io, 1000); + if (retval <= 0) + return retval; + + retval = __guac_fill_instructionbuf(io); + if (retval < 0) + return retval; + + if (retval == 0) + return -1; /* EOF */ + } + +} + +void guac_free_instruction_data(guac_instruction* instruction) { + free(instruction->opcode); + + if (instruction->argv) + free(instruction->argv); +} + +void guac_free_instruction(guac_instruction* instruction) { + guac_free_instruction_data(instruction); + free(instruction); +} + + +int guac_instructions_waiting(GUACIO* io) { + + if (io->instructionbuf_used_length > 0) + return 1; + + return guac_select(io, 1000); +} + From 7cab7d0d2fe8da6a060ae601a5ed8bdf7d1bcec0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 14 Dec 2010 01:27:28 -0800 Subject: [PATCH 002/330] Adding .gitignore --- libguac/.gitignore | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 libguac/.gitignore diff --git a/libguac/.gitignore b/libguac/.gitignore new file mode 100644 index 00000000..e37f9166 --- /dev/null +++ b/libguac/.gitignore @@ -0,0 +1,35 @@ + +# Object code +*.o +*.so +*.lo +*.la + +# Backup files +*~ + +# Release files +*.tar.gz + +# Files currently being edited by vim or vi +*.swp + +# automake/autoconf +.deps/ +.libs/ +Makefile +Makefile.in +aclocal.m4 +autom4te.cache/ +m4/ +config.guess +config.log +config.status +config.sub +configure +depcomp +install-sh +libtool +ltmain.sh +missing + From 36728eb34ed9b96f68f1b96baec38ceb346fc8a2 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 15 Dec 2010 11:41:03 -0800 Subject: [PATCH 003/330] configure.in should specify errors for missing libs --- libguac/configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/configure.in b/libguac/configure.in index 622be0ef..5ed6f722 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -11,7 +11,7 @@ AC_PROG_LIBTOOL # Checks for libraries. AC_CHECK_LIB([dl], [dlopen],, AC_MSG_ERROR("libdl is required for loading client plugins")) -AC_CHECK_LIB([png], [png_write_png]) +AC_CHECK_LIB([png], [png_write_png],, AC_MSG_ERROR("libpng is required for writing png messages")) # Checks for header files. AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h]) From c9c2295dbd33a4714bfd3c7d2b3193b79bb0c560 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 17 Dec 2010 15:10:00 -0800 Subject: [PATCH 004/330] Adding package descriptor for build system --- libguac/.package.dsc | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 libguac/.package.dsc diff --git a/libguac/.package.dsc b/libguac/.package.dsc new file mode 100644 index 00000000..d24d088f --- /dev/null +++ b/libguac/.package.dsc @@ -0,0 +1,2 @@ +PKGNAME=libguac +VERSION=0.0.1 From 62a886d258aad3f35ed2c4ad507b4960ba933efb Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 22 Dec 2010 02:04:09 -0800 Subject: [PATCH 005/330] Fixing leak in client init - GUACIO must be closed (and thus free'd) on init error --- libguac/src/client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libguac/src/client.c b/libguac/src/client.c index 7ac1bd45..4e9e3bb8 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -98,6 +98,7 @@ guac_client* guac_get_client(int client_fd) { int result = guac_read_instruction(io, &instruction); if (result < 0) { syslog(LOG_ERR, "Error reading instruction while waiting for connect"); + guac_close(io); return NULL; } @@ -121,6 +122,7 @@ guac_client* guac_get_client(int client_fd) { syslog(LOG_ERR, "Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); guac_send_error(io, "Could not load server-side client plugin."); guac_flush(io); + guac_close(io); guac_free_instruction_data(&instruction); return NULL; } @@ -134,6 +136,7 @@ guac_client* guac_get_client(int client_fd) { syslog(LOG_ERR, "Could not get guac_client_init in plugin: %s\n", error); guac_send_error(io, "Invalid server-side client plugin."); guac_flush(io); + guac_close(io); guac_free_instruction_data(&instruction); return NULL; } @@ -145,6 +148,7 @@ guac_client* guac_get_client(int client_fd) { if (alias.client_init(client, argc, argv) != 0) { /* NOTE: On error, proxy client will send appropriate error message */ guac_free_instruction_data(&instruction); + guac_close(io); return NULL; } From 46a9529aa4ef0e1f4ad4af16ab2fad365ada1bf1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 22 Dec 2010 22:31:20 -0800 Subject: [PATCH 006/330] Fixed leak of instruction buffer - missing free in guac_close --- libguac/src/guacio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index b6a8a368..e9f0e5b9 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -57,6 +57,7 @@ GUACIO* guac_open(int fd) { void guac_close(GUACIO* io) { guac_flush(io); + free(io->instructionbuf); free(io); } From 455c340318656f9459d3b02303f72f59da38b9fb Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 1 Jan 2011 13:22:17 -0800 Subject: [PATCH 007/330] Implemented select message, allowing args definition. --- libguac/include/protocol.h | 9 +++++++ libguac/src/client.c | 54 ++++++++++++++++++++++++++++++++++---- libguac/src/protocol.c | 21 +++++++++++++++ 3 files changed, 79 insertions(+), 5 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 685a112b..e59167f1 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -95,6 +95,15 @@ char* guac_escape_string(const char* str); */ char* guac_unescape_string_inplace(char* str); +/** + * Sends an args instruction over the given GUACIO connection. Each + * argument name will be automatically escaped for transmission. + * + * @param io The GUACIO connection to use. + * @param args The NULL-terminated array of argument names (strings). + */ +void guac_send_args(GUACIO* io, const char** name); + /** * Sends a name instruction over the given GUACIO connection. The * name given will be automatically escaped for transmission. diff --git a/libguac/src/client.c b/libguac/src/client.c index 4e9e3bb8..fa4cf16d 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -85,27 +85,30 @@ guac_client* guac_get_client(int client_fd) { char* error; + /* Client args description */ + const char** client_args; + /* Client arguments */ int argc; char** argv; - /* Connect instruction */ + /* Instruction */ guac_instruction instruction; - /* Wait for connect instruction */ + /* Wait for select instruction */ for (;;) { int result = guac_read_instruction(io, &instruction); if (result < 0) { - syslog(LOG_ERR, "Error reading instruction while waiting for connect"); + syslog(LOG_ERR, "Error reading instruction while waiting for select"); guac_close(io); return NULL; } - /* Connect instruction read */ + /* Select instruction read */ if (result > 0) { - if (strcmp(instruction.opcode, "connect") == 0) { + if (strcmp(instruction.opcode, "select") == 0) { /* Get protocol from message */ char* protocol = instruction.argv[0]; @@ -141,6 +144,47 @@ guac_client* guac_get_client(int client_fd) { return NULL; } + /* Get usage strig */ + client_args = (const char**) dlsym(client->client_plugin_handle, "GUAC_CLIENT_ARGS"); + + if ((error = dlerror()) != NULL) { + syslog(LOG_ERR, "Could not get GUAC_CLIENT_ in plugin: %s\n", error); + guac_send_error(io, "Invalid server-side client plugin."); + guac_flush(io); + guac_close(io); + guac_free_instruction_data(&instruction); + return NULL; + } + + /* Send args */ + guac_send_args(io, client_args); + guac_flush(io); + + guac_free_instruction_data(&instruction); + break; + + } /* end if select */ + + guac_free_instruction_data(&instruction); + } + + } + + /* Wait for connect instruction */ + for (;;) { + + int result = guac_read_instruction(io, &instruction); + if (result < 0) { + syslog(LOG_ERR, "Error reading instruction while waiting for connect"); + guac_close(io); + return NULL; + } + + /* Connect instruction read */ + if (result > 0) { + + if (strcmp(instruction.opcode, "connect") == 0) { + /* Initialize client arguments */ argc = instruction.argc; argv = instruction.argv; diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index a084d7b7..4d3110e6 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -134,6 +134,27 @@ char* guac_unescape_string_inplace(char* str) { } +void guac_send_args(GUACIO* io, const char** args) { + + int i; + + guac_write_string(io, "args:"); + + for (i=0; args[i] != NULL; i++) { + + if (i > 0) + guac_write_string(io, ","); + + char* escaped = guac_escape_string(args[i]); + guac_write_string(io, escaped); + free(escaped); + + } + + guac_write_string(io, ";"); + +} + void guac_send_name(GUACIO* io, const char* name) { char* escaped = guac_escape_string(name); From 859e739daef75571dfa0a40d53076711e93c0c4a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 21 Jan 2011 03:11:13 -0800 Subject: [PATCH 008/330] Support for "ready" message (both client and server) --- libguac/include/protocol.h | 14 ++++++++++++++ libguac/src/client.c | 32 +++++++++++++++++++------------- libguac/src/protocol.c | 4 ++++ 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index e59167f1..92d93ac9 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -123,6 +123,20 @@ void guac_send_name(GUACIO* io, const char* name); */ void guac_send_error(GUACIO* io, const char* error); +/** + * Sends a ready instruction over the given GUACIO connection. The + * ready instruction merely signals the client that its ready + * instruction has been handled. The ready exchange is intended to + * synchronize instruction handling (if needed) and serve as a health + * indicator for both client and server. + * + * Normally, this functino should not be called by client plugins, as + * the ready instruction will be handled automatically. + * + * @param io The GUACIO connection to use. + */ +void guac_send_ready(GUACIO* io); + /** * Sends a clipboard instruction over the given GUACIO connection. The * clipboard data given will be automatically escaped for transmission. diff --git a/libguac/src/client.c b/libguac/src/client.c index fa4cf16d..647ddc96 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -236,18 +236,6 @@ void guac_start_client(guac_client* client) { /* VNC Client Loop */ for (;;) { - /* Handle server messages */ - if (client->handle_messages) { - - int retval = client->handle_messages(client); - if (retval) { - syslog(LOG_ERR, "Error handling server messages"); - return; - } - - guac_flush(io); - } - wait_result = guac_instructions_waiting(io); if (wait_result > 0) { @@ -258,7 +246,25 @@ void guac_start_client(guac_client* client) { do { - if (strcmp(instruction.opcode, "mouse") == 0) { + if (strcmp(instruction.opcode, "ready") == 0) { + + /* Handle server messages */ + if (client->handle_messages) { + + int retval = client->handle_messages(client); + if (retval) { + syslog(LOG_ERR, "Error handling server messages"); + return; + } + + } + + guac_send_ready(io); + guac_flush(io); + + } + + else if (strcmp(instruction.opcode, "mouse") == 0) { if (client->mouse_handler) if ( client->mouse_handler( diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 4d3110e6..f4c6c2f5 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -175,6 +175,10 @@ void guac_send_size(GUACIO* io, int w, int h) { guac_write_string(io, ";"); } +void guac_send_ready(GUACIO* io) { + guac_write_string(io, "ready;"); +} + void guac_send_clipboard(GUACIO* io, const char* data) { char* escaped = guac_escape_string(data); From 84d79fc2ba096713e92d9242af6aeb494a838659 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 21 Jan 2011 09:39:49 -0800 Subject: [PATCH 009/330] Reverting (partially) ready message change - seems slower --- libguac/src/client.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index 647ddc96..96ab0d3c 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -236,6 +236,19 @@ void guac_start_client(guac_client* client) { /* VNC Client Loop */ for (;;) { + /* Handle server messages */ + if (client->handle_messages) { + + int retval = client->handle_messages(client); + if (retval) { + syslog(LOG_ERR, "Error handling server messages"); + return; + } + + guac_flush(io); + + } + wait_result = guac_instructions_waiting(io); if (wait_result > 0) { @@ -247,21 +260,8 @@ void guac_start_client(guac_client* client) { do { if (strcmp(instruction.opcode, "ready") == 0) { - - /* Handle server messages */ - if (client->handle_messages) { - - int retval = client->handle_messages(client); - if (retval) { - syslog(LOG_ERR, "Error handling server messages"); - return; - } - - } - guac_send_ready(io); guac_flush(io); - } else if (strcmp(instruction.opcode, "mouse") == 0) { From f60824686f50d6e2d15f111935a68317335da7de Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 21 Jan 2011 20:00:14 -0800 Subject: [PATCH 010/330] Removed experimental ready instruction --- libguac/include/protocol.h | 14 -------------- libguac/src/client.c | 7 +------ libguac/src/protocol.c | 4 ---- 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 92d93ac9..e59167f1 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -123,20 +123,6 @@ void guac_send_name(GUACIO* io, const char* name); */ void guac_send_error(GUACIO* io, const char* error); -/** - * Sends a ready instruction over the given GUACIO connection. The - * ready instruction merely signals the client that its ready - * instruction has been handled. The ready exchange is intended to - * synchronize instruction handling (if needed) and serve as a health - * indicator for both client and server. - * - * Normally, this functino should not be called by client plugins, as - * the ready instruction will be handled automatically. - * - * @param io The GUACIO connection to use. - */ -void guac_send_ready(GUACIO* io); - /** * Sends a clipboard instruction over the given GUACIO connection. The * clipboard data given will be automatically escaped for transmission. diff --git a/libguac/src/client.c b/libguac/src/client.c index 96ab0d3c..eae2dc56 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -259,12 +259,7 @@ void guac_start_client(guac_client* client) { do { - if (strcmp(instruction.opcode, "ready") == 0) { - guac_send_ready(io); - guac_flush(io); - } - - else if (strcmp(instruction.opcode, "mouse") == 0) { + if (strcmp(instruction.opcode, "mouse") == 0) { if (client->mouse_handler) if ( client->mouse_handler( diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index f4c6c2f5..4d3110e6 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -175,10 +175,6 @@ void guac_send_size(GUACIO* io, int w, int h) { guac_write_string(io, ";"); } -void guac_send_ready(GUACIO* io) { - guac_write_string(io, "ready;"); -} - void guac_send_clipboard(GUACIO* io, const char* data) { char* escaped = guac_escape_string(data); From fd1485e22014bfe96ea5b39141ed00177638c09b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 8 Feb 2011 18:02:27 -0800 Subject: [PATCH 011/330] Added cross-platform logging. --- libguac/include/guaclog.h | 38 ++++++++++++++++++++++++++++++++++++++ libguac/src/client.c | 34 ++++++++++++++++------------------ 2 files changed, 54 insertions(+), 18 deletions(-) create mode 100644 libguac/include/guaclog.h diff --git a/libguac/include/guaclog.h b/libguac/include/guaclog.h new file mode 100644 index 00000000..22dd637a --- /dev/null +++ b/libguac/include/guaclog.h @@ -0,0 +1,38 @@ + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _GUACLOG_H +#define _GUACLOG_H + +#ifndef __MINGW32__ + + // Logging for UNIX + #include + #define GUAC_LOG_ERROR(...) syslog(LOG_ERR, __VA_ARGS__) + #define GUAC_LOG_INFO(...) syslog(LOG_INFO, __VA_ARGS__) + +#else + + // Logging for W32 + #define GUAC_LOG_ERROR(...) fprintf(stderr, __VA_ARGS__) + #define GUAC_LOG_INFO(...) fprintf(stderr, __VA_ARGS__) + +#endif + +#endif diff --git a/libguac/src/client.c b/libguac/src/client.c index eae2dc56..0a569130 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -20,11 +20,9 @@ #include #include #include - -#include - #include +#include "guaclog.h" #include "guacio.h" #include "protocol.h" #include "client.h" @@ -100,7 +98,7 @@ guac_client* guac_get_client(int client_fd) { int result = guac_read_instruction(io, &instruction); if (result < 0) { - syslog(LOG_ERR, "Error reading instruction while waiting for select"); + GUAC_LOG_ERROR("Error reading instruction while waiting for select"); guac_close(io); return NULL; } @@ -122,7 +120,7 @@ guac_client* guac_get_client(int client_fd) { /* Load client plugin */ client->client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); if (!(client->client_plugin_handle)) { - syslog(LOG_ERR, "Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); + GUAC_LOG_ERROR("Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); guac_send_error(io, "Could not load server-side client plugin."); guac_flush(io); guac_close(io); @@ -136,7 +134,7 @@ guac_client* guac_get_client(int client_fd) { alias.obj = dlsym(client->client_plugin_handle, "guac_client_init"); if ((error = dlerror()) != NULL) { - syslog(LOG_ERR, "Could not get guac_client_init in plugin: %s\n", error); + GUAC_LOG_ERROR("Could not get guac_client_init in plugin: %s\n", error); guac_send_error(io, "Invalid server-side client plugin."); guac_flush(io); guac_close(io); @@ -148,7 +146,7 @@ guac_client* guac_get_client(int client_fd) { client_args = (const char**) dlsym(client->client_plugin_handle, "GUAC_CLIENT_ARGS"); if ((error = dlerror()) != NULL) { - syslog(LOG_ERR, "Could not get GUAC_CLIENT_ in plugin: %s\n", error); + GUAC_LOG_ERROR("Could not get GUAC_CLIENT_ in plugin: %s\n", error); guac_send_error(io, "Invalid server-side client plugin."); guac_flush(io); guac_close(io); @@ -175,7 +173,7 @@ guac_client* guac_get_client(int client_fd) { int result = guac_read_instruction(io, &instruction); if (result < 0) { - syslog(LOG_ERR, "Error reading instruction while waiting for connect"); + GUAC_LOG_ERROR("Error reading instruction while waiting for connect"); guac_close(io); return NULL; } @@ -213,14 +211,14 @@ void guac_free_client(guac_client* client) { if (client->free_handler) { if (client->free_handler(client)) - syslog(LOG_ERR, "Error calling client free handler"); + GUAC_LOG_ERROR("Error calling client free handler"); } guac_close(client->io); /* Unload client plugin */ if (dlclose(client->client_plugin_handle)) { - syslog(LOG_ERR, "Could not close client plugin while unloading client: %s", dlerror()); + GUAC_LOG_ERROR("Could not close client plugin while unloading client: %s", dlerror()); } free(client); @@ -241,7 +239,7 @@ void guac_start_client(guac_client* client) { int retval = client->handle_messages(client); if (retval) { - syslog(LOG_ERR, "Error handling server messages"); + GUAC_LOG_ERROR("Error handling server messages"); return; } @@ -270,7 +268,7 @@ void guac_start_client(guac_client* client) { ) ) { - syslog(LOG_ERR, "Error handling mouse instruction"); + GUAC_LOG_ERROR("Error handling mouse instruction"); guac_free_instruction_data(&instruction); return; @@ -287,7 +285,7 @@ void guac_start_client(guac_client* client) { ) ) { - syslog(LOG_ERR, "Error handling key instruction"); + GUAC_LOG_ERROR("Error handling key instruction"); guac_free_instruction_data(&instruction); return; @@ -303,7 +301,7 @@ void guac_start_client(guac_client* client) { ) ) { - syslog(LOG_ERR, "Error handling clipboard instruction"); + GUAC_LOG_ERROR("Error handling clipboard instruction"); guac_free_instruction_data(&instruction); return; @@ -311,7 +309,7 @@ void guac_start_client(guac_client* client) { } else if (strcmp(instruction.opcode, "disconnect") == 0) { - syslog(LOG_INFO, "Client requested disconnect"); + GUAC_LOG_INFO("Client requested disconnect"); guac_free_instruction_data(&instruction); return; } @@ -321,13 +319,13 @@ void guac_start_client(guac_client* client) { } while ((retval = guac_read_instruction(io, &instruction)) > 0); if (retval < 0) { - syslog(LOG_ERR, "Error reading instruction from stream"); + GUAC_LOG_ERROR("Error reading instruction from stream"); return; } } if (retval < 0) { - syslog(LOG_ERR, "Error or end of stream"); + GUAC_LOG_ERROR("Error or end of stream"); return; /* EOF or error */ } @@ -335,7 +333,7 @@ void guac_start_client(guac_client* client) { } else if (wait_result < 0) { - syslog(LOG_ERR, "Error waiting for next instruction"); + GUAC_LOG_ERROR("Error waiting for next instruction"); return; } From 9c7c09cd7f47bd5fd0470614232d5d7c6f5eefde Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 8 Feb 2011 18:23:10 -0800 Subject: [PATCH 012/330] Removed transfer limit, improved cross-platform logging, added check for png_structp. --- libguac/include/guacio.h | 7 ------ libguac/include/guaclog.h | 6 ++--- libguac/src/guacio.c | 49 +++++---------------------------------- libguac/src/protocol.c | 10 ++++++++ 4 files changed, 19 insertions(+), 53 deletions(-) diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index 8499ea3e..da4aa8f5 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -79,13 +79,6 @@ typedef struct GUACIO { */ char* instructionbuf; - /** - * The transfer limit, in kilobytes per second. If 0, there is no - * transfer limit. If non-zero, sleep calls are used at the end of - * a write to ensure output never exceeds the specified limit. - */ - unsigned int transfer_limit; /* KB/sec */ - } GUACIO; /** diff --git a/libguac/include/guaclog.h b/libguac/include/guaclog.h index 22dd637a..a59c2318 100644 --- a/libguac/include/guaclog.h +++ b/libguac/include/guaclog.h @@ -20,16 +20,16 @@ #ifndef _GUACLOG_H #define _GUACLOG_H -#ifndef __MINGW32__ +#ifdef HAVE_SYSLOG_H - // Logging for UNIX + /* Logging for UNIX */ #include #define GUAC_LOG_ERROR(...) syslog(LOG_ERR, __VA_ARGS__) #define GUAC_LOG_INFO(...) syslog(LOG_INFO, __VA_ARGS__) #else - // Logging for W32 + /* Logging for W32 */ #define GUAC_LOG_ERROR(...) fprintf(stderr, __VA_ARGS__) #define GUAC_LOG_INFO(...) fprintf(stderr, __VA_ARGS__) diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index e9f0e5b9..c0a14b8e 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -23,8 +23,13 @@ #include #include -#include +#ifdef __MINGW32__ +#include +#else #include +#endif + +#include #include #include "guacio.h" @@ -48,9 +53,6 @@ GUACIO* guac_open(int fd) { io->instructionbuf = malloc(io->instructionbuf_size); io->instructionbuf_used_length = 0; - /* Set limit */ - io->transfer_limit = 0; - return io; } @@ -64,41 +66,10 @@ void guac_close(GUACIO* io) { /* Write bytes, limit rate */ ssize_t __guac_write(GUACIO* io, const char* buf, int count) { - struct timeval start, end; int retval; /* Write and time how long the write takes (microseconds) */ - gettimeofday(&start, NULL); retval = write(io->fd, buf, count); - gettimeofday(&end, NULL); - - if (retval < 0) - return retval; - - if (io->transfer_limit > 0) { - - suseconds_t elapsed; - suseconds_t required_usecs; - - /* Get elapsed time */ - elapsed = (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec; - - /* Calculate how much time we must sleep */ - required_usecs = retval * 1000 / io->transfer_limit - elapsed; /* useconds at transfer_limit KB/s*/ - - /* Sleep as necessary */ - if (required_usecs > 0) { - - struct timespec required_sleep; - - required_sleep.tv_sec = required_usecs / 1000000; - required_sleep.tv_nsec = (required_usecs % 1000000) * 1000; - - nanosleep(&required_sleep, NULL); - - } - - } return retval; } @@ -136,19 +107,11 @@ ssize_t guac_write_string(GUACIO* io, const char* str) { /* Flush when necessary, return on error */ if (io->written > 8188 /* sizeof(out_buf) - 4 */) { - struct timeval start, end; - suseconds_t elapsed; - - gettimeofday(&start, NULL); retval = __guac_write(io, out_buf, io->written); - gettimeofday(&end, NULL); if (retval < 0) return retval; - /* Get elapsed time */ - elapsed = (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec; - io->written = 0; } diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 4d3110e6..f050a868 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -23,8 +23,18 @@ #include #include +/* If png_structp not defined in png.h, try to include pngstruct.h */ +#ifndef png_structp +#include +#endif + #include + +#ifdef __MINGW32__ +#include +#else #include +#endif #include "guacio.h" #include "protocol.h" From e37507d31282997ff81411f0fde45c512599d972 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 8 Feb 2011 18:39:08 -0800 Subject: [PATCH 013/330] Added check for wsock32 --- libguac/configure.in | 1 + 1 file changed, 1 insertion(+) diff --git a/libguac/configure.in b/libguac/configure.in index 5ed6f722..76a93868 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -12,6 +12,7 @@ AC_PROG_LIBTOOL # Checks for libraries. AC_CHECK_LIB([dl], [dlopen],, AC_MSG_ERROR("libdl is required for loading client plugins")) AC_CHECK_LIB([png], [png_write_png],, AC_MSG_ERROR("libpng is required for writing png messages")) +AC_CHECK_LIB([wsock32], [main]) # Checks for header files. AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h]) From 60897fc7f8f77c4ab7d9c2a11302091f818cbf88 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 9 Feb 2011 01:39:27 -0800 Subject: [PATCH 014/330] Renamed guaclog.h, added newline to macro --- libguac/Makefile.am | 2 +- libguac/include/{guaclog.h => log.h} | 8 ++++---- libguac/src/client.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename libguac/include/{guaclog.h => log.h} (83%) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index f20371cc..5801e5f7 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -4,7 +4,7 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -Iinclude libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h +libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/log.h lib_LTLIBRARIES = libguac.la diff --git a/libguac/include/guaclog.h b/libguac/include/log.h similarity index 83% rename from libguac/include/guaclog.h rename to libguac/include/log.h index a59c2318..e8499f16 100644 --- a/libguac/include/guaclog.h +++ b/libguac/include/log.h @@ -17,8 +17,8 @@ * along with this program. If not, see . */ -#ifndef _GUACLOG_H -#define _GUACLOG_H +#ifndef _LOG_H +#define _LOG_H #ifdef HAVE_SYSLOG_H @@ -30,8 +30,8 @@ #else /* Logging for W32 */ - #define GUAC_LOG_ERROR(...) fprintf(stderr, __VA_ARGS__) - #define GUAC_LOG_INFO(...) fprintf(stderr, __VA_ARGS__) + #define GUAC_LOG_ERROR(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n") + #define GUAC_LOG_INFO(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n") #endif diff --git a/libguac/src/client.c b/libguac/src/client.c index 0a569130..e5bc4979 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -22,7 +22,7 @@ #include #include -#include "guaclog.h" +#include "log.h" #include "guacio.h" #include "protocol.h" #include "client.h" From 0cb6ad1502012224c85b920999e5487c8af70ae2 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 10 Feb 2011 00:24:17 -0800 Subject: [PATCH 015/330] Use send() instead of write() if MINGW32. --- libguac/src/guacio.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index c0a14b8e..78ec98d6 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -68,8 +68,13 @@ ssize_t __guac_write(GUACIO* io, const char* buf, int count) { int retval; - /* Write and time how long the write takes (microseconds) */ +#ifdef __MINGW32__ + /* MINGW32 WINSOCK only works with send() */ + retval = send(io->fd, buf, count, 0); +#else + /* Use write() for all other platforms */ retval = write(io->fd, buf, count); +#endif return retval; } From a0cb37295f9d849af86fd8062c922c9e76b616a0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 10 Feb 2011 23:53:11 -0800 Subject: [PATCH 016/330] Fixed pngstruct.h detection --- libguac/configure.in | 2 +- libguac/src/protocol.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index 76a93868..c401cf1c 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -15,7 +15,7 @@ AC_CHECK_LIB([png], [png_write_png],, AC_MSG_ERROR("libpng is required for writi AC_CHECK_LIB([wsock32], [main]) # Checks for header files. -AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h]) +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h pngstruct.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index f050a868..a2427f21 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -23,8 +23,7 @@ #include #include -/* If png_structp not defined in png.h, try to include pngstruct.h */ -#ifndef png_structp +#ifdef HAVE_PNGSTRUCT_H #include #endif From 3e6b22b07124d75cad270f2bbd7e5d4c58337a6c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 11 Feb 2011 23:16:46 -0800 Subject: [PATCH 017/330] Layer/buffer support in png and copy instructions --- libguac/include/protocol.h | 16 +++++++++++----- libguac/src/protocol.c | 10 ++++++++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index e59167f1..78999b5e 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -145,22 +145,26 @@ void guac_send_size(GUACIO* io, int w, int h); * Sends a copy instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. + * @param srcl The index of the source layer. * @param srcx The X coordinate of the source rectangle. * @param srcy The Y coordinate of the source rectangle. * @param w The width of the source rectangle. * @param h The height of the source rectangle. + * @param dstl The index of the destination layer. * @param dstx The X coordinate of the destination, where the source rectangle * should be copied. * @param dsty The Y coordinate of the destination, where the source rectangle * should be copied. */ -void guac_send_copy(GUACIO* io, int srcx, int srcy, int w, int h, int dstx, int dsty); +void guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, + int dstl, int dstx, int dsty); /** * Sends a png instruction over the given GUACIO connection. The PNG image data * given will be automatically base64-encoded for transmission. * * @param io The GUACIO connection to use. + * @param layer The index of the destination layer. * @param x The destination X coordinate. * @param y The destination Y coordinate. * @param png_rows A libpng-compatible PNG image buffer containing the image @@ -168,21 +172,23 @@ void guac_send_copy(GUACIO* io, int srcx, int srcy, int w, int h, int dstx, int * @param w The width of the image in the image buffer. * @param h The height of the image in the image buffer. */ -void guac_send_png(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h); +void guac_send_png(GUACIO* io, int layer, int x, int y, + png_byte** png_rows, int w, int h); /** * Sends a cursor instruction over the given GUACIO connection. The PNG image * data given will be automatically base64-encoded for transmission. * * @param io The GUACIO connection to use. - * @param x The destination X coordinate. - * @param y The destination Y coordinate. + * @param x The X coordinate of the cursor hotspot. + * @param y The Y coordinate of the cursor hotspot. * @param png_rows A libpng-compatible PNG image buffer containing the image * data to send. * @param w The width of the image in the image buffer. * @param h The height of the image in the image buffer. */ -void guac_send_cursor(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h); +void guac_send_cursor(GUACIO* io, int x, int y, + png_byte** png_rows, int w, int h); /** * Returns whether new instruction data is available on the given GUACIO diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 4d3110e6..5a37e403 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -199,8 +199,10 @@ void guac_send_error(GUACIO* io, const char* error) { } -void guac_send_copy(GUACIO* io, int srcx, int srcy, int w, int h, int dstx, int dsty) { +void guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int dstl, int dstx, int dsty) { guac_write_string(io, "copy:"); + guac_write_int(io, srcl); + guac_write_string(io, ","); guac_write_int(io, srcx); guac_write_string(io, ","); guac_write_int(io, srcy); @@ -209,6 +211,8 @@ void guac_send_copy(GUACIO* io, int srcx, int srcy, int w, int h, int dstx, int guac_write_string(io, ","); guac_write_int(io, h); guac_write_string(io, ","); + guac_write_int(io, dstl); + guac_write_string(io, ","); guac_write_int(io, dstx); guac_write_string(io, ","); guac_write_int(io, dsty); @@ -228,7 +232,7 @@ void __guac_write_png(png_structp png, png_bytep data, png_size_t length) { void __guac_write_flush(png_structp png) { } -void guac_send_png(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h) { +void guac_send_png(GUACIO* io, int layer, int x, int y, png_byte** png_rows, int w, int h) { png_structp png; png_infop png_info; @@ -272,6 +276,8 @@ void guac_send_png(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h) ); guac_write_string(io, "png:"); + guac_write_int(io, layer); + guac_write_string(io, ","); guac_write_int(io, x); guac_write_string(io, ","); guac_write_int(io, y); From d32b26ffa821d83f2f73ad208a6b74ccc51eead1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 15 Feb 2011 18:04:36 -0800 Subject: [PATCH 018/330] Changing to MPL/GPL/LGPL tri-license --- libguac/COPYING | 1131 +++++++++++++++--------------------- libguac/include/client.h | 47 +- libguac/include/guacio.h | 46 +- libguac/include/log.h | 46 +- libguac/include/protocol.h | 46 +- libguac/src/client.c | 46 +- libguac/src/guacio.c | 46 +- libguac/src/protocol.c | 46 +- 8 files changed, 695 insertions(+), 759 deletions(-) diff --git a/libguac/COPYING b/libguac/COPYING index dba13ed2..7714141d 100644 --- a/libguac/COPYING +++ b/libguac/COPYING @@ -1,661 +1,470 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + diff --git a/libguac/include/client.h b/libguac/include/client.h index 7ece35b7..13938398 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -1,21 +1,40 @@ -/* - * Guacamole - Clientless Remote Desktop - * Copyright (C) 2010 Michael Jumper +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + #ifndef _CLIENT_H #define _CLIENT_H diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index da4aa8f5..0e70c0ea 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -1,21 +1,39 @@ -/* - * Guacamole - Clientless Remote Desktop - * Copyright (C) 2010 Michael Jumper +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ #ifndef _GUACIO_H #define _GUACIO_H diff --git a/libguac/include/log.h b/libguac/include/log.h index e8499f16..0bf039c1 100644 --- a/libguac/include/log.h +++ b/libguac/include/log.h @@ -1,21 +1,39 @@ -/* - * Guacamole - Clientless Remote Desktop - * Copyright (C) 2010 Michael Jumper +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ #ifndef _LOG_H #define _LOG_H diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 78999b5e..6b631ca3 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -1,21 +1,39 @@ -/* - * Guacamole - Clientless Remote Desktop - * Copyright (C) 2010 Michael Jumper +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ #ifndef __PROTOCOL_H #define __PROTOCOL_H diff --git a/libguac/src/client.c b/libguac/src/client.c index e5bc4979..821ec959 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -1,21 +1,39 @@ -/* - * Guacamole - Clientless Remote Desktop - * Copyright (C) 2010 Michael Jumper +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ #include #include diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index 78ec98d6..c27fe5a7 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -1,21 +1,39 @@ -/* - * Guacamole - Clientless Remote Desktop - * Copyright (C) 2010 Michael Jumper +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ #include #include diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index ec63a5da..78cca00f 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -1,21 +1,39 @@ -/* - * Guacamole - Clientless Remote Desktop - * Copyright (C) 2010 Michael Jumper +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ #include #include From 5cdfad50e677d205e5c6fcff3c5bb465c395cf60 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 15 Feb 2011 18:07:19 -0800 Subject: [PATCH 019/330] Detect and use png_get_io_ptr if provided --- libguac/configure.in | 2 +- libguac/src/protocol.c | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index c401cf1c..fce89271 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -24,7 +24,7 @@ AC_TYPE_SSIZE_T # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_REALLOC -AC_CHECK_FUNCS([gettimeofday memmove memset select strdup]) +AC_CHECK_FUNCS([gettimeofday memmove memset select strdup png_get_io_ptr]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 78cca00f..e942648b 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -248,7 +248,15 @@ void guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int void __guac_write_png(png_structp png, png_bytep data, png_size_t length) { - if (guac_write_base64((GUACIO*) png->io_ptr, data, length) < 0) { +#ifdef HAVE_PNG_GET_IO_PTR + GUACIO* io = (GUACIO*) png_get_io_ptr(png); +#else + /* Direct access to io_ptr has been deprecated, but we'll + use it if we have to. */ + GUACIO* io = (GUACIO*) png->io_ptr; +#endif + + if (guac_write_base64(io, data, length) < 0) { perror("Error writing PNG"); png_error(png, "Error writing PNG"); return; From bdaf1db86c0fbd71a9b2af1847dfa1770102a474 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 21 Feb 2011 00:13:44 -0800 Subject: [PATCH 020/330] Making version number match lib version info --- libguac/configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/configure.in b/libguac/configure.in index fce89271..71a6a7cc 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_INIT(src/client.c) -AM_INIT_AUTOMAKE(libguac, 0.0.1) +AM_INIT_AUTOMAKE(libguac, 0.0.0) AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. From 122cbeff156641880866c2942fa1a49e6c3c7bec Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 21 Feb 2011 22:36:34 -0800 Subject: [PATCH 021/330] Migrating to new version number system --- libguac/configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/configure.in b/libguac/configure.in index 71a6a7cc..f88b642c 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_INIT(src/client.c) -AM_INIT_AUTOMAKE(libguac, 0.0.0) +AM_INIT_AUTOMAKE(libguac, 0.3.0) AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. From a1f65ce6599396f1a0fce57b4b24fe605cc72cb9 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 28 Feb 2011 14:51:18 -0800 Subject: [PATCH 022/330] Using dashes instead of underscores for client lib prefix --- libguac/src/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index 821ec959..ca32c468 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -92,7 +92,7 @@ guac_client* guac_get_client(int client_fd) { GUACIO* io = guac_open(client_fd); /* Pluggable client */ - char protocol_lib[256] = "libguac_client_"; + char protocol_lib[256] = "libguac-client-"; union { guac_client_init_handler* client_init; From e9d52be8d56d342a9b36eac9336b6b9e448732f1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 1 Mar 2011 01:04:29 -0800 Subject: [PATCH 023/330] Added ChangeLog, removed unused files, switched to foreign over GNU --- libguac/ChangeLog | 4 ++++ libguac/INSTALL | 0 libguac/{COPYING => LICENSE} | 0 libguac/Makefile.am | 2 +- libguac/NEWS | 0 5 files changed, 5 insertions(+), 1 deletion(-) delete mode 100644 libguac/INSTALL rename libguac/{COPYING => LICENSE} (100%) delete mode 100644 libguac/NEWS diff --git a/libguac/ChangeLog b/libguac/ChangeLog index e69de29b..f5e0feca 100644 --- a/libguac/ChangeLog +++ b/libguac/ChangeLog @@ -0,0 +1,4 @@ +2011-02-28 Michael Jumper + + * Initial release + diff --git a/libguac/INSTALL b/libguac/INSTALL deleted file mode 100644 index e69de29b..00000000 diff --git a/libguac/COPYING b/libguac/LICENSE similarity index 100% rename from libguac/COPYING rename to libguac/LICENSE diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 5801e5f7..82a78101 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -1,4 +1,4 @@ -AUTOMAKE_OPTIONS = gnu +AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -Iinclude diff --git a/libguac/NEWS b/libguac/NEWS deleted file mode 100644 index e69de29b..00000000 From 4477ef66698b4be823858b3669dff1c17e55f17a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 2 Mar 2011 01:20:56 -0800 Subject: [PATCH 024/330] Added license block to Makefile.am and configure.in --- libguac/Makefile.am | 36 ++++++++++++++++++++++++++++++++++++ libguac/configure.in | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 82a78101..fa0d7bba 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -1,3 +1,39 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is libguac. +# +# The Initial Developer of the Original Code is +# Michael Jumper. +# Portions created by the Initial Developer are Copyright (C) 2010 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 diff --git a/libguac/configure.in b/libguac/configure.in index f88b642c..9abab0d3 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -1,5 +1,38 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is libguac. +# +# The Initial Developer of the Original Code is +# Michael Jumper. +# Portions created by the Initial Developer are Copyright (C) 2010 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** AC_INIT(src/client.c) AM_INIT_AUTOMAKE(libguac, 0.3.0) From 1e1ef6f950fdcc5236c26048363292672c748687 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 2 Mar 2011 01:38:01 -0800 Subject: [PATCH 025/330] Added README for libguac --- libguac/README | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/libguac/README b/libguac/README index e69de29b..f0980ec1 100644 --- a/libguac/README +++ b/libguac/README @@ -0,0 +1,74 @@ + +------------------------------------------------------------ + About this README +------------------------------------------------------------ + +This README is intended to provide quick and to-the-point documentation for +technical users intending to compile parts of Guacamole themselves. + +Distribution-specific packages are available from the files section of the main +project page: + + http://sourceforge.net/projects/guacamole/files/ + +Distribution-specific documentation is provided on the Guacamole wiki: + + http://guac-dev.org/ + + +------------------------------------------------------------ + What is libguac? +------------------------------------------------------------ + +libguac is the core library for guacd (the Guacamole proxy) and any protocol +support plugins for guacd. + +libguac provides efficient buffered I/O of text and base64 data, as well as +somewhat abstracted functions for sending Guacamole instructions. + + +------------------------------------------------------------ + Compiling and installing libguac +------------------------------------------------------------ + +Please note that distribution-specific pre-compiled packages are available from +the files section of the main project site: + + http://sourceforge.net/projects/guacamole/files/ + +libguac is built using the popular GNU Automake, and thus provides the standard +configure script. + +1) Run configure + + $ ./configure + + Assuming all dependencies have been installed, this should succeed without + errors. + +2) Run make + + $ make + + libguac will now compile. + +3) Install (as root) + + # make install + + libguac will install to your /usr/local/lib directory by default. You can + change the install location by using the --prefix option for configure. + + Several header files will also be installed to + /usr/local/include/guacamole. + + +------------------------------------------------------------ + Reporting problems +------------------------------------------------------------ + +Please report any bugs encountered by opening a new ticket at the Trac system +hosted at: + + http://sourceforge.net/apps/trac/guacamole/ + From cd4205caf6e0dfa353070f20bb1e24df6cea9aac Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 2 Mar 2011 01:42:30 -0800 Subject: [PATCH 026/330] Added ldconfig instructions --- libguac/README | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libguac/README b/libguac/README index f0980ec1..221f63a5 100644 --- a/libguac/README +++ b/libguac/README @@ -62,6 +62,11 @@ configure script. Several header files will also be installed to /usr/local/include/guacamole. + You will need to run ldconfig (as root) so that the library can be found + when guacd is run: + + # ldconfig + ------------------------------------------------------------ Reporting problems From 47762889cfc7f626065ae8912bd9c289260e5145 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 5 Mar 2011 14:47:02 -0800 Subject: [PATCH 027/330] Reinstated ready instruction --- libguac/include/protocol.h | 13 +++++++++++++ libguac/src/client.c | 39 +++++++++++++++++++++++--------------- libguac/src/protocol.c | 4 ++++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 6b631ca3..e92c5ee4 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -141,6 +141,19 @@ void guac_send_name(GUACIO* io, const char* name); */ void guac_send_error(GUACIO* io, const char* error); +/** + * Sends a ready instruction over the given GUACIO connection. The + * ready instruction signals the client that the proxy is ready to + * handle server messages, and thus is ready to handle the client's + * ready message. + * + * Normally, this function should not be called by client plugins, + * as the ready instruction will be handled automatically. + * + * @param io The GUACIO connection to use. + */ +void guac_send_ready(GUACIO* io); + /** * Sends a clipboard instruction over the given GUACIO connection. The * clipboard data given will be automatically escaped for transmission. diff --git a/libguac/src/client.c b/libguac/src/client.c index ca32c468..76a436c7 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -213,6 +213,11 @@ guac_client* guac_get_client(int client_fd) { } guac_free_instruction_data(&instruction); + + /* Send ready message */ + guac_send_ready(io); + guac_flush(io); + return client; } /* end if connect */ @@ -249,22 +254,9 @@ void guac_start_client(guac_client* client) { guac_instruction instruction; int wait_result; - /* VNC Client Loop */ + /* Client loop */ for (;;) { - /* Handle server messages */ - if (client->handle_messages) { - - int retval = client->handle_messages(client); - if (retval) { - GUAC_LOG_ERROR("Error handling server messages"); - return; - } - - guac_flush(io); - - } - wait_result = guac_instructions_waiting(io); if (wait_result > 0) { @@ -275,7 +267,24 @@ void guac_start_client(guac_client* client) { do { - if (strcmp(instruction.opcode, "mouse") == 0) { + if (strcmp(instruction.opcode, "ready") == 0) { + + /* Handle server messages */ + if (client->handle_messages) { + + int retval = client->handle_messages(client); + if (retval) { + GUAC_LOG_ERROR("Error handling server messages"); + return; + } + + guac_send_ready(io); + guac_flush(io); + + } + + } + else if (strcmp(instruction.opcode, "mouse") == 0) { if (client->mouse_handler) if ( client->mouse_handler( diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index e942648b..8a79c2c3 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -226,6 +226,10 @@ void guac_send_error(GUACIO* io, const char* error) { } +void guac_send_ready(GUACIO* io) { + guac_write_string(io, "ready;"); +} + void guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int dstl, int dstx, int dsty) { guac_write_string(io, "copy:"); guac_write_int(io, srcl); From 90993d5d7536f1eafa4cb0d13b40c0c5cefdaee1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 6 Mar 2011 16:57:13 -0800 Subject: [PATCH 028/330] Revert "Reinstated ready instruction" This reverts commit 283c1f5ecbbfa06da5ed1300fc0243c2afcadfeb. --- libguac/include/protocol.h | 13 ------------- libguac/src/client.c | 39 +++++++++++++++----------------------- libguac/src/protocol.c | 4 ---- 3 files changed, 15 insertions(+), 41 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index e92c5ee4..6b631ca3 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -141,19 +141,6 @@ void guac_send_name(GUACIO* io, const char* name); */ void guac_send_error(GUACIO* io, const char* error); -/** - * Sends a ready instruction over the given GUACIO connection. The - * ready instruction signals the client that the proxy is ready to - * handle server messages, and thus is ready to handle the client's - * ready message. - * - * Normally, this function should not be called by client plugins, - * as the ready instruction will be handled automatically. - * - * @param io The GUACIO connection to use. - */ -void guac_send_ready(GUACIO* io); - /** * Sends a clipboard instruction over the given GUACIO connection. The * clipboard data given will be automatically escaped for transmission. diff --git a/libguac/src/client.c b/libguac/src/client.c index 76a436c7..ca32c468 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -213,11 +213,6 @@ guac_client* guac_get_client(int client_fd) { } guac_free_instruction_data(&instruction); - - /* Send ready message */ - guac_send_ready(io); - guac_flush(io); - return client; } /* end if connect */ @@ -254,9 +249,22 @@ void guac_start_client(guac_client* client) { guac_instruction instruction; int wait_result; - /* Client loop */ + /* VNC Client Loop */ for (;;) { + /* Handle server messages */ + if (client->handle_messages) { + + int retval = client->handle_messages(client); + if (retval) { + GUAC_LOG_ERROR("Error handling server messages"); + return; + } + + guac_flush(io); + + } + wait_result = guac_instructions_waiting(io); if (wait_result > 0) { @@ -267,24 +275,7 @@ void guac_start_client(guac_client* client) { do { - if (strcmp(instruction.opcode, "ready") == 0) { - - /* Handle server messages */ - if (client->handle_messages) { - - int retval = client->handle_messages(client); - if (retval) { - GUAC_LOG_ERROR("Error handling server messages"); - return; - } - - guac_send_ready(io); - guac_flush(io); - - } - - } - else if (strcmp(instruction.opcode, "mouse") == 0) { + if (strcmp(instruction.opcode, "mouse") == 0) { if (client->mouse_handler) if ( client->mouse_handler( diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 8a79c2c3..e942648b 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -226,10 +226,6 @@ void guac_send_error(GUACIO* io, const char* error) { } -void guac_send_ready(GUACIO* io) { - guac_write_string(io, "ready;"); -} - void guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int dstl, int dstx, int dsty) { guac_write_string(io, "copy:"); guac_write_int(io, srcl); From e463360aad4e48deabce584e5ba5d37760037f5c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 11 Mar 2011 18:57:53 -0800 Subject: [PATCH 029/330] Sync message support. --- libguac/configure.in | 4 +-- libguac/include/guacio.h | 2 +- libguac/include/protocol.h | 9 ++++++ libguac/src/client.c | 66 ++++++++++++++++++++++++++++++++++---- libguac/src/guacio.c | 2 +- libguac/src/protocol.c | 8 +++++ 6 files changed, 80 insertions(+), 11 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index 9abab0d3..9e7381a7 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -48,7 +48,7 @@ AC_CHECK_LIB([png], [png_write_png],, AC_MSG_ERROR("libpng is required for writi AC_CHECK_LIB([wsock32], [main]) # Checks for header files. -AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h pngstruct.h]) +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h time.h sys/time.h syslog.h unistd.h pngstruct.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T @@ -57,7 +57,7 @@ AC_TYPE_SSIZE_T # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_REALLOC -AC_CHECK_FUNCS([gettimeofday memmove memset select strdup png_get_io_ptr]) +AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup png_get_io_ptr]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index 0e70c0ea..86dcd22a 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -118,7 +118,7 @@ GUACIO* guac_open(int fd); * @param i The unsigned int to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_int(GUACIO* io, unsigned int i); +ssize_t guac_write_int(GUACIO* io, unsigned long i); /** * Writes the given string to the given GUACIO object. The data diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 6b631ca3..9a00cb99 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -131,6 +131,15 @@ void guac_send_args(GUACIO* io, const char** name); */ void guac_send_name(GUACIO* io, const char* name); +/** + * Sends a sync instruction over the given GUACIO connection. The + * current time in milliseconds should be passed in as the timestamp. + * + * @param io The GUACIO connection to use. + * @param timestamp The current timestamp (in milliseconds). + */ +void guac_send_sync(GUACIO* io, long timestamp); + /** * Sends an error instruction over the given GUACIO connection. The * error description given will be automatically escaped for diff --git a/libguac/src/client.c b/libguac/src/client.c index ca32c468..89485565 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -37,6 +37,11 @@ #include #include +#ifdef HAVE_CLOCK_GETTIME +#include +#else +#include +#endif #include #include @@ -243,11 +248,42 @@ void guac_free_client(guac_client* client) { } +long __guac_current_timestamp() { + +#ifdef HAVE_CLOCK_GETTIME + + struct timespec current; + + /* Get current time */ + clock_gettime(CLOCK_REALTIME, ¤t); + + /* Calculate milliseconds */ + return current.tv_sec * 1000 + current.tv_nsec / 1000000; + +#else + + struct timeval current; + + /* Get current time */ + gettimeofday(¤t, NULL); + + /* Calculate milliseconds */ + return current.tv_sec * 1000 + current.tv_usec / 1000; + +#endif + +} + void guac_start_client(guac_client* client) { GUACIO* io = client->io; guac_instruction instruction; int wait_result; + long last_received_timestamp; + long last_sent_timestamp; + + /* Init timestamps */ + last_received_timestamp = last_sent_timestamp = __guac_current_timestamp(); /* VNC Client Loop */ for (;;) { @@ -255,13 +291,21 @@ void guac_start_client(guac_client* client) { /* Handle server messages */ if (client->handle_messages) { - int retval = client->handle_messages(client); - if (retval) { - GUAC_LOG_ERROR("Error handling server messages"); - return; - } + /* Only handle messages if synced within threshold */ + if (last_sent_timestamp - last_received_timestamp < 200) { - guac_flush(io); + int retval = client->handle_messages(client); + if (retval) { + GUAC_LOG_ERROR("Error handling server messages"); + return; + } + + /* Send sync after updates */ + last_sent_timestamp = __guac_current_timestamp(); + guac_send_sync(io, last_sent_timestamp); + + guac_flush(io); + } } @@ -275,7 +319,15 @@ void guac_start_client(guac_client* client) { do { - if (strcmp(instruction.opcode, "mouse") == 0) { + if (strcmp(instruction.opcode, "sync") == 0) { + last_received_timestamp = atol(instruction.argv[0]); + if (last_received_timestamp > last_sent_timestamp) { + guac_send_error(io, "Received sync from future."); + guac_free_instruction_data(&instruction); + return; + } + } + else if (strcmp(instruction.opcode, "mouse") == 0) { if (client->mouse_handler) if ( client->mouse_handler( diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index c27fe5a7..c7135cd3 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -97,7 +97,7 @@ ssize_t __guac_write(GUACIO* io, const char* buf, int count) { return retval; } -ssize_t guac_write_int(GUACIO* io, unsigned int i) { +ssize_t guac_write_int(GUACIO* io, unsigned long i) { char buffer[128]; char* ptr = &(buffer[127]); diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index e942648b..1192cfc7 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -226,6 +226,14 @@ void guac_send_error(GUACIO* io, const char* error) { } +void guac_send_sync(GUACIO* io, long timestamp) { + + guac_write_string(io, "sync:"); + guac_write_int(io, timestamp); + guac_write_string(io, ";"); + +} + void guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int dstl, int dstx, int dsty) { guac_write_string(io, "copy:"); guac_write_int(io, srcl); From 12d497ca3f3e1c21367dd081cbfa0b084cde89af Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 11 Mar 2011 19:35:44 -0800 Subject: [PATCH 030/330] Working sync control. --- libguac/include/guacio.h | 5 +++++ libguac/src/client.c | 11 ++++++++--- libguac/src/guacio.c | 6 ++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index 86dcd22a..8b57f981 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -74,6 +74,11 @@ typedef struct GUACIO { */ int written; + /** + * The number of bytes written total, since this GUACIO was opened. + */ + int total_written; + /** * The main write buffer. Bytes written go here before being flushed * to the open file descriptor. diff --git a/libguac/src/client.c b/libguac/src/client.c index 89485565..1b132af6 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -291,6 +291,9 @@ void guac_start_client(guac_client* client) { /* Handle server messages */ if (client->handle_messages) { + /* Get previous GUACIO state */ + int last_total_written = io->total_written; + /* Only handle messages if synced within threshold */ if (last_sent_timestamp - last_received_timestamp < 200) { @@ -300,9 +303,11 @@ void guac_start_client(guac_client* client) { return; } - /* Send sync after updates */ - last_sent_timestamp = __guac_current_timestamp(); - guac_send_sync(io, last_sent_timestamp); + /* If data was written during message handling */ + if (io->total_written != last_total_written) { + last_sent_timestamp = __guac_current_timestamp(); + guac_send_sync(io, last_sent_timestamp); + } guac_flush(io); } diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index c7135cd3..902c84fb 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -126,6 +126,7 @@ ssize_t guac_write_string(GUACIO* io, const char* str) { for (; *str != '\0'; str++) { out_buf[io->written++] = *str; + io->total_written++; /* Flush when necessary, return on error */ if (io->written > 8188 /* sizeof(out_buf) - 4 */) { @@ -152,23 +153,28 @@ ssize_t __guac_write_base64_triplet(GUACIO* io, int a, int b, int c) { /* Byte 1 */ out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[(a & 0xFC) >> 2]; /* [AAAAAA]AABBBB BBBBCC CCCCCC */ + io->total_written++; if (b >= 0) { out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4) | ((b & 0xF0) >> 4)]; /* AAAAAA[AABBBB]BBBBCC CCCCCC */ + io->total_written++; if (c >= 0) { out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)]; /* AAAAAA AABBBB[BBBBCC]CCCCCC */ out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[c & 0x3F]; /* AAAAAA AABBBB BBBBCC[CCCCCC] */ + io->total_written += 2; } else { out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2)]; /* AAAAAA AABBBB[BBBB--]------ */ out_buf[io->written++] = '='; /* AAAAAA AABBBB BBBB--[------] */ + io->total_written += 2; } } else { out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4)]; /* AAAAAA[AA----]------ ------ */ out_buf[io->written++] = '='; /* AAAAAA AA----[------]------ */ out_buf[io->written++] = '='; /* AAAAAA AA---- ------[------] */ + io->total_written += 3; } /* At this point, 4 bytes have been io->written */ From 3e90251cb822a7b209dd226aa5686341db83d1d5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 13 Mar 2011 14:52:19 -0700 Subject: [PATCH 031/330] Automatic sleep on message handle --- libguac/configure.in | 2 +- libguac/include/client.h | 16 ++++++++++++++++ libguac/src/client.c | 29 ++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index 9e7381a7..00eb7162 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -57,7 +57,7 @@ AC_TYPE_SSIZE_T # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_REALLOC -AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup png_get_io_ptr]) +AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup png_get_io_ptr nanosleep]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/libguac/include/client.h b/libguac/include/client.h index 13938398..83c04560 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -49,6 +49,22 @@ * @file client.h */ +/** + * The time to allow between sync responses in milliseconds. If a sync + * instruction is sent to the client and no response is received within this + * timeframe, server messages will not be handled until a sync instruction is + * received from the client. + */ +#define GUAC_SYNC_THRESHOLD 500 + +/** + * The amount of time to wait after handling server messages. If a client + * plugin has a message handler, and sends instructions when server messages + * are being handled, there will be a pause of this many milliseconds before + * the next call to the message handler. + */ +#define GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY 50 + typedef struct guac_client guac_client; /** diff --git a/libguac/src/client.c b/libguac/src/client.c index 1b132af6..8b76f84f 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -274,6 +274,26 @@ long __guac_current_timestamp() { } + +void __guac_sleep(int millis) { + +#ifdef HAVE_NANOSLEEP + struct timespec sleep_period; + + sleep_period.tv_sec = 0; + sleep_period.tv_nsec = millis * 1000000L; + + nanosleep(&sleep_period, NULL); +#elif defined(__MINGW32__) + Sleep(millis) +#else +#warning No sleep/nanosleep function available. Clients may not perform as expected. Consider patching libguac to add support for your platform. +#endif + +} + + + void guac_start_client(guac_client* client) { GUACIO* io = client->io; @@ -295,7 +315,8 @@ void guac_start_client(guac_client* client) { int last_total_written = io->total_written; /* Only handle messages if synced within threshold */ - if (last_sent_timestamp - last_received_timestamp < 200) { + if (last_sent_timestamp - last_received_timestamp + < GUAC_SYNC_THRESHOLD) { int retval = client->handle_messages(client); if (retval) { @@ -305,8 +326,14 @@ void guac_start_client(guac_client* client) { /* If data was written during message handling */ if (io->total_written != last_total_written) { + + /* Sleep as necessary */ + __guac_sleep(GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY); + + /* Update sync timestamp and send sync instruction */ last_sent_timestamp = __guac_current_timestamp(); guac_send_sync(io, last_sent_timestamp); + } guac_flush(io); From 8569803cd55fbef2756fbaf29670a008d86e6186 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 14 Mar 2011 11:00:48 -0700 Subject: [PATCH 032/330] Init total_written in open. --- libguac/src/guacio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index 902c84fb..e984c4fc 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -64,6 +64,7 @@ GUACIO* guac_open(int fd) { GUACIO* io = malloc(sizeof(GUACIO)); io->ready = 0; io->written = 0; + io->total_written = 0; io->fd = fd; /* Allocate instruction buffer */ From 5a4633033265990b7c6e2810b2bc6a0288bebdd9 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 15 Mar 2011 22:21:25 -0700 Subject: [PATCH 033/330] Updated changelog --- libguac/ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libguac/ChangeLog b/libguac/ChangeLog index f5e0feca..ccbd5d4f 100644 --- a/libguac/ChangeLog +++ b/libguac/ChangeLog @@ -1,3 +1,8 @@ +2011-03-14 Michael Jumper + + * Lag control ("sync" message) + * Automatic message handle frequency limiting + 2011-02-28 Michael Jumper * Initial release From a9f702ed273600b77276bd2e5cfd3b385654bd1d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 15 Mar 2011 23:02:47 -0700 Subject: [PATCH 034/330] Initial implementation of timeout. --- libguac/include/client.h | 23 ++++++++++++++++++ libguac/src/client.c | 52 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 83c04560..21c3a97d 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -57,6 +57,29 @@ */ #define GUAC_SYNC_THRESHOLD 500 +/** + * The time to allow between server sync messages in milliseconds. A sync + * message from the server will be sent every GUAC_SYNC_FREQUENCY milliseconds. + * As this will induce a response from a client that is not malfunctioning, + * this is used to detect when a client has died. This must be set to a + * reasonable value to avoid clients being disconnected unnecessarily due + * to timeout. + */ +#define GUAC_SYNC_FREQUENCY 5000 + +/** + * The number of milliseconds to wait for messages in any phase before + * timing out and closing the connection with an error. + */ +#define GUAC_TIMEOUT 15000 + +/** + * The number of microseconds to wait for messages in any phase before + * timing out and closing the conncetion with an error. This is always + * equal to GUAC_TIMEOUT * 1000. + */ +#define GUAC_USEC_TIMEOUT (GUAC_TIMEOUT*1000) + /** * The amount of time to wait after handling server messages. If a client * plugin has a message handler, and sends instructions when server messages diff --git a/libguac/src/client.c b/libguac/src/client.c index 8b76f84f..dfd49e22 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -119,9 +119,24 @@ guac_client* guac_get_client(int client_fd) { /* Wait for select instruction */ for (;;) { - int result = guac_read_instruction(io, &instruction); + int result; + + /* Wait for data until timeout */ + result = guac_select(io, GUAC_USEC_TIMEOUT); + if (result == 0) { + guac_send_error(io, "Select timeout."); + guac_close(io); + return NULL; + } + + /* If error occurs while waiting, exit with failure */ + if (result < 0) { + guac_close(io); + return NULL; + } + + result = guac_read_instruction(io, &instruction); if (result < 0) { - GUAC_LOG_ERROR("Error reading instruction while waiting for select"); guac_close(io); return NULL; } @@ -194,7 +209,23 @@ guac_client* guac_get_client(int client_fd) { /* Wait for connect instruction */ for (;;) { - int result = guac_read_instruction(io, &instruction); + int result; + + /* Wait for data until timeout */ + result = guac_select(io, GUAC_USEC_TIMEOUT); + if (result == 0) { + guac_send_error(io, "Connect timeout."); + guac_close(io); + return NULL; + } + + /* If error occurs while waiting, exit with failure */ + if (result < 0) { + guac_close(io); + return NULL; + } + + result = guac_read_instruction(io, &instruction); if (result < 0) { GUAC_LOG_ERROR("Error reading instruction while waiting for connect"); guac_close(io); @@ -308,6 +339,21 @@ void guac_start_client(guac_client* client) { /* VNC Client Loop */ for (;;) { + /* Get current time and check timeout */ + long timestamp = __guac_current_timestamp(); + if (timestamp - last_received_timestamp > GUAC_TIMEOUT) { + guac_send_error(io, "Sync timeout."); + guac_flush(io); + return; + } + + /* If not timed out, ping client with sync */ + if (timestamp - last_sent_timestamp > GUAC_SYNC_FREQUENCY) { + last_sent_timestamp = timestamp; + guac_send_sync(io, last_sent_timestamp); + guac_flush(io); + } + /* Handle server messages */ if (client->handle_messages) { From 3c878e1d59abaab0ccc940f0af7fd119782580f0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 16 Mar 2011 01:24:17 -0700 Subject: [PATCH 035/330] Added input and output threads --- libguac/configure.in | 1 + libguac/include/client.h | 13 ---- libguac/include/protocol.h | 13 ++++ libguac/src/client.c | 130 ++++++++++++++++++++++++++----------- libguac/src/protocol.c | 2 +- 5 files changed, 108 insertions(+), 51 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index 00eb7162..96f3319f 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -45,6 +45,7 @@ AC_PROG_LIBTOOL # Checks for libraries. AC_CHECK_LIB([dl], [dlopen],, AC_MSG_ERROR("libdl is required for loading client plugins")) AC_CHECK_LIB([png], [png_write_png],, AC_MSG_ERROR("libpng is required for writing png messages")) +AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([wsock32], [main]) # Checks for header files. diff --git a/libguac/include/client.h b/libguac/include/client.h index 21c3a97d..7270adba 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -67,19 +67,6 @@ */ #define GUAC_SYNC_FREQUENCY 5000 -/** - * The number of milliseconds to wait for messages in any phase before - * timing out and closing the connection with an error. - */ -#define GUAC_TIMEOUT 15000 - -/** - * The number of microseconds to wait for messages in any phase before - * timing out and closing the conncetion with an error. This is always - * equal to GUAC_TIMEOUT * 1000. - */ -#define GUAC_USEC_TIMEOUT (GUAC_TIMEOUT*1000) - /** * The amount of time to wait after handling server messages. If a client * plugin has a message handler, and sends instructions when server messages diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 9a00cb99..a640c72d 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -51,6 +51,19 @@ */ +/** + * The number of milliseconds to wait for messages in any phase before + * timing out and closing the connection with an error. + */ +#define GUAC_TIMEOUT 15000 + +/** + * The number of microseconds to wait for messages in any phase before + * timing out and closing the conncetion with an error. This is always + * equal to GUAC_TIMEOUT * 1000. + */ +#define GUAC_USEC_TIMEOUT (GUAC_TIMEOUT*1000) + /** * Represents a single instruction within the Guacamole protocol. */ diff --git a/libguac/src/client.c b/libguac/src/client.c index dfd49e22..999c5bf1 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -44,6 +44,7 @@ #endif #include #include +#include #include "log.h" #include "guacio.h" @@ -122,7 +123,7 @@ guac_client* guac_get_client(int client_fd) { int result; /* Wait for data until timeout */ - result = guac_select(io, GUAC_USEC_TIMEOUT); + result = guac_instructions_waiting(io); if (result == 0) { guac_send_error(io, "Select timeout."); guac_close(io); @@ -212,7 +213,7 @@ guac_client* guac_get_client(int client_fd) { int result; /* Wait for data until timeout */ - result = guac_select(io, GUAC_USEC_TIMEOUT); + result = guac_instructions_waiting(io); if (result == 0) { guac_send_error(io, "Connect timeout."); guac_close(io); @@ -324,33 +325,31 @@ void __guac_sleep(int millis) { } +typedef struct __guac_client_thread_common { -void guac_start_client(guac_client* client) { - - GUACIO* io = client->io; - guac_instruction instruction; - int wait_result; + guac_client* client; long last_received_timestamp; long last_sent_timestamp; - /* Init timestamps */ - last_received_timestamp = last_sent_timestamp = __guac_current_timestamp(); + int client_active; - /* VNC Client Loop */ - for (;;) { +} __guac_client_thread_common; - /* Get current time and check timeout */ + +void* __guac_client_output_thread(void* data) { + + __guac_client_thread_common* common = (__guac_client_thread_common*) data; + guac_client* client = common->client; + GUACIO* io = client->io; + + /* Guacamole client output loop */ + while (common->client_active) { + + /* Occasionally ping client with sync */ long timestamp = __guac_current_timestamp(); - if (timestamp - last_received_timestamp > GUAC_TIMEOUT) { - guac_send_error(io, "Sync timeout."); - guac_flush(io); - return; - } - - /* If not timed out, ping client with sync */ - if (timestamp - last_sent_timestamp > GUAC_SYNC_FREQUENCY) { - last_sent_timestamp = timestamp; - guac_send_sync(io, last_sent_timestamp); + if (timestamp - common->last_sent_timestamp > GUAC_SYNC_FREQUENCY) { + guac_send_sync(io, timestamp); + common->last_sent_timestamp = timestamp; guac_flush(io); } @@ -361,13 +360,13 @@ void guac_start_client(guac_client* client) { int last_total_written = io->total_written; /* Only handle messages if synced within threshold */ - if (last_sent_timestamp - last_received_timestamp + if (common->last_sent_timestamp - common->last_received_timestamp < GUAC_SYNC_THRESHOLD) { int retval = client->handle_messages(client); if (retval) { GUAC_LOG_ERROR("Error handling server messages"); - return; + break; } /* If data was written during message handling */ @@ -377,8 +376,8 @@ void guac_start_client(guac_client* client) { __guac_sleep(GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY); /* Update sync timestamp and send sync instruction */ - last_sent_timestamp = __guac_current_timestamp(); - guac_send_sync(io, last_sent_timestamp); + common->last_sent_timestamp = __guac_current_timestamp(); + guac_send_sync(io, common->last_sent_timestamp); } @@ -387,7 +386,29 @@ void guac_start_client(guac_client* client) { } - wait_result = guac_instructions_waiting(io); + /* If no message handler, just sleep until next sync ping */ + else + __guac_sleep(GUAC_SYNC_FREQUENCY); + + } /* End of output loop */ + + common->client_active = 0; + return NULL; + +} + +void* __guac_client_input_thread(void* data) { + + __guac_client_thread_common* common = (__guac_client_thread_common*) data; + guac_client* client = common->client; + GUACIO* io = client->io; + + guac_instruction instruction; + + /* Guacamole client input loop */ + while (common->client_active) { + + int wait_result = guac_instructions_waiting(io); if (wait_result > 0) { int retval; @@ -398,11 +419,11 @@ void guac_start_client(guac_client* client) { do { if (strcmp(instruction.opcode, "sync") == 0) { - last_received_timestamp = atol(instruction.argv[0]); - if (last_received_timestamp > last_sent_timestamp) { + common->last_received_timestamp = atol(instruction.argv[0]); + if (common->last_received_timestamp > common->last_sent_timestamp) { guac_send_error(io, "Received sync from future."); guac_free_instruction_data(&instruction); - return; + break; } } else if (strcmp(instruction.opcode, "mouse") == 0) { @@ -418,7 +439,7 @@ void guac_start_client(guac_client* client) { GUAC_LOG_ERROR("Error handling mouse instruction"); guac_free_instruction_data(&instruction); - return; + break; } } @@ -435,7 +456,7 @@ void guac_start_client(guac_client* client) { GUAC_LOG_ERROR("Error handling key instruction"); guac_free_instruction_data(&instruction); - return; + break; } } @@ -451,7 +472,7 @@ void guac_start_client(guac_client* client) { GUAC_LOG_ERROR("Error handling clipboard instruction"); guac_free_instruction_data(&instruction); - return; + break; } } @@ -459,7 +480,7 @@ void guac_start_client(guac_client* client) { else if (strcmp(instruction.opcode, "disconnect") == 0) { GUAC_LOG_INFO("Client requested disconnect"); guac_free_instruction_data(&instruction); - return; + break; } guac_free_instruction_data(&instruction); @@ -468,13 +489,13 @@ void guac_start_client(guac_client* client) { if (retval < 0) { GUAC_LOG_ERROR("Error reading instruction from stream"); - return; + break; } } if (retval < 0) { GUAC_LOG_ERROR("Error or end of stream"); - return; /* EOF or error */ + break; /* EOF or error */ } /* Otherwise, retval == 0 implies unfinished instruction */ @@ -482,10 +503,45 @@ void guac_start_client(guac_client* client) { } else if (wait_result < 0) { GUAC_LOG_ERROR("Error waiting for next instruction"); - return; + break; + } + else { /* wait_result == 0 */ + GUAC_LOG_ERROR("Timeout"); + break; } } + common->client_active = 0; + return NULL; + +} + +void guac_start_client(guac_client* client) { + + pthread_t input_thread, output_thread; + __guac_client_thread_common common; + + /* Init thread data */ + common.client = client; + common.last_received_timestamp = common.last_sent_timestamp = __guac_current_timestamp(); + common.client_active = 1; + + if (pthread_create(&output_thread, NULL, __guac_client_output_thread, (void*) &common)) { + /* THIS FUNCTION SHOULD RETURN A VALUE! */ + return; + } + + if (pthread_create(&input_thread, NULL, __guac_client_input_thread, (void*) &common)) { + /* THIS FUNCTION SHOULD RETURN A VALUE! */ + return; + } + + /* Wait for I/O threads */ + pthread_join(input_thread, NULL); + pthread_join(output_thread, NULL); + + /* Done */ + } diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 1192cfc7..674f5596 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -529,6 +529,6 @@ int guac_instructions_waiting(GUACIO* io) { if (io->instructionbuf_used_length > 0) return 1; - return guac_select(io, 1000); + return guac_select(io, GUAC_USEC_TIMEOUT); } From 3e14b52b1c2038ee6c9ce4f72177c5175ee4aa10 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 16 Mar 2011 23:46:02 -0700 Subject: [PATCH 036/330] Improved instruction handling, working I/O threads. --- libguac/Makefile.am | 2 +- libguac/include/client-handlers.h | 63 +++++++ libguac/include/client.h | 17 ++ libguac/src/client-handlers.c | 98 +++++++++++ libguac/src/client.c | 273 +++++++++++------------------- 5 files changed, 275 insertions(+), 178 deletions(-) create mode 100644 libguac/include/client-handlers.h create mode 100644 libguac/src/client-handlers.c diff --git a/libguac/Makefile.am b/libguac/Makefile.am index fa0d7bba..30a75fab 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -44,7 +44,7 @@ libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h includ lib_LTLIBRARIES = libguac.la -libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c +libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c libguac_la_LDFLAGS = -version-info 0:0:0 diff --git a/libguac/include/client-handlers.h b/libguac/include/client-handlers.h new file mode 100644 index 00000000..dccad0f7 --- /dev/null +++ b/libguac/include/client-handlers.h @@ -0,0 +1,63 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_CLIENT_HANDLERS__H +#define _GUAC_CLIENT_HANDLERS__H + +#include "client.h" +#include "protocol.h" + +typedef int __guac_instruction_handler(guac_client* client, guac_instruction* copied); + +typedef struct __guac_instruction_handler_mapping { + + char* opcode; + __guac_instruction_handler* handler; + +} __guac_instruction_handler_mapping; + +int __guac_handle_sync(guac_client* client, guac_instruction* instruction); +int __guac_handle_mouse(guac_client* client, guac_instruction* instruction); +int __guac_handle_key(guac_client* client, guac_instruction* instruction); +int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction); +int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction); + +extern __guac_instruction_handler_mapping __guac_instruction_handler_map[]; + +int __guac_handle_instruction(guac_client* client, guac_instruction* instruction); + +#endif diff --git a/libguac/include/client.h b/libguac/include/client.h index 7270adba..8eb72147 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -42,6 +42,7 @@ #include #include "guacio.h" +#include "protocol.h" /** * Provides functions and structures required for defining (and handling) a proxy client. @@ -104,6 +105,11 @@ typedef int guac_client_clipboard_handler(guac_client* client, char* copied); */ typedef int guac_client_free_handler(void* client); +typedef enum guac_client_state { + RUNNING, + STOPPING +} guac_client_state; + /** * Guacamole proxy client. * @@ -120,6 +126,10 @@ struct guac_client { */ GUACIO* io; + guac_client_state state; + long last_received_timestamp; + long last_sent_timestamp; + /** * Reference to dlopen'd client plugin. */ @@ -284,4 +294,11 @@ png_byte** guac_alloc_png_buffer(int w, int h, int bpp); */ void guac_free_png_buffer(png_byte** png_buffer, int h); +int guac_client_handle_instruction(guac_client* client, guac_instruction* instruction); +void guac_client_stop(guac_client* client); + +/* FIXME: MOVE THESE TO protocol.h */ +long guac_client_current_timestamp(); +void guac_client_sleep(int millis); + #endif diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c new file mode 100644 index 00000000..8247e938 --- /dev/null +++ b/libguac/src/client-handlers.c @@ -0,0 +1,98 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include + +#include "client.h" +#include "protocol.h" +#include "client-handlers.h" + +__guac_instruction_handler_mapping __guac_instruction_handler_map[] = { + {"sync", __guac_handle_sync}, + {"mouse", __guac_handle_mouse}, + {"key", __guac_handle_key}, + {"clipboard", __guac_handle_clipboard}, + {"disconnect", __guac_handle_disconnect}, + {NULL, NULL} +}; + + +int __guac_handle_sync(guac_client* client, guac_instruction* instruction) { + long timestamp = atol(instruction->argv[0]); + + /* Error if timestamp is in future */ + if (timestamp > client->last_sent_timestamp) + return -1; + + client->last_received_timestamp = timestamp; + return 0; +} + +int __guac_handle_mouse(guac_client* client, guac_instruction* instruction) { + if (client->mouse_handler) + return client->mouse_handler( + client, + atoi(instruction->argv[0]), /* x */ + atoi(instruction->argv[1]), /* y */ + atoi(instruction->argv[2]) /* mask */ + ); + return 0; +} + +int __guac_handle_key(guac_client* client, guac_instruction* instruction) { + if (client->key_handler) + return client->key_handler( + client, + atoi(instruction->argv[0]), /* keysym */ + atoi(instruction->argv[1]) /* pressed */ + ); + return 0; +} + +int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction) { + if (client->clipboard_handler) + return client->clipboard_handler( + client, + guac_unescape_string_inplace(instruction->argv[0]) /* data */ + ); + return 0; +} + +int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction) { + return -1; +} + diff --git a/libguac/src/client.c b/libguac/src/client.c index 999c5bf1..d37c1a66 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -50,7 +50,7 @@ #include "guacio.h" #include "protocol.h" #include "client.h" - +#include "client-handlers.h" png_byte** guac_alloc_png_buffer(int w, int h, int bpp) { @@ -79,6 +79,50 @@ void guac_free_png_buffer(png_byte** png_buffer, int h) { } + +long guac_client_current_timestamp() { + +#ifdef HAVE_CLOCK_GETTIME + + struct timespec current; + + /* Get current time */ + clock_gettime(CLOCK_REALTIME, ¤t); + + /* Calculate milliseconds */ + return current.tv_sec * 1000 + current.tv_nsec / 1000000; + +#else + + struct timeval current; + + /* Get current time */ + gettimeofday(¤t, NULL); + + /* Calculate milliseconds */ + return current.tv_sec * 1000 + current.tv_usec / 1000; + +#endif + +} + +void guac_client_sleep(int millis) { + +#ifdef HAVE_NANOSLEEP + struct timespec sleep_period; + + sleep_period.tv_sec = 0; + sleep_period.tv_nsec = millis * 1000000L; + + nanosleep(&sleep_period, NULL); +#elif defined(__MINGW32__) + Sleep(millis) +#else +#warning No sleep/nanosleep function available. Clients may not perform as expected. Consider patching libguac to add support for your platform. +#endif + +} + guac_client* __guac_alloc_client(GUACIO* io) { /* Allocate new client (not handoff) */ @@ -87,6 +131,8 @@ guac_client* __guac_alloc_client(GUACIO* io) { /* Init new client */ client->io = io; + client->last_received_timestamp = client->last_sent_timestamp = guac_client_current_timestamp(); + client->state = RUNNING; return client; } @@ -261,6 +307,9 @@ guac_client* guac_get_client(int client_fd) { } +void guac_client_stop(guac_client* client) { + client->state = STOPPING; +} void guac_free_client(guac_client* client) { @@ -280,76 +329,19 @@ void guac_free_client(guac_client* client) { } -long __guac_current_timestamp() { - -#ifdef HAVE_CLOCK_GETTIME - - struct timespec current; - - /* Get current time */ - clock_gettime(CLOCK_REALTIME, ¤t); - - /* Calculate milliseconds */ - return current.tv_sec * 1000 + current.tv_nsec / 1000000; - -#else - - struct timeval current; - - /* Get current time */ - gettimeofday(¤t, NULL); - - /* Calculate milliseconds */ - return current.tv_sec * 1000 + current.tv_usec / 1000; - -#endif - -} - - -void __guac_sleep(int millis) { - -#ifdef HAVE_NANOSLEEP - struct timespec sleep_period; - - sleep_period.tv_sec = 0; - sleep_period.tv_nsec = millis * 1000000L; - - nanosleep(&sleep_period, NULL); -#elif defined(__MINGW32__) - Sleep(millis) -#else -#warning No sleep/nanosleep function available. Clients may not perform as expected. Consider patching libguac to add support for your platform. -#endif - -} - - -typedef struct __guac_client_thread_common { - - guac_client* client; - long last_received_timestamp; - long last_sent_timestamp; - - int client_active; - -} __guac_client_thread_common; - - void* __guac_client_output_thread(void* data) { - __guac_client_thread_common* common = (__guac_client_thread_common*) data; - guac_client* client = common->client; + guac_client* client = (guac_client*) data; GUACIO* io = client->io; /* Guacamole client output loop */ - while (common->client_active) { + while (client->state == RUNNING) { /* Occasionally ping client with sync */ - long timestamp = __guac_current_timestamp(); - if (timestamp - common->last_sent_timestamp > GUAC_SYNC_FREQUENCY) { + long timestamp = guac_client_current_timestamp(); + if (timestamp - client->last_sent_timestamp > GUAC_SYNC_FREQUENCY) { + client->last_sent_timestamp = timestamp; guac_send_sync(io, timestamp); - common->last_sent_timestamp = timestamp; guac_flush(io); } @@ -360,7 +352,7 @@ void* __guac_client_output_thread(void* data) { int last_total_written = io->total_written; /* Only handle messages if synced within threshold */ - if (common->last_sent_timestamp - common->last_received_timestamp + if (client->last_sent_timestamp - client->last_received_timestamp < GUAC_SYNC_THRESHOLD) { int retval = client->handle_messages(client); @@ -373,11 +365,11 @@ void* __guac_client_output_thread(void* data) { if (io->total_written != last_total_written) { /* Sleep as necessary */ - __guac_sleep(GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY); + guac_client_sleep(GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY); - /* Update sync timestamp and send sync instruction */ - common->last_sent_timestamp = __guac_current_timestamp(); - guac_send_sync(io, common->last_sent_timestamp); + /* Send sync instruction */ + client->last_sent_timestamp = guac_client_current_timestamp(); + guac_send_sync(io, client->last_sent_timestamp); } @@ -388,131 +380,46 @@ void* __guac_client_output_thread(void* data) { /* If no message handler, just sleep until next sync ping */ else - __guac_sleep(GUAC_SYNC_FREQUENCY); + guac_client_sleep(GUAC_SYNC_FREQUENCY); } /* End of output loop */ - common->client_active = 0; + guac_client_stop(client); return NULL; } void* __guac_client_input_thread(void* data) { - __guac_client_thread_common* common = (__guac_client_thread_common*) data; - guac_client* client = common->client; + guac_client* client = (guac_client*) data; GUACIO* io = client->io; guac_instruction instruction; /* Guacamole client input loop */ - while (common->client_active) { + while (client->state == RUNNING && guac_instructions_waiting(io) > 0) { - int wait_result = guac_instructions_waiting(io); - if (wait_result > 0) { + int retval; + while ((retval = guac_read_instruction(io, &instruction)) > 0) { - int retval; - retval = guac_read_instruction(io, &instruction); /* 0 if no instructions finished yet, <0 if error or EOF */ - - if (retval > 0) { - - do { - - if (strcmp(instruction.opcode, "sync") == 0) { - common->last_received_timestamp = atol(instruction.argv[0]); - if (common->last_received_timestamp > common->last_sent_timestamp) { - guac_send_error(io, "Received sync from future."); - guac_free_instruction_data(&instruction); - break; - } - } - else if (strcmp(instruction.opcode, "mouse") == 0) { - if (client->mouse_handler) - if ( - client->mouse_handler( - client, - atoi(instruction.argv[0]), /* x */ - atoi(instruction.argv[1]), /* y */ - atoi(instruction.argv[2]) /* mask */ - ) - ) { - - GUAC_LOG_ERROR("Error handling mouse instruction"); - guac_free_instruction_data(&instruction); - break; - - } - } - - else if (strcmp(instruction.opcode, "key") == 0) { - if (client->key_handler) - if ( - client->key_handler( - client, - atoi(instruction.argv[0]), /* keysym */ - atoi(instruction.argv[1]) /* pressed */ - ) - ) { - - GUAC_LOG_ERROR("Error handling key instruction"); - guac_free_instruction_data(&instruction); - break; - - } - } - - else if (strcmp(instruction.opcode, "clipboard") == 0) { - if (client->clipboard_handler) - if ( - client->clipboard_handler( - client, - guac_unescape_string_inplace(instruction.argv[0]) /* data */ - ) - ) { - - GUAC_LOG_ERROR("Error handling clipboard instruction"); - guac_free_instruction_data(&instruction); - break; - - } - } - - else if (strcmp(instruction.opcode, "disconnect") == 0) { - GUAC_LOG_INFO("Client requested disconnect"); - guac_free_instruction_data(&instruction); - break; - } - - guac_free_instruction_data(&instruction); - - } while ((retval = guac_read_instruction(io, &instruction)) > 0); - - if (retval < 0) { - GUAC_LOG_ERROR("Error reading instruction from stream"); - break; - } + if (guac_client_handle_instruction(client, &instruction) < 0) { + guac_free_instruction_data(&instruction); + guac_client_stop(client); + return NULL; } - if (retval < 0) { - GUAC_LOG_ERROR("Error or end of stream"); - break; /* EOF or error */ - } - - /* Otherwise, retval == 0 implies unfinished instruction */ + guac_free_instruction_data(&instruction); } - else if (wait_result < 0) { - GUAC_LOG_ERROR("Error waiting for next instruction"); + + if (retval < 0) break; - } - else { /* wait_result == 0 */ - GUAC_LOG_ERROR("Timeout"); - break; - } + + /* Otherwise, retval == 0 implies unfinished instruction */ } - common->client_active = 0; + guac_client_stop(client); return NULL; } @@ -520,19 +427,13 @@ void* __guac_client_input_thread(void* data) { void guac_start_client(guac_client* client) { pthread_t input_thread, output_thread; - __guac_client_thread_common common; - /* Init thread data */ - common.client = client; - common.last_received_timestamp = common.last_sent_timestamp = __guac_current_timestamp(); - common.client_active = 1; - - if (pthread_create(&output_thread, NULL, __guac_client_output_thread, (void*) &common)) { + if (pthread_create(&output_thread, NULL, __guac_client_output_thread, (void*) client)) { /* THIS FUNCTION SHOULD RETURN A VALUE! */ return; } - if (pthread_create(&input_thread, NULL, __guac_client_input_thread, (void*) &common)) { + if (pthread_create(&input_thread, NULL, __guac_client_input_thread, (void*) client)) { /* THIS FUNCTION SHOULD RETURN A VALUE! */ return; } @@ -545,3 +446,21 @@ void guac_start_client(guac_client* client) { } +int guac_client_handle_instruction(guac_client* client, guac_instruction* instruction) { + + /* For each defined instruction */ + __guac_instruction_handler_mapping* current = __guac_instruction_handler_map; + while (current->opcode != NULL) { + + /* If recognized, call handler */ + if (strcmp(instruction->opcode, current->opcode) == 0) + return current->handler(client, instruction); + + current++; + } + + /* If unrecognized, ignore */ + return 0; + +} + From a08cd5b8b7d7780c980cf89abdacfcf48966f165 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 17 Mar 2011 00:25:35 -0700 Subject: [PATCH 037/330] Changed semantics of guac_read_instruction, fixed timeout. --- libguac/include/protocol.h | 7 ++++--- libguac/src/client.c | 22 +++++++--------------- libguac/src/protocol.c | 9 ++++----- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index a640c72d..d7512d1a 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -248,9 +248,10 @@ int guac_instructions_waiting(GUACIO* io); * will be populated with data read from the given * GUACIO connection. * @return A positive value if data was successfully read, negative on - * error, or zero if the instrucion could not be read completely, - * in which case, subsequent calls to guac_read_instruction() will - * return the parsed instruction once enough data is available. + * error, or zero if the instruction could not be read completely + * because GUAC_TIMEOUT elapsed, in which case subsequent calls to + * guac_read_instruction() will return the parsed instruction once + * enough data is available. */ int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction); diff --git a/libguac/src/client.c b/libguac/src/client.c index d37c1a66..c9065c6c 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -308,6 +308,7 @@ guac_client* guac_get_client(int client_fd) { } void guac_client_stop(guac_client* client) { + fprintf(stderr, "***************** STOPPING! *********************\n"); client->state = STOPPING; } @@ -397,25 +398,16 @@ void* __guac_client_input_thread(void* data) { guac_instruction instruction; /* Guacamole client input loop */ - while (client->state == RUNNING && guac_instructions_waiting(io) > 0) { - - int retval; - while ((retval = guac_read_instruction(io, &instruction)) > 0) { - - if (guac_client_handle_instruction(client, &instruction) < 0) { - guac_free_instruction_data(&instruction); - guac_client_stop(client); - return NULL; - } + while (client->state == RUNNING && guac_read_instruction(io, &instruction) > 0) { + /* Call handler, stop on error */ + if (guac_client_handle_instruction(client, &instruction) < 0) { guac_free_instruction_data(&instruction); - + break; } - if (retval < 0) - break; - - /* Otherwise, retval == 0 implies unfinished instruction */ + /* Free allocate instruction data */ + guac_free_instruction_data(&instruction); } diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 674f5596..dec704be 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -497,16 +497,15 @@ int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction) { } /* No instruction yet? Get more data ... */ - retval = guac_select(io, 1000); + retval = guac_select(io, GUAC_USEC_TIMEOUT); if (retval <= 0) return retval; + /* If more data is available, fill into buffer */ retval = __guac_fill_instructionbuf(io); - if (retval < 0) - return retval; + if (retval < 0) return retval; /* Error */ + if (retval == 0) return -1; /* EOF */ - if (retval == 0) - return -1; /* EOF */ } } From 1b2c27ba96652315458b6ba1a16b2942cac8ad9e Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 17 Mar 2011 00:25:55 -0700 Subject: [PATCH 038/330] Removed debug fprintf. --- libguac/src/client.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index c9065c6c..247fc4b0 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -308,7 +308,6 @@ guac_client* guac_get_client(int client_fd) { } void guac_client_stop(guac_client* client) { - fprintf(stderr, "***************** STOPPING! *********************\n"); client->state = STOPPING; } From 0a3a23f26e302db85bf2174143dd8e1f2302ea61 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 17 Mar 2011 14:04:23 -0700 Subject: [PATCH 039/330] Temporary fix for spinning while waiting for sync --- libguac/src/client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libguac/src/client.c b/libguac/src/client.c index 247fc4b0..e2f789ed 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -376,6 +376,10 @@ void* __guac_client_output_thread(void* data) { guac_flush(io); } + /* If sync threshold exceeded, don't spin waiting for resync */ + else + guac_client_sleep(GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY); + } /* If no message handler, just sleep until next sync ping */ From e20e877d45366ae8fd784b7bf57799e074630a3d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 17 Mar 2011 21:16:29 -0700 Subject: [PATCH 040/330] Moved sleep and timestamp functions, fixed header ifndefs --- libguac/include/client.h | 8 ++--- libguac/include/guacio.h | 4 +-- libguac/include/log.h | 4 +-- libguac/include/protocol.h | 7 +++-- libguac/src/client.c | 61 ++++---------------------------------- libguac/src/protocol.c | 49 ++++++++++++++++++++++++++++++ 6 files changed, 66 insertions(+), 67 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 8eb72147..ecde725f 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -36,8 +36,8 @@ * ***** END LICENSE BLOCK ***** */ -#ifndef _CLIENT_H -#define _CLIENT_H +#ifndef _GUAC_CLIENT_H +#define _GUAC_CLIENT_H #include @@ -297,8 +297,4 @@ void guac_free_png_buffer(png_byte** png_buffer, int h); int guac_client_handle_instruction(guac_client* client, guac_instruction* instruction); void guac_client_stop(guac_client* client); -/* FIXME: MOVE THESE TO protocol.h */ -long guac_client_current_timestamp(); -void guac_client_sleep(int millis); - #endif diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index 8b57f981..e82061ed 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -35,8 +35,8 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef _GUACIO_H -#define _GUACIO_H +#ifndef _GUAC_GUACIO_H +#define _GUAC_GUACIO_H #include diff --git a/libguac/include/log.h b/libguac/include/log.h index 0bf039c1..cb0fab78 100644 --- a/libguac/include/log.h +++ b/libguac/include/log.h @@ -35,8 +35,8 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef _LOG_H -#define _LOG_H +#ifndef _GUAC_LOG_H +#define _GUAC_LOG_H #ifdef HAVE_SYSLOG_H diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index d7512d1a..ac872d38 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -35,8 +35,8 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef __PROTOCOL_H -#define __PROTOCOL_H +#ifndef _GUAC_PROTOCOL_H +#define _GUAC_PROTOCOL_H #include @@ -255,5 +255,8 @@ int guac_instructions_waiting(GUACIO* io); */ int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction); +long guac_current_timestamp(); +void guac_sleep(int millis); + #endif diff --git a/libguac/src/client.c b/libguac/src/client.c index e2f789ed..3de42f73 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -37,11 +37,6 @@ #include #include -#ifdef HAVE_CLOCK_GETTIME -#include -#else -#include -#endif #include #include #include @@ -79,50 +74,6 @@ void guac_free_png_buffer(png_byte** png_buffer, int h) { } - -long guac_client_current_timestamp() { - -#ifdef HAVE_CLOCK_GETTIME - - struct timespec current; - - /* Get current time */ - clock_gettime(CLOCK_REALTIME, ¤t); - - /* Calculate milliseconds */ - return current.tv_sec * 1000 + current.tv_nsec / 1000000; - -#else - - struct timeval current; - - /* Get current time */ - gettimeofday(¤t, NULL); - - /* Calculate milliseconds */ - return current.tv_sec * 1000 + current.tv_usec / 1000; - -#endif - -} - -void guac_client_sleep(int millis) { - -#ifdef HAVE_NANOSLEEP - struct timespec sleep_period; - - sleep_period.tv_sec = 0; - sleep_period.tv_nsec = millis * 1000000L; - - nanosleep(&sleep_period, NULL); -#elif defined(__MINGW32__) - Sleep(millis) -#else -#warning No sleep/nanosleep function available. Clients may not perform as expected. Consider patching libguac to add support for your platform. -#endif - -} - guac_client* __guac_alloc_client(GUACIO* io) { /* Allocate new client (not handoff) */ @@ -131,7 +82,7 @@ guac_client* __guac_alloc_client(GUACIO* io) { /* Init new client */ client->io = io; - client->last_received_timestamp = client->last_sent_timestamp = guac_client_current_timestamp(); + client->last_received_timestamp = client->last_sent_timestamp = guac_current_timestamp(); client->state = RUNNING; return client; @@ -338,7 +289,7 @@ void* __guac_client_output_thread(void* data) { while (client->state == RUNNING) { /* Occasionally ping client with sync */ - long timestamp = guac_client_current_timestamp(); + long timestamp = guac_current_timestamp(); if (timestamp - client->last_sent_timestamp > GUAC_SYNC_FREQUENCY) { client->last_sent_timestamp = timestamp; guac_send_sync(io, timestamp); @@ -365,10 +316,10 @@ void* __guac_client_output_thread(void* data) { if (io->total_written != last_total_written) { /* Sleep as necessary */ - guac_client_sleep(GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY); + guac_sleep(GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY); /* Send sync instruction */ - client->last_sent_timestamp = guac_client_current_timestamp(); + client->last_sent_timestamp = guac_current_timestamp(); guac_send_sync(io, client->last_sent_timestamp); } @@ -378,13 +329,13 @@ void* __guac_client_output_thread(void* data) { /* If sync threshold exceeded, don't spin waiting for resync */ else - guac_client_sleep(GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY); + guac_sleep(GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY); } /* If no message handler, just sleep until next sync ping */ else - guac_client_sleep(GUAC_SYNC_FREQUENCY); + guac_sleep(GUAC_SYNC_FREQUENCY); } /* End of output loop */ diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index dec704be..e18f65d6 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -35,6 +35,12 @@ * * ***** END LICENSE BLOCK ***** */ +#ifdef HAVE_CLOCK_GETTIME +#include +#else +#include +#endif + #include #include #include @@ -531,3 +537,46 @@ int guac_instructions_waiting(GUACIO* io) { return guac_select(io, GUAC_USEC_TIMEOUT); } +long guac_current_timestamp() { + +#ifdef HAVE_CLOCK_GETTIME + + struct timespec current; + + /* Get current time */ + clock_gettime(CLOCK_REALTIME, ¤t); + + /* Calculate milliseconds */ + return current.tv_sec * 1000 + current.tv_nsec / 1000000; + +#else + + struct timeval current; + + /* Get current time */ + gettimeofday(¤t, NULL); + + /* Calculate milliseconds */ + return current.tv_sec * 1000 + current.tv_usec / 1000; + +#endif + +} + +void guac_sleep(int millis) { + +#ifdef HAVE_NANOSLEEP + struct timespec sleep_period; + + sleep_period.tv_sec = 0; + sleep_period.tv_nsec = millis * 1000000L; + + nanosleep(&sleep_period, NULL); +#elif defined(__MINGW32__) + Sleep(millis) +#else +#warning No sleep/nanosleep function available. Clients may not perform as expected. Consider patching libguac to add support for your platform. +#endif + +} + From 599c7ff58a119a30d35619c9c77c63ebbf3f0227 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 18 Mar 2011 00:42:34 -0700 Subject: [PATCH 041/330] Documentation for new client functions and structures. --- libguac/include/client.h | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/libguac/include/client.h b/libguac/include/client.h index ecde725f..bea28762 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -105,9 +105,24 @@ typedef int guac_client_clipboard_handler(guac_client* client, char* copied); */ typedef int guac_client_free_handler(void* client); +/** + * Possible current states of the Guacamole client. Currently, the only + * two states are RUNNING and STOPPING. + */ typedef enum guac_client_state { + + /** + * The state of the client from when it has been allocated by the main + * daemon until it is killed or disconnected. + */ RUNNING, + + /** + * The state of the client when a stop has been requested, signalling the + * I/O threads to shutdown. + */ STOPPING + } guac_client_state; /** @@ -126,8 +141,24 @@ struct guac_client { */ GUACIO* io; + /** + * The current state of the client. When the client is first allocated, + * this will be initialized to RUNNING. It will remain at RUNNING until + * an event occurs which requires the client to shutdown, at which point + * the state becomes STOPPING. + */ guac_client_state state; + + /** + * The time (in milliseconds) of receipt of the last sync message from + * the client. + */ long last_received_timestamp; + + /** + * The time (in milliseconds) that the last sync message was sent to the + * client. + */ long last_sent_timestamp; /** @@ -294,7 +325,25 @@ png_byte** guac_alloc_png_buffer(int w, int h, int bpp); */ void guac_free_png_buffer(png_byte** png_buffer, int h); +/** + * Call the appropriate handler defined by the given client for the given + * instruction. A comparison is made between the instruction opcode and the + * initial handler lookup table defined in client-handlers.c. The intial + * handlers will in turn call the client's handler (if defined). + * + * @param client The proxy client whose handlers should be called. + * @param instruction The instruction to pass to the proxy client via the + * appropriate handler. + */ int guac_client_handle_instruction(guac_client* client, guac_instruction* instruction); + +/** + * Signal the given client to stop. This will set the state of the given client + * to STOPPING, which signals the I/O threads to shutdown, and ultimately + * results in shutdown of the client. + * + * @param client The proxy client to stop. + */ void guac_client_stop(guac_client* client); #endif From 195ad0e25104e00a66a535b5047e50347040c051 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 18 Mar 2011 00:55:14 -0700 Subject: [PATCH 042/330] More documentation. --- libguac/include/client-handlers.h | 59 +++++++++++++++++++++++++++++-- libguac/src/client-handlers.c | 4 +++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/libguac/include/client-handlers.h b/libguac/include/client-handlers.h index dccad0f7..de7603ae 100644 --- a/libguac/include/client-handlers.h +++ b/libguac/include/client-handlers.h @@ -41,23 +41,78 @@ #include "client.h" #include "protocol.h" +/** + * Provides initial handler functions and a lookup structure for automatically + * handling client instructions. This is used only internally within libguac, + * and is not installed along with the library. + * + * @file client-handlers.h + */ + +/** + * Internal handler for Guacamole instructions. + */ typedef int __guac_instruction_handler(guac_client* client, guac_instruction* copied); +/** + * Structure mapping an instruction opcode to an instruction handler. + */ typedef struct __guac_instruction_handler_mapping { + /** + * The instruction opcode which maps to a specific handler. + */ char* opcode; + + /** + * The handler which maps to a specific opcode. + */ __guac_instruction_handler* handler; } __guac_instruction_handler_mapping; +/** + * Internal initial handler for the sync instruction. When a sync instruction + * is received, this handler will be called. Sync instructions are automatically + * handled, thus there is no client handler for sync instruction. + */ int __guac_handle_sync(guac_client* client, guac_instruction* instruction); + +/** + * Internal initial handler for the mouse instruction. When a mouse instruction + * is received, this handler will be called. The client's mouse handler will + * be invoked if defined. + */ int __guac_handle_mouse(guac_client* client, guac_instruction* instruction); + +/** + * Internal initial handler for the key instruction. When a key instruction + * is received, this handler will be called. The client's key handler will + * be invoked if defined. + */ int __guac_handle_key(guac_client* client, guac_instruction* instruction); + +/** + * Internal initial handler for the clipboard instruction. When a clipboard instruction + * is received, this handler will be called. The client's clipboard handler will + * be invoked if defined. + */ int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction); + +/** + * Internal initial handler for the disconnect instruction. When a disconnect instruction + * is received, this handler will be called. Disconnect instructions are automatically + * handled, thus there is no client handler for disconnect instruction. + */ int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction); +/** + * Instruction handler mapping table. This is a NULL-terminated array of + * __guac_instruction_handler_mapping structures, each mapping an opcode + * to a __guac_instruction_handler. The end of the array must be marked + * with a __guac_instruction_handler_mapping with the opcode set to + * NULL (the NULL terminator). + */ extern __guac_instruction_handler_mapping __guac_instruction_handler_map[]; -int __guac_handle_instruction(guac_client* client, guac_instruction* instruction); - #endif diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index 8247e938..380ad19a 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -41,6 +41,8 @@ #include "protocol.h" #include "client-handlers.h" +/* Guacamole instruction handler map */ + __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { {"sync", __guac_handle_sync}, {"mouse", __guac_handle_mouse}, @@ -50,6 +52,7 @@ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { {NULL, NULL} }; +/* Guacamole instruction handlers */ int __guac_handle_sync(guac_client* client, guac_instruction* instruction) { long timestamp = atol(instruction->argv[0]); @@ -93,6 +96,7 @@ int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction) } int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction) { + /* Return error code to force disconnect */ return -1; } From 5a2a6292258a2c3ab53341dd4d69c0d2b00f9a10 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 19 Mar 2011 01:00:40 -0700 Subject: [PATCH 043/330] Fixed guac_client_free_handler definition. --- libguac/include/client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index bea28762..35335985 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -103,7 +103,7 @@ typedef int guac_client_clipboard_handler(guac_client* client, char* copied); * Handler for freeing up any extra data allocated by the client * implementation. */ -typedef int guac_client_free_handler(void* client); +typedef int guac_client_free_handler(guac_client* client); /** * Possible current states of the Guacamole client. Currently, the only From 6300c7c56ada4f600f43aecf852f18344c572d22 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 19 Mar 2011 16:32:35 -0700 Subject: [PATCH 044/330] Return values and error handling for guac_send_* functions in protocol. --- libguac/include/protocol.h | 27 +++-- libguac/src/protocol.c | 196 +++++++++++++++++++++---------------- 2 files changed, 132 insertions(+), 91 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index ac872d38..9db6a260 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -132,8 +132,9 @@ char* guac_unescape_string_inplace(char* str); * * @param io The GUACIO connection to use. * @param args The NULL-terminated array of argument names (strings). + * @return Zero on success, non-zero on error. */ -void guac_send_args(GUACIO* io, const char** name); +int guac_send_args(GUACIO* io, const char** name); /** * Sends a name instruction over the given GUACIO connection. The @@ -141,8 +142,9 @@ void guac_send_args(GUACIO* io, const char** name); * * @param io The GUACIO connection to use. * @param name The name to send within the name instruction. + * @return Zero on success, non-zero on error. */ -void guac_send_name(GUACIO* io, const char* name); +int guac_send_name(GUACIO* io, const char* name); /** * Sends a sync instruction over the given GUACIO connection. The @@ -150,8 +152,9 @@ void guac_send_name(GUACIO* io, const char* name); * * @param io The GUACIO connection to use. * @param timestamp The current timestamp (in milliseconds). + * @return Zero on success, non-zero on error. */ -void guac_send_sync(GUACIO* io, long timestamp); +int guac_send_sync(GUACIO* io, long timestamp); /** * Sends an error instruction over the given GUACIO connection. The @@ -160,8 +163,9 @@ void guac_send_sync(GUACIO* io, long timestamp); * * @param io The GUACIO connection to use. * @param error The description associated with the error. + * @return Zero on success, non-zero on error. */ -void guac_send_error(GUACIO* io, const char* error); +int guac_send_error(GUACIO* io, const char* error); /** * Sends a clipboard instruction over the given GUACIO connection. The @@ -169,8 +173,9 @@ void guac_send_error(GUACIO* io, const char* error); * * @param io The GUACIO connection to use. * @param data The clipboard data to send. + * @return Zero on success, non-zero on error. */ -void guac_send_clipboard(GUACIO* io, const char* data); +int guac_send_clipboard(GUACIO* io, const char* data); /** * Sends a size instruction over the given GUACIO connection. @@ -178,8 +183,9 @@ void guac_send_clipboard(GUACIO* io, const char* data); * @param io The GUACIO connection to use. * @param w The width of the display. * @param h The height of the display. + * @return Zero on success, non-zero on error. */ -void guac_send_size(GUACIO* io, int w, int h); +int guac_send_size(GUACIO* io, int w, int h); /** * Sends a copy instruction over the given GUACIO connection. @@ -195,8 +201,9 @@ void guac_send_size(GUACIO* io, int w, int h); * should be copied. * @param dsty The Y coordinate of the destination, where the source rectangle * should be copied. + * @return Zero on success, non-zero on error. */ -void guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, +int guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int dstl, int dstx, int dsty); /** @@ -211,8 +218,9 @@ void guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, * data to send. * @param w The width of the image in the image buffer. * @param h The height of the image in the image buffer. + * @return Zero on success, non-zero on error. */ -void guac_send_png(GUACIO* io, int layer, int x, int y, +int guac_send_png(GUACIO* io, int layer, int x, int y, png_byte** png_rows, int w, int h); /** @@ -226,8 +234,9 @@ void guac_send_png(GUACIO* io, int layer, int x, int y, * data to send. * @param w The width of the image in the image buffer. * @param h The height of the image in the image buffer. + * @return Zero on success, non-zero on error. */ -void guac_send_cursor(GUACIO* io, int x, int y, +int guac_send_cursor(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h); /** diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index e18f65d6..2591edd3 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -167,97 +167,127 @@ char* guac_unescape_string_inplace(char* str) { } -void guac_send_args(GUACIO* io, const char** args) { +int guac_send_args(GUACIO* io, const char** args) { int i; - guac_write_string(io, "args:"); + if (guac_write_string(io, "args:")) return -1; for (i=0; args[i] != NULL; i++) { - if (i > 0) - guac_write_string(io, ","); + if (i > 0) { + if (guac_write_string(io, ",")) + return -1; + } char* escaped = guac_escape_string(args[i]); - guac_write_string(io, escaped); + if (guac_write_string(io, escaped)) { + free(escaped); + return -1; + } free(escaped); } - guac_write_string(io, ";"); + return guac_write_string(io, ";"); } -void guac_send_name(GUACIO* io, const char* name) { +int guac_send_name(GUACIO* io, const char* name) { char* escaped = guac_escape_string(name); - guac_write_string(io, "name:"); - guac_write_string(io, escaped); - guac_write_string(io, ";"); + if ( + guac_write_string(io, "name:") + || guac_write_string(io, escaped) + || guac_write_string(io, ";") + ) { + free(escaped); + return -1; + } free(escaped); + return 0; } -void guac_send_size(GUACIO* io, int w, int h) { - guac_write_string(io, "size:"); - guac_write_int(io, w); - guac_write_string(io, ","); - guac_write_int(io, h); - guac_write_string(io, ";"); +int guac_send_size(GUACIO* io, int w, int h) { + + return + guac_write_string(io, "size:") + || guac_write_int(io, w) + || guac_write_string(io, ",") + || guac_write_int(io, h) + || guac_write_string(io, ";"); + } -void guac_send_clipboard(GUACIO* io, const char* data) { +int guac_send_clipboard(GUACIO* io, const char* data) { char* escaped = guac_escape_string(data); - guac_write_string(io, "clipboard:"); - guac_write_string(io, escaped); - guac_write_string(io, ";"); + if ( + guac_write_string(io, "clipboard:") + || guac_write_string(io, escaped) + || guac_write_string(io, ";") + ) { + free(escaped); + return -1; + } free(escaped); + return 0; } -void guac_send_error(GUACIO* io, const char* error) { +int guac_send_error(GUACIO* io, const char* error) { char* escaped = guac_escape_string(error); - guac_write_string(io, "error:"); - guac_write_string(io, escaped); - guac_write_string(io, ";"); + if ( + guac_write_string(io, "error:") + || guac_write_string(io, escaped) + || guac_write_string(io, ";") + ) { + free(escaped); + return -1; + } free(escaped); + return 0; } -void guac_send_sync(GUACIO* io, long timestamp) { +int guac_send_sync(GUACIO* io, long timestamp) { - guac_write_string(io, "sync:"); - guac_write_int(io, timestamp); - guac_write_string(io, ";"); + return + guac_write_string(io, "sync:") + || guac_write_int(io, timestamp) + || guac_write_string(io, ";"); } -void guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int dstl, int dstx, int dsty) { - guac_write_string(io, "copy:"); - guac_write_int(io, srcl); - guac_write_string(io, ","); - guac_write_int(io, srcx); - guac_write_string(io, ","); - guac_write_int(io, srcy); - guac_write_string(io, ","); - guac_write_int(io, w); - guac_write_string(io, ","); - guac_write_int(io, h); - guac_write_string(io, ","); - guac_write_int(io, dstl); - guac_write_string(io, ","); - guac_write_int(io, dstx); - guac_write_string(io, ","); - guac_write_int(io, dsty); - guac_write_string(io, ";"); +int guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int dstl, int dstx, int dsty) { + + return + guac_write_string(io, "copy:") + || guac_write_int(io, srcl) + || guac_write_string(io, ",") + || guac_write_int(io, srcx) + || guac_write_string(io, ",") + || guac_write_int(io, srcy) + || guac_write_string(io, ",") + || guac_write_int(io, w) + || guac_write_string(io, ",") + || guac_write_int(io, h) + || guac_write_string(io, ",") + || guac_write_int(io, dstl) + || guac_write_string(io, ",") + || guac_write_int(io, dstx) + || guac_write_string(io, ",") + || guac_write_int(io, dsty) + || guac_write_string(io, ";"); + } void __guac_write_png(png_structp png, png_bytep data, png_size_t length) { @@ -281,7 +311,7 @@ void __guac_write_png(png_structp png, png_bytep data, png_size_t length) { void __guac_write_flush(png_structp png) { } -void guac_send_png(GUACIO* io, int layer, int x, int y, png_byte** png_rows, int w, int h) { +int guac_send_png(GUACIO* io, int layer, int x, int y, png_byte** png_rows, int w, int h) { png_structp png; png_infop png_info; @@ -291,22 +321,19 @@ void guac_send_png(GUACIO* io, int layer, int x, int y, png_byte** png_rows, int /* Set up PNG writer */ png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { - perror("Error initializing libpng write structure"); - return; + return -1; } png_info = png_create_info_struct(png); if (!png_info) { - perror("Error initializing libpng info structure"); png_destroy_write_struct(&png, NULL); - return; + return -1; } /* Set error handler */ if (setjmp(png_jmpbuf(png))) { - perror("Error setting handler"); png_destroy_write_struct(&png, &png_info); - return; + return -1; } png_set_write_fn(png, io, __guac_write_png, __guac_write_flush); @@ -324,30 +351,34 @@ void guac_send_png(GUACIO* io, int layer, int x, int y, png_byte** png_rows, int PNG_FILTER_TYPE_DEFAULT ); - guac_write_string(io, "png:"); - guac_write_int(io, layer); - guac_write_string(io, ","); - guac_write_int(io, x); - guac_write_string(io, ","); - guac_write_int(io, y); - guac_write_string(io, ","); + if ( + guac_write_string(io, "png:") + || guac_write_int(io, layer) + || guac_write_string(io, ",") + || guac_write_int(io, x) + || guac_write_string(io, ",") + || guac_write_int(io, y) + || guac_write_string(io, ",") + ) { + png_destroy_write_struct(&png, &png_info); + return -1; + } + png_set_rows(png, png_info, png_rows); png_write_png(png, png_info, PNG_TRANSFORM_IDENTITY, NULL); if (guac_flush_base64(io) < 0) { - perror("Error flushing PNG"); - png_error(png, "Error flushing PNG"); - return; + png_destroy_write_struct(&png, &png_info); + return -1; } png_destroy_write_struct(&png, &png_info); - - guac_write_string(io, ";"); + return guac_write_string(io, ";"); } -void guac_send_cursor(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h) { +int guac_send_cursor(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h) { png_structp png; png_infop png_info; @@ -357,22 +388,19 @@ void guac_send_cursor(GUACIO* io, int x, int y, png_byte** png_rows, int w, int /* Set up PNG writer */ png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { - perror("Error initializing libpng write structure"); - return; + return -1; } png_info = png_create_info_struct(png); if (!png_info) { - perror("Error initializing libpng info structure"); png_destroy_write_struct(&png, NULL); - return; + return -1; } /* Set error handler */ if (setjmp(png_jmpbuf(png))) { - perror("Error setting handler"); png_destroy_write_struct(&png, &png_info); - return; + return -1; } png_set_write_fn(png, io, __guac_write_png, __guac_write_flush); @@ -390,23 +418,27 @@ void guac_send_cursor(GUACIO* io, int x, int y, png_byte** png_rows, int w, int PNG_FILTER_TYPE_DEFAULT ); - guac_write_string(io, "cursor:"); - guac_write_int(io, x); - guac_write_string(io, ","); - guac_write_int(io, y); - guac_write_string(io, ","); + if ( + guac_write_string(io, "cursor:") + || guac_write_int(io, x) + || guac_write_string(io, ",") + || guac_write_int(io, y) + || guac_write_string(io, ",") + ) { + png_destroy_write_struct(&png, &png_info); + return -1; + } + png_set_rows(png, png_info, png_rows); png_write_png(png, png_info, PNG_TRANSFORM_IDENTITY, NULL); if (guac_flush_base64(io) < 0) { - perror("Error flushing PNG"); - png_error(png, "Error flushing PNG"); - return; + png_destroy_write_struct(&png, &png_info); + return -1; } png_destroy_write_struct(&png, &png_info); - - guac_write_string(io, ";"); + return guac_write_string(io, ";"); } From 71d59845e98cff522510ba3fac456d49b8d5ac00 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 19 Mar 2011 16:39:18 -0700 Subject: [PATCH 045/330] More error handling, style fix. --- libguac/src/client.c | 31 ++++++++++++++++++++++++------- libguac/src/protocol.c | 12 ++++++------ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index 3de42f73..276c7f83 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -190,9 +190,14 @@ guac_client* guac_get_client(int client_fd) { return NULL; } - /* Send args */ - guac_send_args(io, client_args); - guac_flush(io); + if ( /* Send args */ + guac_send_args(io, client_args) + || guac_flush(io) + ) { + guac_close(io); + guac_free_instruction_data(&instruction); + return NULL; + } guac_free_instruction_data(&instruction); break; @@ -292,8 +297,13 @@ void* __guac_client_output_thread(void* data) { long timestamp = guac_current_timestamp(); if (timestamp - client->last_sent_timestamp > GUAC_SYNC_FREQUENCY) { client->last_sent_timestamp = timestamp; - guac_send_sync(io, timestamp); - guac_flush(io); + if ( + guac_send_sync(io, timestamp) + || guac_flush(io) + ) { + guac_client_stop(client); + return NULL; + } } /* Handle server messages */ @@ -320,11 +330,18 @@ void* __guac_client_output_thread(void* data) { /* Send sync instruction */ client->last_sent_timestamp = guac_current_timestamp(); - guac_send_sync(io, client->last_sent_timestamp); + if (guac_send_sync(io, client->last_sent_timestamp)) { + guac_client_stop(client); + return NULL; + } } - guac_flush(io); + if (guac_flush(io)) { + guac_client_stop(client); + return NULL; + } + } /* If sync threshold exceeded, don't spin waiting for resync */ diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 2591edd3..db003763 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -214,7 +214,7 @@ int guac_send_name(GUACIO* io, const char* name) { int guac_send_size(GUACIO* io, int w, int h) { return - guac_write_string(io, "size:") + guac_write_string(io, "size:") || guac_write_int(io, w) || guac_write_string(io, ",") || guac_write_int(io, h) @@ -227,7 +227,7 @@ int guac_send_clipboard(GUACIO* io, const char* data) { char* escaped = guac_escape_string(data); if ( - guac_write_string(io, "clipboard:") + guac_write_string(io, "clipboard:") || guac_write_string(io, escaped) || guac_write_string(io, ";") ) { @@ -245,7 +245,7 @@ int guac_send_error(GUACIO* io, const char* error) { char* escaped = guac_escape_string(error); if ( - guac_write_string(io, "error:") + guac_write_string(io, "error:") || guac_write_string(io, escaped) || guac_write_string(io, ";") ) { @@ -261,7 +261,7 @@ int guac_send_error(GUACIO* io, const char* error) { int guac_send_sync(GUACIO* io, long timestamp) { return - guac_write_string(io, "sync:") + guac_write_string(io, "sync:") || guac_write_int(io, timestamp) || guac_write_string(io, ";"); @@ -270,7 +270,7 @@ int guac_send_sync(GUACIO* io, long timestamp) { int guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int dstl, int dstx, int dsty) { return - guac_write_string(io, "copy:") + guac_write_string(io, "copy:") || guac_write_int(io, srcl) || guac_write_string(io, ",") || guac_write_int(io, srcx) @@ -419,7 +419,7 @@ int guac_send_cursor(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h ); if ( - guac_write_string(io, "cursor:") + guac_write_string(io, "cursor:") || guac_write_int(io, x) || guac_write_string(io, ",") || guac_write_int(io, y) From a72df19449180973eef3230da2a57c5e510d2c8f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 19 Mar 2011 16:44:06 -0700 Subject: [PATCH 046/330] Error handling in guac_start_client. --- libguac/include/client.h | 5 ++++- libguac/src/client.c | 9 ++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 35335985..8d87d092 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -296,8 +296,11 @@ guac_client* guac_get_client(int client_fd); * Enter the main network message handling loop for the given client. * * @param client The proxy client to start handling messages of/for. + * @return Zero if the client successfully started, non-zero if an error + * occurs during startup. Note that this function will still return + * zero if an error occurs while the client is running. */ -void guac_start_client(guac_client* client); +int guac_start_client(guac_client* client); /** * Free all resources associated with the given client. diff --git a/libguac/src/client.c b/libguac/src/client.c index 276c7f83..cff714bc 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -387,18 +387,16 @@ void* __guac_client_input_thread(void* data) { } -void guac_start_client(guac_client* client) { +int guac_start_client(guac_client* client) { pthread_t input_thread, output_thread; if (pthread_create(&output_thread, NULL, __guac_client_output_thread, (void*) client)) { - /* THIS FUNCTION SHOULD RETURN A VALUE! */ - return; + return -1; } if (pthread_create(&input_thread, NULL, __guac_client_input_thread, (void*) client)) { - /* THIS FUNCTION SHOULD RETURN A VALUE! */ - return; + return -1; } /* Wait for I/O threads */ @@ -406,6 +404,7 @@ void guac_start_client(guac_client* client) { pthread_join(output_thread, NULL); /* Done */ + return 0; } From 06dad71273350e671a1769f42a0d7e2c91eff225 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 19 Mar 2011 17:02:30 -0700 Subject: [PATCH 047/330] Using function rather than variadic macro --- libguac/include/log.h | 16 ++------- libguac/src/client.c | 17 ++++----- libguac/src/log.c | 82 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 22 deletions(-) create mode 100644 libguac/src/log.c diff --git a/libguac/include/log.h b/libguac/include/log.h index cb0fab78..4015539e 100644 --- a/libguac/include/log.h +++ b/libguac/include/log.h @@ -38,19 +38,7 @@ #ifndef _GUAC_LOG_H #define _GUAC_LOG_H -#ifdef HAVE_SYSLOG_H - - /* Logging for UNIX */ - #include - #define GUAC_LOG_ERROR(...) syslog(LOG_ERR, __VA_ARGS__) - #define GUAC_LOG_INFO(...) syslog(LOG_INFO, __VA_ARGS__) - -#else - - /* Logging for W32 */ - #define GUAC_LOG_ERROR(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n") - #define GUAC_LOG_INFO(...) fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n") - -#endif +void guac_log_info(const char* str, ...); +void guac_log_error(const char* str, ...); #endif diff --git a/libguac/src/client.c b/libguac/src/client.c index cff714bc..3c2e29ac 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -156,7 +156,7 @@ guac_client* guac_get_client(int client_fd) { /* Load client plugin */ client->client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); if (!(client->client_plugin_handle)) { - GUAC_LOG_ERROR("Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); + guac_log_error("Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); guac_send_error(io, "Could not load server-side client plugin."); guac_flush(io); guac_close(io); @@ -170,7 +170,7 @@ guac_client* guac_get_client(int client_fd) { alias.obj = dlsym(client->client_plugin_handle, "guac_client_init"); if ((error = dlerror()) != NULL) { - GUAC_LOG_ERROR("Could not get guac_client_init in plugin: %s\n", error); + guac_log_error("Could not get guac_client_init in plugin: %s\n", error); guac_send_error(io, "Invalid server-side client plugin."); guac_flush(io); guac_close(io); @@ -182,7 +182,7 @@ guac_client* guac_get_client(int client_fd) { client_args = (const char**) dlsym(client->client_plugin_handle, "GUAC_CLIENT_ARGS"); if ((error = dlerror()) != NULL) { - GUAC_LOG_ERROR("Could not get GUAC_CLIENT_ in plugin: %s\n", error); + guac_log_error("Could not get GUAC_CLIENT_ in plugin: %s\n", error); guac_send_error(io, "Invalid server-side client plugin."); guac_flush(io); guac_close(io); @@ -230,7 +230,7 @@ guac_client* guac_get_client(int client_fd) { result = guac_read_instruction(io, &instruction); if (result < 0) { - GUAC_LOG_ERROR("Error reading instruction while waiting for connect"); + guac_log_error("Error reading instruction while waiting for connect"); guac_close(io); return NULL; } @@ -271,14 +271,14 @@ void guac_free_client(guac_client* client) { if (client->free_handler) { if (client->free_handler(client)) - GUAC_LOG_ERROR("Error calling client free handler"); + guac_log_error("Error calling client free handler"); } guac_close(client->io); /* Unload client plugin */ if (dlclose(client->client_plugin_handle)) { - GUAC_LOG_ERROR("Could not close client plugin while unloading client: %s", dlerror()); + guac_log_error("Could not close client plugin while unloading client: %s", dlerror()); } free(client); @@ -318,8 +318,9 @@ void* __guac_client_output_thread(void* data) { int retval = client->handle_messages(client); if (retval) { - GUAC_LOG_ERROR("Error handling server messages"); - break; + guac_log_error("Error handling server messages"); + guac_client_stop(client); + return NULL; } /* If data was written during message handling */ diff --git a/libguac/src/log.c b/libguac/src/log.c new file mode 100644 index 00000000..540baf38 --- /dev/null +++ b/libguac/src/log.c @@ -0,0 +1,82 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifdef HAVE_SYSLOG_H + #include +#else + #include +#endif + +#include + +#include "log.h" + +void guac_log_info(const char* str, ...) { + + va_list args; + va_start(args, str); + +#ifdef HAVE_SYSLOG_H + vsyslog(LOG_ERR, str, args); +#else + fprintf(stderr, "guacamole: info: "); + vfprintf(stderr, str, args); + fprintf(stderr, "\n"); +#endif + + va_end(args); + +} + +void guac_log_error(const char* str, ...) { + + va_list args; + va_start(args, str); + +#ifdef HAVE_SYSLOG_H + vsyslog(LOG_INFO, str, args); +#else + fprintf(stderr, "guacamole: error: "); + vfprintf(stderr, str, args); + fprintf(stderr, "\n"); +#endif + + va_end(args); + +} + +#endif From 1f4afa6c474a022977bd008f4d583ffe824cc0a2 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 19 Mar 2011 17:06:25 -0700 Subject: [PATCH 048/330] Documentation (doxygen) --- libguac/include/log.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/libguac/include/log.h b/libguac/include/log.h index 4015539e..273f6698 100644 --- a/libguac/include/log.h +++ b/libguac/include/log.h @@ -38,7 +38,32 @@ #ifndef _GUAC_LOG_H #define _GUAC_LOG_H +/** + * Provides basic cross-platform logging facilities. + * + * @file log.h + */ + +/** + * Logs an informational message in the system log, whatever + * that may be for the system being used. This will currently + * log to syslog for platforms supporting it, and stderr for + * all others. + * + * @param str A printf-style format string to log. + * @param ... Arguments to use when filling the format string for printing. + */ void guac_log_info(const char* str, ...); + +/** + * Logs an error message in the system log, whatever + * that may be for the system being used. This will currently + * log to syslog for platforms supporting it, and stderr for + * all others. + * + * @param str A printf-style format string to log. + * @param ... Arguments to use when filling the format string for printing. + */ void guac_log_error(const char* str, ...); #endif From 97a63fae3ef57c242d7bb40bcd0e891e7d99d074 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 19 Mar 2011 17:13:02 -0700 Subject: [PATCH 049/330] Fixed log.c and Makefile.am --- libguac/Makefile.am | 2 +- libguac/src/log.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 30a75fab..e12ea9e6 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -44,7 +44,7 @@ libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h includ lib_LTLIBRARIES = libguac.la -libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c +libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c src/log.c libguac_la_LDFLAGS = -version-info 0:0:0 diff --git a/libguac/src/log.c b/libguac/src/log.c index 540baf38..46568678 100644 --- a/libguac/src/log.c +++ b/libguac/src/log.c @@ -79,4 +79,3 @@ void guac_log_error(const char* str, ...) { } -#endif From 220035746bdd5b6c01aa724dc711e6d97e1097dd Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 20 Mar 2011 00:21:56 -0700 Subject: [PATCH 050/330] Add va_list variants of the guac_log_* functions --- libguac/include/log.h | 32 ++++++++++++++++++++++++++++---- libguac/src/log.c | 42 +++++++++++++++++++++++++----------------- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/libguac/include/log.h b/libguac/include/log.h index 273f6698..43fc7fcf 100644 --- a/libguac/include/log.h +++ b/libguac/include/log.h @@ -50,10 +50,22 @@ * log to syslog for platforms supporting it, and stderr for * all others. * - * @param str A printf-style format string to log. + * @param format A printf-style format string to log. * @param ... Arguments to use when filling the format string for printing. */ -void guac_log_info(const char* str, ...); +void guac_log_info(const char* format, ...); + +/** + * Logs an informational message in the system log, whatever + * that may be for the system being used. This will currently + * log to syslog for platforms supporting it, and stderr for + * all others. + * + * @param format A printf-style format string to log. + * @param ap The va_list containing the arguments to be used when filling the + * format string for printing. + */ +void vguac_log_info(const char* format, va_list ap); /** * Logs an error message in the system log, whatever @@ -61,9 +73,21 @@ void guac_log_info(const char* str, ...); * log to syslog for platforms supporting it, and stderr for * all others. * - * @param str A printf-style format string to log. + * @param format A printf-style format string to log. * @param ... Arguments to use when filling the format string for printing. */ -void guac_log_error(const char* str, ...); +void guac_log_error(const char* format, ...); + +/** + * Logs an error message in the system log, whatever + * that may be for the system being used. This will currently + * log to syslog for platforms supporting it, and stderr for + * all others. + * + * @param format A printf-style format string to log. + * @param ap The va_list containing the arguments to be used when filling the + * format string for printing. + */ +void vguac_log_error(const char* format, va_list ap); #endif diff --git a/libguac/src/log.c b/libguac/src/log.c index 46568678..c51bff15 100644 --- a/libguac/src/log.c +++ b/libguac/src/log.c @@ -45,35 +45,43 @@ #include "log.h" -void guac_log_info(const char* str, ...) { - - va_list args; - va_start(args, str); - +void vguac_log_info(const char* format, va_list ap) { #ifdef HAVE_SYSLOG_H - vsyslog(LOG_ERR, str, args); + vsyslog(LOG_ERR, format, ap); #else fprintf(stderr, "guacamole: info: "); - vfprintf(stderr, str, args); + vfprintf(stderr, format, ap); fprintf(stderr, "\n"); #endif - - va_end(args); - } -void guac_log_error(const char* str, ...) { - - va_list args; - va_start(args, str); - +void vguac_log_error(const char* format, va_list ap) { #ifdef HAVE_SYSLOG_H - vsyslog(LOG_INFO, str, args); + vsyslog(LOG_INFO, format, ap); #else fprintf(stderr, "guacamole: error: "); - vfprintf(stderr, str, args); + vfprintf(stderr, format, ap); fprintf(stderr, "\n"); #endif +} + +void guac_log_info(const char* format, ...) { + + va_list args; + va_start(args, format); + + vguac_log_info(format, args); + + va_end(args); + +} + +void guac_log_error(const char* format, ...) { + + va_list args; + va_start(args, format); + + vguac_log_error(format, args); va_end(args); From d6a5d70278dbf647a50a11d82f42e6b6ea752b81 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 20 Mar 2011 19:34:45 -0700 Subject: [PATCH 051/330] Experimental speed options for PNG encoding (less compression, no filtering) --- libguac/src/protocol.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index db003763..1e36e1cc 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -330,6 +330,12 @@ int guac_send_png(GUACIO* io, int layer, int x, int y, png_byte** png_rows, int return -1; } + /* Do not filter (speed) */ + png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_VALUE_NONE); + + /* Fast compression level */ + png_set_compression_level(png, 1); + /* Set error handler */ if (setjmp(png_jmpbuf(png))) { png_destroy_write_struct(&png, &png_info); From b16eda0d48497166da0dd53836f6673dc8c7b785 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 20 Mar 2011 19:38:36 -0700 Subject: [PATCH 052/330] Fixed missing include --- libguac/include/log.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libguac/include/log.h b/libguac/include/log.h index 43fc7fcf..fc531896 100644 --- a/libguac/include/log.h +++ b/libguac/include/log.h @@ -38,6 +38,8 @@ #ifndef _GUAC_LOG_H #define _GUAC_LOG_H +#include + /** * Provides basic cross-platform logging facilities. * From a2b072995390e9359e1c2567fc590a0bd9cdb1f9 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 20 Mar 2011 21:38:58 -0700 Subject: [PATCH 053/330] Wait for output thread if input thread does not start, fixed typo in error. --- libguac/src/client.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index 3c2e29ac..41045e95 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -182,7 +182,7 @@ guac_client* guac_get_client(int client_fd) { client_args = (const char**) dlsym(client->client_plugin_handle, "GUAC_CLIENT_ARGS"); if ((error = dlerror()) != NULL) { - guac_log_error("Could not get GUAC_CLIENT_ in plugin: %s\n", error); + guac_log_error("Could not get GUAC_CLIENT_ARGS in plugin: %s\n", error); guac_send_error(io, "Invalid server-side client plugin."); guac_flush(io); guac_close(io); @@ -397,6 +397,8 @@ int guac_start_client(guac_client* client) { } if (pthread_create(&input_thread, NULL, __guac_client_input_thread, (void*) client)) { + guac_client_stop(client); + pthread_join(output_thread, NULL); return -1; } From 18e01ee74cff035f9acf5fca24bb8e6823f95223 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 20 Mar 2011 23:02:28 -0700 Subject: [PATCH 054/330] Added ifdef to force fast (less compressed) PNG rendering only when asked. --- libguac/src/protocol.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 1e36e1cc..c0bac8da 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -330,11 +330,13 @@ int guac_send_png(GUACIO* io, int layer, int x, int y, png_byte** png_rows, int return -1; } +#ifdef GUAC_FAST_PNG /* Do not filter (speed) */ png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_VALUE_NONE); /* Fast compression level */ png_set_compression_level(png, 1); +#endif /* Set error handler */ if (setjmp(png_jmpbuf(png))) { From bb994d5c904ac54a892ee378c99ec71c22420608 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 24 Mar 2011 23:11:46 -0700 Subject: [PATCH 055/330] Added -pedantic, fixed warning. --- libguac/Makefile.am | 2 +- libguac/src/protocol.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index e12ea9e6..82e7fa7e 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -37,7 +37,7 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 -AM_CFLAGS = -Werror -Wall -Iinclude +AM_CFLAGS = -Werror -Wall -pedantic -Iinclude libguacincdir = $(includedir)/guacamole libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/log.h diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index c0bac8da..ff37ca17 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -175,12 +175,14 @@ int guac_send_args(GUACIO* io, const char** args) { for (i=0; args[i] != NULL; i++) { + char* escaped; + if (i > 0) { if (guac_write_string(io, ",")) return -1; } - char* escaped = guac_escape_string(args[i]); + escaped = guac_escape_string(args[i]); if (guac_write_string(io, escaped)) { free(escaped); return -1; From f95f2647472fde2756a4a40d71edf0252ebf0d50 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 27 Mar 2011 16:32:49 -0700 Subject: [PATCH 056/330] Using cairo instead of libpng. --- libguac/configure.in | 6 +- libguac/include/client.h | 21 ------ libguac/include/protocol.h | 18 ++--- libguac/src/client.c | 27 ------- libguac/src/protocol.c | 145 ++++++++----------------------------- 5 files changed, 37 insertions(+), 180 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index 96f3319f..144e1613 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -44,12 +44,12 @@ AC_PROG_LIBTOOL # Checks for libraries. AC_CHECK_LIB([dl], [dlopen],, AC_MSG_ERROR("libdl is required for loading client plugins")) -AC_CHECK_LIB([png], [png_write_png],, AC_MSG_ERROR("libpng is required for writing png messages")) +AC_CHECK_LIB([cairo], [cairo_create],, AC_MSG_ERROR("cairo is required for drawing instructions")) AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([wsock32], [main]) # Checks for header files. -AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h time.h sys/time.h syslog.h unistd.h pngstruct.h]) +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h time.h sys/time.h syslog.h unistd.h cairo.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T @@ -58,7 +58,7 @@ AC_TYPE_SSIZE_T # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_REALLOC -AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup png_get_io_ptr nanosleep]) +AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup nanosleep]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/libguac/include/client.h b/libguac/include/client.h index 8d87d092..f4cb9e95 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -39,8 +39,6 @@ #ifndef _GUAC_CLIENT_H #define _GUAC_CLIENT_H -#include - #include "guacio.h" #include "protocol.h" @@ -309,25 +307,6 @@ int guac_start_client(guac_client* client); */ void guac_free_client(guac_client* client); -/** - * Allocate a libpng-compatible buffer to hold raw image data. - * - * @param w The width of the buffer to allocate, in pixels. - * @param h The height of the buffer to allocate, in pixels. - * @param bpp The number of bytes per pixel (3 for RGB images, 4 for RGBA). - * @return A pointer to the newly allocated buffer. - */ -png_byte** guac_alloc_png_buffer(int w, int h, int bpp); - -/** - * Free all memory associated with the given libpng-compatible buffer - * as allocated by guac_alloc_png_buffer. - * - * @param png_buffer The buffer to free. - * @param h The height of the buffer to free. - */ -void guac_free_png_buffer(png_byte** png_buffer, int h); - /** * Call the appropriate handler defined by the given client for the given * instruction. A comparison is made between the instruction opcode and the diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 9db6a260..aeb5b70a 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -38,7 +38,7 @@ #ifndef _GUAC_PROTOCOL_H #define _GUAC_PROTOCOL_H -#include +#include #include "guacio.h" @@ -214,14 +214,10 @@ int guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, * @param layer The index of the destination layer. * @param x The destination X coordinate. * @param y The destination Y coordinate. - * @param png_rows A libpng-compatible PNG image buffer containing the image - * data to send. - * @param w The width of the image in the image buffer. - * @param h The height of the image in the image buffer. + * @param surface A cairo surface containing the image data to send. * @return Zero on success, non-zero on error. */ -int guac_send_png(GUACIO* io, int layer, int x, int y, - png_byte** png_rows, int w, int h); +int guac_send_png(GUACIO* io, int layer, int x, int y, cairo_surface_t* surface); /** * Sends a cursor instruction over the given GUACIO connection. The PNG image @@ -230,14 +226,10 @@ int guac_send_png(GUACIO* io, int layer, int x, int y, * @param io The GUACIO connection to use. * @param x The X coordinate of the cursor hotspot. * @param y The Y coordinate of the cursor hotspot. - * @param png_rows A libpng-compatible PNG image buffer containing the image - * data to send. - * @param w The width of the image in the image buffer. - * @param h The height of the image in the image buffer. + * @param surface A cairo surface containing the image data to send. * @return Zero on success, non-zero on error. */ -int guac_send_cursor(GUACIO* io, int x, int y, - png_byte** png_rows, int w, int h); +int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface); /** * Returns whether new instruction data is available on the given GUACIO diff --git a/libguac/src/client.c b/libguac/src/client.c index 41045e95..c11ebd05 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -47,33 +47,6 @@ #include "client.h" #include "client-handlers.h" -png_byte** guac_alloc_png_buffer(int w, int h, int bpp) { - - png_byte** png_buffer; - png_byte* row; - int y; - - /* Allocate rows for PNG */ - png_buffer = (png_byte**) malloc(h * sizeof(png_byte*)); - for (y=0; y -#else +#endif + +#ifndef HAVE_CLOCK_GETTIME #include #endif @@ -45,11 +47,8 @@ #include #include #include -#include -#ifdef HAVE_PNGSTRUCT_H -#include -#endif +#include #include @@ -292,75 +291,21 @@ int guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int d } -void __guac_write_png(png_structp png, png_bytep data, png_size_t length) { +cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsigned int length) { -#ifdef HAVE_PNG_GET_IO_PTR - GUACIO* io = (GUACIO*) png_get_io_ptr(png); -#else - /* Direct access to io_ptr has been deprecated, but we'll - use it if we have to. */ - GUACIO* io = (GUACIO*) png->io_ptr; -#endif + GUACIO* io = (GUACIO*) closure; - if (guac_write_base64(io, data, length) < 0) { - perror("Error writing PNG"); - png_error(png, "Error writing PNG"); - return; - } + if (guac_write_base64(io, data, length) < 0) + return CAIRO_STATUS_WRITE_ERROR; + + return CAIRO_STATUS_SUCCESS; } -void __guac_write_flush(png_structp png) { -} +int guac_send_png(GUACIO* io, int layer, int x, int y, cairo_surface_t* surface) { -int guac_send_png(GUACIO* io, int layer, int x, int y, png_byte** png_rows, int w, int h) { + /* Write instruction and args */ - png_structp png; - png_infop png_info; - - /* Write image */ - - /* Set up PNG writer */ - png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png) { - return -1; - } - - png_info = png_create_info_struct(png); - if (!png_info) { - png_destroy_write_struct(&png, NULL); - return -1; - } - -#ifdef GUAC_FAST_PNG - /* Do not filter (speed) */ - png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_VALUE_NONE); - - /* Fast compression level */ - png_set_compression_level(png, 1); -#endif - - /* Set error handler */ - if (setjmp(png_jmpbuf(png))) { - png_destroy_write_struct(&png, &png_info); - return -1; - } - - png_set_write_fn(png, io, __guac_write_png, __guac_write_flush); - - /* Set PNG IHDR */ - png_set_IHDR( - png, - png_info, - w, - h, - 8, - PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT - ); - if ( guac_write_string(io, "png:") || guac_write_int(io, layer) @@ -370,64 +315,30 @@ int guac_send_png(GUACIO* io, int layer, int x, int y, png_byte** png_rows, int || guac_write_int(io, y) || guac_write_string(io, ",") ) { - png_destroy_write_struct(&png, &png_info); return -1; } - png_set_rows(png, png_info, png_rows); - png_write_png(png, png_info, PNG_TRANSFORM_IDENTITY, NULL); + /* Write surface */ + + if (cairo_surface_write_to_png_stream(surface, __guac_write_png, io) != CAIRO_STATUS_SUCCESS) { + return -1; + } if (guac_flush_base64(io) < 0) { - png_destroy_write_struct(&png, &png_info); return -1; } - png_destroy_write_struct(&png, &png_info); + /* Finish instruction */ + return guac_write_string(io, ";"); } -int guac_send_cursor(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h) { +int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface) { - png_structp png; - png_infop png_info; + /* Write instruction and args */ - /* Write image */ - - /* Set up PNG writer */ - png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png) { - return -1; - } - - png_info = png_create_info_struct(png); - if (!png_info) { - png_destroy_write_struct(&png, NULL); - return -1; - } - - /* Set error handler */ - if (setjmp(png_jmpbuf(png))) { - png_destroy_write_struct(&png, &png_info); - return -1; - } - - png_set_write_fn(png, io, __guac_write_png, __guac_write_flush); - - /* Set PNG IHDR */ - png_set_IHDR( - png, - png_info, - w, - h, - 8, - PNG_COLOR_TYPE_RGBA, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT - ); - if ( guac_write_string(io, "cursor:") || guac_write_int(io, x) @@ -435,19 +346,21 @@ int guac_send_cursor(GUACIO* io, int x, int y, png_byte** png_rows, int w, int h || guac_write_int(io, y) || guac_write_string(io, ",") ) { - png_destroy_write_struct(&png, &png_info); return -1; } - png_set_rows(png, png_info, png_rows); - png_write_png(png, png_info, PNG_TRANSFORM_IDENTITY, NULL); + /* Write surface */ + + if (cairo_surface_write_to_png_stream(surface, __guac_write_png, io) != CAIRO_STATUS_SUCCESS) { + return -1; + } if (guac_flush_base64(io) < 0) { - png_destroy_write_struct(&png, &png_info); return -1; } - png_destroy_write_struct(&png, &png_info); + /* Finish instruction */ + return guac_write_string(io, ";"); } From ba323a7a208f4b3713c2c3c4e7ac55a7bc3cf0f8 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 30 Mar 2011 00:03:32 -0700 Subject: [PATCH 057/330] Added composite mode. --- libguac/include/protocol.h | 48 +++++++++++++++++++++++++++++++++++--- libguac/src/protocol.c | 11 +++++++-- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index aeb5b70a..b6adad32 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -64,6 +64,44 @@ */ #define GUAC_USEC_TIMEOUT (GUAC_TIMEOUT*1000) + +/** + * Composite modes used by Guacamole draw instructions. Each + * composite mode maps to a unique channel mask integer. + */ +typedef enum guac_composite_mode_t { + + /* + * (NOTE - set notation encoded in UTF-8): + * + * A: Source where destination transparent = S ∩ D′ + * B: Source where destination opaque = S ∩ D + * C: Destination where source transparent = D ∩ S′ + * D: Destination where source opaque = D ∩ S + * + * 0 = Active, 1 = Inactive + */ + /* ABCD */ + NOP = 0x0, /* 0000 */ + RIN = 0x1, /* 0001 */ + ROUT = 0x2, /* 0010 */ + DEST = 0x3, /* 0011 */ + IN = 0x4, /* 0100 */ + /* NO P/D NAME: 0101 */ + ATOP = 0x6, /* 0110 */ + /* NO P/D NAME: 0111 */ + OUT = 0x8, /* 1000 */ + RATOP = 0x9, /* 1001 */ + XOR = 0xA, /* 1010 */ + ROVER = 0xB, /* 1011 */ + SRC = 0xC, /* 1100 */ + /* NO P/D NAME: 1101 */ + OVER = 0xE, /* 1110 */ + PLUS = 0xF /* 1111 */ + +} guac_composite_mode_t; + + /** * Represents a single instruction within the Guacamole protocol. */ @@ -196,6 +234,7 @@ int guac_send_size(GUACIO* io, int w, int h); * @param srcy The Y coordinate of the source rectangle. * @param w The width of the source rectangle. * @param h The height of the source rectangle. + * @param mode The composite mode to use. * @param dstl The index of the destination layer. * @param dstx The X coordinate of the destination, where the source rectangle * should be copied. @@ -203,21 +242,24 @@ int guac_send_size(GUACIO* io, int w, int h); * should be copied. * @return Zero on success, non-zero on error. */ -int guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, - int dstl, int dstx, int dsty); +int guac_send_copy(GUACIO* io, + int srcl, int srcx, int srcy, int w, int h, + guac_composite_mode_t mode, int dstl, int dstx, int dsty); /** * Sends a png instruction over the given GUACIO connection. The PNG image data * given will be automatically base64-encoded for transmission. * * @param io The GUACIO connection to use. + * @param mode The composite mode to use. * @param layer The index of the destination layer. * @param x The destination X coordinate. * @param y The destination Y coordinate. * @param surface A cairo surface containing the image data to send. * @return Zero on success, non-zero on error. */ -int guac_send_png(GUACIO* io, int layer, int x, int y, cairo_surface_t* surface); +int guac_send_png(GUACIO* io, guac_composite_mode_t mode, + int layer, int x, int y, cairo_surface_t* surface); /** * Sends a cursor instruction over the given GUACIO connection. The PNG image diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 4348627c..bcd175d6 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -268,7 +268,9 @@ int guac_send_sync(GUACIO* io, long timestamp) { } -int guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int dstl, int dstx, int dsty) { +int guac_send_copy(GUACIO* io, + int srcl, int srcx, int srcy, int w, int h, + guac_composite_mode_t mode, int dstl, int dstx, int dsty) { return guac_write_string(io, "copy:") @@ -282,6 +284,8 @@ int guac_send_copy(GUACIO* io, int srcl, int srcx, int srcy, int w, int h, int d || guac_write_string(io, ",") || guac_write_int(io, h) || guac_write_string(io, ",") + || guac_write_int(io, mode) + || guac_write_string(io, ",") || guac_write_int(io, dstl) || guac_write_string(io, ",") || guac_write_int(io, dstx) @@ -302,12 +306,15 @@ cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsign } -int guac_send_png(GUACIO* io, int layer, int x, int y, cairo_surface_t* surface) { +int guac_send_png(GUACIO* io, guac_composite_mode_t mode, + int layer, int x, int y, cairo_surface_t* surface) { /* Write instruction and args */ if ( guac_write_string(io, "png:") + || guac_write_int(io, mode) + || guac_write_string(io, ",") || guac_write_int(io, layer) || guac_write_string(io, ",") || guac_write_int(io, x) From 6579eea3f126be4d911c5cb96dbca06a5769225c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 30 Mar 2011 00:31:32 -0700 Subject: [PATCH 058/330] Marked unimplemented masks as such. --- libguac/include/protocol.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index b6adad32..60e1d8d1 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -82,20 +82,20 @@ typedef enum guac_composite_mode_t { * 0 = Active, 1 = Inactive */ /* ABCD */ - NOP = 0x0, /* 0000 */ + /* NOT IMPL'D: 0000 */ RIN = 0x1, /* 0001 */ ROUT = 0x2, /* 0010 */ DEST = 0x3, /* 0011 */ IN = 0x4, /* 0100 */ - /* NO P/D NAME: 0101 */ + /* NOT IMPL'D: 0101 */ ATOP = 0x6, /* 0110 */ - /* NO P/D NAME: 0111 */ + /* NOT IMPL'D: 0111 */ OUT = 0x8, /* 1000 */ RATOP = 0x9, /* 1001 */ XOR = 0xA, /* 1010 */ ROVER = 0xB, /* 1011 */ SRC = 0xC, /* 1100 */ - /* NO P/D NAME: 1101 */ + /* NOT IMPL'D: 1101 */ OVER = 0xE, /* 1110 */ PLUS = 0xF /* 1111 */ From ab3f09dfb0ae5e3a709975925b2d202f2a7b59e8 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 1 Apr 2011 00:30:40 -0700 Subject: [PATCH 059/330] Fixed integer overflow in guac_sleep. --- libguac/src/protocol.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index bcd175d6..198d4623 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -170,6 +170,10 @@ int guac_send_args(GUACIO* io, const char** args) { int i; + /* Handle protocols with no args */ + if (args[0] == NULL) + return guac_write_string(io, "args;"); + if (guac_write_string(io, "args:")) return -1; for (i=0; args[i] != NULL; i++) { @@ -530,8 +534,8 @@ void guac_sleep(int millis) { #ifdef HAVE_NANOSLEEP struct timespec sleep_period; - sleep_period.tv_sec = 0; - sleep_period.tv_nsec = millis * 1000000L; + sleep_period.tv_sec = millis / 1000; + sleep_period.tv_nsec = (millis % 1000) * 1000000L; nanosleep(&sleep_period, NULL); #elif defined(__MINGW32__) From 693fe2a1f5f785391eaab68bad1e22df77b98b66 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 1 Apr 2011 00:53:53 -0700 Subject: [PATCH 060/330] Support for negative numbers in guac_write_int --- libguac/include/guacio.h | 2 +- libguac/src/guacio.c | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index e82061ed..ff3a1639 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -123,7 +123,7 @@ GUACIO* guac_open(int fd); * @param i The unsigned int to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_int(GUACIO* io, unsigned long i); +ssize_t guac_write_int(GUACIO* io, long i); /** * Writes the given string to the given GUACIO object. The data diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index e984c4fc..7c04054c 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -98,21 +98,31 @@ ssize_t __guac_write(GUACIO* io, const char* buf, int count) { return retval; } -ssize_t guac_write_int(GUACIO* io, unsigned long i) { +ssize_t guac_write_int(GUACIO* io, long i) { char buffer[128]; char* ptr = &(buffer[127]); + int nonneg; + + /* Obtain non-negative value */ + if (i < 0) nonneg = -i; + else nonneg = i; + + /* Generate numeric string */ *ptr = 0; do { ptr--; - *ptr = '0' + (i % 10); + *ptr = '0' + (nonneg % 10); - i /= 10; + nonneg /= 10; - } while (i > 0 && ptr >= buffer); + } while (nonneg > 0 && ptr >= buffer); + + /* Prepend with dash if negative */ + if (i < 0 && ptr >= buffer) *(--ptr) = '-'; return guac_write_string(io, ptr); From 2aa580504806b5f5eda89c2d8af79f8f73f0314b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 3 Apr 2011 00:43:13 -0700 Subject: [PATCH 061/330] Fixed guac_write_int - var should have been a long. --- libguac/src/guacio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index 7c04054c..a160633e 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -102,7 +102,7 @@ ssize_t guac_write_int(GUACIO* io, long i) { char buffer[128]; char* ptr = &(buffer[127]); - int nonneg; + long nonneg; /* Obtain non-negative value */ if (i < 0) nonneg = -i; From c97875d5c8f73e20dc04e5e9acfd6d6a3881a8ce Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 21 Apr 2011 15:04:15 -0700 Subject: [PATCH 062/330] Cross-platform thread functions. --- libguac/Makefile.am | 4 +-- libguac/include/thread.h | 63 ++++++++++++++++++++++++++++++++++++++++ libguac/src/thread.c | 63 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 libguac/include/thread.h create mode 100644 libguac/src/thread.c diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 82e7fa7e..4a9e3f4c 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -40,11 +40,11 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -Iinclude libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/log.h +libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/log.h include/thread.h lib_LTLIBRARIES = libguac.la -libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c src/log.c +libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c src/log.c src/thread.c libguac_la_LDFLAGS = -version-info 0:0:0 diff --git a/libguac/include/thread.h b/libguac/include/thread.h new file mode 100644 index 00000000..b0372e5a --- /dev/null +++ b/libguac/include/thread.h @@ -0,0 +1,63 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_THREAD_H +#define _GUAC_THREAD_H + +/** + * Provides basic cross-platform threads. + * + * @file thread.h + */ + +#ifdef HAVE_LIBPTHREAD + +#include +typedef pthread_t guac_thread_t; + +#elif defined(__MINGW32__) + +#include +#include +typedef uintptr_t guac_thread_t; + +#endif + +void guac_thread_create(guac_thread_t* thread, void*(*function)(void*), void* data); +void guac_thread_join(guac_thread_t thread); + +#endif diff --git a/libguac/src/thread.c b/libguac/src/thread.c new file mode 100644 index 00000000..c22dc3a4 --- /dev/null +++ b/libguac/src/thread.c @@ -0,0 +1,63 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "thread.h" + +#ifdef HAVE_LIBPTHREAD +#include +#elif defined(__MINGW32__) +#include +#include +#endif + +void guac_thread_create(guac_thread_t* thread, void*(*function)(void*), void* data) { +#ifdef HAVE_LIBPTHREAD + pthread_create(thread, NULL, function, data); +#elif defined(__MINGW32__) + *thread = _beginthreadex(NULL, 0, + function, data, 0 /* Create running */, NULL); +#endif +} + +void guac_thread_join(guac_thread_t thread) { +#ifdef HAVE_LIBPTHREAD + pthread_join(thread, NULL); +#elif defined(__MINGW32__) + WaitForSingleObject(thread, INFINITE); +#endif +} + From bd8d314c29ac546daca8a6ba0a4dbabd5285725d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 21 Apr 2011 15:07:36 -0700 Subject: [PATCH 063/330] Converted to new thread API. --- libguac/include/thread.h | 2 +- libguac/src/client.c | 14 +++++++------- libguac/src/thread.c | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libguac/include/thread.h b/libguac/include/thread.h index b0372e5a..ae537b1f 100644 --- a/libguac/include/thread.h +++ b/libguac/include/thread.h @@ -57,7 +57,7 @@ typedef uintptr_t guac_thread_t; #endif -void guac_thread_create(guac_thread_t* thread, void*(*function)(void*), void* data); +int guac_thread_create(guac_thread_t* thread, void*(*function)(void*), void* data); void guac_thread_join(guac_thread_t thread); #endif diff --git a/libguac/src/client.c b/libguac/src/client.c index c11ebd05..47ed4636 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -39,8 +39,8 @@ #include #include #include -#include +#include "thread.h" #include "log.h" #include "guacio.h" #include "protocol.h" @@ -363,21 +363,21 @@ void* __guac_client_input_thread(void* data) { int guac_start_client(guac_client* client) { - pthread_t input_thread, output_thread; + guac_thread_t input_thread, output_thread; - if (pthread_create(&output_thread, NULL, __guac_client_output_thread, (void*) client)) { + if (guac_thread_create(&output_thread, __guac_client_output_thread, (void*) client)) { return -1; } - if (pthread_create(&input_thread, NULL, __guac_client_input_thread, (void*) client)) { + if (guac_thread_create(&input_thread, __guac_client_input_thread, (void*) client)) { guac_client_stop(client); - pthread_join(output_thread, NULL); + guac_thread_join(output_thread); return -1; } /* Wait for I/O threads */ - pthread_join(input_thread, NULL); - pthread_join(output_thread, NULL); + guac_thread_join(input_thread); + guac_thread_join(output_thread); /* Done */ return 0; diff --git a/libguac/src/thread.c b/libguac/src/thread.c index c22dc3a4..a449cd52 100644 --- a/libguac/src/thread.c +++ b/libguac/src/thread.c @@ -44,9 +44,9 @@ #include #endif -void guac_thread_create(guac_thread_t* thread, void*(*function)(void*), void* data) { +int guac_thread_create(guac_thread_t* thread, void*(*function)(void*), void* data) { #ifdef HAVE_LIBPTHREAD - pthread_create(thread, NULL, function, data); + return pthread_create(thread, NULL, function, data); #elif defined(__MINGW32__) *thread = _beginthreadex(NULL, 0, function, data, 0 /* Create running */, NULL); From 881d49278d98fe46e6abaf92793241994df573da Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 21 Apr 2011 15:23:53 -0700 Subject: [PATCH 064/330] Changed enum names (collision with windows-defined macros), fixed thread call. --- libguac/include/protocol.h | 34 +++++++++++++++++----------------- libguac/src/protocol.c | 2 +- libguac/src/thread.c | 8 ++++++-- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 60e1d8d1..c0172efe 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -81,23 +81,23 @@ typedef enum guac_composite_mode_t { * * 0 = Active, 1 = Inactive */ - /* ABCD */ - /* NOT IMPL'D: 0000 */ - RIN = 0x1, /* 0001 */ - ROUT = 0x2, /* 0010 */ - DEST = 0x3, /* 0011 */ - IN = 0x4, /* 0100 */ - /* NOT IMPL'D: 0101 */ - ATOP = 0x6, /* 0110 */ - /* NOT IMPL'D: 0111 */ - OUT = 0x8, /* 1000 */ - RATOP = 0x9, /* 1001 */ - XOR = 0xA, /* 1010 */ - ROVER = 0xB, /* 1011 */ - SRC = 0xC, /* 1100 */ - /* NOT IMPL'D: 1101 */ - OVER = 0xE, /* 1110 */ - PLUS = 0xF /* 1111 */ + /* ABCD */ + /* NOT IMPL'D: 0000 */ + GUAC_COMP_RIN = 0x1, /* 0001 */ + GUAC_COMP_ROUT = 0x2, /* 0010 */ + GUAC_COMP_DEST = 0x3, /* 0011 */ + GUAC_COMP_IN = 0x4, /* 0100 */ + /* NOT IMPL'D: 0101 */ + GUAC_COMP_ATOP = 0x6, /* 0110 */ + /* NOT IMPL'D: 0111 */ + GUAC_COMP_OUT = 0x8, /* 1000 */ + GUAC_COMP_RATOP = 0x9, /* 1001 */ + GUAC_COMP_XOR = 0xA, /* 1010 */ + GUAC_COMP_ROVER = 0xB, /* 1011 */ + GUAC_COMP_SRC = 0xC, /* 1100 */ + /* NOT IMPL'D: 1101 */ + GUAC_COMP_OVER = 0xE, /* 1110 */ + GUAC_COMP_PLUS = 0xF /* 1111 */ } guac_composite_mode_t; diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 198d4623..d2b3e91a 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -539,7 +539,7 @@ void guac_sleep(int millis) { nanosleep(&sleep_period, NULL); #elif defined(__MINGW32__) - Sleep(millis) + Sleep(millis); #else #warning No sleep/nanosleep function available. Clients may not perform as expected. Consider patching libguac to add support for your platform. #endif diff --git a/libguac/src/thread.c b/libguac/src/thread.c index a449cd52..d8a0db79 100644 --- a/libguac/src/thread.c +++ b/libguac/src/thread.c @@ -49,7 +49,11 @@ int guac_thread_create(guac_thread_t* thread, void*(*function)(void*), void* dat return pthread_create(thread, NULL, function, data); #elif defined(__MINGW32__) *thread = _beginthreadex(NULL, 0, - function, data, 0 /* Create running */, NULL); + (unsigned(__stdcall*)(void*)) function, data, + 0 /* Create running */, NULL); + if (thread == 0) + return errno; + return 0; #endif } @@ -57,7 +61,7 @@ void guac_thread_join(guac_thread_t thread) { #ifdef HAVE_LIBPTHREAD pthread_join(thread, NULL); #elif defined(__MINGW32__) - WaitForSingleObject(thread, INFINITE); + WaitForSingleObject(&thread, INFINITE); #endif } From 9d8594fb7e7dc42d4109606bd0eb33d1dc3dead3 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 21 Apr 2011 15:30:37 -0700 Subject: [PATCH 065/330] Bumped version numbers. --- libguac/Makefile.am | 2 +- libguac/configure.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 4a9e3f4c..bf587cde 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -46,5 +46,5 @@ lib_LTLIBRARIES = libguac.la libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c src/log.c src/thread.c -libguac_la_LDFLAGS = -version-info 0:0:0 +libguac_la_LDFLAGS = -version-info 1:0:0 diff --git a/libguac/configure.in b/libguac/configure.in index 144e1613..96b49654 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -35,7 +35,7 @@ # ***** END LICENSE BLOCK ***** AC_INIT(src/client.c) -AM_INIT_AUTOMAKE(libguac, 0.3.0) +AM_INIT_AUTOMAKE(libguac, 0.4.0) AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. From 3239f032ae5a4a02747e420f97a25be8e27fecd8 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 21 Apr 2011 23:48:44 -0700 Subject: [PATCH 066/330] Fixed thread implementation for win32 --- libguac/include/thread.h | 2 +- libguac/src/thread.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libguac/include/thread.h b/libguac/include/thread.h index ae537b1f..33bd5d5d 100644 --- a/libguac/include/thread.h +++ b/libguac/include/thread.h @@ -53,7 +53,7 @@ typedef pthread_t guac_thread_t; #include #include -typedef uintptr_t guac_thread_t; +typedef HANDLE guac_thread_t; #endif diff --git a/libguac/src/thread.c b/libguac/src/thread.c index d8a0db79..cacc7b08 100644 --- a/libguac/src/thread.c +++ b/libguac/src/thread.c @@ -48,7 +48,7 @@ int guac_thread_create(guac_thread_t* thread, void*(*function)(void*), void* dat #ifdef HAVE_LIBPTHREAD return pthread_create(thread, NULL, function, data); #elif defined(__MINGW32__) - *thread = _beginthreadex(NULL, 0, + *thread = (guac_thread_t) _beginthreadex(NULL, 0, (unsigned(__stdcall*)(void*)) function, data, 0 /* Create running */, NULL); if (thread == 0) @@ -61,7 +61,7 @@ void guac_thread_join(guac_thread_t thread) { #ifdef HAVE_LIBPTHREAD pthread_join(thread, NULL); #elif defined(__MINGW32__) - WaitForSingleObject(&thread, INFINITE); + WaitForSingleObject(thread, INFINITE); #endif } From 8242c37f11ec45d76c5b51d261149c1b96733992 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 29 Apr 2011 00:45:38 -0700 Subject: [PATCH 067/330] 64-bit timestamps and output --- libguac/include/client.h | 4 ++-- libguac/include/guacio.h | 2 +- libguac/include/protocol.h | 5 +++-- libguac/src/client-handlers.c | 2 +- libguac/src/client.c | 2 +- libguac/src/guacio.c | 4 ++-- libguac/src/protocol.c | 8 ++++---- 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index f4cb9e95..1f449f23 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -151,13 +151,13 @@ struct guac_client { * The time (in milliseconds) of receipt of the last sync message from * the client. */ - long last_received_timestamp; + guac_timestamp_t last_received_timestamp; /** * The time (in milliseconds) that the last sync message was sent to the * client. */ - long last_sent_timestamp; + guac_timestamp_t last_sent_timestamp; /** * Reference to dlopen'd client plugin. diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index ff3a1639..d21fea0c 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -123,7 +123,7 @@ GUACIO* guac_open(int fd); * @param i The unsigned int to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_int(GUACIO* io, long i); +ssize_t guac_write_int(GUACIO* io, int64_t i); /** * Writes the given string to the given GUACIO object. The data diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index c0172efe..d7733cac 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -64,6 +64,7 @@ */ #define GUAC_USEC_TIMEOUT (GUAC_TIMEOUT*1000) +typedef int64_t guac_timestamp_t; /** * Composite modes used by Guacamole draw instructions. Each @@ -192,7 +193,7 @@ int guac_send_name(GUACIO* io, const char* name); * @param timestamp The current timestamp (in milliseconds). * @return Zero on success, non-zero on error. */ -int guac_send_sync(GUACIO* io, long timestamp); +int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp); /** * Sends an error instruction over the given GUACIO connection. The @@ -298,7 +299,7 @@ int guac_instructions_waiting(GUACIO* io); */ int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction); -long guac_current_timestamp(); +guac_timestamp_t guac_current_timestamp(); void guac_sleep(int millis); #endif diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index 380ad19a..83a9481f 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -55,7 +55,7 @@ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { /* Guacamole instruction handlers */ int __guac_handle_sync(guac_client* client, guac_instruction* instruction) { - long timestamp = atol(instruction->argv[0]); + guac_timestamp_t timestamp = atol(instruction->argv[0]); /* Error if timestamp is in future */ if (timestamp > client->last_sent_timestamp) diff --git a/libguac/src/client.c b/libguac/src/client.c index 47ed4636..cdc0cc43 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -267,7 +267,7 @@ void* __guac_client_output_thread(void* data) { while (client->state == RUNNING) { /* Occasionally ping client with sync */ - long timestamp = guac_current_timestamp(); + guac_timestamp_t timestamp = guac_current_timestamp(); if (timestamp - client->last_sent_timestamp > GUAC_SYNC_FREQUENCY) { client->last_sent_timestamp = timestamp; if ( diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index a160633e..3b06fff9 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -98,11 +98,11 @@ ssize_t __guac_write(GUACIO* io, const char* buf, int count) { return retval; } -ssize_t guac_write_int(GUACIO* io, long i) { +ssize_t guac_write_int(GUACIO* io, int64_t i) { char buffer[128]; char* ptr = &(buffer[127]); - long nonneg; + int64_t nonneg; /* Obtain non-negative value */ if (i < 0) nonneg = -i; diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index d2b3e91a..f0c9299f 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -263,7 +263,7 @@ int guac_send_error(GUACIO* io, const char* error) { } -int guac_send_sync(GUACIO* io, long timestamp) { +int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp) { return guac_write_string(io, "sync:") @@ -503,7 +503,7 @@ int guac_instructions_waiting(GUACIO* io) { return guac_select(io, GUAC_USEC_TIMEOUT); } -long guac_current_timestamp() { +guac_timestamp_t guac_current_timestamp() { #ifdef HAVE_CLOCK_GETTIME @@ -513,7 +513,7 @@ long guac_current_timestamp() { clock_gettime(CLOCK_REALTIME, ¤t); /* Calculate milliseconds */ - return current.tv_sec * 1000 + current.tv_nsec / 1000000; + return (guac_timestamp_t) current.tv_sec * 1000 + current.tv_nsec / 1000000; #else @@ -523,7 +523,7 @@ long guac_current_timestamp() { gettimeofday(¤t, NULL); /* Calculate milliseconds */ - return current.tv_sec * 1000 + current.tv_usec / 1000; + return (guac_timestamp_t) current.tv_sec * 1000 + current.tv_usec / 1000; #endif From 532ad2137b467a79d245522a0147f82a4a694784 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 29 Apr 2011 01:35:17 -0700 Subject: [PATCH 068/330] Added guac_parse_int, which handles 64-bit integers regardless of native arch. --- libguac/include/guacio.h | 11 +++++++++++ libguac/src/client-handlers.c | 4 ++-- libguac/src/guacio.c | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index d21fea0c..51b6633c 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -114,6 +114,17 @@ typedef struct GUACIO { */ GUACIO* guac_open(int fd); +/** + * Parses the given string as a decimal number, returning the result as + * a 64-bit signed value. This value will be 64-bit regardless of platform. + * + * @param str The string to parse into a 64-bit integer. + * @return The 64-bit integer representation of the number in the given + * string, undefined if the string does not contain a properly + * formatted number. + */ +int64_t guac_parse_int(const char* str); + /** * Writes the given unsigned int to the given GUACIO object. The data * written may be buffered until the buffer is flushed automatically or diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index 83a9481f..16bfb4d8 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -53,9 +53,9 @@ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { }; /* Guacamole instruction handlers */ - +#include int __guac_handle_sync(guac_client* client, guac_instruction* instruction) { - guac_timestamp_t timestamp = atol(instruction->argv[0]); + guac_timestamp_t timestamp = guac_parse_int(instruction->argv[0]); /* Error if timestamp is in future */ if (timestamp > client->last_sent_timestamp) diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index 3b06fff9..dc4a3105 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -98,6 +98,24 @@ ssize_t __guac_write(GUACIO* io, const char* buf, int count) { return retval; } +int64_t guac_parse_int(const char* str) { + + int sign = 1; + int64_t num = 0; + + for (; *str != '\0'; str++) { + + if (*str == '-') + sign = -sign; + else + num = num * 10 + (*str - '0'); + + } + + return num * sign; + +} + ssize_t guac_write_int(GUACIO* io, int64_t i) { char buffer[128]; From b412f1c16d9dec062d97388f52ec2cd912928c68 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 2 Jun 2011 11:22:20 -0700 Subject: [PATCH 069/330] Added missing include file to Makefile.am --- libguac/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index bf587cde..e6397d5b 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -40,7 +40,7 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -Iinclude libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/log.h include/thread.h +libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/client-handlers.h include/log.h include/thread.h lib_LTLIBRARIES = libguac.la From f55ba6ff4e662879ebf4c513c36e17ea81b6a155 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 14 Jul 2011 09:57:14 -0700 Subject: [PATCH 070/330] Ping with last sync, not new sync. Don't want to update the last update timestamp unnecessarily. --- libguac/src/client.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index cdc0cc43..9a48911f 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -263,15 +263,17 @@ void* __guac_client_output_thread(void* data) { guac_client* client = (guac_client*) data; GUACIO* io = client->io; + guac_timestamp_t last_ping_timestamp = guac_current_timestamp(); + /* Guacamole client output loop */ while (client->state == RUNNING) { - /* Occasionally ping client with sync */ + /* Occasionally ping client with repeat of last sync */ guac_timestamp_t timestamp = guac_current_timestamp(); - if (timestamp - client->last_sent_timestamp > GUAC_SYNC_FREQUENCY) { - client->last_sent_timestamp = timestamp; + if (timestamp - last_ping_timestamp > GUAC_SYNC_FREQUENCY) { + last_ping_timestamp = timestamp; if ( - guac_send_sync(io, timestamp) + guac_send_sync(io, client->last_sent_timestamp) || guac_flush(io) ) { guac_client_stop(client); From 208ff61edd6384e04c4c9f71924d80b9143e6261 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 20 Jul 2011 08:45:23 -0700 Subject: [PATCH 071/330] Added missing stdint.h include. --- libguac/include/guacio.h | 1 + libguac/src/guacio.c | 1 + 2 files changed, 2 insertions(+) diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index 51b6633c..67b5cd01 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -38,6 +38,7 @@ #ifndef _GUAC_GUACIO_H #define _GUAC_GUACIO_H +#include #include /** diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index dc4a3105..f2b0fcad 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef __MINGW32__ #include From 6341346cb7285ab6c1960b57be632b5e5a925e22 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 20 Jul 2011 12:36:02 -0700 Subject: [PATCH 072/330] Using C99, POSIX, and BSD. Added guac_layer and layer/buffer alloc/free. --- libguac/configure.in | 7 +++ libguac/include/client.h | 62 +++++++++++++++++++++++++++ libguac/include/protocol.h | 36 +++++++++++++--- libguac/src/client.c | 87 ++++++++++++++++++++++++++++++++++++++ libguac/src/protocol.c | 12 +++--- 5 files changed, 192 insertions(+), 12 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index 96b49654..193dde7e 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -40,8 +40,15 @@ AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. AC_PROG_CC +AC_PROG_CC_C99 AC_PROG_LIBTOOL +# POSIX +AC_DEFINE(_POSIX_C_SOURCE, 199309L) + +# BSD +AC_DEFINE(_BSD_SOURCE) + # Checks for libraries. AC_CHECK_LIB([dl], [dlopen],, AC_MSG_ERROR("libdl is required for loading client plugins")) AC_CHECK_LIB([cairo], [cairo_create],, AC_MSG_ERROR("cairo is required for drawing instructions")) diff --git a/libguac/include/client.h b/libguac/include/client.h index 1f449f23..9703733c 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -147,6 +147,29 @@ struct guac_client { */ guac_client_state state; + /** + * The head pointer of the list of all available (allocated but not used) + * layers. + */ + guac_layer* available_layers; + + /** + * The index of the next available buffer. + */ + int next_buffer_index; + + /** + * The head pointer of the list of all available (allocated but not used) + * buffers. + */ + guac_layer* available_buffers; + + /** + * The head pointer of the list of all allocated layers, regardless of use + * status. + */ + guac_layer* all_layers; + /** * The time (in milliseconds) of receipt of the last sync message from * the client. @@ -328,4 +351,43 @@ int guac_client_handle_instruction(guac_client* client, guac_instruction* instru */ void guac_client_stop(guac_client* client); +/** + * Allocates a new buffer (invisible layer). An arbitrary index is + * automatically assigned if no existing buffer is available for use. + * + * @param client The proxy client to allocate the buffer for. + * @return The next available buffer, or a newly allocated buffer. + */ +guac_layer* guac_client_alloc_buffer(guac_client* client); + +/** + * Allocates a new layer. The layer will be given the specified index, + * even if the layer returned was a previously used (and free'd) layer. + * + * @param client The proxy client to allocate the layer buffer for. + * @param index The index of the layer to allocate. + * @return The next available layer, or a newly allocated layer. + */ +guac_layer* guac_client_alloc_layer(guac_client* client, int index); + +/** + * Returns the given buffer to the pool of available buffers, such that it + * can be reused by any subsequent call to guac_client_allow_buffer(). + * + * @param client The proxy client to return the buffer to. + * @param layer The buffer to return to the pool of available buffers. + */ +void guac_client_free_buffer(guac_client* client, guac_layer* layer); + +/** + * Returns the given layer to the pool of available layers, such that it + * can be reused by any subsequent call to guac_client_allow_layer(). + * + * @param client The proxy client to return the layer to. + * @param layer The layer to return to the pool of available layers. + */ +void guac_client_free_layer(guac_client* client, guac_layer* layer); + +extern const guac_layer* GUAC_DEFAULT_LAYER; + #endif diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index d7733cac..9d87587e 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -102,6 +102,30 @@ typedef enum guac_composite_mode_t { } guac_composite_mode_t; +typedef struct guac_layer guac_layer; + +/** + * Represents a single layer within the Guacamole protocol. + */ +struct guac_layer { + + /** + * The index of this layer. + */ + int index; + + /** + * The next allocated layer in the list of all layers. + */ + guac_layer* next; + + /** + * The next available (unused) layer in the list of + * allocated but free'd layers. + */ + guac_layer* next_available; + +}; /** * Represents a single instruction within the Guacamole protocol. @@ -230,13 +254,13 @@ int guac_send_size(GUACIO* io, int w, int h); * Sends a copy instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. - * @param srcl The index of the source layer. + * @param srcl The source layer. * @param srcx The X coordinate of the source rectangle. * @param srcy The Y coordinate of the source rectangle. * @param w The width of the source rectangle. * @param h The height of the source rectangle. * @param mode The composite mode to use. - * @param dstl The index of the destination layer. + * @param dstl The destination layer. * @param dstx The X coordinate of the destination, where the source rectangle * should be copied. * @param dsty The Y coordinate of the destination, where the source rectangle @@ -244,8 +268,8 @@ int guac_send_size(GUACIO* io, int w, int h); * @return Zero on success, non-zero on error. */ int guac_send_copy(GUACIO* io, - int srcl, int srcx, int srcy, int w, int h, - guac_composite_mode_t mode, int dstl, int dstx, int dsty); + const guac_layer* srcl, int srcx, int srcy, int w, int h, + guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty); /** * Sends a png instruction over the given GUACIO connection. The PNG image data @@ -253,14 +277,14 @@ int guac_send_copy(GUACIO* io, * * @param io The GUACIO connection to use. * @param mode The composite mode to use. - * @param layer The index of the destination layer. + * @param layer The destination layer. * @param x The destination X coordinate. * @param y The destination Y coordinate. * @param surface A cairo surface containing the image data to send. * @return Zero on success, non-zero on error. */ int guac_send_png(GUACIO* io, guac_composite_mode_t mode, - int layer, int x, int y, cairo_surface_t* surface); + const guac_layer* layer, int x, int y, cairo_surface_t* surface); /** * Sends a cursor instruction over the given GUACIO connection. The PNG image diff --git a/libguac/src/client.c b/libguac/src/client.c index 9a48911f..beb91cf3 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -47,6 +47,15 @@ #include "client.h" #include "client-handlers.h" +guac_layer __GUAC_DEFAULT_LAYER = { + .index = 0, + .next = NULL, + .next_available = NULL +}; + +const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; + + guac_client* __guac_alloc_client(GUACIO* io) { /* Allocate new client (not handoff) */ @@ -58,9 +67,80 @@ guac_client* __guac_alloc_client(GUACIO* io) { client->last_received_timestamp = client->last_sent_timestamp = guac_current_timestamp(); client->state = RUNNING; + client->all_layers = NULL; + client->available_layers = NULL; + client->available_buffers = NULL; + + client->next_buffer_index = -1; + return client; } +guac_layer* guac_client_alloc_layer(guac_client* client, int index) { + + guac_layer* allocd_layer; + + /* If available layers, pop off first available layer */ + if (client->available_layers != NULL) { + allocd_layer = client->available_layers; + client->available_layers = client->available_layers->next_available; + allocd_layer->next_available = NULL; + } + + /* If no available layers, allocate new layer, add to all_layers list */ + else { + + /* Init new layer */ + allocd_layer = malloc(sizeof(guac_layer)); + + /* Add to all_layers list */ + allocd_layer->next = client->all_layers; + client->all_layers = allocd_layer; + + } + + allocd_layer->index = index; + return allocd_layer; + +} + +void guac_client_free_layer(guac_client* client, guac_layer* layer) { + layer->next = client->available_layers; + client->available_layers = layer; +} + +guac_layer* guac_client_alloc_buffer(guac_client* client) { + + guac_layer* allocd_layer; + + /* If available layers, pop off first available buffer */ + if (client->available_buffers != NULL) { + allocd_layer = client->available_buffers; + client->available_buffers = client->available_buffers->next_available; + allocd_layer->next_available = NULL; + } + + /* If no available buffer, allocate new buffer, add to all_layers list */ + else { + + /* Init new layer */ + allocd_layer = malloc(sizeof(guac_layer)); + allocd_layer->index = client->next_buffer_index--; + + /* Add to all_layers list */ + allocd_layer->next = client->all_layers; + client->all_layers = allocd_layer; + + } + + return allocd_layer; + +} + +void guac_client_free_buffer(guac_client* client, guac_layer* layer) { + layer->next = client->available_buffers; + client->available_buffers = layer; +} guac_client* guac_get_client(int client_fd) { @@ -254,6 +334,13 @@ void guac_free_client(guac_client* client) { guac_log_error("Could not close client plugin while unloading client: %s", dlerror()); } + /* Free all layers */ + while (client->all_layers != NULL) { + guac_layer* layer = client->all_layers; + client->all_layers = layer->next; + free(layer); + } + free(client); } diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index f0c9299f..487a5872 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -273,12 +273,12 @@ int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp) { } int guac_send_copy(GUACIO* io, - int srcl, int srcx, int srcy, int w, int h, - guac_composite_mode_t mode, int dstl, int dstx, int dsty) { + const guac_layer* srcl, int srcx, int srcy, int w, int h, + guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty) { return guac_write_string(io, "copy:") - || guac_write_int(io, srcl) + || guac_write_int(io, srcl->index) || guac_write_string(io, ",") || guac_write_int(io, srcx) || guac_write_string(io, ",") @@ -290,7 +290,7 @@ int guac_send_copy(GUACIO* io, || guac_write_string(io, ",") || guac_write_int(io, mode) || guac_write_string(io, ",") - || guac_write_int(io, dstl) + || guac_write_int(io, dstl->index) || guac_write_string(io, ",") || guac_write_int(io, dstx) || guac_write_string(io, ",") @@ -311,7 +311,7 @@ cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsign } int guac_send_png(GUACIO* io, guac_composite_mode_t mode, - int layer, int x, int y, cairo_surface_t* surface) { + const guac_layer* layer, int x, int y, cairo_surface_t* surface) { /* Write instruction and args */ @@ -319,7 +319,7 @@ int guac_send_png(GUACIO* io, guac_composite_mode_t mode, guac_write_string(io, "png:") || guac_write_int(io, mode) || guac_write_string(io, ",") - || guac_write_int(io, layer) + || guac_write_int(io, layer->index) || guac_write_string(io, ",") || guac_write_int(io, x) || guac_write_string(io, ",") From 3828702b64466328f0a6a3071d65fa848240a7f4 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 21 Jul 2011 15:15:58 -0700 Subject: [PATCH 073/330] Clip instruction. --- libguac/include/protocol.h | 34 +++++++++++++++++++++++++++ libguac/src/protocol.c | 48 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 9d87587e..31d6d734 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -271,6 +271,40 @@ int guac_send_copy(GUACIO* io, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty); +/** + * Sends a rect instruction over the given GUACIO connection. + * + * @param io The GUACIO connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param x The X coordinate of the rectangle. + * @param y The Y coordinate of the rectangle. + * @param width The width of the rectangle. + * @param height The height of the rectangle. + * @param r The red component of the color of the rectangle. + * @param g The green component of the color of the rectangle. + * @param b The blue component of the color of the rectangle. + * @param a The alpha (transparency) component of the color of the rectangle. + * @return Zero on success, non-zero on error. + */ +int guac_send_rect(GUACIO* io, + guac_composite_mode_t mode, const guac_layer* layer, + int x, int y, int width, int height, + int r, int g, int b, int a); + +/** + * Sends a clip instruction over the given GUACIO connection. +* + * @param io The GUACIO connection to use. + * @param layer The layer to set the clipping region of. + * @param x The X coordinate of the clipping rectangle. + * @param y The Y coordinate of the clipping rectangle. + * @param width The width of the clipping rectangle. + * @param height The height of the clipping rectangle. + */ +int guac_send_clip(GUACIO* io, const guac_layer* layer, + int x, int y, int width, int height); + /** * Sends a png instruction over the given GUACIO connection. The PNG image data * given will be automatically base64-encoded for transmission. diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 487a5872..14d6acb1 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -299,6 +299,54 @@ int guac_send_copy(GUACIO* io, } +int guac_send_rect(GUACIO* io, + guac_composite_mode_t mode, const guac_layer* layer, + int x, int y, int width, int height, + int r, int g, int b, int a) { + + return + guac_write_string(io, "rect:") + || guac_write_int(io, mode) + || guac_write_string(io, ",") + || guac_write_int(io, layer->index) + || guac_write_string(io, ",") + || guac_write_int(io, x) + || guac_write_string(io, ",") + || guac_write_int(io, y) + || guac_write_string(io, ",") + || guac_write_int(io, width) + || guac_write_string(io, ",") + || guac_write_int(io, height) + || guac_write_string(io, ",") + || guac_write_int(io, r) + || guac_write_string(io, ",") + || guac_write_int(io, g) + || guac_write_string(io, ",") + || guac_write_int(io, b) + || guac_write_string(io, ",") + || guac_write_int(io, a) + || guac_write_string(io, ";"); + +} + +int guac_send_clip(GUACIO* io, const guac_layer* layer, + int x, int y, int width, int height) { + + return + guac_write_string(io, "clip:") + || guac_write_int(io, layer->index) + || guac_write_string(io, ",") + || guac_write_int(io, x) + || guac_write_string(io, ",") + || guac_write_int(io, y) + || guac_write_string(io, ",") + || guac_write_int(io, width) + || guac_write_string(io, ",") + || guac_write_int(io, height) + || guac_write_string(io, ";"); + +} + cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsigned int length) { GUACIO* io = (GUACIO*) closure; From a829018238397cb54ab1e82c8378d574ba4ea575 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 25 Jul 2011 15:57:48 -0700 Subject: [PATCH 074/330] Fixed segfault in free layer/buffer (was using wrong next pointer). --- libguac/src/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index beb91cf3..d04a267d 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -105,7 +105,7 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index) { } void guac_client_free_layer(guac_client* client, guac_layer* layer) { - layer->next = client->available_layers; + layer->next_available = client->available_layers; client->available_layers = layer; } @@ -138,7 +138,7 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { } void guac_client_free_buffer(guac_client* client, guac_layer* layer) { - layer->next = client->available_buffers; + layer->next_available = client->available_buffers; client->available_buffers = layer; } From eea2e035450a26c09bcad6c1db92bec46d274df2 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 10 Aug 2011 15:13:04 -0700 Subject: [PATCH 075/330] Removed unused file. --- libguac/.package.dsc | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 libguac/.package.dsc diff --git a/libguac/.package.dsc b/libguac/.package.dsc deleted file mode 100644 index d24d088f..00000000 --- a/libguac/.package.dsc +++ /dev/null @@ -1,2 +0,0 @@ -PKGNAME=libguac -VERSION=0.0.1 From e5cc6eb7ca0ed031c3828b994d0831eac9269647 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 29 Aug 2011 22:24:45 -0700 Subject: [PATCH 076/330] Improved documentation of channel masks and composite operations. --- libguac/include/protocol.h | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 31d6d734..5f8fa1d0 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -73,32 +73,34 @@ typedef int64_t guac_timestamp_t; typedef enum guac_composite_mode_t { /* - * (NOTE - set notation encoded in UTF-8): - * - * A: Source where destination transparent = S ∩ D′ - * B: Source where destination opaque = S ∩ D - * C: Destination where source transparent = D ∩ S′ - * D: Destination where source opaque = D ∩ S + * A: Source where destination transparent = S n D' + * B: Source where destination opaque = S n D + * C: Destination where source transparent = D n S' + * D: Destination where source opaque = D n S * * 0 = Active, 1 = Inactive */ /* ABCD */ - /* NOT IMPL'D: 0000 */ + GUAC_COMP_ROUT = 0x2, /* 0010 - Clears destination where source opaque */ + GUAC_COMP_DEST = 0x3, /* 0011 - No operation */ + GUAC_COMP_ATOP = 0x6, /* 0110 - Fill where destination opaque only */ + GUAC_COMP_XOR = 0xA, /* 1010 - XOR */ + GUAC_COMP_ROVER = 0xB, /* 1011 - Fill where destination transparent only */ + GUAC_COMP_OVER = 0xE, /* 1110 - Draw normally */ + GUAC_COMP_PLUS = 0xF, /* 1111 - Add */ + + /* Unimplemented in client: */ + /* NOT IMPL'D: 0000 - Clear */ + /* NOT IMPL'D: 0101 - Additive IN */ + /* NOT IMPL'D: 0111 - Additive ATOP */ + /* NOT IMPL'D: 1101 - Additive RATOP */ + + /* Buggy in webkit browsers, as they keep channel C on in all cases: */ GUAC_COMP_RIN = 0x1, /* 0001 */ - GUAC_COMP_ROUT = 0x2, /* 0010 */ - GUAC_COMP_DEST = 0x3, /* 0011 */ GUAC_COMP_IN = 0x4, /* 0100 */ - /* NOT IMPL'D: 0101 */ - GUAC_COMP_ATOP = 0x6, /* 0110 */ - /* NOT IMPL'D: 0111 */ GUAC_COMP_OUT = 0x8, /* 1000 */ GUAC_COMP_RATOP = 0x9, /* 1001 */ - GUAC_COMP_XOR = 0xA, /* 1010 */ - GUAC_COMP_ROVER = 0xB, /* 1011 */ - GUAC_COMP_SRC = 0xC, /* 1100 */ - /* NOT IMPL'D: 1101 */ - GUAC_COMP_OVER = 0xE, /* 1110 */ - GUAC_COMP_PLUS = 0xF /* 1111 */ + GUAC_COMP_SRC = 0xC /* 1100 */ } guac_composite_mode_t; From 621f369130dc010b26dc49128b08f08d3f56b9c1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 30 Aug 2011 10:22:39 -0700 Subject: [PATCH 077/330] More improvements to channel mask documentation. --- libguac/include/protocol.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 5f8fa1d0..679ec59b 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -82,7 +82,6 @@ typedef enum guac_composite_mode_t { */ /* ABCD */ GUAC_COMP_ROUT = 0x2, /* 0010 - Clears destination where source opaque */ - GUAC_COMP_DEST = 0x3, /* 0011 - No operation */ GUAC_COMP_ATOP = 0x6, /* 0110 - Fill where destination opaque only */ GUAC_COMP_XOR = 0xA, /* 1010 - XOR */ GUAC_COMP_ROVER = 0xB, /* 1011 - Fill where destination transparent only */ @@ -90,10 +89,11 @@ typedef enum guac_composite_mode_t { GUAC_COMP_PLUS = 0xF, /* 1111 - Add */ /* Unimplemented in client: */ - /* NOT IMPL'D: 0000 - Clear */ - /* NOT IMPL'D: 0101 - Additive IN */ - /* NOT IMPL'D: 0111 - Additive ATOP */ - /* NOT IMPL'D: 1101 - Additive RATOP */ + /* NOT IMPLEMENTED: 0000 - Clear */ + /* NOT IMPLEMENTED: 0011 - No operation */ + /* NOT IMPLEMENTED: 0101 - Additive IN */ + /* NOT IMPLEMENTED: 0111 - Additive ATOP */ + /* NOT IMPLEMENTED: 1101 - Additive RATOP */ /* Buggy in webkit browsers, as they keep channel C on in all cases: */ GUAC_COMP_RIN = 0x1, /* 0001 */ From f5b44c97ad64e88e9066f2b7c6fd80ee94a87772 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 9 Sep 2011 23:59:07 -0700 Subject: [PATCH 078/330] Removed unescape/escape functions, switched to new instruction format. --- libguac/include/protocol.h | 35 +--- libguac/src/guacio.c | 27 +-- libguac/src/protocol.c | 368 ++++++++++++++----------------------- 3 files changed, 142 insertions(+), 288 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 679ec59b..8276da6a 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -145,8 +145,7 @@ typedef struct guac_instruction { int argc; /** - * Array of all arguments passed to this instruction. Strings - * are not already unescaped. + * Array of all arguments passed to this instruction. */ char** argv; @@ -173,27 +172,7 @@ void guac_free_instruction_data(guac_instruction* instruction); void guac_free_instruction(guac_instruction* instruction); /** - * Escapes the given string as necessary to be passed within - * a Guacamole instruction. The returned string must later be - * released with a call to free(). - * - * @param str The string to escape. - * @return A new escaped string, which must be freed with free(). - */ -char* guac_escape_string(const char* str); - -/** - * Unescapes the given string in-place, as an unescaped string - * is always the same length or shorter than the original. - * - * @param str The string to unescape. - * @return A pointer to the original string, which is now unescaped. - */ -char* guac_unescape_string_inplace(char* str); - -/** - * Sends an args instruction over the given GUACIO connection. Each - * argument name will be automatically escaped for transmission. + * Sends an args instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. * @param args The NULL-terminated array of argument names (strings). @@ -202,8 +181,7 @@ char* guac_unescape_string_inplace(char* str); int guac_send_args(GUACIO* io, const char** name); /** - * Sends a name instruction over the given GUACIO connection. The - * name given will be automatically escaped for transmission. + * Sends a name instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. * @param name The name to send within the name instruction. @@ -222,9 +200,7 @@ int guac_send_name(GUACIO* io, const char* name); int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp); /** - * Sends an error instruction over the given GUACIO connection. The - * error description given will be automatically escaped for - * transmission. + * Sends an error instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. * @param error The description associated with the error. @@ -233,8 +209,7 @@ int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp); int guac_send_error(GUACIO* io, const char* error); /** - * Sends a clipboard instruction over the given GUACIO connection. The - * clipboard data given will be automatically escaped for transmission. + * Sends a clipboard instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. * @param data The clipboard data to send. diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index f2b0fcad..47850672 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -41,6 +41,7 @@ #include #include #include +#include #ifdef __MINGW32__ #include @@ -120,30 +121,8 @@ int64_t guac_parse_int(const char* str) { ssize_t guac_write_int(GUACIO* io, int64_t i) { char buffer[128]; - char* ptr = &(buffer[127]); - int64_t nonneg; - - /* Obtain non-negative value */ - if (i < 0) nonneg = -i; - else nonneg = i; - - /* Generate numeric string */ - - *ptr = 0; - - do { - - ptr--; - *ptr = '0' + (nonneg % 10); - - nonneg /= 10; - - } while (nonneg > 0 && ptr >= buffer); - - /* Prepend with dash if negative */ - if (i < 0 && ptr >= buffer) *(--ptr) = '-'; - - return guac_write_string(io, ptr); + snprintf(buffer, sizeof(buffer), "%"PRIi64, i); + return guac_write_string(io, buffer); } diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 14d6acb1..689b3af1 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -45,6 +45,8 @@ #include #include +#include +#include #include #include @@ -61,108 +63,20 @@ #include "guacio.h" #include "protocol.h" -char* guac_escape_string(const char* str) { +ssize_t __guac_write_length_string(GUACIO* io, const char* str) { - char* escaped; - char* current; - - int i; - int length = 0; - - /* Determine length */ - for (i=0; str[i] != '\0'; i++) { - switch (str[i]) { - - case ';': - case ',': - case '\\': - length += 2; - break; - - default: - length++; - - } - } - - /* Allocate new */ - escaped = malloc(length+1); - - current = escaped; - for (i=0; str[i] != '\0'; i++) { - switch (str[i]) { - - case ';': - *(current++) = '\\'; - *(current++) = 's'; - break; - - case ',': - *(current++) = '\\'; - *(current++) = 'c'; - break; - - case '\\': - *(current++) = '\\'; - *(current++) = '\\'; - break; - - default: - *(current++) = str[i]; - } - - } - - *current = '\0'; - - return escaped; + return + guac_write_int(io, strlen(str)) + || guac_write_string(io, ".") + || guac_write_string(io, str); } -char* guac_unescape_string_inplace(char* str) { +ssize_t __guac_write_length_int(GUACIO* io, int64_t i) { - char* from; - char* to; - - from = to = str; - for (;;) { - - char c = *(from++); - - if (c == '\\') { - - c = *(from++); - if (c == 's') - *(to++) = ';'; - - else if (c == 'c') - *(to++) = ','; - - else if (c == '\\') - *(to++) = '\\'; - - else if (c == '\0') { - *(to++) = '\\'; - break; - } - - else { - *(to++) = '\\'; - *(to++) = c; - } - } - - else if (c == '\0') - break; - - else - *(to++) = c; - - } - - *to = '\0'; - - return str; + char buffer[128]; + snprintf(buffer, sizeof(buffer), "%"PRIi64, i); + return __guac_write_length_string(io, buffer); } @@ -170,27 +84,15 @@ int guac_send_args(GUACIO* io, const char** args) { int i; - /* Handle protocols with no args */ - if (args[0] == NULL) - return guac_write_string(io, "args;"); - - if (guac_write_string(io, "args:")) return -1; + if (guac_write_string(io, "4.args")) return -1; for (i=0; args[i] != NULL; i++) { - char* escaped; - - if (i > 0) { - if (guac_write_string(io, ",")) - return -1; - } - - escaped = guac_escape_string(args[i]); - if (guac_write_string(io, escaped)) { - free(escaped); + if (guac_write_string(io, ",")) + return -1; + + if (__guac_write_length_string(io, args[i])) return -1; - } - free(escaped); } @@ -200,74 +102,46 @@ int guac_send_args(GUACIO* io, const char** args) { int guac_send_name(GUACIO* io, const char* name) { - char* escaped = guac_escape_string(name); - - if ( - guac_write_string(io, "name:") - || guac_write_string(io, escaped) - || guac_write_string(io, ";") - ) { - free(escaped); - return -1; - } - - free(escaped); - return 0; + return + guac_write_string(io, "4.name,") + || __guac_write_length_string(io, name) + || guac_write_string(io, ";"); } int guac_send_size(GUACIO* io, int w, int h) { return - guac_write_string(io, "size:") - || guac_write_int(io, w) + guac_write_string(io, "4.size,") + || __guac_write_length_int(io, w) || guac_write_string(io, ",") - || guac_write_int(io, h) + || __guac_write_length_int(io, h) || guac_write_string(io, ";"); } int guac_send_clipboard(GUACIO* io, const char* data) { - char* escaped = guac_escape_string(data); - - if ( - guac_write_string(io, "clipboard:") - || guac_write_string(io, escaped) - || guac_write_string(io, ";") - ) { - free(escaped); - return -1; - } - - free(escaped); - return 0; + return + guac_write_string(io, "9.clipboard,") + || __guac_write_length_string(io, data) + || guac_write_string(io, ";"); } int guac_send_error(GUACIO* io, const char* error) { - char* escaped = guac_escape_string(error); - - if ( - guac_write_string(io, "error:") - || guac_write_string(io, escaped) - || guac_write_string(io, ";") - ) { - free(escaped); - return -1; - } - - free(escaped); - return 0; - + return + guac_write_string(io, "5.error,") + || __guac_write_length_string(io, error) + || guac_write_string(io, ";"); } int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp) { return - guac_write_string(io, "sync:") - || guac_write_int(io, timestamp) + guac_write_string(io, "4.sync,") + || __guac_write_length_int(io, timestamp) || guac_write_string(io, ";"); } @@ -277,24 +151,24 @@ int guac_send_copy(GUACIO* io, guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty) { return - guac_write_string(io, "copy:") - || guac_write_int(io, srcl->index) + guac_write_string(io, "4.copy,") + || __guac_write_length_int(io, srcl->index) || guac_write_string(io, ",") - || guac_write_int(io, srcx) + || __guac_write_length_int(io, srcx) || guac_write_string(io, ",") - || guac_write_int(io, srcy) + || __guac_write_length_int(io, srcy) || guac_write_string(io, ",") - || guac_write_int(io, w) + || __guac_write_length_int(io, w) || guac_write_string(io, ",") - || guac_write_int(io, h) + || __guac_write_length_int(io, h) || guac_write_string(io, ",") - || guac_write_int(io, mode) + || __guac_write_length_int(io, mode) || guac_write_string(io, ",") - || guac_write_int(io, dstl->index) + || __guac_write_length_int(io, dstl->index) || guac_write_string(io, ",") - || guac_write_int(io, dstx) + || __guac_write_length_int(io, dstx) || guac_write_string(io, ",") - || guac_write_int(io, dsty) + || __guac_write_length_int(io, dsty) || guac_write_string(io, ";"); } @@ -305,26 +179,26 @@ int guac_send_rect(GUACIO* io, int r, int g, int b, int a) { return - guac_write_string(io, "rect:") - || guac_write_int(io, mode) + guac_write_string(io, "4,rect,") + || __guac_write_length_int(io, mode) || guac_write_string(io, ",") - || guac_write_int(io, layer->index) + || __guac_write_length_int(io, layer->index) || guac_write_string(io, ",") - || guac_write_int(io, x) + || __guac_write_length_int(io, x) || guac_write_string(io, ",") - || guac_write_int(io, y) + || __guac_write_length_int(io, y) || guac_write_string(io, ",") - || guac_write_int(io, width) + || __guac_write_length_int(io, width) || guac_write_string(io, ",") - || guac_write_int(io, height) + || __guac_write_length_int(io, height) || guac_write_string(io, ",") - || guac_write_int(io, r) + || __guac_write_length_int(io, r) || guac_write_string(io, ",") - || guac_write_int(io, g) + || __guac_write_length_int(io, g) || guac_write_string(io, ",") - || guac_write_int(io, b) + || __guac_write_length_int(io, b) || guac_write_string(io, ",") - || guac_write_int(io, a) + || __guac_write_length_int(io, a) || guac_write_string(io, ";"); } @@ -333,94 +207,120 @@ int guac_send_clip(GUACIO* io, const guac_layer* layer, int x, int y, int width, int height) { return - guac_write_string(io, "clip:") - || guac_write_int(io, layer->index) + guac_write_string(io, "4.clip,") + || __guac_write_length_int(io, layer->index) || guac_write_string(io, ",") - || guac_write_int(io, x) + || __guac_write_length_int(io, x) || guac_write_string(io, ",") - || guac_write_int(io, y) + || __guac_write_length_int(io, y) || guac_write_string(io, ",") - || guac_write_int(io, width) + || __guac_write_length_int(io, width) || guac_write_string(io, ",") - || guac_write_int(io, height) + || __guac_write_length_int(io, height) || guac_write_string(io, ";"); } +typedef struct __guac_write_png_data { + + GUACIO* io; + + char* buffer; + int buffer_size; + int data_size; + +} __guac_write_png_data; + cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsigned int length) { - GUACIO* io = (GUACIO*) closure; + __guac_write_png_data* png_data = (__guac_write_png_data*) closure; - if (guac_write_base64(io, data, length) < 0) - return CAIRO_STATUS_WRITE_ERROR; + /* Calculate next buffer size */ + int next_size = png_data->data_size + length; + + /* If need resizing, double buffer size until big enough */ + if (next_size > png_data->buffer_size) { + + char* new_buffer; + + do { + png_data->buffer_size <<= 1; + } while (next_size > png_data->buffer_size); + + /* Resize buffer */ + new_buffer = realloc(png_data->buffer, png_data->buffer_size); + png_data->buffer = new_buffer; + + } + + /* Append data to buffer */ + memcpy(png_data->buffer + png_data->data_size, data, length); return CAIRO_STATUS_SUCCESS; } -int guac_send_png(GUACIO* io, guac_composite_mode_t mode, - const guac_layer* layer, int x, int y, cairo_surface_t* surface) { +int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) { - /* Write instruction and args */ - - if ( - guac_write_string(io, "png:") - || guac_write_int(io, mode) - || guac_write_string(io, ",") - || guac_write_int(io, layer->index) - || guac_write_string(io, ",") - || guac_write_int(io, x) - || guac_write_string(io, ",") - || guac_write_int(io, y) - || guac_write_string(io, ",") - ) { - return -1; - } + __guac_write_png_data png_data; + int base64_length; /* Write surface */ - if (cairo_surface_write_to_png_stream(surface, __guac_write_png, io) != CAIRO_STATUS_SUCCESS) { + png_data.io = io; + png_data.buffer_size = 8192; + png_data.buffer = malloc(png_data.buffer_size); + png_data.data_size = 0; + + if (cairo_surface_write_to_png_stream(surface, __guac_write_png, &png_data) != CAIRO_STATUS_SUCCESS) { return -1; } - if (guac_flush_base64(io) < 0) { + base64_length = (png_data.data_size + 2) / 3 * 4; + + /* Write instruction and args */ + if ( + guac_write_int(io, base64_length) + || guac_write_string(io, ".") + || guac_write_base64(io, png_data.buffer, png_data.data_size) + || guac_flush_base64(io)) return -1; - } - /* Finish instruction */ + free(png_data.buffer); + return 0; - return guac_write_string(io, ";"); +} + + +int guac_send_png(GUACIO* io, guac_composite_mode_t mode, + const guac_layer* layer, int x, int y, cairo_surface_t* surface) { + + return + guac_write_string(io, "3.png,") + || __guac_write_length_int(io, mode) + || guac_write_string(io, ",") + || __guac_write_length_int(io, layer->index) + || guac_write_string(io, ",") + || __guac_write_length_int(io, x) + || guac_write_string(io, ",") + || __guac_write_length_int(io, y) + || guac_write_string(io, ",") + || __guac_write_length_png(io, surface) + || guac_write_string(io, ";"); } int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface) { - /* Write instruction and args */ - - if ( - guac_write_string(io, "cursor:") - || guac_write_int(io, x) + return + guac_write_string(io, "6.cursor,") + || __guac_write_length_int(io, x) || guac_write_string(io, ",") - || guac_write_int(io, y) + || __guac_write_length_int(io, y) || guac_write_string(io, ",") - ) { - return -1; - } - - /* Write surface */ - - if (cairo_surface_write_to_png_stream(surface, __guac_write_png, io) != CAIRO_STATUS_SUCCESS) { - return -1; - } - - if (guac_flush_base64(io) < 0) { - return -1; - } - - /* Finish instruction */ - - return guac_write_string(io, ";"); + || __guac_write_length_png(io, surface) + || guac_write_string(io, ";"); } From e19c636bdb1f2f7d87f735003acd42e5911779b5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 10 Sep 2011 00:36:51 -0700 Subject: [PATCH 079/330] Fix guac_write_base64 to match documented return values. --- libguac/src/guacio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index 47850672..01e19ec7 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -242,7 +242,7 @@ ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count) { } - return count; + return 0; } From 12649bd657cef4616a075d08ebc760cafad4f3d5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 10 Sep 2011 00:37:16 -0700 Subject: [PATCH 080/330] Removed use of escape/unescape pending parsing of new instruction format. --- libguac/src/client-handlers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index 16bfb4d8..1221eec4 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -90,7 +90,7 @@ int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction) if (client->clipboard_handler) return client->clipboard_handler( client, - guac_unescape_string_inplace(instruction->argv[0]) /* data */ + instruction->argv[0] /* data */ ); return 0; } From 7c91f7d66c606f1dba707598ed22f4b22b7cfbb0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 10 Sep 2011 00:40:22 -0700 Subject: [PATCH 081/330] Working png/cursor instructions. --- libguac/src/protocol.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 689b3af1..47b38e76 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -255,6 +255,7 @@ cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsign /* Append data to buffer */ memcpy(png_data->buffer + png_data->data_size, data, length); + png_data->data_size += length; return CAIRO_STATUS_SUCCESS; @@ -278,13 +279,15 @@ int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) { base64_length = (png_data.data_size + 2) / 3 * 4; - /* Write instruction and args */ + /* Write length and data */ if ( guac_write_int(io, base64_length) || guac_write_string(io, ".") || guac_write_base64(io, png_data.buffer, png_data.data_size) - || guac_flush_base64(io)) + || guac_flush_base64(io)) { + free(png_data.buffer); return -1; + } free(png_data.buffer); return 0; From 197029c3d81ec16a465818017a31b816af140c8b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 11 Sep 2011 15:56:34 -0700 Subject: [PATCH 082/330] Fixed rect instruction. --- libguac/src/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 47b38e76..d0fa0c06 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -179,7 +179,7 @@ int guac_send_rect(GUACIO* io, int r, int g, int b, int a) { return - guac_write_string(io, "4,rect,") + guac_write_string(io, "4.rect,") || __guac_write_length_int(io, mode) || guac_write_string(io, ",") || __guac_write_length_int(io, layer->index) From 076b749225d244a8159eb5e20181180d9db034df Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 19 Oct 2011 01:28:18 -0700 Subject: [PATCH 083/330] Implemented support for new instruction format (inbound), simplified instruction parsing. --- libguac/include/guacio.h | 16 ++++++ libguac/src/guacio.c | 2 + libguac/src/protocol.c | 103 +++++++++++++++++++++++---------------- 3 files changed, 80 insertions(+), 41 deletions(-) diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index 67b5cd01..f0ee209d 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -86,6 +86,11 @@ typedef struct GUACIO { */ char out_buf[8192]; + /** + * The current location of parsing within the instruction buffer. + */ + int instructionbuf_parse_start; + /** * The current size of the instruction buffer. */ @@ -103,6 +108,17 @@ typedef struct GUACIO { */ char* instructionbuf; + /** + * The number of elements parsed so far. + */ + int instructionbuf_elementc; + + /** + * Array of pointers into the instruction buffer, where each pointer + * points to the start of the corresponding element. + */ + char* instructionbuf_elementv[64]; + } GUACIO; /** diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index 01e19ec7..4d2979da 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -73,6 +73,8 @@ GUACIO* guac_open(int fd) { io->instructionbuf_size = 1024; io->instructionbuf = malloc(io->instructionbuf_size); io->instructionbuf_used_length = 0; + io->instructionbuf_parse_start = 0; + io->instructionbuf_elementc = 0; return io; diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index d0fa0c06..9dfe74f7 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -359,62 +359,83 @@ int __guac_fill_instructionbuf(GUACIO* io) { int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction) { int retval; - int i = 0; - int argcount = 0; - int j; - int current_arg = 0; + int i = io->instructionbuf_parse_start; /* Loop until a instruction is read */ for (;;) { - /* Search for end of instruction */ - for (; i < io->instructionbuf_used_length; i++) { + /* Length of element */ + int element_length = 0; - /* Count arguments as we look for the end */ - if (io->instructionbuf[i] == ',') - argcount++; - else if (io->instructionbuf[i] == ':' && argcount == 0) - argcount++; + /* Parse instruction in buffe */ + while (i < io->instructionbuf_used_length) { - /* End found ... */ - else if (io->instructionbuf[i] == ';') { + /* Read character from buffer */ + char c = io->instructionbuf[i++]; - /* Parse new instruction */ - char* instruction = malloc(i+1); - memcpy(instruction, io->instructionbuf, i+1); - instruction[i] = '\0'; /* Replace semicolon with null terminator. */ + /* If digit, calculate element length */ + if (c >= '0' && c <= '9') + element_length = element_length * 10 + c - '0'; - parsed_instruction->opcode = NULL; + /* Otherwise, if end of length */ + else if (c == '.') { - parsed_instruction->argc = argcount; - parsed_instruction->argv = malloc(sizeof(char*) * argcount); + /* Verify element is fully read */ + if (i + element_length < io->instructionbuf_used_length) { - for (j=0; jinstructionbuf[i]); + + /* Get terminator, set null terminator of elementv */ + char terminator = elementv[element_length]; + elementv[element_length] = '\0'; - /* If encountered a colon, and no opcode parsed yet, set opcode and following argument */ - if (instruction[j] == ':' && parsed_instruction->opcode == NULL) { - instruction[j] = '\0'; - parsed_instruction->argv[current_arg++] = &(instruction[j+1]); - parsed_instruction->opcode = instruction; - } + /* Move to terminator of element */ + i += element_length; - /* If encountered a comma, set following argument */ - else if (instruction[j] == ',') { - instruction[j] = '\0'; - parsed_instruction->argv[current_arg++] = &(instruction[j+1]); - } - } + /* Reset element length */ + element_length = 0; - /* If no arguments, set opcode to entire instruction */ - if (parsed_instruction->opcode == NULL) - parsed_instruction->opcode = instruction; + /* As element has been read successfully, update + * parse start */ + io->instructionbuf_parse_start = i; - /* Found. Reset buffer */ - memmove(io->instructionbuf, io->instructionbuf + i + 1, io->instructionbuf_used_length - i - 1); - io->instructionbuf_used_length -= i + 1; + /* Save element */ + io->instructionbuf_elementv[io->instructionbuf_elementc++] = elementv; + + /* Finish parse if terminator is a semicolon */ + if (terminator == ';') { + + int j; + + /* Init parsed instruction */ + parsed_instruction->argc = io->instructionbuf_elementc - 1; + parsed_instruction->argv = malloc(sizeof(char*) * parsed_instruction->argc); + + /* Set opcode */ + parsed_instruction->opcode = strdup(io->instructionbuf_elementv[0]); + + /* Copy element values to parsed instruction */ + for (j=0; jargc; j++) + parsed_instruction->argv[j] = strdup(io->instructionbuf_elementv[j+1]); + + /* Reset buffer */ + memmove(io->instructionbuf, io->instructionbuf + i + 1, io->instructionbuf_used_length - i - 1); + io->instructionbuf_used_length -= i + 1; + io->instructionbuf_parse_start = 0; + io->instructionbuf_elementc = 0; + + /* Done */ + return 1; + + } /* end if terminator */ + + } /* end if element fully read */ + + /* Otherwise, read more data */ + else + break; - /* Done */ - return 1; } } From 665f907a18263509aaf77cd6457f03f221f97428 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Oct 2011 14:43:26 -0700 Subject: [PATCH 084/330] Fixed comments, added prototypes for guac_layer_* instruction queueing functions and guac_layer_flush(). --- libguac/include/protocol.h | 87 +++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 8276da6a..b680fa5e 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -271,13 +271,14 @@ int guac_send_rect(GUACIO* io, /** * Sends a clip instruction over the given GUACIO connection. -* + * * @param io The GUACIO connection to use. * @param layer The layer to set the clipping region of. * @param x The X coordinate of the clipping rectangle. * @param y The Y coordinate of the clipping rectangle. * @param width The width of the clipping rectangle. * @param height The height of the clipping rectangle. + * @return Zero on success, non-zero on error. */ int guac_send_clip(GUACIO* io, const guac_layer* layer, int x, int y, int width, int height); @@ -309,6 +310,90 @@ int guac_send_png(GUACIO* io, guac_composite_mode_t mode, */ int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface); +/** + * Queues a png instruction in the given layer. The layer may combine + * and re-order multiple instructions into more efficient instructions + * providing the end result is the same image. + * + * @param layer The destination layer. + * @param mode The composite mode to use. + * @param x The destination X coordinate. + * @param y The destination Y coordinate. + * @param surface A cairo surface containing the image data to send. + */ +void guac_layer_png(guac_layer* layer, guac_composite_mode_t mode, + int x, int y, cairo_surface_t* surface); + +/** + * Queues a copy instruction in a given layer. The layer may combine + * and re-order multiple instructions into more efficient instructions + * providing the end result is the same image. + * + * @param layer The destination layer. + * @param mode The composite mode to use. + * @param srcl The source layer. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. + * @param dstx The X coordinate of the destination, where the source rectangle + * should be copied. + * @param dsty The Y coordinate of the destination, where the source rectangle + * should be copied. + */ +void guac_layer_copy(guac_layer* layer, guac_composite_mode_t mode, + const guac_layer* srcl, int srcx, int srcy, int w, int h, + int dstx, int dsty); + +/** + * Queues a clip instruction in a given layer. The layer may combine + * and re-order multiple instructions into more efficient instructions + * providing the end result is the same image. + * + * @param layer The layer to set the clipping region of. + * @param x The X coordinate of the clipping rectangle. + * @param y The Y coordinate of the clipping rectangle. + * @param width The width of the clipping rectangle. + * @param height The height of the clipping rectangle. + */ +void guac_layer_clip(guac_layer* layer, + int x, int y, int width, int height); + +/** + * Queues a rect instruction in a given layer. The layer may combine + * and re-order multiple instructions into more efficient instructions + * providing the end result is the same image. + * + * @param layer The destination layer. + * @param mode The composite mode to use. + * @param x The X coordinate of the rectangle. + * @param y The Y coordinate of the rectangle. + * @param width The width of the rectangle. + * @param height The height of the rectangle. + * @param r The red component of the color of the rectangle. + * @param g The green component of the color of the rectangle. + * @param b The blue component of the color of the rectangle. + * @param a The alpha (transparency) component of the color of the rectangle. + */ +void guac_layer_rect(guac_layer* layer, guac_composite_mode_t mode, + int x, int y, int width, int height, + int r, int g, int b, int a); + +/** + * Flushes any queued instructions in the given layer, sending those + * instructions over the given GUACIO connection. These instructions + * may not be identical to the instructions originally queued; they + * may be re-ordered or combined providing the end result of executing + * all instructions sent by guac_flush() is identical to executing all + * previously queued instructions as specified and in order. + * + * @param layer The layer to flush. + * @param io The GUACIO connection to use. + * @return Zero on success, non-zero on error. + */ +int guac_layer_flush(guac_layer* layer, GUACIO* io); + + /** * Returns whether new instruction data is available on the given GUACIO * connection for parsing. From 70e150e2e92a3658eb70aecb524e42d66255f7f6 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Oct 2011 14:48:26 -0700 Subject: [PATCH 085/330] Bumped libtool version-info (API changes) --- libguac/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index e6397d5b..194075c2 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -46,5 +46,5 @@ lib_LTLIBRARIES = libguac.la libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c src/log.c src/thread.c -libguac_la_LDFLAGS = -version-info 1:0:0 +libguac_la_LDFLAGS = -version-info 2:0:0 From 7da95aa6cf6bb1051371d24dcbf930cfb36773a7 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Oct 2011 15:35:23 -0700 Subject: [PATCH 086/330] Removed guac_client_free_layer (doesn't make sense), added free() for update queue, added update queue structures. --- libguac/include/client.h | 15 ------ libguac/include/protocol.h | 98 ++++++++++++++++++++++++++++++++++++++ libguac/src/client.c | 62 +++++++++++++++--------- libguac/src/protocol.c | 21 ++++++++ 4 files changed, 158 insertions(+), 38 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 9703733c..ae7e2362 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -147,12 +147,6 @@ struct guac_client { */ guac_client_state state; - /** - * The head pointer of the list of all available (allocated but not used) - * layers. - */ - guac_layer* available_layers; - /** * The index of the next available buffer. */ @@ -379,15 +373,6 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); */ void guac_client_free_buffer(guac_client* client, guac_layer* layer); -/** - * Returns the given layer to the pool of available layers, such that it - * can be reused by any subsequent call to guac_client_allow_layer(). - * - * @param client The proxy client to return the layer to. - * @param layer The layer to return to the pool of available layers. - */ -void guac_client_free_layer(guac_client* client, guac_layer* layer); - extern const guac_layer* GUAC_DEFAULT_LAYER; #endif diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index b680fa5e..3ca809f4 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -104,8 +104,101 @@ typedef enum guac_composite_mode_t { } guac_composite_mode_t; +typedef struct guac_layer_update guac_layer_update; typedef struct guac_layer guac_layer; + +/** + * The type of a layer update (png, copy, or rect, for + * example). + */ +typedef enum guac_layer_update_type_t { + + GUAC_LAYER_UPDATE_PNG, + GUAC_LAYER_UPDATE_COPY, + GUAC_LAYER_UPDATE_CLIP, + GUAC_LAYER_UPDATE_RECT + +} guac_layer_update_type_t; + +/** + * Represents an abstract graphical update or state change + * of a layer, including dirty rectangle information. + */ +struct guac_layer_update { + + /** + * The type of this update. Update type corresponds + * directly to the instruction that would be sent + * if the queue is flushed. + */ + guac_layer_update_type_t type; + + /** + * The composite mode to use in this update. + */ + guac_composite_mode_t mode; + + /** + * The layer to retrieve image data from. + */ + guac_layer* src_layer; + + /** + * The surface to retrieve image data from. + */ + cairo_surface_t* src_image; + + /** + * The X coordinage of the upper-left corner of the + * source rectangle. + */ + int src_x; + + /** + * The Y coordinage of the upper-left corner of the + * source rectangle. + */ + int src_y; + + /** + * The layer this update should affect. + */ + guac_layer* dst_layer; + + /** + * The X coordinate of the upper-left corner of the + * destination rectangle. + */ + int dst_x; + + /** + * The Y coordinate of the upper-left corner of the + * destination rectangle. + */ + int dst_y; + + /** + * The width of the destination or source rectangle. + * The dimensions of the destination and source + * rectangles are always identical. + */ + int width; + + /** + * The height of the destination or source rectangle. + * The dimensions of the destination and source + * rectangles are always identical. + */ + int height; + + /** + * The next update in the update queue, if any. + */ + guac_layer_update* next; + +}; + /** * Represents a single layer within the Guacamole protocol. */ @@ -127,6 +220,11 @@ struct guac_layer { */ guac_layer* next_available; + /** + * The first element in this layer's update queue. + */ + guac_layer_update* update_queue_head; + }; /** diff --git a/libguac/src/client.c b/libguac/src/client.c index d04a267d..1208fc90 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -68,7 +68,6 @@ guac_client* __guac_alloc_client(GUACIO* io) { client->state = RUNNING; client->all_layers = NULL; - client->available_layers = NULL; client->available_buffers = NULL; client->next_buffer_index = -1; @@ -80,35 +79,19 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index) { guac_layer* allocd_layer; - /* If available layers, pop off first available layer */ - if (client->available_layers != NULL) { - allocd_layer = client->available_layers; - client->available_layers = client->available_layers->next_available; - allocd_layer->next_available = NULL; - } + /* Init new layer */ + allocd_layer = malloc(sizeof(guac_layer)); + allocd_layer->update_queue_head = NULL; - /* If no available layers, allocate new layer, add to all_layers list */ - else { - - /* Init new layer */ - allocd_layer = malloc(sizeof(guac_layer)); - - /* Add to all_layers list */ - allocd_layer->next = client->all_layers; - client->all_layers = allocd_layer; - - } + /* Add to all_layers list */ + allocd_layer->next = client->all_layers; + client->all_layers = allocd_layer; allocd_layer->index = index; return allocd_layer; } -void guac_client_free_layer(guac_client* client, guac_layer* layer) { - layer->next_available = client->available_layers; - client->available_layers = layer; -} - guac_layer* guac_client_alloc_buffer(guac_client* client) { guac_layer* allocd_layer; @@ -126,6 +109,7 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { /* Init new layer */ allocd_layer = malloc(sizeof(guac_layer)); allocd_layer->index = client->next_buffer_index--; + allocd_layer->update_queue_head = NULL; /* Add to all_layers list */ allocd_layer->next = client->all_layers; @@ -138,8 +122,23 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { } void guac_client_free_buffer(guac_client* client, guac_layer* layer) { + + /* Add layer to pool of available buffers */ layer->next_available = client->available_buffers; client->available_buffers = layer; + + /* Free all queued updates */ + while (layer->update_queue_head != NULL) { + + /* Get unflushed update, update queue head */ + guac_layer_update* unflushed_update = layer->update_queue_head; + layer->update_queue_head = unflushed_update->next; + + /* Free update */ + free(unflushed_update); + + } + } guac_client* guac_get_client(int client_fd) { @@ -336,9 +335,26 @@ void guac_free_client(guac_client* client) { /* Free all layers */ while (client->all_layers != NULL) { + + /* Get layer, update layer pool head */ guac_layer* layer = client->all_layers; client->all_layers = layer->next; + + /* Free all queued updates */ + while (layer->update_queue_head != NULL) { + + /* Get unflushed update, update queue head */ + guac_layer_update* unflushed_update = layer->update_queue_head; + layer->update_queue_head = unflushed_update->next; + + /* Free update */ + free(unflushed_update); + + } + + /* Free layer */ free(layer); + } free(client); diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 9dfe74f7..efd1fb32 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -518,3 +518,24 @@ void guac_sleep(int millis) { } +void guac_layer_png(guac_layer* layer, guac_composite_mode_t mode, + int x, int y, cairo_surface_t* surface) { + /* STUB */ +} + +void guac_layer_copy(guac_layer* layer, guac_composite_mode_t mode, + const guac_layer* srcl, int srcx, int srcy, int w, int h, + int dstx, int dsty) { + /* STUB */ +} + +void guac_layer_clip(guac_layer* layer, + int x, int y, int width, int height) { + /* STUB */ +} + +int guac_layer_flush(guac_layer* layer, GUACIO* io) { + /* STUB */ + return 0; +} + From c721a94b6eae6d3a4ef0682afc5669ab01a4fd8b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Oct 2011 15:53:22 -0700 Subject: [PATCH 087/330] Implemented guac_layer_* queue updates. --- libguac/include/protocol.h | 22 +++++++++- libguac/src/protocol.c | 83 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 101 insertions(+), 4 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 3ca809f4..770aaa06 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -142,13 +142,33 @@ struct guac_layer_update { /** * The layer to retrieve image data from. */ - guac_layer* src_layer; + const guac_layer* src_layer; /** * The surface to retrieve image data from. */ cairo_surface_t* src_image; + /** + * The red component of the source color. + */ + int src_red; + + /** + * The green component of the source color. + */ + int src_green; + + /** + * The blue component of the source color. + */ + int src_blue; + + /** + * The alpha component of the source color. + */ + int src_alpha; + /** * The X coordinage of the upper-left corner of the * source rectangle. diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index efd1fb32..a3243b6e 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -518,20 +518,97 @@ void guac_sleep(int millis) { } +void _guac_layer_add_update(guac_layer* layer, guac_layer_update* update) { + + /* Add update to queue head */ + update->next = layer->update_queue_head; + layer->update_queue_head = update; + +} + void guac_layer_png(guac_layer* layer, guac_composite_mode_t mode, int x, int y, cairo_surface_t* surface) { - /* STUB */ + + /* Allocate update */ + guac_layer_update* update = (guac_layer_update*) malloc(sizeof(guac_layer_update)); + + /* Set parameters of update */ + update->type = GUAC_LAYER_UPDATE_PNG; + update->mode = mode; + update->src_image = surface; + update->dst_layer = layer; + update->dst_x = x; + update->dst_y = y; + + /* Add to layer queue */ + _guac_layer_add_update(layer, update); + } void guac_layer_copy(guac_layer* layer, guac_composite_mode_t mode, const guac_layer* srcl, int srcx, int srcy, int w, int h, int dstx, int dsty) { - /* STUB */ + + /* Allocate update */ + guac_layer_update* update = (guac_layer_update*) malloc(sizeof(guac_layer_update)); + + /* Set parameters of update */ + update->type = GUAC_LAYER_UPDATE_COPY; + update->mode = mode; + update->src_layer = srcl; + update->src_x = srcx; + update->src_y = srcy; + update->width = w; + update->height = h; + update->dst_layer = layer; + update->dst_x = dstx; + update->dst_y = dsty; + + /* Add to layer queue */ + _guac_layer_add_update(layer, update); + } void guac_layer_clip(guac_layer* layer, int x, int y, int width, int height) { - /* STUB */ + + /* Allocate update */ + guac_layer_update* update = (guac_layer_update*) malloc(sizeof(guac_layer_update)); + + /* Set parameters of update */ + update->type = GUAC_LAYER_UPDATE_CLIP; + update->dst_x = x; + update->dst_y = y; + update->width = width; + update->height = height; + + /* Add to layer queue */ + _guac_layer_add_update(layer, update); + +} + +void guac_layer_rect(guac_layer* layer, guac_composite_mode_t mode, + int x, int y, int width, int height, + int r, int g, int b, int a) { + + /* Allocate update */ + guac_layer_update* update = (guac_layer_update*) malloc(sizeof(guac_layer_update)); + + /* Set parameters of update */ + update->type = GUAC_LAYER_UPDATE_RECT; + update->mode = mode; + update->src_red = r; + update->src_green = g; + update->src_blue = b; + update->src_alpha = a; + update->dst_x = x; + update->dst_y = y; + update->width = width; + update->height = height; + + /* Add to layer queue */ + _guac_layer_add_update(layer, update); + } int guac_layer_flush(guac_layer* layer, GUACIO* io) { From 35fedc1eb612954c7f24b7e5044d80ab2e9b047a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Oct 2011 16:12:31 -0700 Subject: [PATCH 088/330] Implemented guac_layer_flush(). --- libguac/src/protocol.c | 93 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index a3243b6e..1e2b8711 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -612,7 +612,98 @@ void guac_layer_rect(guac_layer* layer, guac_composite_mode_t mode, } int guac_layer_flush(guac_layer* layer, GUACIO* io) { - /* STUB */ + + while (layer->update_queue_head != NULL) { + + /* Get next update, update queue head. */ + guac_layer_update* update = layer->update_queue_head; + layer->update_queue_head = update->next; + + /* Send instruction appropriate for update type */ + switch (update->type) { + + /* "png" instruction */ + case GUAC_LAYER_UPDATE_PNG: + + if (guac_send_png(io, + update->mode, + update->dst_layer, + update->dst_x, + update->dst_y, + update->src_image + )) { + cairo_surface_destroy(update->src_image); + free(update); + return -1; + } + + cairo_surface_destroy(update->src_image); + break; + + /* "copy" instruction */ + case GUAC_LAYER_UPDATE_COPY: + + if (guac_send_copy(io, + update->src_layer, + update->src_x, + update->src_y, + update->width, + update->height, + update->mode, + update->dst_layer, + update->dst_x, + update->dst_y + )) { + free(update); + return -1; + } + + break; + + /* "clip" instruction */ + case GUAC_LAYER_UPDATE_CLIP: + + if (guac_send_clip(io, + update->dst_layer, + update->dst_x, + update->dst_y, + update->width, + update->height + )) { + free(update); + return -1; + } + + break; + + /* "rect" instruction */ + case GUAC_LAYER_UPDATE_RECT: + + if (guac_send_rect(io, + update->mode, + update->dst_layer, + update->dst_x, + update->dst_y, + update->width, + update->height, + update->src_red, + update->src_green, + update->src_blue, + update->src_alpha + )) { + free(update); + return -1; + } + + break; + + } /* end of switch update type */ + + /* Free update */ + free(update); + + } + return 0; } From 44a456aecea20a42a0306ff463d84343ac419575 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Oct 2011 23:11:29 -0700 Subject: [PATCH 089/330] Implemented naiive update condensing for PNGs in the simplest case. Added queue tail. Now adding to tail of queue. --- libguac/include/client.h | 7 +- libguac/include/protocol.h | 5 + libguac/src/client.c | 17 +- libguac/src/protocol.c | 176 ++- libguac/test | 2408 ++++++++++++++++++++++++++++++++++++ 5 files changed, 2584 insertions(+), 29 deletions(-) create mode 100644 libguac/test diff --git a/libguac/include/client.h b/libguac/include/client.h index ae7e2362..4ab1c0e5 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -164,6 +164,11 @@ struct guac_client { */ guac_layer* all_layers; + /** + * Pointer to a pre-allocated default layer (layer 0) + */ + guac_layer* default_layer; + /** * The time (in milliseconds) of receipt of the last sync message from * the client. @@ -373,6 +378,4 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); */ void guac_client_free_buffer(guac_client* client, guac_layer* layer); -extern const guac_layer* GUAC_DEFAULT_LAYER; - #endif diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 770aaa06..128a9b2f 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -245,6 +245,11 @@ struct guac_layer { */ guac_layer_update* update_queue_head; + /** + * The last element in this layer's update queue. + */ + guac_layer_update* update_queue_tail; + }; /** diff --git a/libguac/src/client.c b/libguac/src/client.c index 1208fc90..f914e3d7 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -47,15 +47,6 @@ #include "client.h" #include "client-handlers.h" -guac_layer __GUAC_DEFAULT_LAYER = { - .index = 0, - .next = NULL, - .next_available = NULL -}; - -const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; - - guac_client* __guac_alloc_client(GUACIO* io) { /* Allocate new client (not handoff) */ @@ -72,6 +63,9 @@ guac_client* __guac_alloc_client(GUACIO* io) { client->next_buffer_index = -1; + /* Allocate default layer */ + client->default_layer = guac_client_alloc_layer(client, 0); + return client; } @@ -82,6 +76,7 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index) { /* Init new layer */ allocd_layer = malloc(sizeof(guac_layer)); allocd_layer->update_queue_head = NULL; + allocd_layer->update_queue_tail = NULL; /* Add to all_layers list */ allocd_layer->next = client->all_layers; @@ -110,6 +105,7 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { allocd_layer = malloc(sizeof(guac_layer)); allocd_layer->index = client->next_buffer_index--; allocd_layer->update_queue_head = NULL; + allocd_layer->update_queue_tail = NULL; /* Add to all_layers list */ allocd_layer->next = client->all_layers; @@ -139,6 +135,9 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) { } + /* Queue is now empty */ + layer->update_queue_tail = NULL; + } guac_client* guac_get_client(int client_fd) { diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 1e2b8711..739162d8 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -63,6 +63,9 @@ #include "guacio.h" #include "protocol.h" +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + ssize_t __guac_write_length_string(GUACIO* io, const char* str) { return @@ -518,11 +521,17 @@ void guac_sleep(int millis) { } -void _guac_layer_add_update(guac_layer* layer, guac_layer_update* update) { +void __guac_layer_add_update(guac_layer* layer, guac_layer_update* update) { - /* Add update to queue head */ - update->next = layer->update_queue_head; - layer->update_queue_head = update; + /* Add update to queue tail */ + if (layer->update_queue_tail != NULL) + layer->update_queue_tail = layer->update_queue_tail->next = update; + + /* Set both head and tail if necessary */ + else + layer->update_queue_tail = layer->update_queue_head = update; + + update->next = NULL; } @@ -539,9 +548,11 @@ void guac_layer_png(guac_layer* layer, guac_composite_mode_t mode, update->dst_layer = layer; update->dst_x = x; update->dst_y = y; + update->width = cairo_image_surface_get_width(surface); + update->height = cairo_image_surface_get_height(surface); /* Add to layer queue */ - _guac_layer_add_update(layer, update); + __guac_layer_add_update(layer, update); } @@ -565,7 +576,7 @@ void guac_layer_copy(guac_layer* layer, guac_composite_mode_t mode, update->dst_y = dsty; /* Add to layer queue */ - _guac_layer_add_update(layer, update); + __guac_layer_add_update(layer, update); } @@ -583,7 +594,7 @@ void guac_layer_clip(guac_layer* layer, update->height = height; /* Add to layer queue */ - _guac_layer_add_update(layer, update); + __guac_layer_add_update(layer, update); } @@ -607,7 +618,32 @@ void guac_layer_rect(guac_layer* layer, guac_composite_mode_t mode, update->height = height; /* Add to layer queue */ - _guac_layer_add_update(layer, update); + __guac_layer_add_update(layer, update); + +} + +int __guac_layer_update_intersects( + const guac_layer_update* update1, const guac_layer_update* update2) { + + /* If update1 X is within width of update2 + or update2 X is within width of update1 */ + if ((update1->dst_x >= update2->dst_x && update1->dst_x < update2->dst_x + update2->width) + || (update2->dst_x >= update1->dst_x && update2->dst_x < update1->dst_x + update2->width)) { + + /* If update1 Y is within height of update2 + or update2 Y is within height of update1 */ + if ((update1->dst_y >= update2->dst_y && update1->dst_y < update2->dst_y + update2->height) + || (update2->dst_y >= update1->dst_y && update2->dst_y < update1->dst_y + update2->height)) { + + /* Register instersection */ + return 1; + + } + + } + + /* Otherwise, no intersection */ + return 0; } @@ -615,6 +651,9 @@ int guac_layer_flush(guac_layer* layer, GUACIO* io) { while (layer->update_queue_head != NULL) { + guac_layer_update* later_update; + int update_merged = 0; + /* Get next update, update queue head. */ guac_layer_update* update = layer->update_queue_head; layer->update_queue_head = update->next; @@ -625,16 +664,114 @@ int guac_layer_flush(guac_layer* layer, GUACIO* io) { /* "png" instruction */ case GUAC_LAYER_UPDATE_PNG: - if (guac_send_png(io, - update->mode, - update->dst_layer, - update->dst_x, - update->dst_y, - update->src_image - )) { - cairo_surface_destroy(update->src_image); - free(update); - return -1; + /* Decide whether or not to send */ + later_update = update->next; + while (later_update != NULL) { + + /* If destination rectangles intersect */ + if (__guac_layer_update_intersects(update, later_update)) { + + cairo_surface_t* merged_surface; + cairo_t* cairo; + int merged_x, merged_y, merged_width, merged_height; + + /* Cannot combine anything if intersection with non-PNG */ + if (later_update->type != GUAC_LAYER_UPDATE_PNG) + break; + + /* Cannot combine if modes differ */ + if (later_update->mode != update->mode) + break; + + /* For now, only combine for GUAC_COMP_OVER */ + if (later_update->mode != GUAC_COMP_OVER) + break; + + /* Calculate merged dimensions */ + merged_x = MIN(update->dst_x, later_update->dst_x); + merged_y = MIN(update->dst_y, later_update->dst_y); + + merged_width = MAX( + update->dst_x + update->width, + later_update->dst_x + later_update->width + ) - merged_x; + + merged_height = MAX( + update->dst_y + update->height, + later_update->dst_y + later_update->height + ) - merged_y; + + /* Create surface for merging */ + merged_surface = cairo_image_surface_create( + CAIRO_FORMAT_ARGB32, merged_width, merged_height); + + /* Get drawing context */ + cairo = cairo_create(merged_surface); + + /* Draw first update within merged surface */ + cairo_set_source_surface(cairo, + update->src_image, + update->dst_x - merged_x, + update->dst_y - merged_y); + + cairo_rectangle(cairo, + update->dst_x - merged_x, + update->dst_y - merged_y, + update->width, + update->height); + + cairo_fill(cairo); + + /* Draw second update within merged surface */ + cairo_set_source_surface(cairo, + later_update->src_image, + later_update->dst_x - merged_x, + later_update->dst_y - merged_y); + + cairo_rectangle(cairo, + later_update->dst_x - merged_x, + later_update->dst_y - merged_y, + later_update->width, + later_update->height); + + cairo_fill(cairo); + + /* Done drawing */ + cairo_destroy(cairo); + + /* Alter update dimensions */ + later_update->dst_x = merged_x; + later_update->dst_y = merged_y; + later_update->width = merged_width; + later_update->height = merged_height; + + /* Alter update to include merged data*/ + cairo_surface_destroy(later_update->src_image); + later_update->src_image = merged_surface; + + update_merged = 1; + break; + + } + + /* Get next update */ + later_update = later_update->next; + + } + + /* Send instruction if update was not merged */ + if (!update_merged) { + if (guac_send_png(io, + update->mode, + update->dst_layer, + update->dst_x, + update->dst_y, + update->src_image + )) { + cairo_surface_destroy(update->src_image); + free(update); + return -1; + } } cairo_surface_destroy(update->src_image); @@ -704,6 +841,9 @@ int guac_layer_flush(guac_layer* layer, GUACIO* io) { } + /* Queue is now empty */ + layer->update_queue_tail = NULL; + return 0; } diff --git a/libguac/test b/libguac/test new file mode 100644 index 00000000..5505cd39 --- /dev/null +++ b/libguac/test @@ -0,0 +1,2408 @@ +==4221== Memcheck, a memory error detector +==4221== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. +==4221== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info +==4221== Command: /home/zhz/guacamole/roots/unstable/sbin/guacd -l 4823 +==4221== Parent PID: 1533 +==4221== +==4221== +==4221== HEAP SUMMARY: +==4221== in use at exit: 0 bytes in 0 blocks +==4221== total heap usage: 0 allocs, 0 frees, 0 bytes allocated +==4221== +==4221== All heap blocks were freed -- no leaks are possible +==4221== +==4221== For counts of detected and suppressed errors, rerun with: -v +==4221== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) +==4226== Syscall param write(buf) points to uninitialised byte(s) +==4226== at 0x4E37040: __write_nocancel (syscall-template.S:82) +==4226== by 0x7FB4646: WriteToRFBServer (sockets.c:216) +==4226== by 0x7FAA9BB: SetFormatAndEncodings (rfbproto.c:677) +==4226== by 0x7FB4CCF: rfbInitClient (vncviewer.c:201) +==4226== by 0x7DA0209: guac_client_init (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x5047E71: guac_get_client (client.c:293) +==4226== by 0x400EC3: start_client_thread (in /home/zhz/guacamole/roots/unstable/sbin/guacd) +==4226== by 0x4013B6: main (in /home/zhz/guacamole/roots/unstable/sbin/guacd) +==4226== Address 0x7ff000051 is on thread 1's stack +==4226== +==4226== Syscall param write(buf) points to uninitialised byte(s) +==4226== at 0x4E37040: __write_nocancel (syscall-template.S:82) +==4226== by 0x7FB4646: WriteToRFBServer (sockets.c:216) +==4226== by 0x7FAAA70: SetFormatAndEncodings (rfbproto.c:853) +==4226== by 0x7FB4CCF: rfbInitClient (vncviewer.c:201) +==4226== by 0x7DA0209: guac_client_init (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x5047E71: guac_get_client (client.c:293) +==4226== by 0x400EC3: start_client_thread (in /home/zhz/guacamole/roots/unstable/sbin/guacd) +==4226== by 0x4013B6: main (in /home/zhz/guacamole/roots/unstable/sbin/guacd) +==4226== Address 0x7fefffff1 is on thread 1's stack +==4226== +==4226== Thread 2: +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6EDF290: inflateReset2 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDF37F: inflateInit2_ (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x7FAF00F: HandleZRLE24 (zrle.c:126) +==4226== by 0x7FB3556: HandleRFBServerMessage (rfbproto.c:1468) +==4226== by 0x7D9FDBD: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x504A08A: _guac_layer_update_intersects (protocol.c:622) +==4226== by 0x504A1AD: guac_layer_flush (protocol.c:664) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x504A0B8: _guac_layer_update_intersects (protocol.c:622) +==4226== by 0x504A1AD: guac_layer_flush (protocol.c:664) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x504A0E6: _guac_layer_update_intersects (protocol.c:627) +==4226== by 0x504A1AD: guac_layer_flush (protocol.c:664) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x504A114: _guac_layer_update_intersects (protocol.c:627) +==4226== by 0x504A1AD: guac_layer_flush (protocol.c:664) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A62A8C: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A62A90: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A62B8B: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A62BA0: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A62BBB: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C237C3: calloc (vg_replace_malloc.c:467) +==4226== by 0x5A62BD5: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55D533A: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE71C: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55D533F: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE71C: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DE752: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DE763: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55CDEAC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD851: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55CDF13: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD851: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55CDF1D: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD851: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55CDF26: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD851: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55CD8F1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55CD956: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF566: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF575: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF588: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF595: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF5B9: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF5C0: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF5D2: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF5DD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF62C: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF64E: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF658: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF274: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF287: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF353: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55DF358: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A40F43: pixman_region32_init_rect (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A438AE: pixman_region32_init_rects (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55D5854: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DF38F: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A40F48: pixman_region32_init_rect (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A438AE: pixman_region32_init_rects (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55D5854: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DF38F: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55D533A: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE0AE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55D533F: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE0AE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x504A339: guac_layer_flush (protocol.c:717) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A658EB: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6660A: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A658F3: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6660A: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A65193: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A65254: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A5D40A: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A5D578: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A34F96: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A62EB8: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D5EA: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A34FB6: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A62EB8: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D5EA: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26A7E: memset (mc_replace_strmem.c:602) +==4226== by 0x5A5D5EA: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26AC1: memset (mc_replace_strmem.c:602) +==4226== by 0x5A5D5EA: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A772ED: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A772F6: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A7740E: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x5A77599: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A774D5: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A775CE: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A5D681: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A65325: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5A6539D: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) +==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55FA8A0: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55FA8AE: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55FA8BC: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55FA8E8: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55FA925: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x614840C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6148415: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6148422: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6148430: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x614843D: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x614844A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6148457: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6148464: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6148477: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x614A785: png_set_IHDR (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7CA9: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6153CF4: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157A97: png_write_info_before_PLTE (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157CD9: png_write_info (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA88: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7CBB: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6153CF4: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157A97: png_write_info_before_PLTE (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157CD9: png_write_info (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA88: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7CBF: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6153CF4: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157A97: png_write_info_before_PLTE (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157CD9: png_write_info (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA88: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7CC6: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6153CF4: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157A97: png_write_info_before_PLTE (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157CD9: png_write_info (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAA88: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6157223: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x61505D0: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) +==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x61505D0: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x615070A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) +==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x615070A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x615F075: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) +==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x615F075: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26A7E: memset (mc_replace_strmem.c:602) +==4226== by 0x615F08A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26AA9: memset (mc_replace_strmem.c:602) +==4226== by 0x615F08A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26AC1: memset (mc_replace_strmem.c:602) +==4226== by 0x615F08A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C26AC8: memset (mc_replace_strmem.c:602) +==4226== by 0x615F08A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26AD3: memset (mc_replace_strmem.c:602) +==4226== by 0x615F08A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x615076A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) +==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x615076A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x615073A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) +==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x615073A: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x61506E4: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) +==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) +==4226== by 0x61506E4: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25F0A: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25F13: memcpy (mc_replace_strmem.c:77) +==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== +==4226== More than 100 errors detected. Subsequent errors +==4226== will still be recorded, but in less detail than before. +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25F19: memcpy (mc_replace_strmem.c:80) +==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25F28: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25F75: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26030: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C2603C: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C26040: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26070: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C26047: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26090: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55F9ED9: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x615ECEF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x615701A: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55F9F83: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x615ECEF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x615701A: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x55F9F0A: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x615ECEF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x615701A: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615302E: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6153058: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6152D6E: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6152D87: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6152E17: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6152E27: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6152F1D: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6152F37: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615340F: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615343F: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6EDA217: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25F0A: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25F28: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25F8A: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C25F98: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C25F9D: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25FCE: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C25FA1: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C25FA7: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25FE7: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C25FF8: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C25FFC: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C2600A: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26A7E: memset (mc_replace_strmem.c:602) +==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C26A88: memset (mc_replace_strmem.c:602) +==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26AA9: memset (mc_replace_strmem.c:602) +==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C26AA9: memset (mc_replace_strmem.c:602) +==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26AC1: memset (mc_replace_strmem.c:602) +==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C26AC8: memset (mc_replace_strmem.c:602) +==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26AD3: memset (mc_replace_strmem.c:602) +==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6152904: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6157240: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6EDA200: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25F13: memcpy (mc_replace_strmem.c:77) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25F75: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C25F19: memcpy (mc_replace_strmem.c:80) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26030: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C2603C: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C26044: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26070: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C2604C: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C26090: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C260A0: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C260AB: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x4C260B6: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C26040: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C26047: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x4C2600A: memcpy (mc_replace_strmem.c:497) +==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6EDA17A: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x615292C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6EDA223: deflate (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x615292C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615274F: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x615275F: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x6152796: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7B6C: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7B7B: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7B82: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7BAC: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7BDD: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7C03: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7C12: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7ADD: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x6ED7AE8: crc32 (in /usr/lib/libz.so.1.2.3.4) +==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) +==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) +==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) +==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) +==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5048621: __guac_write_base64_triplet (guacio.c:169) +==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) +==4226== by 0x5048935: guac_write_base64 (guacio.c:241) +==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x5048658: __guac_write_base64_triplet (guacio.c:170) +==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) +==4226== by 0x5048935: guac_write_base64 (guacio.c:241) +==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x504867D: __guac_write_base64_triplet (guacio.c:173) +==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) +==4226== by 0x5048935: guac_write_base64 (guacio.c:241) +==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x50486B6: __guac_write_base64_triplet (guacio.c:174) +==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) +==4226== by 0x5048935: guac_write_base64 (guacio.c:241) +==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x50486E4: __guac_write_base64_triplet (guacio.c:175) +==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) +==4226== by 0x5048935: guac_write_base64 (guacio.c:241) +==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5048828: __guac_write_base64_triplet (guacio.c:202) +==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) +==4226== by 0x5048935: guac_write_base64 (guacio.c:241) +==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Conditional jump or move depends on uninitialised value(s) +==4226== at 0x5048835: __guac_write_base64_triplet (guacio.c:205) +==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) +==4226== by 0x5048935: guac_write_base64 (guacio.c:241) +==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== Use of uninitialised value of size 8 +==4226== at 0x50485FC: __guac_write_base64_triplet (guacio.c:166) +==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) +==4226== by 0x5048935: guac_write_base64 (guacio.c:241) +==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) +==4226== by 0x50497EE: guac_send_png (protocol.c:315) +==4226== by 0x504A497: guac_layer_flush (protocol.c:759) +==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) +==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) +==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) +==4226== +==4226== +==4226== HEAP SUMMARY: +==4226== in use at exit: 6,641,231 bytes in 726 blocks +==4226== total heap usage: 2,736 allocs, 2,010 frees, 39,039,517 bytes allocated +==4226== +==4226== LEAK SUMMARY: +==4226== definitely lost: 6,632,823 bytes in 720 blocks +==4226== indirectly lost: 0 bytes in 0 blocks +==4226== possibly lost: 0 bytes in 0 blocks +==4226== still reachable: 8,408 bytes in 6 blocks +==4226== suppressed: 0 bytes in 0 blocks +==4226== Rerun with --leak-check=full to see details of leaked memory +==4226== +==4226== For counts of detected and suppressed errors, rerun with: -v +==4226== Use --track-origins=yes to see where uninitialised values come from +==4226== ERROR SUMMARY: 6162923 errors from 182 contexts (suppressed: 1842450 from 38) +==4224== +==4224== HEAP SUMMARY: +==4224== in use at exit: 4 bytes in 1 blocks +==4224== total heap usage: 12 allocs, 11 frees, 11,345 bytes allocated +==4224== +==4224== LEAK SUMMARY: +==4224== definitely lost: 0 bytes in 0 blocks +==4224== indirectly lost: 0 bytes in 0 blocks +==4224== possibly lost: 0 bytes in 0 blocks +==4224== still reachable: 4 bytes in 1 blocks +==4224== suppressed: 0 bytes in 0 blocks +==4224== Rerun with --leak-check=full to see details of leaked memory +==4224== +==4224== For counts of detected and suppressed errors, rerun with: -v +==4224== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) From 820a4b1fff8afb259e4ac1072dd3530a0a55b5fa Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 23 Oct 2011 23:19:49 -0700 Subject: [PATCH 090/330] Removed accidentally-committed test file --- libguac/test | 2408 -------------------------------------------------- 1 file changed, 2408 deletions(-) delete mode 100644 libguac/test diff --git a/libguac/test b/libguac/test deleted file mode 100644 index 5505cd39..00000000 --- a/libguac/test +++ /dev/null @@ -1,2408 +0,0 @@ -==4221== Memcheck, a memory error detector -==4221== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. -==4221== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info -==4221== Command: /home/zhz/guacamole/roots/unstable/sbin/guacd -l 4823 -==4221== Parent PID: 1533 -==4221== -==4221== -==4221== HEAP SUMMARY: -==4221== in use at exit: 0 bytes in 0 blocks -==4221== total heap usage: 0 allocs, 0 frees, 0 bytes allocated -==4221== -==4221== All heap blocks were freed -- no leaks are possible -==4221== -==4221== For counts of detected and suppressed errors, rerun with: -v -==4221== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) -==4226== Syscall param write(buf) points to uninitialised byte(s) -==4226== at 0x4E37040: __write_nocancel (syscall-template.S:82) -==4226== by 0x7FB4646: WriteToRFBServer (sockets.c:216) -==4226== by 0x7FAA9BB: SetFormatAndEncodings (rfbproto.c:677) -==4226== by 0x7FB4CCF: rfbInitClient (vncviewer.c:201) -==4226== by 0x7DA0209: guac_client_init (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x5047E71: guac_get_client (client.c:293) -==4226== by 0x400EC3: start_client_thread (in /home/zhz/guacamole/roots/unstable/sbin/guacd) -==4226== by 0x4013B6: main (in /home/zhz/guacamole/roots/unstable/sbin/guacd) -==4226== Address 0x7ff000051 is on thread 1's stack -==4226== -==4226== Syscall param write(buf) points to uninitialised byte(s) -==4226== at 0x4E37040: __write_nocancel (syscall-template.S:82) -==4226== by 0x7FB4646: WriteToRFBServer (sockets.c:216) -==4226== by 0x7FAAA70: SetFormatAndEncodings (rfbproto.c:853) -==4226== by 0x7FB4CCF: rfbInitClient (vncviewer.c:201) -==4226== by 0x7DA0209: guac_client_init (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x5047E71: guac_get_client (client.c:293) -==4226== by 0x400EC3: start_client_thread (in /home/zhz/guacamole/roots/unstable/sbin/guacd) -==4226== by 0x4013B6: main (in /home/zhz/guacamole/roots/unstable/sbin/guacd) -==4226== Address 0x7fefffff1 is on thread 1's stack -==4226== -==4226== Thread 2: -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6EDF290: inflateReset2 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDF37F: inflateInit2_ (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x7FAF00F: HandleZRLE24 (zrle.c:126) -==4226== by 0x7FB3556: HandleRFBServerMessage (rfbproto.c:1468) -==4226== by 0x7D9FDBD: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x504A08A: _guac_layer_update_intersects (protocol.c:622) -==4226== by 0x504A1AD: guac_layer_flush (protocol.c:664) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x504A0B8: _guac_layer_update_intersects (protocol.c:622) -==4226== by 0x504A1AD: guac_layer_flush (protocol.c:664) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x504A0E6: _guac_layer_update_intersects (protocol.c:627) -==4226== by 0x504A1AD: guac_layer_flush (protocol.c:664) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x504A114: _guac_layer_update_intersects (protocol.c:627) -==4226== by 0x504A1AD: guac_layer_flush (protocol.c:664) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A62A8C: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A62A90: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A62B8B: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A62BA0: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A62BBB: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C237C3: calloc (vg_replace_malloc.c:467) -==4226== by 0x5A62BD5: pixman_image_create_bits (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C7D05: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A2A8: guac_layer_flush (protocol.c:699) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55D533A: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE71C: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55D533F: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE71C: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DE752: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DE763: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55CDEAC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD851: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55CDF13: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD851: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55CDF1D: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD851: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55CDF26: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD851: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55CD8F1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55CD956: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF566: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF575: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF588: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF595: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF5B9: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF5C0: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF5D2: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF5DD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF62C: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF64E: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF658: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DFBBD: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55CD936: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7B1: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF274: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF287: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF353: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55DF358: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A40F43: pixman_region32_init_rect (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A438AE: pixman_region32_init_rects (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55D5854: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DF38F: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A40F48: pixman_region32_init_rect (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A438AE: pixman_region32_init_rects (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55D5854: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DF38F: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE01B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55D533A: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE0AE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55D533F: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE0AE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x504A339: guac_layer_flush (protocol.c:717) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A658EB: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6660A: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A658F3: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6660A: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A65193: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A65254: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A5D40A: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A5D578: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A34F96: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A62EB8: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D5EA: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A34FB6: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A62EB8: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D5EA: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26A7E: memset (mc_replace_strmem.c:602) -==4226== by 0x5A5D5EA: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26AC1: memset (mc_replace_strmem.c:602) -==4226== by 0x5A5D5EA: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A772ED: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A772F6: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A7740E: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x5A77599: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A774D5: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A775CE: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D731: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A5D681: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A65321: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A65325: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5A6539D: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A6668F: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5D2F9: ??? (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x5A5E12B: pixman_image_composite (in /usr/lib/libpixman-1.so.0.16.4) -==4226== by 0x55C776B: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DBFEC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE4DE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DE7D3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55DAFEE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55C3C19: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE97F: cairo_fill_preserve (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55BE998: cairo_fill (in /usr/lib/libcairo.so.2.10800.10) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55FA8A0: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55FA8AE: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55FA8BC: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55FA8E8: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55FA925: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x614840C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6148415: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6148422: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6148430: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x614843D: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x614844A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6148457: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6148464: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6148477: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x614A752: png_set_IHDR (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x614A785: png_set_IHDR (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA51: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7CA9: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6153CF4: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157A97: png_write_info_before_PLTE (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157CD9: png_write_info (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA88: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7CBB: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6153CF4: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157A97: png_write_info_before_PLTE (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157CD9: png_write_info (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA88: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7CBF: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6153CF4: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157A97: png_write_info_before_PLTE (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157CD9: png_write_info (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA88: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7CC6: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6153CF4: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157A97: png_write_info_before_PLTE (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157CD9: png_write_info (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAA88: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6157223: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x61505D0: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) -==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x61505D0: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x615070A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) -==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x615070A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x615F075: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) -==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x615F075: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26A7E: memset (mc_replace_strmem.c:602) -==4226== by 0x615F08A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26AA9: memset (mc_replace_strmem.c:602) -==4226== by 0x615F08A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26AC1: memset (mc_replace_strmem.c:602) -==4226== by 0x615F08A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C26AC8: memset (mc_replace_strmem.c:602) -==4226== by 0x615F08A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26AD3: memset (mc_replace_strmem.c:602) -==4226== by 0x615F08A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x61506AA: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x615076A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) -==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x615076A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x615073A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) -==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x615073A: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF9B: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x61506E4: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615EF73: png_malloc_default (in /lib/libpng12.so.0.44.0) -==4226== by 0x615F004: png_malloc (in /lib/libpng12.so.0.44.0) -==4226== by 0x61506E4: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156ED1: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25F0A: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25F13: memcpy (mc_replace_strmem.c:77) -==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== -==4226== More than 100 errors detected. Subsequent errors -==4226== will still be recorded, but in less detail than before. -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25F19: memcpy (mc_replace_strmem.c:80) -==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25F28: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25F75: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26030: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C2603C: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C26040: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26070: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C26047: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26090: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6156F70: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55F9ED9: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x615ECEF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x615701A: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55F9F83: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x615ECEF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x615701A: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x55F9F0A: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x615ECEF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x615701A: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615302E: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6153058: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6152D6E: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6152D87: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6152E17: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6152E27: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6152F1D: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6152F37: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615340F: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615343F: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6EDA217: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25F0A: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25F28: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25F8A: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C25F98: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C25F9D: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25FCE: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C25FA1: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C25FA7: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25FE7: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C25FF8: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C25FFC: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C2600A: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26A7E: memset (mc_replace_strmem.c:602) -==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C26A88: memset (mc_replace_strmem.c:602) -==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26AA9: memset (mc_replace_strmem.c:602) -==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C26AA9: memset (mc_replace_strmem.c:602) -==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26AC1: memset (mc_replace_strmem.c:602) -==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C26AC8: memset (mc_replace_strmem.c:602) -==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26AD3: memset (mc_replace_strmem.c:602) -==4226== by 0x6EDB039: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6152904: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6157240: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6EDA200: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25F13: memcpy (mc_replace_strmem.c:77) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25F75: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C25F19: memcpy (mc_replace_strmem.c:80) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26030: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C2603C: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C26044: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26070: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C2604C: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C26090: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C260A0: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C260AB: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x4C260B6: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C26040: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C26047: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x4C2600A: memcpy (mc_replace_strmem.c:497) -==4226== by 0x6EDAE60: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDBCFC: ??? (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6EDA250: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x6152B95: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6EDA17A: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x615292C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6EDA223: deflate (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x615292C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615274F: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x615275F: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x6152796: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7B6C: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7B7B: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7B82: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7BAC: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7BDD: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7C03: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7C12: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7ADD: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x6ED7AE8: crc32 (in /usr/lib/libz.so.1.2.3.4) -==4226== by 0x614921C: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6151A86: png_write_chunk (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152711: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152B11: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152C23: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6152FBF: ??? (in /lib/libpng12.so.0.44.0) -==4226== by 0x6156FC8: png_write_row (in /lib/libpng12.so.0.44.0) -==4226== by 0x6157238: png_write_image (in /lib/libpng12.so.0.44.0) -==4226== by 0x55FAAB3: ??? (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x55FABFB: cairo_surface_write_to_png_stream (in /usr/lib/libcairo.so.2.10800.10) -==4226== by 0x5049614: __guac_write_length_png (protocol.c:279) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5048621: __guac_write_base64_triplet (guacio.c:169) -==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) -==4226== by 0x5048935: guac_write_base64 (guacio.c:241) -==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x5048658: __guac_write_base64_triplet (guacio.c:170) -==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) -==4226== by 0x5048935: guac_write_base64 (guacio.c:241) -==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x504867D: __guac_write_base64_triplet (guacio.c:173) -==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) -==4226== by 0x5048935: guac_write_base64 (guacio.c:241) -==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x50486B6: __guac_write_base64_triplet (guacio.c:174) -==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) -==4226== by 0x5048935: guac_write_base64 (guacio.c:241) -==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x50486E4: __guac_write_base64_triplet (guacio.c:175) -==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) -==4226== by 0x5048935: guac_write_base64 (guacio.c:241) -==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5048828: __guac_write_base64_triplet (guacio.c:202) -==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) -==4226== by 0x5048935: guac_write_base64 (guacio.c:241) -==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Conditional jump or move depends on uninitialised value(s) -==4226== at 0x5048835: __guac_write_base64_triplet (guacio.c:205) -==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) -==4226== by 0x5048935: guac_write_base64 (guacio.c:241) -==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== Use of uninitialised value of size 8 -==4226== at 0x50485FC: __guac_write_base64_triplet (guacio.c:166) -==4226== by 0x50488C3: __guac_write_base64_byte (guacio.c:222) -==4226== by 0x5048935: guac_write_base64 (guacio.c:241) -==4226== by 0x504968D: __guac_write_length_png (protocol.c:290) -==4226== by 0x50497EE: guac_send_png (protocol.c:315) -==4226== by 0x504A497: guac_layer_flush (protocol.c:759) -==4226== by 0x7D9FDF3: vnc_guac_client_handle_messages (in /home/zhz/guacamole/roots/unstable/lib/libguac-client-vnc.so.0.0.0) -==4226== by 0x50480CD: __guac_client_output_thread (client.c:391) -==4226== by 0x4E2F8B9: start_thread (pthread_create.c:300) -==4226== -==4226== -==4226== HEAP SUMMARY: -==4226== in use at exit: 6,641,231 bytes in 726 blocks -==4226== total heap usage: 2,736 allocs, 2,010 frees, 39,039,517 bytes allocated -==4226== -==4226== LEAK SUMMARY: -==4226== definitely lost: 6,632,823 bytes in 720 blocks -==4226== indirectly lost: 0 bytes in 0 blocks -==4226== possibly lost: 0 bytes in 0 blocks -==4226== still reachable: 8,408 bytes in 6 blocks -==4226== suppressed: 0 bytes in 0 blocks -==4226== Rerun with --leak-check=full to see details of leaked memory -==4226== -==4226== For counts of detected and suppressed errors, rerun with: -v -==4226== Use --track-origins=yes to see where uninitialised values come from -==4226== ERROR SUMMARY: 6162923 errors from 182 contexts (suppressed: 1842450 from 38) -==4224== -==4224== HEAP SUMMARY: -==4224== in use at exit: 4 bytes in 1 blocks -==4224== total heap usage: 12 allocs, 11 frees, 11,345 bytes allocated -==4224== -==4224== LEAK SUMMARY: -==4224== definitely lost: 0 bytes in 0 blocks -==4224== indirectly lost: 0 bytes in 0 blocks -==4224== possibly lost: 0 bytes in 0 blocks -==4224== still reachable: 4 bytes in 1 blocks -==4224== suppressed: 0 bytes in 0 blocks -==4224== Rerun with --leak-check=full to see details of leaked memory -==4224== -==4224== For counts of detected and suppressed errors, rerun with: -v -==4224== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) From 185d23fb5efef05586b75c02f2a4f5619db45a98 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 25 Oct 2011 22:01:53 -0700 Subject: [PATCH 091/330] Migrated queue from layer to client, restored GUAC_DEFAULT_LAYER. --- libguac/include/client.h | 215 +++++++++++++++++++- libguac/include/protocol.h | 123 ------------ libguac/src/client.c | 391 +++++++++++++++++++++++++++++++++---- libguac/src/protocol.c | 329 ------------------------------- 4 files changed, 569 insertions(+), 489 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 4ab1c0e5..e29aca2d 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -103,6 +103,120 @@ typedef int guac_client_clipboard_handler(guac_client* client, char* copied); */ typedef int guac_client_free_handler(guac_client* client); +typedef struct guac_client_update guac_client_update; + +/** + * The type of a layer update (png, copy, or rect, for + * example). + */ +typedef enum guac_client_update_type_t { + + GUAC_CLIENT_UPDATE_PNG, + GUAC_CLIENT_UPDATE_COPY, + GUAC_CLIENT_UPDATE_CLIP, + GUAC_CLIENT_UPDATE_RECT + +} guac_client_update_type_t; + +/** + * Represents an abstract graphical update or state change + * of a client, including dirty rectangle information. + */ +struct guac_client_update { + + /** + * The type of this update. Update type corresponds + * directly to the instruction that would be sent + * if the queue is flushed. + */ + guac_client_update_type_t type; + + /** + * The composite mode to use in this update. + */ + guac_composite_mode_t mode; + + /** + * The layer to retrieve image data from. + */ + const guac_layer* src_layer; + + /** + * The surface to retrieve image data from. + */ + cairo_surface_t* src_image; + + /** + * The red component of the source color. + */ + int src_red; + + /** + * The green component of the source color. + */ + int src_green; + + /** + * The blue component of the source color. + */ + int src_blue; + + /** + * The alpha component of the source color. + */ + int src_alpha; + + /** + * The X coordinage of the upper-left corner of the + * source rectangle. + */ + int src_x; + + /** + * The Y coordinage of the upper-left corner of the + * source rectangle. + */ + int src_y; + + /** + * The layer this update should affect. + */ + const guac_layer* dst_layer; + + /** + * The X coordinate of the upper-left corner of the + * destination rectangle. + */ + int dst_x; + + /** + * The Y coordinate of the upper-left corner of the + * destination rectangle. + */ + int dst_y; + + /** + * The width of the destination or source rectangle. + * The dimensions of the destination and source + * rectangles are always identical. + */ + int width; + + /** + * The height of the destination or source rectangle. + * The dimensions of the destination and source + * rectangles are always identical. + */ + int height; + + /** + * The next update in the update queue, if any. + */ + guac_client_update* next; + +}; + + /** * Possible current states of the Guacamole client. Currently, the only * two states are RUNNING and STOPPING. @@ -165,9 +279,14 @@ struct guac_client { guac_layer* all_layers; /** - * Pointer to a pre-allocated default layer (layer 0) + * The first element in this client's update queue. */ - guac_layer* default_layer; + guac_client_update* update_queue_head; + + /** + * The last element in this client's update queue. + */ + guac_client_update* update_queue_tail; /** * The time (in milliseconds) of receipt of the last sync message from @@ -378,4 +497,96 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); */ void guac_client_free_buffer(guac_client* client, guac_layer* layer); +/** + * Queues a png instruction in the given client. The client may combine + * and re-order multiple instructions into more efficient instructions + * providing the end result is the same image. + * + * @param client The proxy client which will queue the instruction. + * @param layer The destination layer. + * @param mode The composite mode to use. + * @param x The destination X coordinate. + * @param y The destination Y coordinate. + * @param surface A cairo surface containing the image data to send. + */ +void guac_client_queue_png(guac_client* client, guac_composite_mode_t mode, + const guac_layer* layer, int x, int y, cairo_surface_t* surface); + +/** + * Queues a copy instruction in a given client. The client may combine + * and re-order multiple instructions into more efficient instructions + * providing the end result is the same image. + * + * @param client The proxy client which will queue the instruction. + * @param srcl The source layer. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. + * @param mode The composite mode to use. + * @param dstl The destination layer. + * @param dstx The X coordinate of the destination, where the source rectangle + * should be copied. + * @param dsty The Y coordinate of the destination, where the source rectangle + * should be copied. + */ +void guac_client_queue_copy(guac_client* client, + const guac_layer* srcl, int srcx, int srcy, int w, int h, + guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty); + +/** + * Queues a clip instruction in a given client. The client may combine + * and re-order multiple instructions into more efficient instructions + * providing the end result is the same image. + * + * @param client The proxy client which will queue the instruction. + * @param layer The layer to set the clipping region of. + * @param x The X coordinate of the clipping rectangle. + * @param y The Y coordinate of the clipping rectangle. + * @param width The width of the clipping rectangle. + * @param height The height of the clipping rectangle. + */ +void guac_client_queue_clip(guac_client* client, const guac_layer* layer, + int x, int y, int width, int height); + +/** + * Queues a rect instruction in a given layer. The layer may combine + * and re-order multiple instructions into more efficient instructions + * providing the end result is the same image. + * + * @param client The proxy client which will queue the instruction. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param x The X coordinate of the rectangle. + * @param y The Y coordinate of the rectangle. + * @param width The width of the rectangle. + * @param height The height of the rectangle. + * @param r The red component of the color of the rectangle. + * @param g The green component of the color of the rectangle. + * @param b The blue component of the color of the rectangle. + * @param a The alpha (transparency) component of the color of the rectangle. + */ +void guac_client_queue_rect(guac_client* client, + const guac_layer* layer, guac_composite_mode_t mode, + int x, int y, int width, int height, + int r, int g, int b, int a); + +/** + * Flushes any queued instructions in the given client, sending those + * instructions over the given GUACIO connection. These instructions + * may not be identical to the instructions originally queued; they + * may be re-ordered or combined providing the end result of executing + * all instructions sent by guac_client_queue_flush() is identical to + * executing all previously queued instructions as specified and in order. + * + * @param client The client to flush. + * @return Zero on success, non-zero on error. + */ +int guac_client_queue_flush(guac_client* client); + +/** + * The default Guacamole client layer, layer 0. + */ +extern const guac_layer* GUAC_DEFAULT_LAYER; + #endif diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 128a9b2f..b680fa5e 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -104,121 +104,8 @@ typedef enum guac_composite_mode_t { } guac_composite_mode_t; -typedef struct guac_layer_update guac_layer_update; typedef struct guac_layer guac_layer; - -/** - * The type of a layer update (png, copy, or rect, for - * example). - */ -typedef enum guac_layer_update_type_t { - - GUAC_LAYER_UPDATE_PNG, - GUAC_LAYER_UPDATE_COPY, - GUAC_LAYER_UPDATE_CLIP, - GUAC_LAYER_UPDATE_RECT - -} guac_layer_update_type_t; - -/** - * Represents an abstract graphical update or state change - * of a layer, including dirty rectangle information. - */ -struct guac_layer_update { - - /** - * The type of this update. Update type corresponds - * directly to the instruction that would be sent - * if the queue is flushed. - */ - guac_layer_update_type_t type; - - /** - * The composite mode to use in this update. - */ - guac_composite_mode_t mode; - - /** - * The layer to retrieve image data from. - */ - const guac_layer* src_layer; - - /** - * The surface to retrieve image data from. - */ - cairo_surface_t* src_image; - - /** - * The red component of the source color. - */ - int src_red; - - /** - * The green component of the source color. - */ - int src_green; - - /** - * The blue component of the source color. - */ - int src_blue; - - /** - * The alpha component of the source color. - */ - int src_alpha; - - /** - * The X coordinage of the upper-left corner of the - * source rectangle. - */ - int src_x; - - /** - * The Y coordinage of the upper-left corner of the - * source rectangle. - */ - int src_y; - - /** - * The layer this update should affect. - */ - guac_layer* dst_layer; - - /** - * The X coordinate of the upper-left corner of the - * destination rectangle. - */ - int dst_x; - - /** - * The Y coordinate of the upper-left corner of the - * destination rectangle. - */ - int dst_y; - - /** - * The width of the destination or source rectangle. - * The dimensions of the destination and source - * rectangles are always identical. - */ - int width; - - /** - * The height of the destination or source rectangle. - * The dimensions of the destination and source - * rectangles are always identical. - */ - int height; - - /** - * The next update in the update queue, if any. - */ - guac_layer_update* next; - -}; - /** * Represents a single layer within the Guacamole protocol. */ @@ -240,16 +127,6 @@ struct guac_layer { */ guac_layer* next_available; - /** - * The first element in this layer's update queue. - */ - guac_layer_update* update_queue_head; - - /** - * The last element in this layer's update queue. - */ - guac_layer_update* update_queue_tail; - }; /** diff --git a/libguac/src/client.c b/libguac/src/client.c index f914e3d7..6cd81028 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -47,6 +47,17 @@ #include "client.h" #include "client-handlers.h" +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +guac_layer __GUAC_DEFAULT_LAYER = { + .index = 0, + .next = NULL, + .next_available = NULL +}; + +const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; + guac_client* __guac_alloc_client(GUACIO* io) { /* Allocate new client (not handoff) */ @@ -58,13 +69,13 @@ guac_client* __guac_alloc_client(GUACIO* io) { client->last_received_timestamp = client->last_sent_timestamp = guac_current_timestamp(); client->state = RUNNING; - client->all_layers = NULL; + client->all_layers = NULL; client->available_buffers = NULL; - client->next_buffer_index = -1; + client->update_queue_head = NULL; + client->update_queue_tail = NULL; - /* Allocate default layer */ - client->default_layer = guac_client_alloc_layer(client, 0); + client->next_buffer_index = -1; return client; } @@ -75,8 +86,6 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index) { /* Init new layer */ allocd_layer = malloc(sizeof(guac_layer)); - allocd_layer->update_queue_head = NULL; - allocd_layer->update_queue_tail = NULL; /* Add to all_layers list */ allocd_layer->next = client->all_layers; @@ -104,8 +113,6 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { /* Init new layer */ allocd_layer = malloc(sizeof(guac_layer)); allocd_layer->index = client->next_buffer_index--; - allocd_layer->update_queue_head = NULL; - allocd_layer->update_queue_tail = NULL; /* Add to all_layers list */ allocd_layer->next = client->all_layers; @@ -123,21 +130,6 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) { layer->next_available = client->available_buffers; client->available_buffers = layer; - /* Free all queued updates */ - while (layer->update_queue_head != NULL) { - - /* Get unflushed update, update queue head */ - guac_layer_update* unflushed_update = layer->update_queue_head; - layer->update_queue_head = unflushed_update->next; - - /* Free update */ - free(unflushed_update); - - } - - /* Queue is now empty */ - layer->update_queue_tail = NULL; - } guac_client* guac_get_client(int client_fd) { @@ -339,23 +331,23 @@ void guac_free_client(guac_client* client) { guac_layer* layer = client->all_layers; client->all_layers = layer->next; - /* Free all queued updates */ - while (layer->update_queue_head != NULL) { - - /* Get unflushed update, update queue head */ - guac_layer_update* unflushed_update = layer->update_queue_head; - layer->update_queue_head = unflushed_update->next; - - /* Free update */ - free(unflushed_update); - - } - /* Free layer */ free(layer); } + /* Free all queued updates */ + while (client->update_queue_head != NULL) { + + /* Get unflushed update, update queue head */ + guac_client_update* unflushed_update = client->update_queue_head; + client->update_queue_head = unflushed_update->next; + + /* Free update */ + free(unflushed_update); + + } + free(client); } @@ -506,3 +498,332 @@ int guac_client_handle_instruction(guac_client* client, guac_instruction* instru } +void __guac_client_queue_add_update(guac_client* client, guac_client_update* update) { + + /* Add update to queue tail */ + if (client->update_queue_tail != NULL) + client->update_queue_tail = client->update_queue_tail->next = update; + + /* Set both head and tail if necessary */ + else + client->update_queue_tail = client->update_queue_head = update; + + update->next = NULL; + +} + +void guac_client_queue_png(guac_client* client, guac_composite_mode_t mode, + const guac_layer* layer, int x, int y, cairo_surface_t* surface) { + + /* Allocate update */ + guac_client_update* update = (guac_client_update*) malloc(sizeof(guac_client_update)); + + /* Set parameters of update */ + update->type = GUAC_CLIENT_UPDATE_PNG; + update->mode = mode; + update->src_image = surface; + update->dst_layer = layer; + update->dst_x = x; + update->dst_y = y; + update->width = cairo_image_surface_get_width(surface); + update->height = cairo_image_surface_get_height(surface); + + /* Add to client queue */ + __guac_client_queue_add_update(client, update); + +} + +void guac_client_queue_copy(guac_client* client, + const guac_layer* srcl, int srcx, int srcy, int w, int h, + guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty) { + + /* Allocate update */ + guac_client_update* update = (guac_client_update*) malloc(sizeof(guac_client_update)); + + /* Set parameters of update */ + update->type = GUAC_CLIENT_UPDATE_COPY; + update->mode = mode; + update->src_layer = srcl; + update->src_x = srcx; + update->src_y = srcy; + update->width = w; + update->height = h; + update->dst_layer = dstl; + update->dst_x = dstx; + update->dst_y = dsty; + + /* Add to client queue */ + __guac_client_queue_add_update(client, update); + +} + +void guac_client_queue_clip(guac_client* client, const guac_layer* layer, + int x, int y, int width, int height) { + + /* Allocate update */ + guac_client_update* update = (guac_client_update*) malloc(sizeof(guac_client_update)); + + /* Set parameters of update */ + update->type = GUAC_CLIENT_UPDATE_CLIP; + update->dst_x = x; + update->dst_y = y; + update->width = width; + update->height = height; + + /* Add to client queue */ + __guac_client_queue_add_update(client, update); + +} + +void guac_client_queue_rect(guac_client* client, + const guac_layer* layer, guac_composite_mode_t mode, + int x, int y, int width, int height, + int r, int g, int b, int a) { + + /* Allocate update */ + guac_client_update* update = (guac_client_update*) malloc(sizeof(guac_client_update)); + + /* Set parameters of update */ + update->type = GUAC_CLIENT_UPDATE_RECT; + update->mode = mode; + update->src_red = r; + update->src_green = g; + update->src_blue = b; + update->src_alpha = a; + update->dst_x = x; + update->dst_y = y; + update->width = width; + update->height = height; + + /* Add to client queue */ + __guac_client_queue_add_update(client, update); + +} + +int __guac_client_update_intersects( + const guac_client_update* update1, const guac_client_update* update2) { + + /* If update1 X is within width of update2 + or update2 X is within width of update1 */ + if ((update1->dst_x >= update2->dst_x && update1->dst_x < update2->dst_x + update2->width) + || (update2->dst_x >= update1->dst_x && update2->dst_x < update1->dst_x + update2->width)) { + + /* If update1 Y is within height of update2 + or update2 Y is within height of update1 */ + if ((update1->dst_y >= update2->dst_y && update1->dst_y < update2->dst_y + update2->height) + || (update2->dst_y >= update1->dst_y && update2->dst_y < update1->dst_y + update2->height)) { + + /* Register instersection */ + return 1; + + } + + } + + /* Otherwise, no intersection */ + return 0; + +} + +int guac_client_queue_flush(guac_client* client) { + + GUACIO* io = client->io; + + while (client->update_queue_head != NULL) { + + guac_client_update* later_update; + int update_merged = 0; + + /* Get next update, update queue head. */ + guac_client_update* update = client->update_queue_head; + client->update_queue_head = update->next; + + /* Send instruction appropriate for update type */ + switch (update->type) { + + /* "png" instruction */ + case GUAC_CLIENT_UPDATE_PNG: + + /* Decide whether or not to send */ + later_update = update->next; + while (later_update != NULL) { + + /* If destination rectangles intersect */ + if (__guac_client_update_intersects(update, later_update)) { + + cairo_surface_t* merged_surface; + cairo_t* cairo; + int merged_x, merged_y, merged_width, merged_height; + + /* Cannot combine anything if intersection with non-PNG */ + if (later_update->type != GUAC_CLIENT_UPDATE_PNG) + break; + + /* Cannot combine if modes differ */ + if (later_update->mode != update->mode) + break; + + /* For now, only combine for GUAC_COMP_OVER */ + if (later_update->mode != GUAC_COMP_OVER) + break; + + /* Calculate merged dimensions */ + merged_x = MIN(update->dst_x, later_update->dst_x); + merged_y = MIN(update->dst_y, later_update->dst_y); + + merged_width = MAX( + update->dst_x + update->width, + later_update->dst_x + later_update->width + ) - merged_x; + + merged_height = MAX( + update->dst_y + update->height, + later_update->dst_y + later_update->height + ) - merged_y; + + /* Create surface for merging */ + merged_surface = cairo_image_surface_create( + CAIRO_FORMAT_ARGB32, merged_width, merged_height); + + /* Get drawing context */ + cairo = cairo_create(merged_surface); + + /* Draw first update within merged surface */ + cairo_set_source_surface(cairo, + update->src_image, + update->dst_x - merged_x, + update->dst_y - merged_y); + + cairo_rectangle(cairo, + update->dst_x - merged_x, + update->dst_y - merged_y, + update->width, + update->height); + + cairo_fill(cairo); + + /* Draw second update within merged surface */ + cairo_set_source_surface(cairo, + later_update->src_image, + later_update->dst_x - merged_x, + later_update->dst_y - merged_y); + + cairo_rectangle(cairo, + later_update->dst_x - merged_x, + later_update->dst_y - merged_y, + later_update->width, + later_update->height); + + cairo_fill(cairo); + + /* Done drawing */ + cairo_destroy(cairo); + + /* Alter update dimensions */ + later_update->dst_x = merged_x; + later_update->dst_y = merged_y; + later_update->width = merged_width; + later_update->height = merged_height; + + /* Alter update to include merged data*/ + cairo_surface_destroy(later_update->src_image); + later_update->src_image = merged_surface; + + update_merged = 1; + break; + + } + + /* Get next update */ + later_update = later_update->next; + + } + + /* Send instruction if update was not merged */ + if (!update_merged) { + if (guac_send_png(io, + update->mode, + update->dst_layer, + update->dst_x, + update->dst_y, + update->src_image + )) { + cairo_surface_destroy(update->src_image); + free(update); + return -1; + } + } + + cairo_surface_destroy(update->src_image); + break; + + /* "copy" instruction */ + case GUAC_CLIENT_UPDATE_COPY: + + if (guac_send_copy(io, + update->src_layer, + update->src_x, + update->src_y, + update->width, + update->height, + update->mode, + update->dst_layer, + update->dst_x, + update->dst_y + )) { + free(update); + return -1; + } + + break; + + /* "clip" instruction */ + case GUAC_CLIENT_UPDATE_CLIP: + + if (guac_send_clip(io, + update->dst_layer, + update->dst_x, + update->dst_y, + update->width, + update->height + )) { + free(update); + return -1; + } + + break; + + /* "rect" instruction */ + case GUAC_CLIENT_UPDATE_RECT: + + if (guac_send_rect(io, + update->mode, + update->dst_layer, + update->dst_x, + update->dst_y, + update->width, + update->height, + update->src_red, + update->src_green, + update->src_blue, + update->src_alpha + )) { + free(update); + return -1; + } + + break; + + } /* end of switch update type */ + + /* Free update */ + free(update); + + } + + /* Queue is now empty */ + client->update_queue_tail = NULL; + + return 0; +} + diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 739162d8..9dfe74f7 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -63,9 +63,6 @@ #include "guacio.h" #include "protocol.h" -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) - ssize_t __guac_write_length_string(GUACIO* io, const char* str) { return @@ -521,329 +518,3 @@ void guac_sleep(int millis) { } -void __guac_layer_add_update(guac_layer* layer, guac_layer_update* update) { - - /* Add update to queue tail */ - if (layer->update_queue_tail != NULL) - layer->update_queue_tail = layer->update_queue_tail->next = update; - - /* Set both head and tail if necessary */ - else - layer->update_queue_tail = layer->update_queue_head = update; - - update->next = NULL; - -} - -void guac_layer_png(guac_layer* layer, guac_composite_mode_t mode, - int x, int y, cairo_surface_t* surface) { - - /* Allocate update */ - guac_layer_update* update = (guac_layer_update*) malloc(sizeof(guac_layer_update)); - - /* Set parameters of update */ - update->type = GUAC_LAYER_UPDATE_PNG; - update->mode = mode; - update->src_image = surface; - update->dst_layer = layer; - update->dst_x = x; - update->dst_y = y; - update->width = cairo_image_surface_get_width(surface); - update->height = cairo_image_surface_get_height(surface); - - /* Add to layer queue */ - __guac_layer_add_update(layer, update); - -} - -void guac_layer_copy(guac_layer* layer, guac_composite_mode_t mode, - const guac_layer* srcl, int srcx, int srcy, int w, int h, - int dstx, int dsty) { - - /* Allocate update */ - guac_layer_update* update = (guac_layer_update*) malloc(sizeof(guac_layer_update)); - - /* Set parameters of update */ - update->type = GUAC_LAYER_UPDATE_COPY; - update->mode = mode; - update->src_layer = srcl; - update->src_x = srcx; - update->src_y = srcy; - update->width = w; - update->height = h; - update->dst_layer = layer; - update->dst_x = dstx; - update->dst_y = dsty; - - /* Add to layer queue */ - __guac_layer_add_update(layer, update); - -} - -void guac_layer_clip(guac_layer* layer, - int x, int y, int width, int height) { - - /* Allocate update */ - guac_layer_update* update = (guac_layer_update*) malloc(sizeof(guac_layer_update)); - - /* Set parameters of update */ - update->type = GUAC_LAYER_UPDATE_CLIP; - update->dst_x = x; - update->dst_y = y; - update->width = width; - update->height = height; - - /* Add to layer queue */ - __guac_layer_add_update(layer, update); - -} - -void guac_layer_rect(guac_layer* layer, guac_composite_mode_t mode, - int x, int y, int width, int height, - int r, int g, int b, int a) { - - /* Allocate update */ - guac_layer_update* update = (guac_layer_update*) malloc(sizeof(guac_layer_update)); - - /* Set parameters of update */ - update->type = GUAC_LAYER_UPDATE_RECT; - update->mode = mode; - update->src_red = r; - update->src_green = g; - update->src_blue = b; - update->src_alpha = a; - update->dst_x = x; - update->dst_y = y; - update->width = width; - update->height = height; - - /* Add to layer queue */ - __guac_layer_add_update(layer, update); - -} - -int __guac_layer_update_intersects( - const guac_layer_update* update1, const guac_layer_update* update2) { - - /* If update1 X is within width of update2 - or update2 X is within width of update1 */ - if ((update1->dst_x >= update2->dst_x && update1->dst_x < update2->dst_x + update2->width) - || (update2->dst_x >= update1->dst_x && update2->dst_x < update1->dst_x + update2->width)) { - - /* If update1 Y is within height of update2 - or update2 Y is within height of update1 */ - if ((update1->dst_y >= update2->dst_y && update1->dst_y < update2->dst_y + update2->height) - || (update2->dst_y >= update1->dst_y && update2->dst_y < update1->dst_y + update2->height)) { - - /* Register instersection */ - return 1; - - } - - } - - /* Otherwise, no intersection */ - return 0; - -} - -int guac_layer_flush(guac_layer* layer, GUACIO* io) { - - while (layer->update_queue_head != NULL) { - - guac_layer_update* later_update; - int update_merged = 0; - - /* Get next update, update queue head. */ - guac_layer_update* update = layer->update_queue_head; - layer->update_queue_head = update->next; - - /* Send instruction appropriate for update type */ - switch (update->type) { - - /* "png" instruction */ - case GUAC_LAYER_UPDATE_PNG: - - /* Decide whether or not to send */ - later_update = update->next; - while (later_update != NULL) { - - /* If destination rectangles intersect */ - if (__guac_layer_update_intersects(update, later_update)) { - - cairo_surface_t* merged_surface; - cairo_t* cairo; - int merged_x, merged_y, merged_width, merged_height; - - /* Cannot combine anything if intersection with non-PNG */ - if (later_update->type != GUAC_LAYER_UPDATE_PNG) - break; - - /* Cannot combine if modes differ */ - if (later_update->mode != update->mode) - break; - - /* For now, only combine for GUAC_COMP_OVER */ - if (later_update->mode != GUAC_COMP_OVER) - break; - - /* Calculate merged dimensions */ - merged_x = MIN(update->dst_x, later_update->dst_x); - merged_y = MIN(update->dst_y, later_update->dst_y); - - merged_width = MAX( - update->dst_x + update->width, - later_update->dst_x + later_update->width - ) - merged_x; - - merged_height = MAX( - update->dst_y + update->height, - later_update->dst_y + later_update->height - ) - merged_y; - - /* Create surface for merging */ - merged_surface = cairo_image_surface_create( - CAIRO_FORMAT_ARGB32, merged_width, merged_height); - - /* Get drawing context */ - cairo = cairo_create(merged_surface); - - /* Draw first update within merged surface */ - cairo_set_source_surface(cairo, - update->src_image, - update->dst_x - merged_x, - update->dst_y - merged_y); - - cairo_rectangle(cairo, - update->dst_x - merged_x, - update->dst_y - merged_y, - update->width, - update->height); - - cairo_fill(cairo); - - /* Draw second update within merged surface */ - cairo_set_source_surface(cairo, - later_update->src_image, - later_update->dst_x - merged_x, - later_update->dst_y - merged_y); - - cairo_rectangle(cairo, - later_update->dst_x - merged_x, - later_update->dst_y - merged_y, - later_update->width, - later_update->height); - - cairo_fill(cairo); - - /* Done drawing */ - cairo_destroy(cairo); - - /* Alter update dimensions */ - later_update->dst_x = merged_x; - later_update->dst_y = merged_y; - later_update->width = merged_width; - later_update->height = merged_height; - - /* Alter update to include merged data*/ - cairo_surface_destroy(later_update->src_image); - later_update->src_image = merged_surface; - - update_merged = 1; - break; - - } - - /* Get next update */ - later_update = later_update->next; - - } - - /* Send instruction if update was not merged */ - if (!update_merged) { - if (guac_send_png(io, - update->mode, - update->dst_layer, - update->dst_x, - update->dst_y, - update->src_image - )) { - cairo_surface_destroy(update->src_image); - free(update); - return -1; - } - } - - cairo_surface_destroy(update->src_image); - break; - - /* "copy" instruction */ - case GUAC_LAYER_UPDATE_COPY: - - if (guac_send_copy(io, - update->src_layer, - update->src_x, - update->src_y, - update->width, - update->height, - update->mode, - update->dst_layer, - update->dst_x, - update->dst_y - )) { - free(update); - return -1; - } - - break; - - /* "clip" instruction */ - case GUAC_LAYER_UPDATE_CLIP: - - if (guac_send_clip(io, - update->dst_layer, - update->dst_x, - update->dst_y, - update->width, - update->height - )) { - free(update); - return -1; - } - - break; - - /* "rect" instruction */ - case GUAC_LAYER_UPDATE_RECT: - - if (guac_send_rect(io, - update->mode, - update->dst_layer, - update->dst_x, - update->dst_y, - update->width, - update->height, - update->src_red, - update->src_green, - update->src_blue, - update->src_alpha - )) { - free(update); - return -1; - } - - break; - - } /* end of switch update type */ - - /* Free update */ - free(update); - - } - - /* Queue is now empty */ - layer->update_queue_tail = NULL; - - return 0; -} - From a48f43ef6bda6f98db03378e8470ed1dc4537ccf Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 25 Oct 2011 22:07:30 -0700 Subject: [PATCH 092/330] Removed old guac_layer_* queue functions. --- libguac/include/protocol.h | 84 -------------------------------------- 1 file changed, 84 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index b680fa5e..ba4c04c6 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -310,90 +310,6 @@ int guac_send_png(GUACIO* io, guac_composite_mode_t mode, */ int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface); -/** - * Queues a png instruction in the given layer. The layer may combine - * and re-order multiple instructions into more efficient instructions - * providing the end result is the same image. - * - * @param layer The destination layer. - * @param mode The composite mode to use. - * @param x The destination X coordinate. - * @param y The destination Y coordinate. - * @param surface A cairo surface containing the image data to send. - */ -void guac_layer_png(guac_layer* layer, guac_composite_mode_t mode, - int x, int y, cairo_surface_t* surface); - -/** - * Queues a copy instruction in a given layer. The layer may combine - * and re-order multiple instructions into more efficient instructions - * providing the end result is the same image. - * - * @param layer The destination layer. - * @param mode The composite mode to use. - * @param srcl The source layer. - * @param srcx The X coordinate of the source rectangle. - * @param srcy The Y coordinate of the source rectangle. - * @param w The width of the source rectangle. - * @param h The height of the source rectangle. - * @param dstx The X coordinate of the destination, where the source rectangle - * should be copied. - * @param dsty The Y coordinate of the destination, where the source rectangle - * should be copied. - */ -void guac_layer_copy(guac_layer* layer, guac_composite_mode_t mode, - const guac_layer* srcl, int srcx, int srcy, int w, int h, - int dstx, int dsty); - -/** - * Queues a clip instruction in a given layer. The layer may combine - * and re-order multiple instructions into more efficient instructions - * providing the end result is the same image. - * - * @param layer The layer to set the clipping region of. - * @param x The X coordinate of the clipping rectangle. - * @param y The Y coordinate of the clipping rectangle. - * @param width The width of the clipping rectangle. - * @param height The height of the clipping rectangle. - */ -void guac_layer_clip(guac_layer* layer, - int x, int y, int width, int height); - -/** - * Queues a rect instruction in a given layer. The layer may combine - * and re-order multiple instructions into more efficient instructions - * providing the end result is the same image. - * - * @param layer The destination layer. - * @param mode The composite mode to use. - * @param x The X coordinate of the rectangle. - * @param y The Y coordinate of the rectangle. - * @param width The width of the rectangle. - * @param height The height of the rectangle. - * @param r The red component of the color of the rectangle. - * @param g The green component of the color of the rectangle. - * @param b The blue component of the color of the rectangle. - * @param a The alpha (transparency) component of the color of the rectangle. - */ -void guac_layer_rect(guac_layer* layer, guac_composite_mode_t mode, - int x, int y, int width, int height, - int r, int g, int b, int a); - -/** - * Flushes any queued instructions in the given layer, sending those - * instructions over the given GUACIO connection. These instructions - * may not be identical to the instructions originally queued; they - * may be re-ordered or combined providing the end result of executing - * all instructions sent by guac_flush() is identical to executing all - * previously queued instructions as specified and in order. - * - * @param layer The layer to flush. - * @param io The GUACIO connection to use. - * @return Zero on success, non-zero on error. - */ -int guac_layer_flush(guac_layer* layer, GUACIO* io); - - /** * Returns whether new instruction data is available on the given GUACIO * connection for parsing. From df02126676a5e633fa047476b52082a1fcef9428 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 3 Nov 2011 13:48:05 -0700 Subject: [PATCH 093/330] Removed guac_client_queue_*() and associated structures (out of scope). --- libguac/include/client.h | 211 ------------------------ libguac/src/client.c | 344 --------------------------------------- 2 files changed, 555 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index e29aca2d..533ac9f5 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -103,120 +103,6 @@ typedef int guac_client_clipboard_handler(guac_client* client, char* copied); */ typedef int guac_client_free_handler(guac_client* client); -typedef struct guac_client_update guac_client_update; - -/** - * The type of a layer update (png, copy, or rect, for - * example). - */ -typedef enum guac_client_update_type_t { - - GUAC_CLIENT_UPDATE_PNG, - GUAC_CLIENT_UPDATE_COPY, - GUAC_CLIENT_UPDATE_CLIP, - GUAC_CLIENT_UPDATE_RECT - -} guac_client_update_type_t; - -/** - * Represents an abstract graphical update or state change - * of a client, including dirty rectangle information. - */ -struct guac_client_update { - - /** - * The type of this update. Update type corresponds - * directly to the instruction that would be sent - * if the queue is flushed. - */ - guac_client_update_type_t type; - - /** - * The composite mode to use in this update. - */ - guac_composite_mode_t mode; - - /** - * The layer to retrieve image data from. - */ - const guac_layer* src_layer; - - /** - * The surface to retrieve image data from. - */ - cairo_surface_t* src_image; - - /** - * The red component of the source color. - */ - int src_red; - - /** - * The green component of the source color. - */ - int src_green; - - /** - * The blue component of the source color. - */ - int src_blue; - - /** - * The alpha component of the source color. - */ - int src_alpha; - - /** - * The X coordinage of the upper-left corner of the - * source rectangle. - */ - int src_x; - - /** - * The Y coordinage of the upper-left corner of the - * source rectangle. - */ - int src_y; - - /** - * The layer this update should affect. - */ - const guac_layer* dst_layer; - - /** - * The X coordinate of the upper-left corner of the - * destination rectangle. - */ - int dst_x; - - /** - * The Y coordinate of the upper-left corner of the - * destination rectangle. - */ - int dst_y; - - /** - * The width of the destination or source rectangle. - * The dimensions of the destination and source - * rectangles are always identical. - */ - int width; - - /** - * The height of the destination or source rectangle. - * The dimensions of the destination and source - * rectangles are always identical. - */ - int height; - - /** - * The next update in the update queue, if any. - */ - guac_client_update* next; - -}; - - /** * Possible current states of the Guacamole client. Currently, the only * two states are RUNNING and STOPPING. @@ -278,16 +164,6 @@ struct guac_client { */ guac_layer* all_layers; - /** - * The first element in this client's update queue. - */ - guac_client_update* update_queue_head; - - /** - * The last element in this client's update queue. - */ - guac_client_update* update_queue_tail; - /** * The time (in milliseconds) of receipt of the last sync message from * the client. @@ -497,93 +373,6 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); */ void guac_client_free_buffer(guac_client* client, guac_layer* layer); -/** - * Queues a png instruction in the given client. The client may combine - * and re-order multiple instructions into more efficient instructions - * providing the end result is the same image. - * - * @param client The proxy client which will queue the instruction. - * @param layer The destination layer. - * @param mode The composite mode to use. - * @param x The destination X coordinate. - * @param y The destination Y coordinate. - * @param surface A cairo surface containing the image data to send. - */ -void guac_client_queue_png(guac_client* client, guac_composite_mode_t mode, - const guac_layer* layer, int x, int y, cairo_surface_t* surface); - -/** - * Queues a copy instruction in a given client. The client may combine - * and re-order multiple instructions into more efficient instructions - * providing the end result is the same image. - * - * @param client The proxy client which will queue the instruction. - * @param srcl The source layer. - * @param srcx The X coordinate of the source rectangle. - * @param srcy The Y coordinate of the source rectangle. - * @param w The width of the source rectangle. - * @param h The height of the source rectangle. - * @param mode The composite mode to use. - * @param dstl The destination layer. - * @param dstx The X coordinate of the destination, where the source rectangle - * should be copied. - * @param dsty The Y coordinate of the destination, where the source rectangle - * should be copied. - */ -void guac_client_queue_copy(guac_client* client, - const guac_layer* srcl, int srcx, int srcy, int w, int h, - guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty); - -/** - * Queues a clip instruction in a given client. The client may combine - * and re-order multiple instructions into more efficient instructions - * providing the end result is the same image. - * - * @param client The proxy client which will queue the instruction. - * @param layer The layer to set the clipping region of. - * @param x The X coordinate of the clipping rectangle. - * @param y The Y coordinate of the clipping rectangle. - * @param width The width of the clipping rectangle. - * @param height The height of the clipping rectangle. - */ -void guac_client_queue_clip(guac_client* client, const guac_layer* layer, - int x, int y, int width, int height); - -/** - * Queues a rect instruction in a given layer. The layer may combine - * and re-order multiple instructions into more efficient instructions - * providing the end result is the same image. - * - * @param client The proxy client which will queue the instruction. - * @param mode The composite mode to use. - * @param layer The destination layer. - * @param x The X coordinate of the rectangle. - * @param y The Y coordinate of the rectangle. - * @param width The width of the rectangle. - * @param height The height of the rectangle. - * @param r The red component of the color of the rectangle. - * @param g The green component of the color of the rectangle. - * @param b The blue component of the color of the rectangle. - * @param a The alpha (transparency) component of the color of the rectangle. - */ -void guac_client_queue_rect(guac_client* client, - const guac_layer* layer, guac_composite_mode_t mode, - int x, int y, int width, int height, - int r, int g, int b, int a); - -/** - * Flushes any queued instructions in the given client, sending those - * instructions over the given GUACIO connection. These instructions - * may not be identical to the instructions originally queued; they - * may be re-ordered or combined providing the end result of executing - * all instructions sent by guac_client_queue_flush() is identical to - * executing all previously queued instructions as specified and in order. - * - * @param client The client to flush. - * @return Zero on success, non-zero on error. - */ -int guac_client_queue_flush(guac_client* client); - /** * The default Guacamole client layer, layer 0. */ diff --git a/libguac/src/client.c b/libguac/src/client.c index 6cd81028..e8d2cc83 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -72,9 +72,6 @@ guac_client* __guac_alloc_client(GUACIO* io) { client->all_layers = NULL; client->available_buffers = NULL; - client->update_queue_head = NULL; - client->update_queue_tail = NULL; - client->next_buffer_index = -1; return client; @@ -336,18 +333,6 @@ void guac_free_client(guac_client* client) { } - /* Free all queued updates */ - while (client->update_queue_head != NULL) { - - /* Get unflushed update, update queue head */ - guac_client_update* unflushed_update = client->update_queue_head; - client->update_queue_head = unflushed_update->next; - - /* Free update */ - free(unflushed_update); - - } - free(client); } @@ -498,332 +483,3 @@ int guac_client_handle_instruction(guac_client* client, guac_instruction* instru } -void __guac_client_queue_add_update(guac_client* client, guac_client_update* update) { - - /* Add update to queue tail */ - if (client->update_queue_tail != NULL) - client->update_queue_tail = client->update_queue_tail->next = update; - - /* Set both head and tail if necessary */ - else - client->update_queue_tail = client->update_queue_head = update; - - update->next = NULL; - -} - -void guac_client_queue_png(guac_client* client, guac_composite_mode_t mode, - const guac_layer* layer, int x, int y, cairo_surface_t* surface) { - - /* Allocate update */ - guac_client_update* update = (guac_client_update*) malloc(sizeof(guac_client_update)); - - /* Set parameters of update */ - update->type = GUAC_CLIENT_UPDATE_PNG; - update->mode = mode; - update->src_image = surface; - update->dst_layer = layer; - update->dst_x = x; - update->dst_y = y; - update->width = cairo_image_surface_get_width(surface); - update->height = cairo_image_surface_get_height(surface); - - /* Add to client queue */ - __guac_client_queue_add_update(client, update); - -} - -void guac_client_queue_copy(guac_client* client, - const guac_layer* srcl, int srcx, int srcy, int w, int h, - guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty) { - - /* Allocate update */ - guac_client_update* update = (guac_client_update*) malloc(sizeof(guac_client_update)); - - /* Set parameters of update */ - update->type = GUAC_CLIENT_UPDATE_COPY; - update->mode = mode; - update->src_layer = srcl; - update->src_x = srcx; - update->src_y = srcy; - update->width = w; - update->height = h; - update->dst_layer = dstl; - update->dst_x = dstx; - update->dst_y = dsty; - - /* Add to client queue */ - __guac_client_queue_add_update(client, update); - -} - -void guac_client_queue_clip(guac_client* client, const guac_layer* layer, - int x, int y, int width, int height) { - - /* Allocate update */ - guac_client_update* update = (guac_client_update*) malloc(sizeof(guac_client_update)); - - /* Set parameters of update */ - update->type = GUAC_CLIENT_UPDATE_CLIP; - update->dst_x = x; - update->dst_y = y; - update->width = width; - update->height = height; - - /* Add to client queue */ - __guac_client_queue_add_update(client, update); - -} - -void guac_client_queue_rect(guac_client* client, - const guac_layer* layer, guac_composite_mode_t mode, - int x, int y, int width, int height, - int r, int g, int b, int a) { - - /* Allocate update */ - guac_client_update* update = (guac_client_update*) malloc(sizeof(guac_client_update)); - - /* Set parameters of update */ - update->type = GUAC_CLIENT_UPDATE_RECT; - update->mode = mode; - update->src_red = r; - update->src_green = g; - update->src_blue = b; - update->src_alpha = a; - update->dst_x = x; - update->dst_y = y; - update->width = width; - update->height = height; - - /* Add to client queue */ - __guac_client_queue_add_update(client, update); - -} - -int __guac_client_update_intersects( - const guac_client_update* update1, const guac_client_update* update2) { - - /* If update1 X is within width of update2 - or update2 X is within width of update1 */ - if ((update1->dst_x >= update2->dst_x && update1->dst_x < update2->dst_x + update2->width) - || (update2->dst_x >= update1->dst_x && update2->dst_x < update1->dst_x + update2->width)) { - - /* If update1 Y is within height of update2 - or update2 Y is within height of update1 */ - if ((update1->dst_y >= update2->dst_y && update1->dst_y < update2->dst_y + update2->height) - || (update2->dst_y >= update1->dst_y && update2->dst_y < update1->dst_y + update2->height)) { - - /* Register instersection */ - return 1; - - } - - } - - /* Otherwise, no intersection */ - return 0; - -} - -int guac_client_queue_flush(guac_client* client) { - - GUACIO* io = client->io; - - while (client->update_queue_head != NULL) { - - guac_client_update* later_update; - int update_merged = 0; - - /* Get next update, update queue head. */ - guac_client_update* update = client->update_queue_head; - client->update_queue_head = update->next; - - /* Send instruction appropriate for update type */ - switch (update->type) { - - /* "png" instruction */ - case GUAC_CLIENT_UPDATE_PNG: - - /* Decide whether or not to send */ - later_update = update->next; - while (later_update != NULL) { - - /* If destination rectangles intersect */ - if (__guac_client_update_intersects(update, later_update)) { - - cairo_surface_t* merged_surface; - cairo_t* cairo; - int merged_x, merged_y, merged_width, merged_height; - - /* Cannot combine anything if intersection with non-PNG */ - if (later_update->type != GUAC_CLIENT_UPDATE_PNG) - break; - - /* Cannot combine if modes differ */ - if (later_update->mode != update->mode) - break; - - /* For now, only combine for GUAC_COMP_OVER */ - if (later_update->mode != GUAC_COMP_OVER) - break; - - /* Calculate merged dimensions */ - merged_x = MIN(update->dst_x, later_update->dst_x); - merged_y = MIN(update->dst_y, later_update->dst_y); - - merged_width = MAX( - update->dst_x + update->width, - later_update->dst_x + later_update->width - ) - merged_x; - - merged_height = MAX( - update->dst_y + update->height, - later_update->dst_y + later_update->height - ) - merged_y; - - /* Create surface for merging */ - merged_surface = cairo_image_surface_create( - CAIRO_FORMAT_ARGB32, merged_width, merged_height); - - /* Get drawing context */ - cairo = cairo_create(merged_surface); - - /* Draw first update within merged surface */ - cairo_set_source_surface(cairo, - update->src_image, - update->dst_x - merged_x, - update->dst_y - merged_y); - - cairo_rectangle(cairo, - update->dst_x - merged_x, - update->dst_y - merged_y, - update->width, - update->height); - - cairo_fill(cairo); - - /* Draw second update within merged surface */ - cairo_set_source_surface(cairo, - later_update->src_image, - later_update->dst_x - merged_x, - later_update->dst_y - merged_y); - - cairo_rectangle(cairo, - later_update->dst_x - merged_x, - later_update->dst_y - merged_y, - later_update->width, - later_update->height); - - cairo_fill(cairo); - - /* Done drawing */ - cairo_destroy(cairo); - - /* Alter update dimensions */ - later_update->dst_x = merged_x; - later_update->dst_y = merged_y; - later_update->width = merged_width; - later_update->height = merged_height; - - /* Alter update to include merged data*/ - cairo_surface_destroy(later_update->src_image); - later_update->src_image = merged_surface; - - update_merged = 1; - break; - - } - - /* Get next update */ - later_update = later_update->next; - - } - - /* Send instruction if update was not merged */ - if (!update_merged) { - if (guac_send_png(io, - update->mode, - update->dst_layer, - update->dst_x, - update->dst_y, - update->src_image - )) { - cairo_surface_destroy(update->src_image); - free(update); - return -1; - } - } - - cairo_surface_destroy(update->src_image); - break; - - /* "copy" instruction */ - case GUAC_CLIENT_UPDATE_COPY: - - if (guac_send_copy(io, - update->src_layer, - update->src_x, - update->src_y, - update->width, - update->height, - update->mode, - update->dst_layer, - update->dst_x, - update->dst_y - )) { - free(update); - return -1; - } - - break; - - /* "clip" instruction */ - case GUAC_CLIENT_UPDATE_CLIP: - - if (guac_send_clip(io, - update->dst_layer, - update->dst_x, - update->dst_y, - update->width, - update->height - )) { - free(update); - return -1; - } - - break; - - /* "rect" instruction */ - case GUAC_CLIENT_UPDATE_RECT: - - if (guac_send_rect(io, - update->mode, - update->dst_layer, - update->dst_x, - update->dst_y, - update->width, - update->height, - update->src_red, - update->src_green, - update->src_blue, - update->src_alpha - )) { - free(update); - return -1; - } - - break; - - } /* end of switch update type */ - - /* Free update */ - free(update); - - } - - /* Queue is now empty */ - client->update_queue_tail = NULL; - - return 0; -} - From 6cec48c20d08ceb2ad0e3b85c078639ad0dafe7a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 12 Nov 2011 16:51:42 -0800 Subject: [PATCH 094/330] Moved badly positioned include. --- libguac/src/client-handlers.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index 1221eec4..66e9d792 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -36,6 +36,7 @@ * ***** END LICENSE BLOCK ***** */ #include +#include #include "client.h" #include "protocol.h" @@ -53,7 +54,7 @@ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { }; /* Guacamole instruction handlers */ -#include + int __guac_handle_sync(guac_client* client, guac_instruction* instruction) { guac_timestamp_t timestamp = guac_parse_int(instruction->argv[0]); From cd82b43b5f2b7b433bcd11d367e56c5bb7eb04c1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 16 Nov 2011 00:11:05 -0800 Subject: [PATCH 095/330] Added base error.h definitions of status codes and prototype of string conversion function. --- libguac/include/error.h | 101 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 libguac/include/error.h diff --git a/libguac/include/error.h b/libguac/include/error.h new file mode 100644 index 00000000..46054106 --- /dev/null +++ b/libguac/include/error.h @@ -0,0 +1,101 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#ifndef _GUAC_ERROR_H +#define _GUAC_ERROR_H + +/** + * Provides functions and structures required for handling return values and + * errors. + * + * @file error.h + */ + +/** + * Return codes shared by all Guacamole functions which can fail. + */ +typedef enum guac_status_t { + + /** + * No errors occurred and the operation was successful. + */ + GUAC_STATUS_SUCCESS = 0, + + /** + * Insufficient memory to complete the operation. + */ + GUAC_STATUS_NO_MEMORY, + + /** + * The end of the input stream associated with the operation + * has been reached. + */ + GUAC_STATUS_NO_INPUT, + + /** + * A timeout occurred while reading from the input stream associated + * with the operation. + */ + GUAC_STATUS_INPUT_TIMEOUT, + + /** + * An error prevented the operation from writing to its associated + * output stream. + */ + GUAC_STATUS_OUTPUT_ERROR, + + /** + * The operation could not be performed because an invalid argument was + * given. + */ + GUAC_STATUS_BAD_ARGUMENT, + + /** + * The state of the associated system prevents an operation from being + * performed which would otherwise be allowed. + */ + GUAC_STATUS_BAD_STATE + +} guac_status_t; + +/** + * Returns a human-readable explanation of the status code given. + */ +const char* guac_status_string(guac_status_t status); + +#endif From af5f610e76b23c5cde005a254737c8bf7a317161 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 16 Nov 2011 00:23:38 -0800 Subject: [PATCH 096/330] Added error.h and error.c to Makefile.am, implemented string conversion function. --- libguac/Makefile.am | 4 +- libguac/src/error.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 libguac/src/error.c diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 194075c2..1eccf165 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -40,11 +40,11 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -Iinclude libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/client-handlers.h include/log.h include/thread.h +libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/client-handlers.h include/log.h include/thread.h include/error.h lib_LTLIBRARIES = libguac.la -libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c src/log.c src/thread.c +libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c src/log.c src/thread.c src/error.c libguac_la_LDFLAGS = -version-info 2:0:0 diff --git a/libguac/src/error.c b/libguac/src/error.c new file mode 100644 index 00000000..6b66b592 --- /dev/null +++ b/libguac/src/error.c @@ -0,0 +1,91 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "error.h" + + +/* Error strings */ + +const char* __GUAC_STATUS_SUCCESS_STR = "Success"; +const char* __GUAC_STATUS_NO_MEMORY_STR = "Insufficient memory"; +const char* __GUAC_STATUS_NO_INPUT_STR = "End of input stream"; +const char* __GUAC_STATUS_INPUT_TIMEOUT_STR = "Read timeout"; +const char* __GUAC_STATUS_OUTPUT_ERROR_STR = "Output error"; +const char* __GUAC_STATUS_BAD_ARGUMENT_STR = "Invalid argument"; +const char* __GUAC_STATUS_BAD_STATE_STR = "Illegal state"; +const char* __GUAC_STATUS_INVALID_STATUS_STR = "UNKNOWN STATUS CODE"; + + +const char* guac_status_string(guac_status_t status) { + + switch (status) { + + /* No error */ + case GUAC_STATUS_SUCCESS: + return __GUAC_STATUS_SUCCESS_STR; + + /* Out of memory */ + case GUAC_STATUS_NO_MEMORY: + return __GUAC_STATUS_NO_MEMORY_STR; + + /* End of input */ + case GUAC_STATUS_NO_INPUT: + return __GUAC_STATUS_NO_INPUT_STR; + + /* Input timeout */ + case GUAC_STATUS_INPUT_TIMEOUT: + return __GUAC_STATUS_INPUT_TIMEOUT_STR; + + /* Output error */ + case GUAC_STATUS_OUTPUT_ERROR: + return __GUAC_STATUS_OUTPUT_ERROR_STR; + + /* Invalid argument */ + case GUAC_STATUS_BAD_ARGUMENT: + return __GUAC_STATUS_BAD_ARGUMENT_STR; + + /* Illegal state */ + case GUAC_STATUS_BAD_STATE: + return __GUAC_STATUS_BAD_STATE_STR; + + default: + return __GUAC_STATUS_INVALID_STATUS_STR; + + } + +} + From d61335b18733c3ffc09141bc86232db3172adb7c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 16 Nov 2011 15:11:48 -0800 Subject: [PATCH 097/330] guac_status_t -> guac_status, mockup in client.h --- libguac/include/client.h | 23 ++++++++++++----------- libguac/include/error.h | 6 +++--- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 533ac9f5..059bb27e 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -41,6 +41,7 @@ #include "guacio.h" #include "protocol.h" +#include "error.h" /** * Provides functions and structures required for defining (and handling) a proxy client. @@ -80,28 +81,28 @@ typedef struct guac_client guac_client; * Handler for server messages (where "server" refers to the server that * the proxy client is connected to). */ -typedef int guac_client_handle_messages(guac_client* client); +typedef guac_status guac_client_handle_messages(guac_client* client); /** * Handler for Guacamole mouse events. */ -typedef int guac_client_mouse_handler(guac_client* client, int x, int y, int button_mask); +typedef guac_status guac_client_mouse_handler(guac_client* client, int x, int y, int button_mask); /** * Handler for Guacamole key events. */ -typedef int guac_client_key_handler(guac_client* client, int keysym, int pressed); +typedef guac_status guac_client_key_handler(guac_client* client, int keysym, int pressed); /** * Handler for Guacamole clipboard events. */ -typedef int guac_client_clipboard_handler(guac_client* client, char* copied); +typedef guac_status guac_client_clipboard_handler(guac_client* client, char* copied); /** * Handler for freeing up any extra data allocated by the client * implementation. */ -typedef int guac_client_free_handler(guac_client* client); +typedef guac_status guac_client_free_handler(guac_client* client); /** * Possible current states of the Guacamole client. Currently, the only @@ -295,7 +296,7 @@ struct guac_client { /** * Handler which should initialize the given guac_client. */ -typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); +typedef guac_status guac_client_init_handler(guac_client* client, int argc, char** argv); /** * Initialize and return a new guac_client. The pluggable client will be chosen based on @@ -315,14 +316,14 @@ guac_client* guac_get_client(int client_fd); * occurs during startup. Note that this function will still return * zero if an error occurs while the client is running. */ -int guac_start_client(guac_client* client); +guac_status guac_start_client(guac_client* client); /** * Free all resources associated with the given client. * * @param client The proxy client to free all reasources of. */ -void guac_free_client(guac_client* client); +guac_status guac_free_client(guac_client* client); /** * Call the appropriate handler defined by the given client for the given @@ -334,7 +335,7 @@ void guac_free_client(guac_client* client); * @param instruction The instruction to pass to the proxy client via the * appropriate handler. */ -int guac_client_handle_instruction(guac_client* client, guac_instruction* instruction); +guac_status guac_client_handle_instruction(guac_client* client, guac_instruction* instruction); /** * Signal the given client to stop. This will set the state of the given client @@ -343,7 +344,7 @@ int guac_client_handle_instruction(guac_client* client, guac_instruction* instru * * @param client The proxy client to stop. */ -void guac_client_stop(guac_client* client); +guac_status guac_client_stop(guac_client* client); /** * Allocates a new buffer (invisible layer). An arbitrary index is @@ -371,7 +372,7 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); * @param client The proxy client to return the buffer to. * @param layer The buffer to return to the pool of available buffers. */ -void guac_client_free_buffer(guac_client* client, guac_layer* layer); +guac_status guac_client_free_buffer(guac_client* client, guac_layer* layer); /** * The default Guacamole client layer, layer 0. diff --git a/libguac/include/error.h b/libguac/include/error.h index 46054106..06da4a8f 100644 --- a/libguac/include/error.h +++ b/libguac/include/error.h @@ -49,7 +49,7 @@ /** * Return codes shared by all Guacamole functions which can fail. */ -typedef enum guac_status_t { +typedef enum guac_status { /** * No errors occurred and the operation was successful. @@ -91,11 +91,11 @@ typedef enum guac_status_t { */ GUAC_STATUS_BAD_STATE -} guac_status_t; +} guac_status; /** * Returns a human-readable explanation of the status code given. */ -const char* guac_status_string(guac_status_t status); +const char* guac_status_string(guac_status status); #endif From 4d6218560f65b2fbebe20e377766a502375ee420 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 16 Nov 2011 15:43:28 -0800 Subject: [PATCH 098/330] Removed inconsistent _t suffix from types. --- libguac/include/client.h | 4 ++-- libguac/include/protocol.h | 16 ++++++++-------- libguac/include/thread.h | 8 ++++---- libguac/src/client-handlers.c | 2 +- libguac/src/client.c | 6 +++--- libguac/src/protocol.c | 14 +++++++------- libguac/src/thread.c | 6 +++--- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 059bb27e..3483ce01 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -169,13 +169,13 @@ struct guac_client { * The time (in milliseconds) of receipt of the last sync message from * the client. */ - guac_timestamp_t last_received_timestamp; + guac_timestamp last_received_timestamp; /** * The time (in milliseconds) that the last sync message was sent to the * client. */ - guac_timestamp_t last_sent_timestamp; + guac_timestamp last_sent_timestamp; /** * Reference to dlopen'd client plugin. diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index ba4c04c6..5f73191f 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -64,13 +64,13 @@ */ #define GUAC_USEC_TIMEOUT (GUAC_TIMEOUT*1000) -typedef int64_t guac_timestamp_t; +typedef int64_t guac_timestamp; /** * Composite modes used by Guacamole draw instructions. Each * composite mode maps to a unique channel mask integer. */ -typedef enum guac_composite_mode_t { +typedef enum guac_composite_mode { /* * A: Source where destination transparent = S n D' @@ -102,7 +102,7 @@ typedef enum guac_composite_mode_t { GUAC_COMP_RATOP = 0x9, /* 1001 */ GUAC_COMP_SRC = 0xC /* 1100 */ -} guac_composite_mode_t; +} guac_composite_mode; typedef struct guac_layer guac_layer; @@ -197,7 +197,7 @@ int guac_send_name(GUACIO* io, const char* name); * @param timestamp The current timestamp (in milliseconds). * @return Zero on success, non-zero on error. */ -int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp); +int guac_send_sync(GUACIO* io, guac_timestamp timestamp); /** * Sends an error instruction over the given GUACIO connection. @@ -246,7 +246,7 @@ int guac_send_size(GUACIO* io, int w, int h); */ int guac_send_copy(GUACIO* io, const guac_layer* srcl, int srcx, int srcy, int w, int h, - guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty); + guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty); /** * Sends a rect instruction over the given GUACIO connection. @@ -265,7 +265,7 @@ int guac_send_copy(GUACIO* io, * @return Zero on success, non-zero on error. */ int guac_send_rect(GUACIO* io, - guac_composite_mode_t mode, const guac_layer* layer, + guac_composite_mode mode, const guac_layer* layer, int x, int y, int width, int height, int r, int g, int b, int a); @@ -295,7 +295,7 @@ int guac_send_clip(GUACIO* io, const guac_layer* layer, * @param surface A cairo surface containing the image data to send. * @return Zero on success, non-zero on error. */ -int guac_send_png(GUACIO* io, guac_composite_mode_t mode, +int guac_send_png(GUACIO* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface); /** @@ -335,7 +335,7 @@ int guac_instructions_waiting(GUACIO* io); */ int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction); -guac_timestamp_t guac_current_timestamp(); +guac_timestamp guac_current_timestamp(); void guac_sleep(int millis); #endif diff --git a/libguac/include/thread.h b/libguac/include/thread.h index 33bd5d5d..f39c5682 100644 --- a/libguac/include/thread.h +++ b/libguac/include/thread.h @@ -47,17 +47,17 @@ #ifdef HAVE_LIBPTHREAD #include -typedef pthread_t guac_thread_t; +typedef pthread_t guac_thread; #elif defined(__MINGW32__) #include #include -typedef HANDLE guac_thread_t; +typedef HANDLE guac_thread; #endif -int guac_thread_create(guac_thread_t* thread, void*(*function)(void*), void* data); -void guac_thread_join(guac_thread_t thread); +int guac_thread_create(guac_thread* thread, void*(*function)(void*), void* data); +void guac_thread_join(guac_thread thread); #endif diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index 66e9d792..91e533a2 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -56,7 +56,7 @@ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { /* Guacamole instruction handlers */ int __guac_handle_sync(guac_client* client, guac_instruction* instruction) { - guac_timestamp_t timestamp = guac_parse_int(instruction->argv[0]); + guac_timestamp timestamp = guac_parse_int(instruction->argv[0]); /* Error if timestamp is in future */ if (timestamp > client->last_sent_timestamp) diff --git a/libguac/src/client.c b/libguac/src/client.c index e8d2cc83..a1cafa18 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -342,13 +342,13 @@ void* __guac_client_output_thread(void* data) { guac_client* client = (guac_client*) data; GUACIO* io = client->io; - guac_timestamp_t last_ping_timestamp = guac_current_timestamp(); + guac_timestamp last_ping_timestamp = guac_current_timestamp(); /* Guacamole client output loop */ while (client->state == RUNNING) { /* Occasionally ping client with repeat of last sync */ - guac_timestamp_t timestamp = guac_current_timestamp(); + guac_timestamp timestamp = guac_current_timestamp(); if (timestamp - last_ping_timestamp > GUAC_SYNC_FREQUENCY) { last_ping_timestamp = timestamp; if ( @@ -444,7 +444,7 @@ void* __guac_client_input_thread(void* data) { int guac_start_client(guac_client* client) { - guac_thread_t input_thread, output_thread; + guac_thread input_thread, output_thread; if (guac_thread_create(&output_thread, __guac_client_output_thread, (void*) client)) { return -1; diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 9dfe74f7..89ead2f4 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -137,7 +137,7 @@ int guac_send_error(GUACIO* io, const char* error) { || guac_write_string(io, ";"); } -int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp) { +int guac_send_sync(GUACIO* io, guac_timestamp timestamp) { return guac_write_string(io, "4.sync,") @@ -148,7 +148,7 @@ int guac_send_sync(GUACIO* io, guac_timestamp_t timestamp) { int guac_send_copy(GUACIO* io, const guac_layer* srcl, int srcx, int srcy, int w, int h, - guac_composite_mode_t mode, const guac_layer* dstl, int dstx, int dsty) { + guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty) { return guac_write_string(io, "4.copy,") @@ -174,7 +174,7 @@ int guac_send_copy(GUACIO* io, } int guac_send_rect(GUACIO* io, - guac_composite_mode_t mode, const guac_layer* layer, + guac_composite_mode mode, const guac_layer* layer, int x, int y, int width, int height, int r, int g, int b, int a) { @@ -295,7 +295,7 @@ int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) { } -int guac_send_png(GUACIO* io, guac_composite_mode_t mode, +int guac_send_png(GUACIO* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface) { return @@ -475,7 +475,7 @@ int guac_instructions_waiting(GUACIO* io) { return guac_select(io, GUAC_USEC_TIMEOUT); } -guac_timestamp_t guac_current_timestamp() { +guac_timestamp guac_current_timestamp() { #ifdef HAVE_CLOCK_GETTIME @@ -485,7 +485,7 @@ guac_timestamp_t guac_current_timestamp() { clock_gettime(CLOCK_REALTIME, ¤t); /* Calculate milliseconds */ - return (guac_timestamp_t) current.tv_sec * 1000 + current.tv_nsec / 1000000; + return (guac_timestamp) current.tv_sec * 1000 + current.tv_nsec / 1000000; #else @@ -495,7 +495,7 @@ guac_timestamp_t guac_current_timestamp() { gettimeofday(¤t, NULL); /* Calculate milliseconds */ - return (guac_timestamp_t) current.tv_sec * 1000 + current.tv_usec / 1000; + return (guac_timestamp) current.tv_sec * 1000 + current.tv_usec / 1000; #endif diff --git a/libguac/src/thread.c b/libguac/src/thread.c index cacc7b08..ffa8a647 100644 --- a/libguac/src/thread.c +++ b/libguac/src/thread.c @@ -44,11 +44,11 @@ #include #endif -int guac_thread_create(guac_thread_t* thread, void*(*function)(void*), void* data) { +int guac_thread_create(guac_thread* thread, void*(*function)(void*), void* data) { #ifdef HAVE_LIBPTHREAD return pthread_create(thread, NULL, function, data); #elif defined(__MINGW32__) - *thread = (guac_thread_t) _beginthreadex(NULL, 0, + *thread = (guac_thread) _beginthreadex(NULL, 0, (unsigned(__stdcall*)(void*)) function, data, 0 /* Create running */, NULL); if (thread == 0) @@ -57,7 +57,7 @@ int guac_thread_create(guac_thread_t* thread, void*(*function)(void*), void* dat #endif } -void guac_thread_join(guac_thread_t thread) { +void guac_thread_join(guac_thread thread) { #ifdef HAVE_LIBPTHREAD pthread_join(thread, NULL); #elif defined(__MINGW32__) From 8ef7d724bb004cf933b72f6cbf8214e9a68ca326 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 19 Nov 2011 14:34:08 -0800 Subject: [PATCH 099/330] Refactor of prototypes, partial continuation of refactor into client. --- libguac/include/client-handlers.h | 13 ++++--- libguac/include/client.h | 16 +++++--- libguac/include/error.h | 6 +++ libguac/include/guacio.h | 12 +++--- libguac/include/protocol.h | 63 ++++++++++++++++--------------- libguac/src/client.c | 16 ++++---- libguac/src/error.c | 21 +++++++---- 7 files changed, 83 insertions(+), 64 deletions(-) diff --git a/libguac/include/client-handlers.h b/libguac/include/client-handlers.h index de7603ae..8ad48435 100644 --- a/libguac/include/client-handlers.h +++ b/libguac/include/client-handlers.h @@ -40,6 +40,7 @@ #include "client.h" #include "protocol.h" +#include "error.h" /** * Provides initial handler functions and a lookup structure for automatically @@ -52,7 +53,7 @@ /** * Internal handler for Guacamole instructions. */ -typedef int __guac_instruction_handler(guac_client* client, guac_instruction* copied); +typedef guac_status __guac_instruction_handler(guac_client* client, guac_instruction* copied); /** * Structure mapping an instruction opcode to an instruction handler. @@ -76,35 +77,35 @@ typedef struct __guac_instruction_handler_mapping { * is received, this handler will be called. Sync instructions are automatically * handled, thus there is no client handler for sync instruction. */ -int __guac_handle_sync(guac_client* client, guac_instruction* instruction); +guac_status __guac_handle_sync(guac_client* client, guac_instruction* instruction); /** * Internal initial handler for the mouse instruction. When a mouse instruction * is received, this handler will be called. The client's mouse handler will * be invoked if defined. */ -int __guac_handle_mouse(guac_client* client, guac_instruction* instruction); +guac_status __guac_handle_mouse(guac_client* client, guac_instruction* instruction); /** * Internal initial handler for the key instruction. When a key instruction * is received, this handler will be called. The client's key handler will * be invoked if defined. */ -int __guac_handle_key(guac_client* client, guac_instruction* instruction); +guac_status __guac_handle_key(guac_client* client, guac_instruction* instruction); /** * Internal initial handler for the clipboard instruction. When a clipboard instruction * is received, this handler will be called. The client's clipboard handler will * be invoked if defined. */ -int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction); +guac_status __guac_handle_clipboard(guac_client* client, guac_instruction* instruction); /** * Internal initial handler for the disconnect instruction. When a disconnect instruction * is received, this handler will be called. Disconnect instructions are automatically * handled, thus there is no client handler for disconnect instruction. */ -int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction); +guac_status __guac_handle_disconnect(guac_client* client, guac_instruction* instruction); /** * Instruction handler mapping table. This is a NULL-terminated array of diff --git a/libguac/include/client.h b/libguac/include/client.h index 3483ce01..3c3e5387 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -312,9 +312,10 @@ guac_client* guac_get_client(int client_fd); * Enter the main network message handling loop for the given client. * * @param client The proxy client to start handling messages of/for. - * @return Zero if the client successfully started, non-zero if an error - * occurs during startup. Note that this function will still return - * zero if an error occurs while the client is running. + * @return GUAC_STATUS_SUCCESS if the client successfully started, or any + * other status code if an error occurs during startup. Note that + * this function will still return GUAC_STATUS_SUCCESS + * if an error occurs while the client is running. */ guac_status guac_start_client(guac_client* client); @@ -323,7 +324,7 @@ guac_status guac_start_client(guac_client* client); * * @param client The proxy client to free all reasources of. */ -guac_status guac_free_client(guac_client* client); +void guac_free_client(guac_client* client); /** * Call the appropriate handler defined by the given client for the given @@ -334,6 +335,9 @@ guac_status guac_free_client(guac_client* client); * @param client The proxy client whose handlers should be called. * @param instruction The instruction to pass to the proxy client via the * appropriate handler. + * @return GUAC_STATUS_SUCCESS if no handler was defined or if the handler + * was called successfully, or any other status code if an error + * occurs while calling the defined handler. */ guac_status guac_client_handle_instruction(guac_client* client, guac_instruction* instruction); @@ -344,7 +348,7 @@ guac_status guac_client_handle_instruction(guac_client* client, guac_instruction * * @param client The proxy client to stop. */ -guac_status guac_client_stop(guac_client* client); +void guac_client_stop(guac_client* client); /** * Allocates a new buffer (invisible layer). An arbitrary index is @@ -372,7 +376,7 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); * @param client The proxy client to return the buffer to. * @param layer The buffer to return to the pool of available buffers. */ -guac_status guac_client_free_buffer(guac_client* client, guac_layer* layer); +void guac_client_free_buffer(guac_client* client, guac_layer* layer); /** * The default Guacamole client layer, layer 0. diff --git a/libguac/include/error.h b/libguac/include/error.h index 06da4a8f..2b897339 100644 --- a/libguac/include/error.h +++ b/libguac/include/error.h @@ -67,6 +67,12 @@ typedef enum guac_status { */ GUAC_STATUS_NO_INPUT, + /** + * No data could be read from an input stream, but data may be available + * if the operation is retried. + */ + GUAC_STATUS_INPUT_UNAVAILABLE, + /** * A timeout occurred while reading from the input stream associated * with the operation. diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index f0ee209d..c5ba5afb 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -151,7 +151,7 @@ int64_t guac_parse_int(const char* str); * @param i The unsigned int to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_int(GUACIO* io, int64_t i); +guac_status guac_write_int(GUACIO* io, int64_t i); /** * Writes the given string to the given GUACIO object. The data @@ -164,7 +164,7 @@ ssize_t guac_write_int(GUACIO* io, int64_t i); * @param str The string to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_string(GUACIO* io, const char* str); +guac_status guac_write_string(GUACIO* io, const char* str); /** * Writes the given binary data to the given GUACIO object as base64-encoded @@ -179,7 +179,7 @@ ssize_t guac_write_string(GUACIO* io, const char* str); * @param count The number of bytes to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count); +guac_status guac_write_base64(GUACIO* io, const void* buf, size_t count); /** * Flushes the base64 buffer, writing padding characters as necessary. @@ -187,7 +187,7 @@ ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count); * @param io The GUACIO object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ -ssize_t guac_flush_base64(GUACIO* io); +guac_status guac_flush_base64(GUACIO* io); /** * Flushes the write buffer. @@ -195,7 +195,7 @@ ssize_t guac_flush_base64(GUACIO* io); * @param io The GUACIO object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ -ssize_t guac_flush(GUACIO* io); +guac_status guac_flush(GUACIO* io); /** @@ -208,7 +208,7 @@ ssize_t guac_flush(GUACIO* io); * @return Positive on success, zero if the timeout elapsed and no data is * available, negative on error. */ -int guac_select(GUACIO* io, int usec_timeout); +guac_status guac_select(GUACIO* io, int usec_timeout); /** * Frees resources allocated to the given GUACIO object. Note that this diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 5f73191f..8ae52846 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -176,18 +176,18 @@ void guac_free_instruction(guac_instruction* instruction); * * @param io The GUACIO connection to use. * @param args The NULL-terminated array of argument names (strings). - * @return Zero on success, non-zero on error. + * @return GUAC_STATUS_SUCCESS on success, any other status code on error. */ -int guac_send_args(GUACIO* io, const char** name); +guac_status guac_send_args(GUACIO* io, const char** name); /** * Sends a name instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. * @param name The name to send within the name instruction. - * @return Zero on success, non-zero on error. + * @return GUAC_STATUS_SUCCESS on success, any other status code on error. */ -int guac_send_name(GUACIO* io, const char* name); +guac_status guac_send_name(GUACIO* io, const char* name); /** * Sends a sync instruction over the given GUACIO connection. The @@ -195,27 +195,27 @@ int guac_send_name(GUACIO* io, const char* name); * * @param io The GUACIO connection to use. * @param timestamp The current timestamp (in milliseconds). - * @return Zero on success, non-zero on error. + * @return GUAC_STATUS_SUCCESS on success, any other status code on error. */ -int guac_send_sync(GUACIO* io, guac_timestamp timestamp); +guac_status guac_send_sync(GUACIO* io, guac_timestamp timestamp); /** * Sends an error instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. * @param error The description associated with the error. - * @return Zero on success, non-zero on error. + * @return GUAC_STATUS_SUCCESS on success, any other status code on error. */ -int guac_send_error(GUACIO* io, const char* error); +guac_status guac_send_error(GUACIO* io, const char* error); /** * Sends a clipboard instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. * @param data The clipboard data to send. - * @return Zero on success, non-zero on error. + * @return GUAC_STATUS_SUCCESS on success, any other status code on error. */ -int guac_send_clipboard(GUACIO* io, const char* data); +guac_status guac_send_clipboard(GUACIO* io, const char* data); /** * Sends a size instruction over the given GUACIO connection. @@ -223,9 +223,9 @@ int guac_send_clipboard(GUACIO* io, const char* data); * @param io The GUACIO connection to use. * @param w The width of the display. * @param h The height of the display. - * @return Zero on success, non-zero on error. + * @return GUAC_STATUS_SUCCESS on success, any other status code on error. */ -int guac_send_size(GUACIO* io, int w, int h); +guac_status guac_send_size(GUACIO* io, int w, int h); /** * Sends a copy instruction over the given GUACIO connection. @@ -242,9 +242,9 @@ int guac_send_size(GUACIO* io, int w, int h); * should be copied. * @param dsty The Y coordinate of the destination, where the source rectangle * should be copied. - * @return Zero on success, non-zero on error. + * @return GUAC_STATUS_SUCCESS on success, any other status code on error. */ -int guac_send_copy(GUACIO* io, +guac_status guac_send_copy(GUACIO* io, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty); @@ -262,9 +262,9 @@ int guac_send_copy(GUACIO* io, * @param g The green component of the color of the rectangle. * @param b The blue component of the color of the rectangle. * @param a The alpha (transparency) component of the color of the rectangle. - * @return Zero on success, non-zero on error. + * @return GUAC_STATUS_SUCCESS on success, any other status code on error. */ -int guac_send_rect(GUACIO* io, +guac_status guac_send_rect(GUACIO* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, int width, int height, int r, int g, int b, int a); @@ -278,9 +278,9 @@ int guac_send_rect(GUACIO* io, * @param y The Y coordinate of the clipping rectangle. * @param width The width of the clipping rectangle. * @param height The height of the clipping rectangle. - * @return Zero on success, non-zero on error. + * @return GUAC_STATUS_SUCCESS on success, any other status code on error. */ -int guac_send_clip(GUACIO* io, const guac_layer* layer, +guac_status guac_send_clip(GUACIO* io, const guac_layer* layer, int x, int y, int width, int height); /** @@ -293,9 +293,9 @@ int guac_send_clip(GUACIO* io, const guac_layer* layer, * @param x The destination X coordinate. * @param y The destination Y coordinate. * @param surface A cairo surface containing the image data to send. - * @return Zero on success, non-zero on error. + * @return GUAC_STATUS_SUCCESS on success, any other status code on error. */ -int guac_send_png(GUACIO* io, guac_composite_mode mode, +guac_status guac_send_png(GUACIO* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface); /** @@ -306,19 +306,20 @@ int guac_send_png(GUACIO* io, guac_composite_mode mode, * @param x The X coordinate of the cursor hotspot. * @param y The Y coordinate of the cursor hotspot. * @param surface A cairo surface containing the image data to send. - * @return Zero on success, non-zero on error. + * @return GUAC_STATUS_SUCCESS on success, any other status code on error. */ -int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface); +guac_status guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface); /** * Returns whether new instruction data is available on the given GUACIO * connection for parsing. * * @param io The GUACIO connection to use. - * @return A positive value if data is available, negative on error, or - * zero if no data is currently available. + * @return GUAC_STATUS_SUCCESS if data is available, + * GUAC_STATUS_NO_INPUT if no data is currently available, + * or any other status code on error. */ -int guac_instructions_waiting(GUACIO* io); +guac_status guac_instructions_waiting(GUACIO* io); /** * Reads a single instruction from the given GUACIO connection. @@ -327,13 +328,13 @@ int guac_instructions_waiting(GUACIO* io); * @param parsed_instruction A pointer to a guac_instruction structure which * will be populated with data read from the given * GUACIO connection. - * @return A positive value if data was successfully read, negative on - * error, or zero if the instruction could not be read completely - * because GUAC_TIMEOUT elapsed, in which case subsequent calls to - * guac_read_instruction() will return the parsed instruction once - * enough data is available. + * @return GUAC_STATUS_SUCCESS if data was successfully read, + * GUAC_STATUS_INPUT_UNAVAILABLE if the instruction could not be read + * completely because GUAC_TIMEOUT elapsed, in which case subsequent + * calls to guac_read_instruction() will return the parsed instruction + * once enough data is available, or any other status code on error. */ -int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction); +guac_status guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction); guac_timestamp guac_current_timestamp(); void guac_sleep(int millis); diff --git a/libguac/src/client.c b/libguac/src/client.c index a1cafa18..ba5a2d4d 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -161,26 +161,22 @@ guac_client* guac_get_client(int client_fd) { /* Wait for data until timeout */ result = guac_instructions_waiting(io); - if (result == 0) { + if (result == GUAC_STATUS_TIMEOUT) { guac_send_error(io, "Select timeout."); guac_close(io); return NULL; } /* If error occurs while waiting, exit with failure */ - if (result < 0) { + if (result != GUAC_STATUS_SUCCESS) { guac_close(io); return NULL; } result = guac_read_instruction(io, &instruction); - if (result < 0) { - guac_close(io); - return NULL; - } /* Select instruction read */ - if (result > 0) { + if (result == GUAC_STATUS_SUCCESS) { if (strcmp(instruction.opcode, "select") == 0) { @@ -247,6 +243,12 @@ guac_client* guac_get_client(int client_fd) { guac_free_instruction_data(&instruction); } + /* Give up on any legitimate error */ + else if (result != GUAC_STATUS_INPUT_UNAVAILABLE) { + guac_close(io); + return NULL; + } + } /* Wait for connect instruction */ diff --git a/libguac/src/error.c b/libguac/src/error.c index 6b66b592..310a7377 100644 --- a/libguac/src/error.c +++ b/libguac/src/error.c @@ -40,14 +40,15 @@ /* Error strings */ -const char* __GUAC_STATUS_SUCCESS_STR = "Success"; -const char* __GUAC_STATUS_NO_MEMORY_STR = "Insufficient memory"; -const char* __GUAC_STATUS_NO_INPUT_STR = "End of input stream"; -const char* __GUAC_STATUS_INPUT_TIMEOUT_STR = "Read timeout"; -const char* __GUAC_STATUS_OUTPUT_ERROR_STR = "Output error"; -const char* __GUAC_STATUS_BAD_ARGUMENT_STR = "Invalid argument"; -const char* __GUAC_STATUS_BAD_STATE_STR = "Illegal state"; -const char* __GUAC_STATUS_INVALID_STATUS_STR = "UNKNOWN STATUS CODE"; +const char* __GUAC_STATUS_SUCCESS_STR = "Success"; +const char* __GUAC_STATUS_NO_MEMORY_STR = "Insufficient memory"; +const char* __GUAC_STATUS_NO_INPUT_STR = "End of input stream"; +const char* __GUAC_STATUS_INPUT_UNAVAILABLE_STR = "Input unavailable"; +const char* __GUAC_STATUS_INPUT_TIMEOUT_STR = "Read timeout"; +const char* __GUAC_STATUS_OUTPUT_ERROR_STR = "Output error"; +const char* __GUAC_STATUS_BAD_ARGUMENT_STR = "Invalid argument"; +const char* __GUAC_STATUS_BAD_STATE_STR = "Illegal state"; +const char* __GUAC_STATUS_INVALID_STATUS_STR = "UNKNOWN STATUS CODE"; const char* guac_status_string(guac_status_t status) { @@ -66,6 +67,10 @@ const char* guac_status_string(guac_status_t status) { case GUAC_STATUS_NO_INPUT: return __GUAC_STATUS_NO_INPUT_STR; + /* Input unavailable */ + case GUAC_STATUS_INPUT_UNAVAILABLE: + return __GUAC_STATUS_INPUT_UNAVAILABLE_STR; + /* Input timeout */ case GUAC_STATUS_INPUT_TIMEOUT: return __GUAC_STATUS_INPUT_TIMEOUT_STR; From ca34a2f4a2edf6dfd59e71bed793e233abcaf844 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 20 Nov 2011 22:59:34 -0800 Subject: [PATCH 100/330] Added guac_error (thread-local) --- libguac/include/error.h | 4 +++ libguac/src/error.c | 62 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/libguac/include/error.h b/libguac/include/error.h index 2b897339..b6c569d6 100644 --- a/libguac/include/error.h +++ b/libguac/include/error.h @@ -104,4 +104,8 @@ typedef enum guac_status { */ const char* guac_status_string(guac_status status); +#define guac_error (*__guac_error()) + +guac_status* __guac_error(); + #endif diff --git a/libguac/src/error.c b/libguac/src/error.c index 310a7377..c48204fa 100644 --- a/libguac/src/error.c +++ b/libguac/src/error.c @@ -35,8 +35,13 @@ * * ***** END LICENSE BLOCK ***** */ -#include "error.h" +#include +#ifdef HAVE_LIBPTHREAD +#include +#endif + +#include "error.h" /* Error strings */ @@ -51,7 +56,7 @@ const char* __GUAC_STATUS_BAD_STATE_STR = "Illegal state"; const char* __GUAC_STATUS_INVALID_STATUS_STR = "UNKNOWN STATUS CODE"; -const char* guac_status_string(guac_status_t status) { +const char* guac_status_string(guac_status status) { switch (status) { @@ -94,3 +99,56 @@ const char* guac_status_string(guac_status_t status) { } +#ifdef HAVE_LIBPTHREAD + +/* PThread implementation of __guac_error */ + +static pthread_key_t __guac_error_key; +static pthread_once_t __guac_error_key_init = PTHREAD_ONCE_INIT; + +static void __guac_free_error(void* status) { + + /* Free memory allocated to status variable */ + free(status); + +} + +static void __guac_alloc_error_key() { + + /* Create key, destroy any allocated variable on thread exit */ + pthread_key_create(&__guac_error_key, __guac_free_error); + +} + +guac_status* __guac_error() { + + /* Pointer for thread-local data */ + guac_status* status; + + /* Init error key, if not already initialized */ + pthread_once(&__guac_error_key_init, __guac_alloc_error_key); + + /* Retrieve thread-local status variable */ + status = (guac_status*) pthread_getspecific(__guac_error_key); + + /* Allocate thread-local status variable if not already allocated */ + if (status == NULL) { + status = malloc(sizeof(guac_status)); + pthread_setspecific(__guac_error_key, status); + } + + return status; + +} + +#else + +/* Default (not-threadsafe) implementation */ +static guac_status __guac_error_unsafe_storage; + +guac_status* __guac_error() { + return &__guac_error_unsafe_storage; +} + +#endif + From b50d89d8303e41954863f20cc8ee4787b3798ee3 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 20 Nov 2011 23:09:02 -0800 Subject: [PATCH 101/330] Revert "Refactor of prototypes, partial continuation of refactor into client." This reverts commit a7a4a126c2a670c78bef4bc34d8823f98754bc5c. --- libguac/include/client-handlers.h | 13 +++---- libguac/include/client.h | 16 +++----- libguac/include/error.h | 6 --- libguac/include/guacio.h | 12 +++--- libguac/include/protocol.h | 63 +++++++++++++++---------------- libguac/src/client.c | 16 ++++---- libguac/src/error.c | 21 ++++------- 7 files changed, 64 insertions(+), 83 deletions(-) diff --git a/libguac/include/client-handlers.h b/libguac/include/client-handlers.h index 8ad48435..de7603ae 100644 --- a/libguac/include/client-handlers.h +++ b/libguac/include/client-handlers.h @@ -40,7 +40,6 @@ #include "client.h" #include "protocol.h" -#include "error.h" /** * Provides initial handler functions and a lookup structure for automatically @@ -53,7 +52,7 @@ /** * Internal handler for Guacamole instructions. */ -typedef guac_status __guac_instruction_handler(guac_client* client, guac_instruction* copied); +typedef int __guac_instruction_handler(guac_client* client, guac_instruction* copied); /** * Structure mapping an instruction opcode to an instruction handler. @@ -77,35 +76,35 @@ typedef struct __guac_instruction_handler_mapping { * is received, this handler will be called. Sync instructions are automatically * handled, thus there is no client handler for sync instruction. */ -guac_status __guac_handle_sync(guac_client* client, guac_instruction* instruction); +int __guac_handle_sync(guac_client* client, guac_instruction* instruction); /** * Internal initial handler for the mouse instruction. When a mouse instruction * is received, this handler will be called. The client's mouse handler will * be invoked if defined. */ -guac_status __guac_handle_mouse(guac_client* client, guac_instruction* instruction); +int __guac_handle_mouse(guac_client* client, guac_instruction* instruction); /** * Internal initial handler for the key instruction. When a key instruction * is received, this handler will be called. The client's key handler will * be invoked if defined. */ -guac_status __guac_handle_key(guac_client* client, guac_instruction* instruction); +int __guac_handle_key(guac_client* client, guac_instruction* instruction); /** * Internal initial handler for the clipboard instruction. When a clipboard instruction * is received, this handler will be called. The client's clipboard handler will * be invoked if defined. */ -guac_status __guac_handle_clipboard(guac_client* client, guac_instruction* instruction); +int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction); /** * Internal initial handler for the disconnect instruction. When a disconnect instruction * is received, this handler will be called. Disconnect instructions are automatically * handled, thus there is no client handler for disconnect instruction. */ -guac_status __guac_handle_disconnect(guac_client* client, guac_instruction* instruction); +int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction); /** * Instruction handler mapping table. This is a NULL-terminated array of diff --git a/libguac/include/client.h b/libguac/include/client.h index 3c3e5387..3483ce01 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -312,10 +312,9 @@ guac_client* guac_get_client(int client_fd); * Enter the main network message handling loop for the given client. * * @param client The proxy client to start handling messages of/for. - * @return GUAC_STATUS_SUCCESS if the client successfully started, or any - * other status code if an error occurs during startup. Note that - * this function will still return GUAC_STATUS_SUCCESS - * if an error occurs while the client is running. + * @return Zero if the client successfully started, non-zero if an error + * occurs during startup. Note that this function will still return + * zero if an error occurs while the client is running. */ guac_status guac_start_client(guac_client* client); @@ -324,7 +323,7 @@ guac_status guac_start_client(guac_client* client); * * @param client The proxy client to free all reasources of. */ -void guac_free_client(guac_client* client); +guac_status guac_free_client(guac_client* client); /** * Call the appropriate handler defined by the given client for the given @@ -335,9 +334,6 @@ void guac_free_client(guac_client* client); * @param client The proxy client whose handlers should be called. * @param instruction The instruction to pass to the proxy client via the * appropriate handler. - * @return GUAC_STATUS_SUCCESS if no handler was defined or if the handler - * was called successfully, or any other status code if an error - * occurs while calling the defined handler. */ guac_status guac_client_handle_instruction(guac_client* client, guac_instruction* instruction); @@ -348,7 +344,7 @@ guac_status guac_client_handle_instruction(guac_client* client, guac_instruction * * @param client The proxy client to stop. */ -void guac_client_stop(guac_client* client); +guac_status guac_client_stop(guac_client* client); /** * Allocates a new buffer (invisible layer). An arbitrary index is @@ -376,7 +372,7 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); * @param client The proxy client to return the buffer to. * @param layer The buffer to return to the pool of available buffers. */ -void guac_client_free_buffer(guac_client* client, guac_layer* layer); +guac_status guac_client_free_buffer(guac_client* client, guac_layer* layer); /** * The default Guacamole client layer, layer 0. diff --git a/libguac/include/error.h b/libguac/include/error.h index b6c569d6..29ac594d 100644 --- a/libguac/include/error.h +++ b/libguac/include/error.h @@ -67,12 +67,6 @@ typedef enum guac_status { */ GUAC_STATUS_NO_INPUT, - /** - * No data could be read from an input stream, but data may be available - * if the operation is retried. - */ - GUAC_STATUS_INPUT_UNAVAILABLE, - /** * A timeout occurred while reading from the input stream associated * with the operation. diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index c5ba5afb..f0ee209d 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -151,7 +151,7 @@ int64_t guac_parse_int(const char* str); * @param i The unsigned int to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -guac_status guac_write_int(GUACIO* io, int64_t i); +ssize_t guac_write_int(GUACIO* io, int64_t i); /** * Writes the given string to the given GUACIO object. The data @@ -164,7 +164,7 @@ guac_status guac_write_int(GUACIO* io, int64_t i); * @param str The string to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -guac_status guac_write_string(GUACIO* io, const char* str); +ssize_t guac_write_string(GUACIO* io, const char* str); /** * Writes the given binary data to the given GUACIO object as base64-encoded @@ -179,7 +179,7 @@ guac_status guac_write_string(GUACIO* io, const char* str); * @param count The number of bytes to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -guac_status guac_write_base64(GUACIO* io, const void* buf, size_t count); +ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count); /** * Flushes the base64 buffer, writing padding characters as necessary. @@ -187,7 +187,7 @@ guac_status guac_write_base64(GUACIO* io, const void* buf, size_t count); * @param io The GUACIO object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ -guac_status guac_flush_base64(GUACIO* io); +ssize_t guac_flush_base64(GUACIO* io); /** * Flushes the write buffer. @@ -195,7 +195,7 @@ guac_status guac_flush_base64(GUACIO* io); * @param io The GUACIO object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ -guac_status guac_flush(GUACIO* io); +ssize_t guac_flush(GUACIO* io); /** @@ -208,7 +208,7 @@ guac_status guac_flush(GUACIO* io); * @return Positive on success, zero if the timeout elapsed and no data is * available, negative on error. */ -guac_status guac_select(GUACIO* io, int usec_timeout); +int guac_select(GUACIO* io, int usec_timeout); /** * Frees resources allocated to the given GUACIO object. Note that this diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 8ae52846..5f73191f 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -176,18 +176,18 @@ void guac_free_instruction(guac_instruction* instruction); * * @param io The GUACIO connection to use. * @param args The NULL-terminated array of argument names (strings). - * @return GUAC_STATUS_SUCCESS on success, any other status code on error. + * @return Zero on success, non-zero on error. */ -guac_status guac_send_args(GUACIO* io, const char** name); +int guac_send_args(GUACIO* io, const char** name); /** * Sends a name instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. * @param name The name to send within the name instruction. - * @return GUAC_STATUS_SUCCESS on success, any other status code on error. + * @return Zero on success, non-zero on error. */ -guac_status guac_send_name(GUACIO* io, const char* name); +int guac_send_name(GUACIO* io, const char* name); /** * Sends a sync instruction over the given GUACIO connection. The @@ -195,27 +195,27 @@ guac_status guac_send_name(GUACIO* io, const char* name); * * @param io The GUACIO connection to use. * @param timestamp The current timestamp (in milliseconds). - * @return GUAC_STATUS_SUCCESS on success, any other status code on error. + * @return Zero on success, non-zero on error. */ -guac_status guac_send_sync(GUACIO* io, guac_timestamp timestamp); +int guac_send_sync(GUACIO* io, guac_timestamp timestamp); /** * Sends an error instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. * @param error The description associated with the error. - * @return GUAC_STATUS_SUCCESS on success, any other status code on error. + * @return Zero on success, non-zero on error. */ -guac_status guac_send_error(GUACIO* io, const char* error); +int guac_send_error(GUACIO* io, const char* error); /** * Sends a clipboard instruction over the given GUACIO connection. * * @param io The GUACIO connection to use. * @param data The clipboard data to send. - * @return GUAC_STATUS_SUCCESS on success, any other status code on error. + * @return Zero on success, non-zero on error. */ -guac_status guac_send_clipboard(GUACIO* io, const char* data); +int guac_send_clipboard(GUACIO* io, const char* data); /** * Sends a size instruction over the given GUACIO connection. @@ -223,9 +223,9 @@ guac_status guac_send_clipboard(GUACIO* io, const char* data); * @param io The GUACIO connection to use. * @param w The width of the display. * @param h The height of the display. - * @return GUAC_STATUS_SUCCESS on success, any other status code on error. + * @return Zero on success, non-zero on error. */ -guac_status guac_send_size(GUACIO* io, int w, int h); +int guac_send_size(GUACIO* io, int w, int h); /** * Sends a copy instruction over the given GUACIO connection. @@ -242,9 +242,9 @@ guac_status guac_send_size(GUACIO* io, int w, int h); * should be copied. * @param dsty The Y coordinate of the destination, where the source rectangle * should be copied. - * @return GUAC_STATUS_SUCCESS on success, any other status code on error. + * @return Zero on success, non-zero on error. */ -guac_status guac_send_copy(GUACIO* io, +int guac_send_copy(GUACIO* io, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty); @@ -262,9 +262,9 @@ guac_status guac_send_copy(GUACIO* io, * @param g The green component of the color of the rectangle. * @param b The blue component of the color of the rectangle. * @param a The alpha (transparency) component of the color of the rectangle. - * @return GUAC_STATUS_SUCCESS on success, any other status code on error. + * @return Zero on success, non-zero on error. */ -guac_status guac_send_rect(GUACIO* io, +int guac_send_rect(GUACIO* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, int width, int height, int r, int g, int b, int a); @@ -278,9 +278,9 @@ guac_status guac_send_rect(GUACIO* io, * @param y The Y coordinate of the clipping rectangle. * @param width The width of the clipping rectangle. * @param height The height of the clipping rectangle. - * @return GUAC_STATUS_SUCCESS on success, any other status code on error. + * @return Zero on success, non-zero on error. */ -guac_status guac_send_clip(GUACIO* io, const guac_layer* layer, +int guac_send_clip(GUACIO* io, const guac_layer* layer, int x, int y, int width, int height); /** @@ -293,9 +293,9 @@ guac_status guac_send_clip(GUACIO* io, const guac_layer* layer, * @param x The destination X coordinate. * @param y The destination Y coordinate. * @param surface A cairo surface containing the image data to send. - * @return GUAC_STATUS_SUCCESS on success, any other status code on error. + * @return Zero on success, non-zero on error. */ -guac_status guac_send_png(GUACIO* io, guac_composite_mode mode, +int guac_send_png(GUACIO* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface); /** @@ -306,20 +306,19 @@ guac_status guac_send_png(GUACIO* io, guac_composite_mode mode, * @param x The X coordinate of the cursor hotspot. * @param y The Y coordinate of the cursor hotspot. * @param surface A cairo surface containing the image data to send. - * @return GUAC_STATUS_SUCCESS on success, any other status code on error. + * @return Zero on success, non-zero on error. */ -guac_status guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface); +int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface); /** * Returns whether new instruction data is available on the given GUACIO * connection for parsing. * * @param io The GUACIO connection to use. - * @return GUAC_STATUS_SUCCESS if data is available, - * GUAC_STATUS_NO_INPUT if no data is currently available, - * or any other status code on error. + * @return A positive value if data is available, negative on error, or + * zero if no data is currently available. */ -guac_status guac_instructions_waiting(GUACIO* io); +int guac_instructions_waiting(GUACIO* io); /** * Reads a single instruction from the given GUACIO connection. @@ -328,13 +327,13 @@ guac_status guac_instructions_waiting(GUACIO* io); * @param parsed_instruction A pointer to a guac_instruction structure which * will be populated with data read from the given * GUACIO connection. - * @return GUAC_STATUS_SUCCESS if data was successfully read, - * GUAC_STATUS_INPUT_UNAVAILABLE if the instruction could not be read - * completely because GUAC_TIMEOUT elapsed, in which case subsequent - * calls to guac_read_instruction() will return the parsed instruction - * once enough data is available, or any other status code on error. + * @return A positive value if data was successfully read, negative on + * error, or zero if the instruction could not be read completely + * because GUAC_TIMEOUT elapsed, in which case subsequent calls to + * guac_read_instruction() will return the parsed instruction once + * enough data is available. */ -guac_status guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction); +int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction); guac_timestamp guac_current_timestamp(); void guac_sleep(int millis); diff --git a/libguac/src/client.c b/libguac/src/client.c index ba5a2d4d..a1cafa18 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -161,22 +161,26 @@ guac_client* guac_get_client(int client_fd) { /* Wait for data until timeout */ result = guac_instructions_waiting(io); - if (result == GUAC_STATUS_TIMEOUT) { + if (result == 0) { guac_send_error(io, "Select timeout."); guac_close(io); return NULL; } /* If error occurs while waiting, exit with failure */ - if (result != GUAC_STATUS_SUCCESS) { + if (result < 0) { guac_close(io); return NULL; } result = guac_read_instruction(io, &instruction); + if (result < 0) { + guac_close(io); + return NULL; + } /* Select instruction read */ - if (result == GUAC_STATUS_SUCCESS) { + if (result > 0) { if (strcmp(instruction.opcode, "select") == 0) { @@ -243,12 +247,6 @@ guac_client* guac_get_client(int client_fd) { guac_free_instruction_data(&instruction); } - /* Give up on any legitimate error */ - else if (result != GUAC_STATUS_INPUT_UNAVAILABLE) { - guac_close(io); - return NULL; - } - } /* Wait for connect instruction */ diff --git a/libguac/src/error.c b/libguac/src/error.c index c48204fa..3ceedf43 100644 --- a/libguac/src/error.c +++ b/libguac/src/error.c @@ -45,15 +45,14 @@ /* Error strings */ -const char* __GUAC_STATUS_SUCCESS_STR = "Success"; -const char* __GUAC_STATUS_NO_MEMORY_STR = "Insufficient memory"; -const char* __GUAC_STATUS_NO_INPUT_STR = "End of input stream"; -const char* __GUAC_STATUS_INPUT_UNAVAILABLE_STR = "Input unavailable"; -const char* __GUAC_STATUS_INPUT_TIMEOUT_STR = "Read timeout"; -const char* __GUAC_STATUS_OUTPUT_ERROR_STR = "Output error"; -const char* __GUAC_STATUS_BAD_ARGUMENT_STR = "Invalid argument"; -const char* __GUAC_STATUS_BAD_STATE_STR = "Illegal state"; -const char* __GUAC_STATUS_INVALID_STATUS_STR = "UNKNOWN STATUS CODE"; +const char* __GUAC_STATUS_SUCCESS_STR = "Success"; +const char* __GUAC_STATUS_NO_MEMORY_STR = "Insufficient memory"; +const char* __GUAC_STATUS_NO_INPUT_STR = "End of input stream"; +const char* __GUAC_STATUS_INPUT_TIMEOUT_STR = "Read timeout"; +const char* __GUAC_STATUS_OUTPUT_ERROR_STR = "Output error"; +const char* __GUAC_STATUS_BAD_ARGUMENT_STR = "Invalid argument"; +const char* __GUAC_STATUS_BAD_STATE_STR = "Illegal state"; +const char* __GUAC_STATUS_INVALID_STATUS_STR = "UNKNOWN STATUS CODE"; const char* guac_status_string(guac_status status) { @@ -72,10 +71,6 @@ const char* guac_status_string(guac_status status) { case GUAC_STATUS_NO_INPUT: return __GUAC_STATUS_NO_INPUT_STR; - /* Input unavailable */ - case GUAC_STATUS_INPUT_UNAVAILABLE: - return __GUAC_STATUS_INPUT_UNAVAILABLE_STR; - /* Input timeout */ case GUAC_STATUS_INPUT_TIMEOUT: return __GUAC_STATUS_INPUT_TIMEOUT_STR; From d7b0c5085ee3d26298ba58692ab17c11cdf1e826 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 20 Nov 2011 23:14:20 -0800 Subject: [PATCH 102/330] Revert changes to client.h (mockup of guac_status refactor) --- libguac/include/client.h | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 3483ce01..38565f4c 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -41,7 +41,6 @@ #include "guacio.h" #include "protocol.h" -#include "error.h" /** * Provides functions and structures required for defining (and handling) a proxy client. @@ -81,28 +80,28 @@ typedef struct guac_client guac_client; * Handler for server messages (where "server" refers to the server that * the proxy client is connected to). */ -typedef guac_status guac_client_handle_messages(guac_client* client); +typedef int guac_client_handle_messages(guac_client* client); /** * Handler for Guacamole mouse events. */ -typedef guac_status guac_client_mouse_handler(guac_client* client, int x, int y, int button_mask); +typedef int guac_client_mouse_handler(guac_client* client, int x, int y, int button_mask); /** * Handler for Guacamole key events. */ -typedef guac_status guac_client_key_handler(guac_client* client, int keysym, int pressed); +typedef int guac_client_key_handler(guac_client* client, int keysym, int pressed); /** * Handler for Guacamole clipboard events. */ -typedef guac_status guac_client_clipboard_handler(guac_client* client, char* copied); +typedef int guac_client_clipboard_handler(guac_client* client, char* copied); /** * Handler for freeing up any extra data allocated by the client * implementation. */ -typedef guac_status guac_client_free_handler(guac_client* client); +typedef int guac_client_free_handler(guac_client* client); /** * Possible current states of the Guacamole client. Currently, the only @@ -296,7 +295,7 @@ struct guac_client { /** * Handler which should initialize the given guac_client. */ -typedef guac_status guac_client_init_handler(guac_client* client, int argc, char** argv); +typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); /** * Initialize and return a new guac_client. The pluggable client will be chosen based on @@ -316,14 +315,14 @@ guac_client* guac_get_client(int client_fd); * occurs during startup. Note that this function will still return * zero if an error occurs while the client is running. */ -guac_status guac_start_client(guac_client* client); +int guac_start_client(guac_client* client); /** * Free all resources associated with the given client. * * @param client The proxy client to free all reasources of. */ -guac_status guac_free_client(guac_client* client); +void guac_free_client(guac_client* client); /** * Call the appropriate handler defined by the given client for the given @@ -335,7 +334,7 @@ guac_status guac_free_client(guac_client* client); * @param instruction The instruction to pass to the proxy client via the * appropriate handler. */ -guac_status guac_client_handle_instruction(guac_client* client, guac_instruction* instruction); +int guac_client_handle_instruction(guac_client* client, guac_instruction* instruction); /** * Signal the given client to stop. This will set the state of the given client @@ -344,7 +343,7 @@ guac_status guac_client_handle_instruction(guac_client* client, guac_instruction * * @param client The proxy client to stop. */ -guac_status guac_client_stop(guac_client* client); +void guac_client_stop(guac_client* client); /** * Allocates a new buffer (invisible layer). An arbitrary index is @@ -372,7 +371,7 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); * @param client The proxy client to return the buffer to. * @param layer The buffer to return to the pool of available buffers. */ -guac_status guac_client_free_buffer(guac_client* client, guac_layer* layer); +void guac_client_free_buffer(guac_client* client, guac_layer* layer); /** * The default Guacamole client layer, layer 0. From 797c30de753ec7581958121bffb792df66c8562b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 21 Nov 2011 01:32:04 -0800 Subject: [PATCH 103/330] Added guac_error usage to guacio --- libguac/include/guacio.h | 21 ++++++++++++++++++++- libguac/src/guacio.c | 21 +++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index f0ee209d..9271c792 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -125,9 +125,13 @@ typedef struct GUACIO { * Allocates and initializes a new GUACIO object with the given open * file descriptor. * + * If an error occurs while allocating the GUACIO object, NULL is returned, + * and guac_error is set appropriately. + * * @param fd An open file descriptor that this GUACIO object should manage. * @return A newly allocated GUACIO object associated with the given - * file descriptor. + * file descriptor, or NULL if an error occurs while allocating + * the GUACIO object. */ GUACIO* guac_open(int fd); @@ -147,6 +151,9 @@ int64_t guac_parse_int(const char* str); * written may be buffered until the buffer is flushed automatically or * manually. * + * If an error occurs while writing, a non-zero value is returned, and + * guac_error is set appropriately. + * * @param io The GUACIO object to write to. * @param i The unsigned int to write. * @return Zero on success, or non-zero if an error occurs while writing. @@ -160,6 +167,9 @@ ssize_t guac_write_int(GUACIO* io, int64_t i); * internally by the Guacamole protocol (commas, semicolons, or * backslashes) it will need to be escaped. * + * If an error occurs while writing, a non-zero value is returned, and + * guac_error is set appropriately. + * * @param io The GUACIO object to write to. * @param str The string to write. * @return Zero on success, or non-zero if an error occurs while writing. @@ -174,6 +184,9 @@ ssize_t guac_write_string(GUACIO* io, const char* str); * be made before non-base64 writes (or writes of an independent block of * base64 data) can be made. * + * If an error occurs while writing, a non-zero value is returned, and + * guac_error is set appropriately. + * * @param io The GUACIO object to write to. * @param buf A buffer containing the data to write. * @param count The number of bytes to write. @@ -184,6 +197,9 @@ ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count); /** * Flushes the base64 buffer, writing padding characters as necessary. * + * If an error occurs while writing, a non-zero value is returned, and + * guac_error is set appropriately. + * * @param io The GUACIO object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ @@ -192,6 +208,9 @@ ssize_t guac_flush_base64(GUACIO* io); /** * Flushes the write buffer. * + * If an error occurs while writing, a non-zero value is returned, and + * guac_error is set appropriately. + * * @param io The GUACIO object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index 4d2979da..b59a157c 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -53,6 +53,7 @@ #include #include "guacio.h" +#include "error.h" char __GUACIO_BASE64_CHARACTERS[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', @@ -64,6 +65,13 @@ char __GUACIO_BASE64_CHARACTERS[64] = { GUACIO* guac_open(int fd) { GUACIO* io = malloc(sizeof(GUACIO)); + + /* If no memory available, return with error */ + if (io == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + return NULL; + } + io->ready = 0; io->written = 0; io->total_written = 0; @@ -72,6 +80,15 @@ GUACIO* guac_open(int fd) { /* Allocate instruction buffer */ io->instructionbuf_size = 1024; io->instructionbuf = malloc(io->instructionbuf_size); + + /* If no memory available, return with error */ + if (io->instructionbuf == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + free(io); + return NULL; + } + + /* Init members */ io->instructionbuf_used_length = 0; io->instructionbuf_parse_start = 0; io->instructionbuf_elementc = 0; @@ -99,6 +116,10 @@ ssize_t __guac_write(GUACIO* io, const char* buf, int count) { retval = write(io->fd, buf, count); #endif + /* Record errors in guac_error */ + if (retval < 0) + guac_error = GUAC_STATUS_OUTPUT_ERROR; + return retval; } From 40f773e7337e812d76cb82491d6f11cb69c3337b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 21 Nov 2011 01:37:16 -0800 Subject: [PATCH 104/330] Added documentation for guac_error --- libguac/include/error.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libguac/include/error.h b/libguac/include/error.h index 29ac594d..aee205fa 100644 --- a/libguac/include/error.h +++ b/libguac/include/error.h @@ -98,6 +98,14 @@ typedef enum guac_status { */ const char* guac_status_string(guac_status status); +/** + * Returns the status code associated with the error which occurred during the + * last function call. This value will only be set by functions documented to + * use it (most libguac functions), and is undefined if no error occurred. + * + * The storage of this value is thread-local. Assignment of a status code to + * guac_error in one thread will not affect its value in another thread. + */ #define guac_error (*__guac_error()) guac_status* __guac_error(); From 1b42db58e982ae5eeb2e8beda13ce3aad84504d7 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 21 Nov 2011 01:42:16 -0800 Subject: [PATCH 105/330] Added warning for non-threadsafe impl --- libguac/src/error.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libguac/src/error.c b/libguac/src/error.c index 3ceedf43..9f5a0fa2 100644 --- a/libguac/src/error.c +++ b/libguac/src/error.c @@ -145,5 +145,8 @@ guac_status* __guac_error() { return &__guac_error_unsafe_storage; } +/* Warn about threadsafety */ +#warn No threadsafe implementation of __guac_error exists for your platform, so a default non-threadsafe implementation has been used instead. This may lead to incorrect status codes being reported for failures. Please consider adding support for your platform, or filing a bug report with the Guacamole project. + #endif From dd356d4fe28b6b2fea91e44f4ae61cb4debc9aed Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 21 Nov 2011 02:05:05 -0800 Subject: [PATCH 106/330] Updated documentation of protocol.h --- libguac/include/protocol.h | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 5f73191f..a033e4b9 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -64,6 +64,9 @@ */ #define GUAC_USEC_TIMEOUT (GUAC_TIMEOUT*1000) +/** + * An arbitrary timestamp denoting a relative time value in milliseconds. + */ typedef int64_t guac_timestamp; /** @@ -174,6 +177,9 @@ void guac_free_instruction(guac_instruction* instruction); /** * Sends an args instruction over the given GUACIO connection. * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * * @param io The GUACIO connection to use. * @param args The NULL-terminated array of argument names (strings). * @return Zero on success, non-zero on error. @@ -193,6 +199,9 @@ int guac_send_name(GUACIO* io, const char* name); * Sends a sync instruction over the given GUACIO connection. The * current time in milliseconds should be passed in as the timestamp. * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * * @param io The GUACIO connection to use. * @param timestamp The current timestamp (in milliseconds). * @return Zero on success, non-zero on error. @@ -202,6 +211,9 @@ int guac_send_sync(GUACIO* io, guac_timestamp timestamp); /** * Sends an error instruction over the given GUACIO connection. * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * * @param io The GUACIO connection to use. * @param error The description associated with the error. * @return Zero on success, non-zero on error. @@ -211,6 +223,9 @@ int guac_send_error(GUACIO* io, const char* error); /** * Sends a clipboard instruction over the given GUACIO connection. * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * * @param io The GUACIO connection to use. * @param data The clipboard data to send. * @return Zero on success, non-zero on error. @@ -220,6 +235,9 @@ int guac_send_clipboard(GUACIO* io, const char* data); /** * Sends a size instruction over the given GUACIO connection. * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * * @param io The GUACIO connection to use. * @param w The width of the display. * @param h The height of the display. @@ -230,6 +248,9 @@ int guac_send_size(GUACIO* io, int w, int h); /** * Sends a copy instruction over the given GUACIO connection. * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * * @param io The GUACIO connection to use. * @param srcl The source layer. * @param srcx The X coordinate of the source rectangle. @@ -251,6 +272,9 @@ int guac_send_copy(GUACIO* io, /** * Sends a rect instruction over the given GUACIO connection. * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * * @param io The GUACIO connection to use. * @param mode The composite mode to use. * @param layer The destination layer. @@ -272,6 +296,9 @@ int guac_send_rect(GUACIO* io, /** * Sends a clip instruction over the given GUACIO connection. * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * * @param io The GUACIO connection to use. * @param layer The layer to set the clipping region of. * @param x The X coordinate of the clipping rectangle. @@ -287,6 +314,9 @@ int guac_send_clip(GUACIO* io, const guac_layer* layer, * Sends a png instruction over the given GUACIO connection. The PNG image data * given will be automatically base64-encoded for transmission. * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * * @param io The GUACIO connection to use. * @param mode The composite mode to use. * @param layer The destination layer. @@ -302,6 +332,9 @@ int guac_send_png(GUACIO* io, guac_composite_mode mode, * Sends a cursor instruction over the given GUACIO connection. The PNG image * data given will be automatically base64-encoded for transmission. * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * * @param io The GUACIO connection to use. * @param x The X coordinate of the cursor hotspot. * @param y The Y coordinate of the cursor hotspot. @@ -323,6 +356,9 @@ int guac_instructions_waiting(GUACIO* io); /** * Reads a single instruction from the given GUACIO connection. * + * If an error occurs reading the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * * @param io The GUACIO connection to use. * @param parsed_instruction A pointer to a guac_instruction structure which * will be populated with data read from the given @@ -335,7 +371,22 @@ int guac_instructions_waiting(GUACIO* io); */ int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction); +/** + * Returns an arbitrary timestamp. The difference between return values of any + * two calls is equal to the amount of time in milliseconds between those + * calls. The return value from a single call will not have any useful + * (or defined) meaning. + * + * @return An arbitrary millisecond timestamp. + */ guac_timestamp guac_current_timestamp(); + +/** + * Suspends execution of the current thread for the given number of + * milliseconds. + * + * @param millis The number of milliseconds to sleep. + */ void guac_sleep(int millis); #endif From 84254cfddf7da036377d3a10f22badefc9a5a339 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 22 Nov 2011 23:51:43 -0800 Subject: [PATCH 107/330] Removed daemon-specific functions --- libguac/include/client.h | 19 ------ libguac/src/client.c | 133 --------------------------------------- 2 files changed, 152 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 38565f4c..6a187761 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -307,16 +307,6 @@ typedef int guac_client_init_handler(guac_client* client, int argc, char** argv) */ guac_client* guac_get_client(int client_fd); -/** - * Enter the main network message handling loop for the given client. - * - * @param client The proxy client to start handling messages of/for. - * @return Zero if the client successfully started, non-zero if an error - * occurs during startup. Note that this function will still return - * zero if an error occurs while the client is running. - */ -int guac_start_client(guac_client* client); - /** * Free all resources associated with the given client. * @@ -336,15 +326,6 @@ void guac_free_client(guac_client* client); */ int guac_client_handle_instruction(guac_client* client, guac_instruction* instruction); -/** - * Signal the given client to stop. This will set the state of the given client - * to STOPPING, which signals the I/O threads to shutdown, and ultimately - * results in shutdown of the client. - * - * @param client The proxy client to stop. - */ -void guac_client_stop(guac_client* client); - /** * Allocates a new buffer (invisible layer). An arbitrary index is * automatically assigned if no existing buffer is available for use. diff --git a/libguac/src/client.c b/libguac/src/client.c index a1cafa18..5d27c0eb 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -303,10 +303,6 @@ guac_client* guac_get_client(int client_fd) { } -void guac_client_stop(guac_client* client) { - client->state = STOPPING; -} - void guac_free_client(guac_client* client) { if (client->free_handler) { @@ -336,135 +332,6 @@ void guac_free_client(guac_client* client) { free(client); } - -void* __guac_client_output_thread(void* data) { - - guac_client* client = (guac_client*) data; - GUACIO* io = client->io; - - guac_timestamp last_ping_timestamp = guac_current_timestamp(); - - /* Guacamole client output loop */ - while (client->state == RUNNING) { - - /* Occasionally ping client with repeat of last sync */ - guac_timestamp timestamp = guac_current_timestamp(); - if (timestamp - last_ping_timestamp > GUAC_SYNC_FREQUENCY) { - last_ping_timestamp = timestamp; - if ( - guac_send_sync(io, client->last_sent_timestamp) - || guac_flush(io) - ) { - guac_client_stop(client); - return NULL; - } - } - - /* Handle server messages */ - if (client->handle_messages) { - - /* Get previous GUACIO state */ - int last_total_written = io->total_written; - - /* Only handle messages if synced within threshold */ - if (client->last_sent_timestamp - client->last_received_timestamp - < GUAC_SYNC_THRESHOLD) { - - int retval = client->handle_messages(client); - if (retval) { - guac_log_error("Error handling server messages"); - guac_client_stop(client); - return NULL; - } - - /* If data was written during message handling */ - if (io->total_written != last_total_written) { - - /* Sleep as necessary */ - guac_sleep(GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY); - - /* Send sync instruction */ - client->last_sent_timestamp = guac_current_timestamp(); - if (guac_send_sync(io, client->last_sent_timestamp)) { - guac_client_stop(client); - return NULL; - } - - } - - if (guac_flush(io)) { - guac_client_stop(client); - return NULL; - } - - } - - /* If sync threshold exceeded, don't spin waiting for resync */ - else - guac_sleep(GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY); - - } - - /* If no message handler, just sleep until next sync ping */ - else - guac_sleep(GUAC_SYNC_FREQUENCY); - - } /* End of output loop */ - - guac_client_stop(client); - return NULL; - -} - -void* __guac_client_input_thread(void* data) { - - guac_client* client = (guac_client*) data; - GUACIO* io = client->io; - - guac_instruction instruction; - - /* Guacamole client input loop */ - while (client->state == RUNNING && guac_read_instruction(io, &instruction) > 0) { - - /* Call handler, stop on error */ - if (guac_client_handle_instruction(client, &instruction) < 0) { - guac_free_instruction_data(&instruction); - break; - } - - /* Free allocate instruction data */ - guac_free_instruction_data(&instruction); - - } - - guac_client_stop(client); - return NULL; - -} - -int guac_start_client(guac_client* client) { - - guac_thread input_thread, output_thread; - - if (guac_thread_create(&output_thread, __guac_client_output_thread, (void*) client)) { - return -1; - } - - if (guac_thread_create(&input_thread, __guac_client_input_thread, (void*) client)) { - guac_client_stop(client); - guac_thread_join(output_thread); - return -1; - } - - /* Wait for I/O threads */ - guac_thread_join(input_thread); - guac_thread_join(output_thread); - - /* Done */ - return 0; - -} - int guac_client_handle_instruction(guac_client* client, guac_instruction* instruction) { /* For each defined instruction */ From a932c2f1a064b9712b4bcc757057b9e63561de86 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 23 Nov 2011 00:22:12 -0800 Subject: [PATCH 108/330] Removed out-of-scope threads API. --- libguac/Makefile.am | 4 +-- libguac/include/thread.h | 63 ------------------------------------- libguac/src/client.c | 1 - libguac/src/thread.c | 67 ---------------------------------------- 4 files changed, 2 insertions(+), 133 deletions(-) delete mode 100644 libguac/include/thread.h delete mode 100644 libguac/src/thread.c diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 1eccf165..7db1ad03 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -40,11 +40,11 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -Iinclude libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/client-handlers.h include/log.h include/thread.h include/error.h +libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/client-handlers.h include/log.h include/error.h lib_LTLIBRARIES = libguac.la -libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c src/log.c src/thread.c src/error.c +libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c src/log.c src/error.c libguac_la_LDFLAGS = -version-info 2:0:0 diff --git a/libguac/include/thread.h b/libguac/include/thread.h deleted file mode 100644 index f39c5682..00000000 --- a/libguac/include/thread.h +++ /dev/null @@ -1,63 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef _GUAC_THREAD_H -#define _GUAC_THREAD_H - -/** - * Provides basic cross-platform threads. - * - * @file thread.h - */ - -#ifdef HAVE_LIBPTHREAD - -#include -typedef pthread_t guac_thread; - -#elif defined(__MINGW32__) - -#include -#include -typedef HANDLE guac_thread; - -#endif - -int guac_thread_create(guac_thread* thread, void*(*function)(void*), void* data); -void guac_thread_join(guac_thread thread); - -#endif diff --git a/libguac/src/client.c b/libguac/src/client.c index 5d27c0eb..572e62b5 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -40,7 +40,6 @@ #include #include -#include "thread.h" #include "log.h" #include "guacio.h" #include "protocol.h" diff --git a/libguac/src/thread.c b/libguac/src/thread.c deleted file mode 100644 index ffa8a647..00000000 --- a/libguac/src/thread.c +++ /dev/null @@ -1,67 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "thread.h" - -#ifdef HAVE_LIBPTHREAD -#include -#elif defined(__MINGW32__) -#include -#include -#endif - -int guac_thread_create(guac_thread* thread, void*(*function)(void*), void* data) { -#ifdef HAVE_LIBPTHREAD - return pthread_create(thread, NULL, function, data); -#elif defined(__MINGW32__) - *thread = (guac_thread) _beginthreadex(NULL, 0, - (unsigned(__stdcall*)(void*)) function, data, - 0 /* Create running */, NULL); - if (thread == 0) - return errno; - return 0; -#endif -} - -void guac_thread_join(guac_thread thread) { -#ifdef HAVE_LIBPTHREAD - pthread_join(thread, NULL); -#elif defined(__MINGW32__) - WaitForSingleObject(thread, INFINITE); -#endif -} - From 087ed54fc283704def58e3077e03b6e6a2a91b06 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 23 Nov 2011 00:43:30 -0800 Subject: [PATCH 109/330] Removed GUAC_*_TIMEOUT, added usec_timeout parameters to functions which need them, updated docs. --- libguac/include/client.h | 8 +++++--- libguac/include/protocol.h | 24 ++++++++---------------- libguac/src/client.c | 10 +++++----- libguac/src/protocol.c | 9 +++++---- 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 6a187761..c3f038b7 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -301,11 +301,13 @@ typedef int guac_client_init_handler(guac_client* client, int argc, char** argv) * Initialize and return a new guac_client. The pluggable client will be chosen based on * the first connect message received on the given file descriptor. * - * @param client_fd The file descriptor associated with the socket associated with the connection to the - * web-client tunnel. + * @param client_fd The file descriptor associated with the socket associated + * with the connection to the web-client tunnel. + * @param usec_timeout The maximum number of microseconds to wait for each + * instruction during the initial client handshake. * @return A pointer to the newly initialized client. */ -guac_client* guac_get_client(int client_fd); +guac_client* guac_get_client(int client_fd, int usec_timeout); /** * Free all resources associated with the given client. diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index a033e4b9..9339ef50 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -51,19 +51,6 @@ */ -/** - * The number of milliseconds to wait for messages in any phase before - * timing out and closing the connection with an error. - */ -#define GUAC_TIMEOUT 15000 - -/** - * The number of microseconds to wait for messages in any phase before - * timing out and closing the conncetion with an error. This is always - * equal to GUAC_TIMEOUT * 1000. - */ -#define GUAC_USEC_TIMEOUT (GUAC_TIMEOUT*1000) - /** * An arbitrary timestamp denoting a relative time value in milliseconds. */ @@ -348,10 +335,12 @@ int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface); * connection for parsing. * * @param io The GUACIO connection to use. + * @param usec_timeout The maximum number of microseconds to wait before + * giving up. * @return A positive value if data is available, negative on error, or * zero if no data is currently available. */ -int guac_instructions_waiting(GUACIO* io); +int guac_instructions_waiting(GUACIO* io, int usec_timeout); /** * Reads a single instruction from the given GUACIO connection. @@ -360,16 +349,19 @@ int guac_instructions_waiting(GUACIO* io); * returned, and guac_error is set appropriately. * * @param io The GUACIO connection to use. + * @param usec_timeout The maximum number of microseconds to wait before + * giving up. * @param parsed_instruction A pointer to a guac_instruction structure which * will be populated with data read from the given * GUACIO connection. * @return A positive value if data was successfully read, negative on * error, or zero if the instruction could not be read completely - * because GUAC_TIMEOUT elapsed, in which case subsequent calls to + * because the timeout elapsed, in which case subsequent calls to * guac_read_instruction() will return the parsed instruction once * enough data is available. */ -int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction); +int guac_read_instruction(GUACIO* io, int usec_timeout, + guac_instruction* parsed_instruction); /** * Returns an arbitrary timestamp. The difference between return values of any diff --git a/libguac/src/client.c b/libguac/src/client.c index 572e62b5..cfe59813 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -128,7 +128,7 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) { } -guac_client* guac_get_client(int client_fd) { +guac_client* guac_get_client(int client_fd, int usec_timeout) { guac_client* client; GUACIO* io = guac_open(client_fd); @@ -159,7 +159,7 @@ guac_client* guac_get_client(int client_fd) { int result; /* Wait for data until timeout */ - result = guac_instructions_waiting(io); + result = guac_instructions_waiting(io, usec_timeout); if (result == 0) { guac_send_error(io, "Select timeout."); guac_close(io); @@ -172,7 +172,7 @@ guac_client* guac_get_client(int client_fd) { return NULL; } - result = guac_read_instruction(io, &instruction); + result = guac_read_instruction(io, usec_timeout, &instruction); if (result < 0) { guac_close(io); return NULL; @@ -254,7 +254,7 @@ guac_client* guac_get_client(int client_fd) { int result; /* Wait for data until timeout */ - result = guac_instructions_waiting(io); + result = guac_instructions_waiting(io, usec_timeout); if (result == 0) { guac_send_error(io, "Connect timeout."); guac_close(io); @@ -267,7 +267,7 @@ guac_client* guac_get_client(int client_fd) { return NULL; } - result = guac_read_instruction(io, &instruction); + result = guac_read_instruction(io, usec_timeout, &instruction); if (result < 0) { guac_log_error("Error reading instruction while waiting for connect"); guac_close(io); diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 89ead2f4..fcebc1ce 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -356,7 +356,8 @@ int __guac_fill_instructionbuf(GUACIO* io) { } /* Returns new instruction if one exists, or NULL if no more instructions. */ -int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction) { +int guac_read_instruction(GUACIO* io, int usec_timeout, + guac_instruction* parsed_instruction) { int retval; int i = io->instructionbuf_parse_start; @@ -441,7 +442,7 @@ int guac_read_instruction(GUACIO* io, guac_instruction* parsed_instruction) { } /* No instruction yet? Get more data ... */ - retval = guac_select(io, GUAC_USEC_TIMEOUT); + retval = guac_select(io, usec_timeout); if (retval <= 0) return retval; @@ -467,12 +468,12 @@ void guac_free_instruction(guac_instruction* instruction) { } -int guac_instructions_waiting(GUACIO* io) { +int guac_instructions_waiting(GUACIO* io, int usec_timeout) { if (io->instructionbuf_used_length > 0) return 1; - return guac_select(io, GUAC_USEC_TIMEOUT); + return guac_select(io, usec_timeout); } guac_timestamp guac_current_timestamp() { From 2abc6d19b5f312df4450bbb46ae33a5bca7348ea Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 23 Nov 2011 15:03:40 -0800 Subject: [PATCH 110/330] Exclude private symbols from generated docs. --- libguac/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/Doxyfile b/libguac/Doxyfile index b8a2290e..0bfde8d4 100644 --- a/libguac/Doxyfile +++ b/libguac/Doxyfile @@ -625,7 +625,7 @@ EXCLUDE_PATTERNS = # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = __* # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see From eb11efc67e01080874dda5d414cd5ee5d8f21fc0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 23 Nov 2011 15:49:46 -0800 Subject: [PATCH 111/330] Removed unused defines. --- libguac/include/client.h | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index c3f038b7..8fddd851 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -48,32 +48,6 @@ * @file client.h */ -/** - * The time to allow between sync responses in milliseconds. If a sync - * instruction is sent to the client and no response is received within this - * timeframe, server messages will not be handled until a sync instruction is - * received from the client. - */ -#define GUAC_SYNC_THRESHOLD 500 - -/** - * The time to allow between server sync messages in milliseconds. A sync - * message from the server will be sent every GUAC_SYNC_FREQUENCY milliseconds. - * As this will induce a response from a client that is not malfunctioning, - * this is used to detect when a client has died. This must be set to a - * reasonable value to avoid clients being disconnected unnecessarily due - * to timeout. - */ -#define GUAC_SYNC_FREQUENCY 5000 - -/** - * The amount of time to wait after handling server messages. If a client - * plugin has a message handler, and sends instructions when server messages - * are being handled, there will be a pause of this many milliseconds before - * the next call to the message handler. - */ -#define GUAC_SERVER_MESSAGE_HANDLE_FREQUENCY 50 - typedef struct guac_client guac_client; /** From 97f7249e60c0e19fe5f485b8681c49ad2d243231 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 23 Nov 2011 16:08:33 -0800 Subject: [PATCH 112/330] Renamed private members, adding __ (double underscore) prefix. --- libguac/include/client.h | 8 ++-- libguac/include/guacio.h | 25 +++++------- libguac/include/protocol.h | 4 +- libguac/src/client.c | 54 ++++++++++++------------- libguac/src/guacio.c | 81 +++++++++++++++++--------------------- libguac/src/protocol.c | 46 +++++++++++----------- 6 files changed, 103 insertions(+), 115 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 8fddd851..fbe00a0b 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -124,19 +124,19 @@ struct guac_client { /** * The index of the next available buffer. */ - int next_buffer_index; + int __next_buffer_index; /** * The head pointer of the list of all available (allocated but not used) * buffers. */ - guac_layer* available_buffers; + guac_layer* __available_buffers; /** * The head pointer of the list of all allocated layers, regardless of use * status. */ - guac_layer* all_layers; + guac_layer* __all_layers; /** * The time (in milliseconds) of receipt of the last sync message from @@ -153,7 +153,7 @@ struct guac_client { /** * Reference to dlopen'd client plugin. */ - void* client_plugin_handle; + void* __client_plugin_handle; /** * Arbitrary reference to proxy client-specific data. Implementors of a diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index 9271c792..49055ba7 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -62,62 +62,57 @@ typedef struct GUACIO { /** * The number of bytes present in the base64 "ready" buffer. */ - int ready; + int __ready; /** * The base64 "ready" buffer. Once this buffer is filled, base64 data is * flushed to the main write buffer. */ - int ready_buf[3]; + int __ready_buf[3]; /** * The number of bytes currently in the main write buffer. */ - int written; - - /** - * The number of bytes written total, since this GUACIO was opened. - */ - int total_written; + int __written; /** * The main write buffer. Bytes written go here before being flushed * to the open file descriptor. */ - char out_buf[8192]; + char __out_buf[8192]; /** * The current location of parsing within the instruction buffer. */ - int instructionbuf_parse_start; + int __instructionbuf_parse_start; /** * The current size of the instruction buffer. */ - int instructionbuf_size; + int __instructionbuf_size; /** * The number of bytes currently in the instruction buffer. */ - int instructionbuf_used_length; + int __instructionbuf_used_length; /** * The instruction buffer. This is essentially the input buffer, * provided as a convenience to be used to buffer instructions until * those instructions are complete and ready to be parsed. */ - char* instructionbuf; + char* __instructionbuf; /** * The number of elements parsed so far. */ - int instructionbuf_elementc; + int __instructionbuf_elementc; /** * Array of pointers into the instruction buffer, where each pointer * points to the start of the corresponding element. */ - char* instructionbuf_elementv[64]; + char* __instructionbuf_elementv[64]; } GUACIO; diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 9339ef50..f8bdf0df 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -109,13 +109,13 @@ struct guac_layer { /** * The next allocated layer in the list of all layers. */ - guac_layer* next; + guac_layer* __next; /** * The next available (unused) layer in the list of * allocated but free'd layers. */ - guac_layer* next_available; + guac_layer* __next_available; }; diff --git a/libguac/src/client.c b/libguac/src/client.c index cfe59813..96817eba 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -51,8 +51,8 @@ guac_layer __GUAC_DEFAULT_LAYER = { .index = 0, - .next = NULL, - .next_available = NULL + .__next = NULL, + .__next_available = NULL }; const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; @@ -68,10 +68,10 @@ guac_client* __guac_alloc_client(GUACIO* io) { client->last_received_timestamp = client->last_sent_timestamp = guac_current_timestamp(); client->state = RUNNING; - client->all_layers = NULL; - client->available_buffers = NULL; + client->__all_layers = NULL; + client->__available_buffers = NULL; - client->next_buffer_index = -1; + client->__next_buffer_index = -1; return client; } @@ -83,9 +83,9 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index) { /* Init new layer */ allocd_layer = malloc(sizeof(guac_layer)); - /* Add to all_layers list */ - allocd_layer->next = client->all_layers; - client->all_layers = allocd_layer; + /* Add to __all_layers list */ + allocd_layer->__next = client->__all_layers; + client->__all_layers = allocd_layer; allocd_layer->index = index; return allocd_layer; @@ -97,22 +97,22 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { guac_layer* allocd_layer; /* If available layers, pop off first available buffer */ - if (client->available_buffers != NULL) { - allocd_layer = client->available_buffers; - client->available_buffers = client->available_buffers->next_available; - allocd_layer->next_available = NULL; + if (client->__available_buffers != NULL) { + allocd_layer = client->__available_buffers; + client->__available_buffers = client->__available_buffers->__next_available; + allocd_layer->__next_available = NULL; } - /* If no available buffer, allocate new buffer, add to all_layers list */ + /* If no available buffer, allocate new buffer, add to __all_layers list */ else { /* Init new layer */ allocd_layer = malloc(sizeof(guac_layer)); - allocd_layer->index = client->next_buffer_index--; + allocd_layer->index = client->__next_buffer_index--; - /* Add to all_layers list */ - allocd_layer->next = client->all_layers; - client->all_layers = allocd_layer; + /* Add to __all_layers list */ + allocd_layer->__next = client->__all_layers; + client->__all_layers = allocd_layer; } @@ -123,8 +123,8 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { void guac_client_free_buffer(guac_client* client, guac_layer* layer) { /* Add layer to pool of available buffers */ - layer->next_available = client->available_buffers; - client->available_buffers = layer; + layer->__next_available = client->__available_buffers; + client->__available_buffers = layer; } @@ -193,8 +193,8 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { client = __guac_alloc_client(io); /* Load client plugin */ - client->client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); - if (!(client->client_plugin_handle)) { + client->__client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); + if (!(client->__client_plugin_handle)) { guac_log_error("Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); guac_send_error(io, "Could not load server-side client plugin."); guac_flush(io); @@ -206,7 +206,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { dlerror(); /* Clear errors */ /* Get init function */ - alias.obj = dlsym(client->client_plugin_handle, "guac_client_init"); + alias.obj = dlsym(client->__client_plugin_handle, "guac_client_init"); if ((error = dlerror()) != NULL) { guac_log_error("Could not get guac_client_init in plugin: %s\n", error); @@ -218,7 +218,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { } /* Get usage strig */ - client_args = (const char**) dlsym(client->client_plugin_handle, "GUAC_CLIENT_ARGS"); + client_args = (const char**) dlsym(client->__client_plugin_handle, "GUAC_CLIENT_ARGS"); if ((error = dlerror()) != NULL) { guac_log_error("Could not get GUAC_CLIENT_ARGS in plugin: %s\n", error); @@ -312,16 +312,16 @@ void guac_free_client(guac_client* client) { guac_close(client->io); /* Unload client plugin */ - if (dlclose(client->client_plugin_handle)) { + if (dlclose(client->__client_plugin_handle)) { guac_log_error("Could not close client plugin while unloading client: %s", dlerror()); } /* Free all layers */ - while (client->all_layers != NULL) { + while (client->__all_layers != NULL) { /* Get layer, update layer pool head */ - guac_layer* layer = client->all_layers; - client->all_layers = layer->next; + guac_layer* layer = client->__all_layers; + client->__all_layers = layer->__next; /* Free layer */ free(layer); diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index b59a157c..da0b9e00 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -72,26 +72,25 @@ GUACIO* guac_open(int fd) { return NULL; } - io->ready = 0; - io->written = 0; - io->total_written = 0; + io->__ready = 0; + io->__written = 0; io->fd = fd; /* Allocate instruction buffer */ - io->instructionbuf_size = 1024; - io->instructionbuf = malloc(io->instructionbuf_size); + io->__instructionbuf_size = 1024; + io->__instructionbuf = malloc(io->__instructionbuf_size); /* If no memory available, return with error */ - if (io->instructionbuf == NULL) { + if (io->__instructionbuf == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; free(io); return NULL; } /* Init members */ - io->instructionbuf_used_length = 0; - io->instructionbuf_parse_start = 0; - io->instructionbuf_elementc = 0; + io->__instructionbuf_used_length = 0; + io->__instructionbuf_parse_start = 0; + io->__instructionbuf_elementc = 0; return io; @@ -99,7 +98,7 @@ GUACIO* guac_open(int fd) { void guac_close(GUACIO* io) { guac_flush(io); - free(io->instructionbuf); + free(io->__instructionbuf); free(io); } @@ -151,24 +150,23 @@ ssize_t guac_write_int(GUACIO* io, int64_t i) { ssize_t guac_write_string(GUACIO* io, const char* str) { - char* out_buf = io->out_buf; + char* __out_buf = io->__out_buf; int retval; for (; *str != '\0'; str++) { - out_buf[io->written++] = *str; - io->total_written++; + __out_buf[io->__written++] = *str; /* Flush when necessary, return on error */ - if (io->written > 8188 /* sizeof(out_buf) - 4 */) { + if (io->__written > 8188 /* sizeof(__out_buf) - 4 */) { - retval = __guac_write(io, out_buf, io->written); + retval = __guac_write(io, __out_buf, io->__written); if (retval < 0) return retval; - io->written = 0; + io->__written = 0; } } @@ -179,45 +177,40 @@ ssize_t guac_write_string(GUACIO* io, const char* str) { ssize_t __guac_write_base64_triplet(GUACIO* io, int a, int b, int c) { - char* out_buf = io->out_buf; + char* __out_buf = io->__out_buf; int retval; /* Byte 1 */ - out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[(a & 0xFC) >> 2]; /* [AAAAAA]AABBBB BBBBCC CCCCCC */ - io->total_written++; + __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[(a & 0xFC) >> 2]; /* [AAAAAA]AABBBB BBBBCC CCCCCC */ if (b >= 0) { - out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4) | ((b & 0xF0) >> 4)]; /* AAAAAA[AABBBB]BBBBCC CCCCCC */ - io->total_written++; + __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4) | ((b & 0xF0) >> 4)]; /* AAAAAA[AABBBB]BBBBCC CCCCCC */ if (c >= 0) { - out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)]; /* AAAAAA AABBBB[BBBBCC]CCCCCC */ - out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[c & 0x3F]; /* AAAAAA AABBBB BBBBCC[CCCCCC] */ - io->total_written += 2; + __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)]; /* AAAAAA AABBBB[BBBBCC]CCCCCC */ + __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[c & 0x3F]; /* AAAAAA AABBBB BBBBCC[CCCCCC] */ } else { - out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2)]; /* AAAAAA AABBBB[BBBB--]------ */ - out_buf[io->written++] = '='; /* AAAAAA AABBBB BBBB--[------] */ - io->total_written += 2; + __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2)]; /* AAAAAA AABBBB[BBBB--]------ */ + __out_buf[io->__written++] = '='; /* AAAAAA AABBBB BBBB--[------] */ } } else { - out_buf[io->written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4)]; /* AAAAAA[AA----]------ ------ */ - out_buf[io->written++] = '='; /* AAAAAA AA----[------]------ */ - out_buf[io->written++] = '='; /* AAAAAA AA---- ------[------] */ - io->total_written += 3; + __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4)]; /* AAAAAA[AA----]------ ------ */ + __out_buf[io->__written++] = '='; /* AAAAAA AA----[------]------ */ + __out_buf[io->__written++] = '='; /* AAAAAA AA---- ------[------] */ } - /* At this point, 4 bytes have been io->written */ + /* At this point, 4 bytes have been io->__written */ /* Flush when necessary, return on error */ - if (io->written > 8188 /* sizeof(out_buf) - 4 */) { - retval = __guac_write(io, out_buf, io->written); + if (io->__written > 8188 /* sizeof(__out_buf) - 4 */) { + retval = __guac_write(io, __out_buf, io->__written); if (retval < 0) return retval; - io->written = 0; + io->__written = 0; } if (b < 0) @@ -232,19 +225,19 @@ ssize_t __guac_write_base64_triplet(GUACIO* io, int a, int b, int c) { ssize_t __guac_write_base64_byte(GUACIO* io, char buf) { - int* ready_buf = io->ready_buf; + int* __ready_buf = io->__ready_buf; int retval; - ready_buf[io->ready++] = buf & 0xFF; + __ready_buf[io->__ready++] = buf & 0xFF; /* Flush triplet */ - if (io->ready == 3) { - retval = __guac_write_base64_triplet(io, ready_buf[0], ready_buf[1], ready_buf[2]); + if (io->__ready == 3) { + retval = __guac_write_base64_triplet(io, __ready_buf[0], __ready_buf[1], __ready_buf[2]); if (retval < 0) return retval; - io->ready = 0; + io->__ready = 0; } return 1; @@ -274,12 +267,12 @@ ssize_t guac_flush(GUACIO* io) { int retval; /* Flush remaining bytes in buffer */ - if (io->written > 0) { - retval = __guac_write(io, io->out_buf, io->written); + if (io->__written > 0) { + retval = __guac_write(io, io->__out_buf, io->__written); if (retval < 0) return retval; - io->written = 0; + io->__written = 0; } return 0; @@ -291,7 +284,7 @@ ssize_t guac_flush_base64(GUACIO* io) { int retval; /* Flush triplet to output buffer */ - while (io->ready > 0) { + while (io->__ready > 0) { retval = __guac_write_base64_byte(io, -1); if (retval < 0) return retval; diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index fcebc1ce..d7786937 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -328,27 +328,27 @@ int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface) { } -int __guac_fill_instructionbuf(GUACIO* io) { +int __guac_fill___instructionbuf(GUACIO* io) { int retval; /* Attempt to fill buffer */ retval = recv( io->fd, - io->instructionbuf + io->instructionbuf_used_length, - io->instructionbuf_size - io->instructionbuf_used_length, + io->__instructionbuf + io->__instructionbuf_used_length, + io->__instructionbuf_size - io->__instructionbuf_used_length, 0 ); if (retval < 0) return retval; - io->instructionbuf_used_length += retval; + io->__instructionbuf_used_length += retval; /* Expand buffer if necessary */ - if (io->instructionbuf_used_length > io->instructionbuf_size / 2) { - io->instructionbuf_size *= 2; - io->instructionbuf = realloc(io->instructionbuf, io->instructionbuf_size); + if (io->__instructionbuf_used_length > io->__instructionbuf_size / 2) { + io->__instructionbuf_size *= 2; + io->__instructionbuf = realloc(io->__instructionbuf, io->__instructionbuf_size); } return retval; @@ -360,7 +360,7 @@ int guac_read_instruction(GUACIO* io, int usec_timeout, guac_instruction* parsed_instruction) { int retval; - int i = io->instructionbuf_parse_start; + int i = io->__instructionbuf_parse_start; /* Loop until a instruction is read */ for (;;) { @@ -369,10 +369,10 @@ int guac_read_instruction(GUACIO* io, int usec_timeout, int element_length = 0; /* Parse instruction in buffe */ - while (i < io->instructionbuf_used_length) { + while (i < io->__instructionbuf_used_length) { /* Read character from buffer */ - char c = io->instructionbuf[i++]; + char c = io->__instructionbuf[i++]; /* If digit, calculate element length */ if (c >= '0' && c <= '9') @@ -382,10 +382,10 @@ int guac_read_instruction(GUACIO* io, int usec_timeout, else if (c == '.') { /* Verify element is fully read */ - if (i + element_length < io->instructionbuf_used_length) { + if (i + element_length < io->__instructionbuf_used_length) { /* Get element value */ - char* elementv = &(io->instructionbuf[i]); + char* elementv = &(io->__instructionbuf[i]); /* Get terminator, set null terminator of elementv */ char terminator = elementv[element_length]; @@ -399,10 +399,10 @@ int guac_read_instruction(GUACIO* io, int usec_timeout, /* As element has been read successfully, update * parse start */ - io->instructionbuf_parse_start = i; + io->__instructionbuf_parse_start = i; /* Save element */ - io->instructionbuf_elementv[io->instructionbuf_elementc++] = elementv; + io->__instructionbuf_elementv[io->__instructionbuf_elementc++] = elementv; /* Finish parse if terminator is a semicolon */ if (terminator == ';') { @@ -410,21 +410,21 @@ int guac_read_instruction(GUACIO* io, int usec_timeout, int j; /* Init parsed instruction */ - parsed_instruction->argc = io->instructionbuf_elementc - 1; + parsed_instruction->argc = io->__instructionbuf_elementc - 1; parsed_instruction->argv = malloc(sizeof(char*) * parsed_instruction->argc); /* Set opcode */ - parsed_instruction->opcode = strdup(io->instructionbuf_elementv[0]); + parsed_instruction->opcode = strdup(io->__instructionbuf_elementv[0]); /* Copy element values to parsed instruction */ for (j=0; jargc; j++) - parsed_instruction->argv[j] = strdup(io->instructionbuf_elementv[j+1]); + parsed_instruction->argv[j] = strdup(io->__instructionbuf_elementv[j+1]); /* Reset buffer */ - memmove(io->instructionbuf, io->instructionbuf + i + 1, io->instructionbuf_used_length - i - 1); - io->instructionbuf_used_length -= i + 1; - io->instructionbuf_parse_start = 0; - io->instructionbuf_elementc = 0; + memmove(io->__instructionbuf, io->__instructionbuf + i + 1, io->__instructionbuf_used_length - i - 1); + io->__instructionbuf_used_length -= i + 1; + io->__instructionbuf_parse_start = 0; + io->__instructionbuf_elementc = 0; /* Done */ return 1; @@ -447,7 +447,7 @@ int guac_read_instruction(GUACIO* io, int usec_timeout, return retval; /* If more data is available, fill into buffer */ - retval = __guac_fill_instructionbuf(io); + retval = __guac_fill___instructionbuf(io); if (retval < 0) return retval; /* Error */ if (retval == 0) return -1; /* EOF */ @@ -470,7 +470,7 @@ void guac_free_instruction(guac_instruction* instruction) { int guac_instructions_waiting(GUACIO* io, int usec_timeout) { - if (io->instructionbuf_used_length > 0) + if (io->__instructionbuf_used_length > 0) return 1; return guac_select(io, usec_timeout); From 5214b1538d1015bb530f225d03c3bb94846dde2f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 23 Nov 2011 16:25:25 -0800 Subject: [PATCH 113/330] Set guac_error in guac_select() --- libguac/include/guacio.h | 6 ++++++ libguac/src/guacio.c | 23 +++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/libguac/include/guacio.h b/libguac/include/guacio.h index 49055ba7..6b5ac161 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/guacio.h @@ -216,6 +216,12 @@ ssize_t guac_flush(GUACIO* io); * Waits for input to be available on the given GUACIO object until the * specified timeout elapses. * + * If an error occurs while waiting, a negative value is returned, and + * guac_error is set appropriately. + * + * If a timeout occurs while waiting, zero value is returned, and + * guac_error is set to GUAC_STATUS_INPUT_TIMEOUT. + * * @param io The GUACIO object to wait for. * @param usec_timeout The maximum number of microseconds to wait for data, or * -1 to potentially wait forever. diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index da0b9e00..9ed2ba33 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -299,17 +299,28 @@ int guac_select(GUACIO* io, int usec_timeout) { fd_set fds; struct timeval timeout; + int retval; + /* No timeout if usec_timeout is negative */ if (usec_timeout < 0) - return select(io->fd + 1, &fds, NULL, NULL, NULL); + retval = select(io->fd + 1, &fds, NULL, NULL, NULL); - timeout.tv_sec = usec_timeout/1000000; - timeout.tv_usec = usec_timeout%1000000; + /* Handle timeout if specified */ + else { + timeout.tv_sec = usec_timeout/1000000; + timeout.tv_usec = usec_timeout%1000000; - FD_ZERO(&fds); - FD_SET(io->fd, &fds); + FD_ZERO(&fds); + FD_SET(io->fd, &fds); - return select(io->fd + 1, &fds, NULL, NULL, &timeout); + retval = select(io->fd + 1, &fds, NULL, NULL, &timeout); + } + + /* Properly set guac_error */ + if (retval < 0) guac_error = GUAC_STATUS_INPUT_ERROR; + if (retval == 0) guac_error = GUAC_STATUS_INPUT_TIMEOUT; + + return retval; } From 857c2e03c9e65d31c8f9ce8587452d4709db723d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 24 Nov 2011 18:18:03 -0800 Subject: [PATCH 114/330] Refactor of guac_read_instruction, migrate to new guac_read_instruction --- libguac/include/error.h | 6 ++++ libguac/include/protocol.h | 31 +++++------------- libguac/src/client.c | 42 ++++++++++++------------ libguac/src/error.c | 5 +++ libguac/src/guacio.c | 4 +-- libguac/src/protocol.c | 66 ++++++++++++++++++++++++++++++++------ 6 files changed, 99 insertions(+), 55 deletions(-) diff --git a/libguac/include/error.h b/libguac/include/error.h index aee205fa..af62dcfb 100644 --- a/libguac/include/error.h +++ b/libguac/include/error.h @@ -73,6 +73,12 @@ typedef enum guac_status { */ GUAC_STATUS_INPUT_TIMEOUT, + /** + * An error occurred, and further information about the error is already + * stored in errno. + */ + GUAC_STATUS_SEE_ERRNO, + /** * An error prevented the operation from writing to its associated * output stream. diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index f8bdf0df..5c165492 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -143,19 +143,7 @@ typedef struct guac_instruction { /** - * Frees all memory allocated to the given instruction opcode - * and arguments. The instruction structure itself will not - * be freed. - * - * @param instruction The instruction to free. - */ -void guac_free_instruction_data(guac_instruction* instruction); - - -/** - * Frees all memory allocated to the given instruction. This - * includes freeing memory allocated for the structure - * itself. + * Frees all memory allocated to the given instruction. * * @param instruction The instruction to free. */ @@ -345,23 +333,20 @@ int guac_instructions_waiting(GUACIO* io, int usec_timeout); /** * Reads a single instruction from the given GUACIO connection. * - * If an error occurs reading the instruction, a non-zero value is - * returned, and guac_error is set appropriately. + * If an error occurs reading the instruction, NULL is returned, + * and guac_error is set appropriately. * * @param io The GUACIO connection to use. * @param usec_timeout The maximum number of microseconds to wait before * giving up. - * @param parsed_instruction A pointer to a guac_instruction structure which - * will be populated with data read from the given - * GUACIO connection. - * @return A positive value if data was successfully read, negative on - * error, or zero if the instruction could not be read completely - * because the timeout elapsed, in which case subsequent calls to + * @return A new instruction if data was successfully read, NULL on + * error or if the instruction could not be read completely + * because the timeout elapsed, in which case guac_error will be + * set to GUAC_STATUS_INPUT_TIMEOUT and subsequent calls to * guac_read_instruction() will return the parsed instruction once * enough data is available. */ -int guac_read_instruction(GUACIO* io, int usec_timeout, - guac_instruction* parsed_instruction); +guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout); /** * Returns an arbitrary timestamp. The difference between return values of any diff --git a/libguac/src/client.c b/libguac/src/client.c index 96817eba..320c10a3 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -151,7 +151,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { char** argv; /* Instruction */ - guac_instruction instruction; + guac_instruction* instruction; /* Wait for select instruction */ for (;;) { @@ -172,19 +172,19 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { return NULL; } - result = guac_read_instruction(io, usec_timeout, &instruction); - if (result < 0) { + instruction = guac_read_instruction(io, usec_timeout); + if (instruction == NULL) { guac_close(io); return NULL; } /* Select instruction read */ - if (result > 0) { + else { - if (strcmp(instruction.opcode, "select") == 0) { + if (strcmp(instruction->opcode, "select") == 0) { /* Get protocol from message */ - char* protocol = instruction.argv[0]; + char* protocol = instruction->argv[0]; strcat(protocol_lib, protocol); strcat(protocol_lib, ".so"); @@ -199,7 +199,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { guac_send_error(io, "Could not load server-side client plugin."); guac_flush(io); guac_close(io); - guac_free_instruction_data(&instruction); + guac_free_instruction(instruction); return NULL; } @@ -213,7 +213,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { guac_send_error(io, "Invalid server-side client plugin."); guac_flush(io); guac_close(io); - guac_free_instruction_data(&instruction); + guac_free_instruction(instruction); return NULL; } @@ -225,7 +225,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { guac_send_error(io, "Invalid server-side client plugin."); guac_flush(io); guac_close(io); - guac_free_instruction_data(&instruction); + guac_free_instruction(instruction); return NULL; } @@ -234,16 +234,16 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { || guac_flush(io) ) { guac_close(io); - guac_free_instruction_data(&instruction); + guac_free_instruction(instruction); return NULL; } - guac_free_instruction_data(&instruction); + guac_free_instruction(instruction); break; } /* end if select */ - guac_free_instruction_data(&instruction); + guac_free_instruction(instruction); } } @@ -267,35 +267,35 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { return NULL; } - result = guac_read_instruction(io, usec_timeout, &instruction); - if (result < 0) { + instruction = guac_read_instruction(io, usec_timeout); + if (instruction == NULL) { guac_log_error("Error reading instruction while waiting for connect"); guac_close(io); return NULL; } /* Connect instruction read */ - if (result > 0) { + else { - if (strcmp(instruction.opcode, "connect") == 0) { + if (strcmp(instruction->opcode, "connect") == 0) { /* Initialize client arguments */ - argc = instruction.argc; - argv = instruction.argv; + argc = instruction->argc; + argv = instruction->argv; if (alias.client_init(client, argc, argv) != 0) { /* NOTE: On error, proxy client will send appropriate error message */ - guac_free_instruction_data(&instruction); + guac_free_instruction(instruction); guac_close(io); return NULL; } - guac_free_instruction_data(&instruction); + guac_free_instruction(instruction); return client; } /* end if connect */ - guac_free_instruction_data(&instruction); + guac_free_instruction(instruction); } } diff --git a/libguac/src/error.c b/libguac/src/error.c index 9f5a0fa2..d7411db1 100644 --- a/libguac/src/error.c +++ b/libguac/src/error.c @@ -49,6 +49,7 @@ const char* __GUAC_STATUS_SUCCESS_STR = "Success"; const char* __GUAC_STATUS_NO_MEMORY_STR = "Insufficient memory"; const char* __GUAC_STATUS_NO_INPUT_STR = "End of input stream"; const char* __GUAC_STATUS_INPUT_TIMEOUT_STR = "Read timeout"; +const char* __GUAC_STATUS_SEE_ERRNO_STR = "(see value of errno)"; const char* __GUAC_STATUS_OUTPUT_ERROR_STR = "Output error"; const char* __GUAC_STATUS_BAD_ARGUMENT_STR = "Invalid argument"; const char* __GUAC_STATUS_BAD_STATE_STR = "Illegal state"; @@ -75,6 +76,10 @@ const char* guac_status_string(guac_status status) { case GUAC_STATUS_INPUT_TIMEOUT: return __GUAC_STATUS_INPUT_TIMEOUT_STR; + /* Further information in errno */ + case GUAC_STATUS_SEE_ERRNO: + return __GUAC_STATUS_SEE_ERRNO_STR; + /* Output error */ case GUAC_STATUS_OUTPUT_ERROR: return __GUAC_STATUS_OUTPUT_ERROR_STR; diff --git a/libguac/src/guacio.c b/libguac/src/guacio.c index 9ed2ba33..cd523c17 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/guacio.c @@ -117,7 +117,7 @@ ssize_t __guac_write(GUACIO* io, const char* buf, int count) { /* Record errors in guac_error */ if (retval < 0) - guac_error = GUAC_STATUS_OUTPUT_ERROR; + guac_error = GUAC_STATUS_SEE_ERRNO; return retval; } @@ -317,7 +317,7 @@ int guac_select(GUACIO* io, int usec_timeout) { } /* Properly set guac_error */ - if (retval < 0) guac_error = GUAC_STATUS_INPUT_ERROR; + if (retval < 0) guac_error = GUAC_STATUS_SEE_ERRNO; if (retval == 0) guac_error = GUAC_STATUS_INPUT_TIMEOUT; return retval; diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index d7786937..f2c86791 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -62,6 +62,7 @@ #include "guacio.h" #include "protocol.h" +#include "error.h" ssize_t __guac_write_length_string(GUACIO* io, const char* str) { @@ -328,7 +329,7 @@ int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface) { } -int __guac_fill___instructionbuf(GUACIO* io) { +int __guac_fill_instructionbuf(GUACIO* io) { int retval; @@ -356,8 +357,7 @@ int __guac_fill___instructionbuf(GUACIO* io) { } /* Returns new instruction if one exists, or NULL if no more instructions. */ -int guac_read_instruction(GUACIO* io, int usec_timeout, - guac_instruction* parsed_instruction) { +guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout) { int retval; int i = io->__instructionbuf_parse_start; @@ -407,19 +407,59 @@ int guac_read_instruction(GUACIO* io, int usec_timeout, /* Finish parse if terminator is a semicolon */ if (terminator == ';') { + guac_instruction* parsed_instruction; int j; + /* Allocate instruction */ + parsed_instruction = malloc(sizeof(guac_instruction)); + if (parsed_instruction == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + return NULL; + } + /* Init parsed instruction */ parsed_instruction->argc = io->__instructionbuf_elementc - 1; parsed_instruction->argv = malloc(sizeof(char*) * parsed_instruction->argc); + /* Fail if memory could not be alloc'd for argv */ + if (parsed_instruction->argv == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + free(parsed_instruction); + return NULL; + } + /* Set opcode */ parsed_instruction->opcode = strdup(io->__instructionbuf_elementv[0]); + /* Fail if memory could not be alloc'd for opcode */ + if (parsed_instruction->opcode == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + free(parsed_instruction->argv); + free(parsed_instruction); + return NULL; + } + + /* Copy element values to parsed instruction */ - for (j=0; jargc; j++) + for (j=0; jargc; j++) { parsed_instruction->argv[j] = strdup(io->__instructionbuf_elementv[j+1]); + /* Free memory and fail if out of mem */ + if (parsed_instruction->argv[j] == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + + /* Free all alloc'd argv values */ + while (--j >= 0) + free(parsed_instruction->argv[j]); + + free(parsed_instruction->opcode); + free(parsed_instruction->argv); + free(parsed_instruction); + return NULL; + } + + } + /* Reset buffer */ memmove(io->__instructionbuf, io->__instructionbuf + i + 1, io->__instructionbuf_used_length - i - 1); io->__instructionbuf_used_length -= i + 1; @@ -427,7 +467,7 @@ int guac_read_instruction(GUACIO* io, int usec_timeout, io->__instructionbuf_elementc = 0; /* Done */ - return 1; + return parsed_instruction; } /* end if terminator */ @@ -444,12 +484,20 @@ int guac_read_instruction(GUACIO* io, int usec_timeout, /* No instruction yet? Get more data ... */ retval = guac_select(io, usec_timeout); if (retval <= 0) - return retval; + return NULL; /* If more data is available, fill into buffer */ - retval = __guac_fill___instructionbuf(io); - if (retval < 0) return retval; /* Error */ - if (retval == 0) return -1; /* EOF */ + retval = __guac_fill_instructionbuf(io); + + /* Error, guac_error already set */ + if (retval < 0) + return NULL; + + /* EOF */ + if (retval == 0) { + guac_error = GUAC_STATUS_NO_INPUT; + return NULL; + } } From c6d1916afac5f44ae19209f4f6bad41fe765436a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 24 Nov 2011 18:46:06 -0800 Subject: [PATCH 115/330] Properly check errno if guac_error is GUAC_STATUS_SEE_ERRNO --- libguac/src/error.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libguac/src/error.c b/libguac/src/error.c index d7411db1..67ef367c 100644 --- a/libguac/src/error.c +++ b/libguac/src/error.c @@ -36,6 +36,8 @@ * ***** END LICENSE BLOCK ***** */ #include +#include +#include #ifdef HAVE_LIBPTHREAD #include @@ -49,7 +51,6 @@ const char* __GUAC_STATUS_SUCCESS_STR = "Success"; const char* __GUAC_STATUS_NO_MEMORY_STR = "Insufficient memory"; const char* __GUAC_STATUS_NO_INPUT_STR = "End of input stream"; const char* __GUAC_STATUS_INPUT_TIMEOUT_STR = "Read timeout"; -const char* __GUAC_STATUS_SEE_ERRNO_STR = "(see value of errno)"; const char* __GUAC_STATUS_OUTPUT_ERROR_STR = "Output error"; const char* __GUAC_STATUS_BAD_ARGUMENT_STR = "Invalid argument"; const char* __GUAC_STATUS_BAD_STATE_STR = "Illegal state"; @@ -78,7 +79,7 @@ const char* guac_status_string(guac_status status) { /* Further information in errno */ case GUAC_STATUS_SEE_ERRNO: - return __GUAC_STATUS_SEE_ERRNO_STR; + return strerror(errno); /* Output error */ case GUAC_STATUS_OUTPUT_ERROR: From 682344f7783edc3dce654824c91db839ebbb19d1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 25 Nov 2011 12:17:20 -0800 Subject: [PATCH 116/330] Conversion to new naming conventions, partial logging. --- libguac/Makefile.am | 4 +- libguac/include/client.h | 136 ++++++++++-- libguac/include/log.h | 95 --------- libguac/include/protocol.h | 110 ++++++---- libguac/include/{guacio.h => socket.h} | 68 +++--- libguac/src/client.c | 93 ++++---- libguac/src/log.c | 89 -------- libguac/src/protocol.c | 284 ++++++++++++++----------- libguac/src/{guacio.c => socket.c} | 56 ++--- 9 files changed, 455 insertions(+), 480 deletions(-) delete mode 100644 libguac/include/log.h rename libguac/include/{guacio.h => socket.h} (76%) delete mode 100644 libguac/src/log.c rename libguac/src/{guacio.c => socket.c} (75%) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 7db1ad03..fff061c1 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -40,11 +40,11 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -Iinclude libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/guacio.h include/protocol.h include/client-handlers.h include/log.h include/error.h +libguacinc_HEADERS = include/client.h include/socket.h include/protocol.h include/client-handlers.h include/error.h lib_LTLIBRARIES = libguac.la -libguac_la_SOURCES = src/client.c src/guacio.c src/protocol.c src/client-handlers.c src/log.c src/error.c +libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handlers.c src/error.c libguac_la_LDFLAGS = -version-info 2:0:0 diff --git a/libguac/include/client.h b/libguac/include/client.h index fbe00a0b..d3aa7e0a 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -39,7 +39,9 @@ #ifndef _GUAC_CLIENT_H #define _GUAC_CLIENT_H -#include "guacio.h" +#include + +#include "socket.h" #include "protocol.h" /** @@ -77,6 +79,11 @@ typedef int guac_client_clipboard_handler(guac_client* client, char* copied); */ typedef int guac_client_free_handler(guac_client* client); +/** + * Handler for logging messages + */ +typedef void guac_client_log_handler(guac_client* client, const char* format, va_list args); + /** * Possible current states of the Guacamole client. Currently, the only * two states are RUNNING and STOPPING. @@ -106,12 +113,12 @@ typedef enum guac_client_state { struct guac_client { /** - * The GUACIO structure to be used to communicate with the web-client. It is + * The guac_socket structure to be used to communicate with the web-client. It is * expected that the implementor of any Guacamole proxy client will provide - * their own mechanism of I/O for their protocol. The GUACIO structure is + * their own mechanism of I/O for their protocol. The guac_socket structure is * used only to communicate conveniently with the Guacamole web-client. */ - GUACIO* io; + guac_socket* io; /** * The current state of the client. When the client is first allocated, @@ -169,7 +176,7 @@ struct guac_client { * * Example: * @code - * void handle_messages(guac_client* client); + * int handle_messages(guac_client* client); * * int guac_client_init(guac_client* client, int argc, char** argv) { * client->handle_messages = handle_messages; @@ -196,7 +203,7 @@ struct guac_client { * Example: * @code - * void mouse_handler(guac_client* client, int x, int y, int button_mask); + * int mouse_handler(guac_client* client, int x, int y, int button_mask); * * int guac_client_init(guac_client* client, int argc, char** argv) { * client->mouse_handler = mouse_handler; @@ -214,7 +221,7 @@ struct guac_client { * * Example: * @code - * void key_handler(guac_client* client, int keysym, int pressed); + * int key_handler(guac_client* client, int keysym, int pressed); * * int guac_client_init(guac_client* client, int argc, char** argv) { * client->key_handler = key_handler; @@ -235,7 +242,7 @@ struct guac_client { * * Example: * @code - * void clipboard_handler(guac_client* client, char* copied); + * int clipboard_handler(guac_client* client, char* copied); * * int guac_client_init(guac_client* client, int argc, char** argv) { * client->clipboard_handler = clipboard_handler; @@ -255,7 +262,7 @@ struct guac_client { * * Example: * @code - * void free_handler(guac_client* client); + * int free_handler(guac_client* client); * * int guac_client_init(guac_client* client, int argc, char** argv) { * client->free_handler = free_handler; @@ -264,6 +271,60 @@ struct guac_client { */ guac_client_free_handler* free_handler; + /** + * Handler for logging informational messages. This handler will be called + * via guac_client_log_info() when the client needs to log information. + * + * In general, only programs loading the client should implement this + * handler, as those are the programs that would provide the logging + * facilities. + * + * Client implementations should expect these handlers to already be + * set. + * + * Example: + * @code + * void log_handler(guac_client* client, const char* format, va_list args); + * + * void function_of_daemon() { + * + * guac_client* client = [client from guac_get_client()]; + * + * client->log_info_handler = log_handler; + * + * } + * @endcode + */ + guac_client_log_handler* log_info_handler; + + + /** + * Handler for logging error messages. This handler will be called + * via guac_client_log_error() when the client needs to log an error. + * + * In general, only programs loading the client should implement this + * handler, as those are the programs that would provide the logging + * facilities. + * + * Client implementations should expect these handlers to already be + * set. + * + * Example: + * @code + * void log_handler(guac_client* client, const char* format, va_list args); + * + * void function_of_daemon() { + * + * guac_client* client = [client from guac_get_client()]; + * + * client->log_error_handler = log_handler; + * + * } + * @endcode + */ + guac_client_log_handler* log_error_handler; + + }; /** @@ -272,8 +333,9 @@ struct guac_client { typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); /** - * Initialize and return a new guac_client. The pluggable client will be chosen based on - * the first connect message received on the given file descriptor. + * Initialize and return a new guac_client. The pluggable client will be + * chosen based on the first connect message received on the given file + * descriptor. * * @param client_fd The file descriptor associated with the socket associated * with the connection to the web-client tunnel. @@ -288,7 +350,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout); * * @param client The proxy client to free all reasources of. */ -void guac_free_client(guac_client* client); +void guac_client_free(guac_client* client); /** * Call the appropriate handler defined by the given client for the given @@ -330,6 +392,56 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); */ void guac_client_free_buffer(guac_client* client, guac_layer* layer); +/** + * Logs an informational message in the log used by the given client. The + * logger used will normally be defined by guacd (or whichever program loads + * the proxy client) by setting the logging handlers of the client when it is + * loaded. + * + * @param client The proxy client to log an informational message for. + * @param format A printf-style format string to log. + * @param ... Arguments to use when filling the format string for printing. + */ +void guac_client_log_info(guac_client* client, const char* format, ...); + +/** + * Logs an error message in the log used by the given client. The logger + * used will normally be defined by guacd (or whichever program loads the + * proxy client) by setting the logging handlers of the client when it is + * loaded. + * + * @param client The proxy client to log an error for. + * @param format A printf-style format string to log. + * @param ... Arguments to use when filling the format string for printing. + */ +void guac_client_log_error(guac_client* client, const char* format, ...); + +/** + * Logs an informational message in the log used by the given client. The + * logger used will normally be defined by guacd (or whichever program loads + * the proxy client) by setting the logging handlers of the client when it is + * loaded. + * + * @param client The proxy client to log an informational message for. + * @param format A printf-style format string to log. + * @param ap The va_list containing the arguments to be used when filling the + * format string for printing. + */ +void vguac_client_log_info(guac_client* client, const char* format, va_list ap); + +/** + * Logs an error message in the log used by the given client. The logger + * used will normally be defined by guacd (or whichever program loads the + * proxy client) by setting the logging handlers of the client when it is + * loaded. + * + * @param client The proxy client to log an error for. + * @param format A printf-style format string to log. + * @param ap The va_list containing the arguments to be used when filling the + * format string for printing. + */ +void vguac_client_log_error(guac_client* client, const char* format, va_list ap); + /** * The default Guacamole client layer, layer 0. */ diff --git a/libguac/include/log.h b/libguac/include/log.h deleted file mode 100644 index fc531896..00000000 --- a/libguac/include/log.h +++ /dev/null @@ -1,95 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef _GUAC_LOG_H -#define _GUAC_LOG_H - -#include - -/** - * Provides basic cross-platform logging facilities. - * - * @file log.h - */ - -/** - * Logs an informational message in the system log, whatever - * that may be for the system being used. This will currently - * log to syslog for platforms supporting it, and stderr for - * all others. - * - * @param format A printf-style format string to log. - * @param ... Arguments to use when filling the format string for printing. - */ -void guac_log_info(const char* format, ...); - -/** - * Logs an informational message in the system log, whatever - * that may be for the system being used. This will currently - * log to syslog for platforms supporting it, and stderr for - * all others. - * - * @param format A printf-style format string to log. - * @param ap The va_list containing the arguments to be used when filling the - * format string for printing. - */ -void vguac_log_info(const char* format, va_list ap); - -/** - * Logs an error message in the system log, whatever - * that may be for the system being used. This will currently - * log to syslog for platforms supporting it, and stderr for - * all others. - * - * @param format A printf-style format string to log. - * @param ... Arguments to use when filling the format string for printing. - */ -void guac_log_error(const char* format, ...); - -/** - * Logs an error message in the system log, whatever - * that may be for the system being used. This will currently - * log to syslog for platforms supporting it, and stderr for - * all others. - * - * @param format A printf-style format string to log. - * @param ap The va_list containing the arguments to be used when filling the - * format string for printing. - */ -void vguac_log_error(const char* format, va_list ap); - -#endif diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 5c165492..302c71e2 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -40,11 +40,11 @@ #include -#include "guacio.h" +#include "socket.h" /** * Provides functions and structures required for communicating using the - * Guacamole protocol over a GUACIO connection, such as that provided by + * Guacamole protocol over a guac_socket connection, such as that provided by * guac_client objects. * * @file protocol.h @@ -147,86 +147,86 @@ typedef struct guac_instruction { * * @param instruction The instruction to free. */ -void guac_free_instruction(guac_instruction* instruction); +void guac_instruction_free(guac_instruction* instruction); /** - * Sends an args instruction over the given GUACIO connection. + * Sends an args instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param args The NULL-terminated array of argument names (strings). * @return Zero on success, non-zero on error. */ -int guac_send_args(GUACIO* io, const char** name); +int guac_protocol_send_args(guac_socket* io, const char** name); /** - * Sends a name instruction over the given GUACIO connection. + * Sends a name instruction over the given guac_socket connection. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param name The name to send within the name instruction. * @return Zero on success, non-zero on error. */ -int guac_send_name(GUACIO* io, const char* name); +int guac_protocol_send_name(guac_socket* io, const char* name); /** - * Sends a sync instruction over the given GUACIO connection. The + * Sends a sync instruction over the given guac_socket connection. The * current time in milliseconds should be passed in as the timestamp. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param timestamp The current timestamp (in milliseconds). * @return Zero on success, non-zero on error. */ -int guac_send_sync(GUACIO* io, guac_timestamp timestamp); +int guac_protocol_send_sync(guac_socket* io, guac_timestamp timestamp); /** - * Sends an error instruction over the given GUACIO connection. + * Sends an error instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param error The description associated with the error. * @return Zero on success, non-zero on error. */ -int guac_send_error(GUACIO* io, const char* error); +int guac_protocol_send_error(guac_socket* io, const char* error); /** - * Sends a clipboard instruction over the given GUACIO connection. + * Sends a clipboard instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param data The clipboard data to send. * @return Zero on success, non-zero on error. */ -int guac_send_clipboard(GUACIO* io, const char* data); +int guac_protocol_send_clipboard(guac_socket* io, const char* data); /** - * Sends a size instruction over the given GUACIO connection. + * Sends a size instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param w The width of the display. * @param h The height of the display. * @return Zero on success, non-zero on error. */ -int guac_send_size(GUACIO* io, int w, int h); +int guac_protocol_send_size(guac_socket* io, int w, int h); /** - * Sends a copy instruction over the given GUACIO connection. + * Sends a copy instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param srcl The source layer. * @param srcx The X coordinate of the source rectangle. * @param srcy The Y coordinate of the source rectangle. @@ -240,17 +240,17 @@ int guac_send_size(GUACIO* io, int w, int h); * should be copied. * @return Zero on success, non-zero on error. */ -int guac_send_copy(GUACIO* io, +int guac_protocol_send_copy(guac_socket* io, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty); /** - * Sends a rect instruction over the given GUACIO connection. + * Sends a rect instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. * @param x The X coordinate of the rectangle. @@ -263,18 +263,18 @@ int guac_send_copy(GUACIO* io, * @param a The alpha (transparency) component of the color of the rectangle. * @return Zero on success, non-zero on error. */ -int guac_send_rect(GUACIO* io, +int guac_protocol_send_rect(guac_socket* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, int width, int height, int r, int g, int b, int a); /** - * Sends a clip instruction over the given GUACIO connection. + * Sends a clip instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param layer The layer to set the clipping region of. * @param x The X coordinate of the clipping rectangle. * @param y The Y coordinate of the clipping rectangle. @@ -282,17 +282,17 @@ int guac_send_rect(GUACIO* io, * @param height The height of the clipping rectangle. * @return Zero on success, non-zero on error. */ -int guac_send_clip(GUACIO* io, const guac_layer* layer, +int guac_protocol_send_clip(guac_socket* io, const guac_layer* layer, int x, int y, int width, int height); /** - * Sends a png instruction over the given GUACIO connection. The PNG image data + * Sends a png instruction over the given guac_socket connection. The PNG image data * given will be automatically base64-encoded for transmission. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. * @param x The destination X coordinate. @@ -300,53 +300,75 @@ int guac_send_clip(GUACIO* io, const guac_layer* layer, * @param surface A cairo surface containing the image data to send. * @return Zero on success, non-zero on error. */ -int guac_send_png(GUACIO* io, guac_composite_mode mode, +int guac_protocol_send_png(guac_socket* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface); /** - * Sends a cursor instruction over the given GUACIO connection. The PNG image + * Sends a cursor instruction over the given guac_socket connection. The PNG image * data given will be automatically base64-encoded for transmission. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param x The X coordinate of the cursor hotspot. * @param y The Y coordinate of the cursor hotspot. * @param surface A cairo surface containing the image data to send. * @return Zero on success, non-zero on error. */ -int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface); +int guac_protocol_send_cursor(guac_socket* io, int x, int y, cairo_surface_t* surface); /** - * Returns whether new instruction data is available on the given GUACIO + * Returns whether new instruction data is available on the given guac_socket * connection for parsing. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param usec_timeout The maximum number of microseconds to wait before * giving up. * @return A positive value if data is available, negative on error, or * zero if no data is currently available. */ -int guac_instructions_waiting(GUACIO* io, int usec_timeout); +int guac_protocol_instructions_waiting(guac_socket* io, int usec_timeout); /** - * Reads a single instruction from the given GUACIO connection. + * Reads a single instruction from the given guac_socket connection. * * If an error occurs reading the instruction, NULL is returned, * and guac_error is set appropriately. * - * @param io The GUACIO connection to use. + * @param io The guac_socket connection to use. * @param usec_timeout The maximum number of microseconds to wait before * giving up. * @return A new instruction if data was successfully read, NULL on * error or if the instruction could not be read completely * because the timeout elapsed, in which case guac_error will be * set to GUAC_STATUS_INPUT_TIMEOUT and subsequent calls to - * guac_read_instruction() will return the parsed instruction once + * guac_protocol_read_instruction() will return the parsed instruction once * enough data is available. */ -guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout); +guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeout); + +/** + * Reads a single instruction with the given opcode from the given guac_socket + * connection. + * + * If an error occurs reading the instruction, NULL is returned, + * and guac_error is set appropriately. + * + * If the instruction read is not the expected instruction, NULL is returned, + * and guac_error is set to GUAC_STATUS_BAD_STATE. + * + * @param io The guac_socket connection to use. + * @param usec_timeout The maximum number of microseconds to wait before + * giving up. + * @param opcode The opcode of the instruction to read. + * @return A new instruction if an instruction with the given opcode was read, + * NULL otherwise. If an instruction was read, but the instruction had + * a different opcode, NULL is returned and guac_error is set to + * GUAC_STATUS_BAD_STATE. + */ +guac_instruction* guac_protocol_expect_instruction(guac_socket* io, int usec_timeout, + const char* opcode); /** * Returns an arbitrary timestamp. The difference between return values of any @@ -356,7 +378,7 @@ guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout); * * @return An arbitrary millisecond timestamp. */ -guac_timestamp guac_current_timestamp(); +guac_timestamp guac_protocol_get_timestamp(); /** * Suspends execution of the current thread for the given number of diff --git a/libguac/include/guacio.h b/libguac/include/socket.h similarity index 76% rename from libguac/include/guacio.h rename to libguac/include/socket.h index 6b5ac161..38f8108a 100644 --- a/libguac/include/guacio.h +++ b/libguac/include/socket.h @@ -35,24 +35,24 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef _GUAC_GUACIO_H -#define _GUAC_GUACIO_H +#ifndef _GUAC_SOCKET_H +#define _GUAC_SOCKET_H #include #include /** - * Defines the GUACIO object and functionss for using and manipulating it. + * Defines the guac_socket object and functionss for using and manipulating it. * - * @file guacio.h + * @file socket.h */ /** - * The core I/O object of Guacamole. GUACIO provides buffered input and output - * as well as convenience methods for efficiently writing base64 data. + * The core I/O object of Guacamole. guac_socket provides buffered input and + * output as well as convenience methods for efficiently writing base64 data. */ -typedef struct GUACIO { +typedef struct guac_socket { /** * The file descriptor to be read from / written to. @@ -114,21 +114,21 @@ typedef struct GUACIO { */ char* __instructionbuf_elementv[64]; -} GUACIO; +} guac_socket; /** - * Allocates and initializes a new GUACIO object with the given open + * Allocates and initializes a new guac_socket object with the given open * file descriptor. * - * If an error occurs while allocating the GUACIO object, NULL is returned, + * If an error occurs while allocating the guac_socket object, NULL is returned, * and guac_error is set appropriately. * - * @param fd An open file descriptor that this GUACIO object should manage. - * @return A newly allocated GUACIO object associated with the given + * @param fd An open file descriptor that this guac_socket object should manage. + * @return A newly allocated guac_socket object associated with the given * file descriptor, or NULL if an error occurs while allocating - * the GUACIO object. + * the guac_socket object. */ -GUACIO* guac_open(int fd); +guac_socket* guac_socket_open(int fd); /** * Parses the given string as a decimal number, returning the result as @@ -142,21 +142,21 @@ GUACIO* guac_open(int fd); int64_t guac_parse_int(const char* str); /** - * Writes the given unsigned int to the given GUACIO object. The data + * Writes the given unsigned int to the given guac_socket object. The data * written may be buffered until the buffer is flushed automatically or * manually. * * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The GUACIO object to write to. + * @param io The guac_socket object to write to. * @param i The unsigned int to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_int(GUACIO* io, int64_t i); +ssize_t guac_socket_write_int(guac_socket* io, int64_t i); /** - * Writes the given string to the given GUACIO object. The data + * Writes the given string to the given guac_socket object. The data * written may be buffered until the buffer is flushed automatically or * manually. Note that if the string can contain characters used * internally by the Guacamole protocol (commas, semicolons, or @@ -165,29 +165,29 @@ ssize_t guac_write_int(GUACIO* io, int64_t i); * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The GUACIO object to write to. + * @param io The guac_socket object to write to. * @param str The string to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_string(GUACIO* io, const char* str); +ssize_t guac_socket_write_string(guac_socket* io, const char* str); /** - * Writes the given binary data to the given GUACIO object as base64-encoded + * Writes the given binary data to the given guac_socket object as base64-encoded * data. The data written may be buffered until the buffer is flushed * automatically or manually. Beware that because base64 data is buffered - * on top of the write buffer already used, a call to guac_flush_base64() must + * on top of the write buffer already used, a call to guac_socket_flush_base64() must * be made before non-base64 writes (or writes of an independent block of * base64 data) can be made. * * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The GUACIO object to write to. + * @param io The guac_socket object to write to. * @param buf A buffer containing the data to write. * @param count The number of bytes to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count); +ssize_t guac_socket_write_base64(guac_socket* io, const void* buf, size_t count); /** * Flushes the base64 buffer, writing padding characters as necessary. @@ -195,10 +195,10 @@ ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count); * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The GUACIO object to flush + * @param io The guac_socket object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ -ssize_t guac_flush_base64(GUACIO* io); +ssize_t guac_socket_flush_base64(guac_socket* io); /** * Flushes the write buffer. @@ -206,14 +206,14 @@ ssize_t guac_flush_base64(GUACIO* io); * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The GUACIO object to flush + * @param io The guac_socket object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ -ssize_t guac_flush(GUACIO* io); +ssize_t guac_socket_flush(guac_socket* io); /** - * Waits for input to be available on the given GUACIO object until the + * Waits for input to be available on the given guac_socket object until the * specified timeout elapses. * * If an error occurs while waiting, a negative value is returned, and @@ -222,22 +222,22 @@ ssize_t guac_flush(GUACIO* io); * If a timeout occurs while waiting, zero value is returned, and * guac_error is set to GUAC_STATUS_INPUT_TIMEOUT. * - * @param io The GUACIO object to wait for. + * @param io The guac_socket object to wait for. * @param usec_timeout The maximum number of microseconds to wait for data, or * -1 to potentially wait forever. * @return Positive on success, zero if the timeout elapsed and no data is * available, negative on error. */ -int guac_select(GUACIO* io, int usec_timeout); +int guac_socket_select(guac_socket* io, int usec_timeout); /** - * Frees resources allocated to the given GUACIO object. Note that this + * Frees resources allocated to the given guac_socket object. Note that this * implicitly flush all buffers, but will NOT close the associated file * descriptor. * - * @param io The GUACIO object to close. + * @param io The guac_socket object to close. */ -void guac_close(GUACIO* io); +void guac_socket_close(guac_socket* io); #endif diff --git a/libguac/src/client.c b/libguac/src/client.c index 320c10a3..0ba54118 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -40,8 +40,7 @@ #include #include -#include "log.h" -#include "guacio.h" +#include "socket.h" #include "protocol.h" #include "client.h" #include "client-handlers.h" @@ -57,7 +56,7 @@ guac_layer __GUAC_DEFAULT_LAYER = { const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; -guac_client* __guac_alloc_client(GUACIO* io) { +guac_client* __guac_alloc_client(guac_socket* io) { /* Allocate new client (not handoff) */ guac_client* client = malloc(sizeof(guac_client)); @@ -65,7 +64,7 @@ guac_client* __guac_alloc_client(GUACIO* io) { /* Init new client */ client->io = io; - client->last_received_timestamp = client->last_sent_timestamp = guac_current_timestamp(); + client->last_received_timestamp = client->last_sent_timestamp = guac_protocol_get_timestamp(); client->state = RUNNING; client->__all_layers = NULL; @@ -131,7 +130,7 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) { guac_client* guac_get_client(int client_fd, int usec_timeout) { guac_client* client; - GUACIO* io = guac_open(client_fd); + guac_socket* io = guac_socket_open(client_fd); /* Pluggable client */ char protocol_lib[256] = "libguac-client-"; @@ -159,22 +158,22 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { int result; /* Wait for data until timeout */ - result = guac_instructions_waiting(io, usec_timeout); + result = guac_protocol_instructions_waiting(io, usec_timeout); if (result == 0) { - guac_send_error(io, "Select timeout."); - guac_close(io); + guac_protocol_send_error(io, "Select timeout."); + guac_socket_close(io); return NULL; } /* If error occurs while waiting, exit with failure */ if (result < 0) { - guac_close(io); + guac_socket_close(io); return NULL; } - instruction = guac_read_instruction(io, usec_timeout); + instruction = guac_protocol_read_instruction(io, usec_timeout); if (instruction == NULL) { - guac_close(io); + guac_socket_close(io); return NULL; } @@ -195,11 +194,11 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { /* Load client plugin */ client->__client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); if (!(client->__client_plugin_handle)) { - guac_log_error("Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); - guac_send_error(io, "Could not load server-side client plugin."); - guac_flush(io); - guac_close(io); - guac_free_instruction(instruction); + guac_client_log_error(client, "Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); + guac_protocol_send_error(io, "Could not load server-side client plugin."); + guac_socket_flush(io); + guac_socket_close(io); + guac_instruction_free(instruction); return NULL; } @@ -209,11 +208,11 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { alias.obj = dlsym(client->__client_plugin_handle, "guac_client_init"); if ((error = dlerror()) != NULL) { - guac_log_error("Could not get guac_client_init in plugin: %s\n", error); - guac_send_error(io, "Invalid server-side client plugin."); - guac_flush(io); - guac_close(io); - guac_free_instruction(instruction); + guac_client_log_error(client, "Could not get guac_client_init in plugin: %s\n", error); + guac_protocol_send_error(io, "Invalid server-side client plugin."); + guac_socket_flush(io); + guac_socket_close(io); + guac_instruction_free(instruction); return NULL; } @@ -221,29 +220,29 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { client_args = (const char**) dlsym(client->__client_plugin_handle, "GUAC_CLIENT_ARGS"); if ((error = dlerror()) != NULL) { - guac_log_error("Could not get GUAC_CLIENT_ARGS in plugin: %s\n", error); - guac_send_error(io, "Invalid server-side client plugin."); - guac_flush(io); - guac_close(io); - guac_free_instruction(instruction); + guac_client_log_error(client, "Could not get GUAC_CLIENT_ARGS in plugin: %s\n", error); + guac_protocol_send_error(io, "Invalid server-side client plugin."); + guac_socket_flush(io); + guac_socket_close(io); + guac_instruction_free(instruction); return NULL; } if ( /* Send args */ - guac_send_args(io, client_args) - || guac_flush(io) + guac_protocol_send_args(io, client_args) + || guac_socket_flush(io) ) { - guac_close(io); - guac_free_instruction(instruction); + guac_socket_close(io); + guac_instruction_free(instruction); return NULL; } - guac_free_instruction(instruction); + guac_instruction_free(instruction); break; } /* end if select */ - guac_free_instruction(instruction); + guac_instruction_free(instruction); } } @@ -254,23 +253,23 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { int result; /* Wait for data until timeout */ - result = guac_instructions_waiting(io, usec_timeout); + result = guac_protocol_instructions_waiting(io, usec_timeout); if (result == 0) { - guac_send_error(io, "Connect timeout."); - guac_close(io); + guac_protocol_send_error(io, "Connect timeout."); + guac_socket_close(io); return NULL; } /* If error occurs while waiting, exit with failure */ if (result < 0) { - guac_close(io); + guac_socket_close(io); return NULL; } - instruction = guac_read_instruction(io, usec_timeout); + instruction = guac_protocol_read_instruction(io, usec_timeout); if (instruction == NULL) { - guac_log_error("Error reading instruction while waiting for connect"); - guac_close(io); + guac_client_log_error(client, "Error reading instruction while waiting for connect"); + guac_socket_close(io); return NULL; } @@ -285,35 +284,35 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { if (alias.client_init(client, argc, argv) != 0) { /* NOTE: On error, proxy client will send appropriate error message */ - guac_free_instruction(instruction); - guac_close(io); + guac_instruction_free(instruction); + guac_socket_close(io); return NULL; } - guac_free_instruction(instruction); + guac_instruction_free(instruction); return client; } /* end if connect */ - guac_free_instruction(instruction); + guac_instruction_free(instruction); } } } -void guac_free_client(guac_client* client) { +void guac_client_free(guac_client* client) { if (client->free_handler) { if (client->free_handler(client)) - guac_log_error("Error calling client free handler"); + guac_client_log_error(client, "Error calling client free handler"); } - guac_close(client->io); + guac_socket_close(client->io); /* Unload client plugin */ if (dlclose(client->__client_plugin_handle)) { - guac_log_error("Could not close client plugin while unloading client: %s", dlerror()); + guac_client_log_error(client, "Could not close client plugin while unloading client: %s", dlerror()); } /* Free all layers */ diff --git a/libguac/src/log.c b/libguac/src/log.c deleted file mode 100644 index c51bff15..00000000 --- a/libguac/src/log.c +++ /dev/null @@ -1,89 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifdef HAVE_SYSLOG_H - #include -#else - #include -#endif - -#include - -#include "log.h" - -void vguac_log_info(const char* format, va_list ap) { -#ifdef HAVE_SYSLOG_H - vsyslog(LOG_ERR, format, ap); -#else - fprintf(stderr, "guacamole: info: "); - vfprintf(stderr, format, ap); - fprintf(stderr, "\n"); -#endif -} - -void vguac_log_error(const char* format, va_list ap) { -#ifdef HAVE_SYSLOG_H - vsyslog(LOG_INFO, format, ap); -#else - fprintf(stderr, "guacamole: error: "); - vfprintf(stderr, format, ap); - fprintf(stderr, "\n"); -#endif -} - -void guac_log_info(const char* format, ...) { - - va_list args; - va_start(args, format); - - vguac_log_info(format, args); - - va_end(args); - -} - -void guac_log_error(const char* format, ...) { - - va_list args; - va_start(args, format); - - vguac_log_error(format, args); - - va_end(args); - -} - diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index f2c86791..faafe65d 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -60,181 +60,181 @@ #include #endif -#include "guacio.h" +#include "socket.h" #include "protocol.h" #include "error.h" -ssize_t __guac_write_length_string(GUACIO* io, const char* str) { +ssize_t __guac_socket_write_length_string(guac_socket* io, const char* str) { return - guac_write_int(io, strlen(str)) - || guac_write_string(io, ".") - || guac_write_string(io, str); + guac_socket_write_int(io, strlen(str)) + || guac_socket_write_string(io, ".") + || guac_socket_write_string(io, str); } -ssize_t __guac_write_length_int(GUACIO* io, int64_t i) { +ssize_t __guac_socket_write_length_int(guac_socket* io, int64_t i) { char buffer[128]; snprintf(buffer, sizeof(buffer), "%"PRIi64, i); - return __guac_write_length_string(io, buffer); + return __guac_socket_write_length_string(io, buffer); } -int guac_send_args(GUACIO* io, const char** args) { +int guac_protocol_send_args(guac_socket* io, const char** args) { int i; - if (guac_write_string(io, "4.args")) return -1; + if (guac_socket_write_string(io, "4.args")) return -1; for (i=0; args[i] != NULL; i++) { - if (guac_write_string(io, ",")) + if (guac_socket_write_string(io, ",")) return -1; - if (__guac_write_length_string(io, args[i])) + if (__guac_socket_write_length_string(io, args[i])) return -1; } - return guac_write_string(io, ";"); + return guac_socket_write_string(io, ";"); } -int guac_send_name(GUACIO* io, const char* name) { +int guac_protocol_send_name(guac_socket* io, const char* name) { return - guac_write_string(io, "4.name,") - || __guac_write_length_string(io, name) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.name,") + || __guac_socket_write_length_string(io, name) + || guac_socket_write_string(io, ";"); } -int guac_send_size(GUACIO* io, int w, int h) { +int guac_protocol_send_size(guac_socket* io, int w, int h) { return - guac_write_string(io, "4.size,") - || __guac_write_length_int(io, w) - || guac_write_string(io, ",") - || __guac_write_length_int(io, h) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.size,") + || __guac_socket_write_length_int(io, w) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, h) + || guac_socket_write_string(io, ";"); } -int guac_send_clipboard(GUACIO* io, const char* data) { +int guac_protocol_send_clipboard(guac_socket* io, const char* data) { return - guac_write_string(io, "9.clipboard,") - || __guac_write_length_string(io, data) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "9.clipboard,") + || __guac_socket_write_length_string(io, data) + || guac_socket_write_string(io, ";"); } -int guac_send_error(GUACIO* io, const char* error) { +int guac_protocol_send_error(guac_socket* io, const char* error) { return - guac_write_string(io, "5.error,") - || __guac_write_length_string(io, error) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "5.error,") + || __guac_socket_write_length_string(io, error) + || guac_socket_write_string(io, ";"); } -int guac_send_sync(GUACIO* io, guac_timestamp timestamp) { +int guac_protocol_send_sync(guac_socket* io, guac_timestamp timestamp) { return - guac_write_string(io, "4.sync,") - || __guac_write_length_int(io, timestamp) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.sync,") + || __guac_socket_write_length_int(io, timestamp) + || guac_socket_write_string(io, ";"); } -int guac_send_copy(GUACIO* io, +int guac_protocol_send_copy(guac_socket* io, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty) { return - guac_write_string(io, "4.copy,") - || __guac_write_length_int(io, srcl->index) - || guac_write_string(io, ",") - || __guac_write_length_int(io, srcx) - || guac_write_string(io, ",") - || __guac_write_length_int(io, srcy) - || guac_write_string(io, ",") - || __guac_write_length_int(io, w) - || guac_write_string(io, ",") - || __guac_write_length_int(io, h) - || guac_write_string(io, ",") - || __guac_write_length_int(io, mode) - || guac_write_string(io, ",") - || __guac_write_length_int(io, dstl->index) - || guac_write_string(io, ",") - || __guac_write_length_int(io, dstx) - || guac_write_string(io, ",") - || __guac_write_length_int(io, dsty) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.copy,") + || __guac_socket_write_length_int(io, srcl->index) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, srcx) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, srcy) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, w) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, h) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, mode) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, dstl->index) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, dstx) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, dsty) + || guac_socket_write_string(io, ";"); } -int guac_send_rect(GUACIO* io, +int guac_protocol_send_rect(guac_socket* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, int width, int height, int r, int g, int b, int a) { return - guac_write_string(io, "4.rect,") - || __guac_write_length_int(io, mode) - || guac_write_string(io, ",") - || __guac_write_length_int(io, layer->index) - || guac_write_string(io, ",") - || __guac_write_length_int(io, x) - || guac_write_string(io, ",") - || __guac_write_length_int(io, y) - || guac_write_string(io, ",") - || __guac_write_length_int(io, width) - || guac_write_string(io, ",") - || __guac_write_length_int(io, height) - || guac_write_string(io, ",") - || __guac_write_length_int(io, r) - || guac_write_string(io, ",") - || __guac_write_length_int(io, g) - || guac_write_string(io, ",") - || __guac_write_length_int(io, b) - || guac_write_string(io, ",") - || __guac_write_length_int(io, a) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.rect,") + || __guac_socket_write_length_int(io, mode) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, layer->index) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, x) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, y) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, width) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, height) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, r) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, g) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, b) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, a) + || guac_socket_write_string(io, ";"); } -int guac_send_clip(GUACIO* io, const guac_layer* layer, +int guac_protocol_send_clip(guac_socket* io, const guac_layer* layer, int x, int y, int width, int height) { return - guac_write_string(io, "4.clip,") - || __guac_write_length_int(io, layer->index) - || guac_write_string(io, ",") - || __guac_write_length_int(io, x) - || guac_write_string(io, ",") - || __guac_write_length_int(io, y) - || guac_write_string(io, ",") - || __guac_write_length_int(io, width) - || guac_write_string(io, ",") - || __guac_write_length_int(io, height) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "4.clip,") + || __guac_socket_write_length_int(io, layer->index) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, x) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, y) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, width) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, height) + || guac_socket_write_string(io, ";"); } -typedef struct __guac_write_png_data { +typedef struct __guac_socket_write_png_data { - GUACIO* io; + guac_socket* io; char* buffer; int buffer_size; int data_size; -} __guac_write_png_data; +} __guac_socket_write_png_data; -cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsigned int length) { +cairo_status_t __guac_socket_write_png(void* closure, const unsigned char* data, unsigned int length) { - __guac_write_png_data* png_data = (__guac_write_png_data*) closure; + __guac_socket_write_png_data* png_data = (__guac_socket_write_png_data*) closure; /* Calculate next buffer size */ int next_size = png_data->data_size + length; @@ -262,9 +262,9 @@ cairo_status_t __guac_write_png(void* closure, const unsigned char* data, unsign } -int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) { +int __guac_socket_write_length_png(guac_socket* io, cairo_surface_t* surface) { - __guac_write_png_data png_data; + __guac_socket_write_png_data png_data; int base64_length; /* Write surface */ @@ -274,7 +274,7 @@ int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) { png_data.buffer = malloc(png_data.buffer_size); png_data.data_size = 0; - if (cairo_surface_write_to_png_stream(surface, __guac_write_png, &png_data) != CAIRO_STATUS_SUCCESS) { + if (cairo_surface_write_to_png_stream(surface, __guac_socket_write_png, &png_data) != CAIRO_STATUS_SUCCESS) { return -1; } @@ -282,10 +282,10 @@ int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) { /* Write length and data */ if ( - guac_write_int(io, base64_length) - || guac_write_string(io, ".") - || guac_write_base64(io, png_data.buffer, png_data.data_size) - || guac_flush_base64(io)) { + guac_socket_write_int(io, base64_length) + || guac_socket_write_string(io, ".") + || guac_socket_write_base64(io, png_data.buffer, png_data.data_size) + || guac_socket_flush_base64(io)) { free(png_data.buffer); return -1; } @@ -296,40 +296,40 @@ int __guac_write_length_png(GUACIO* io, cairo_surface_t* surface) { } -int guac_send_png(GUACIO* io, guac_composite_mode mode, +int guac_protocol_send_png(guac_socket* io, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface) { return - guac_write_string(io, "3.png,") - || __guac_write_length_int(io, mode) - || guac_write_string(io, ",") - || __guac_write_length_int(io, layer->index) - || guac_write_string(io, ",") - || __guac_write_length_int(io, x) - || guac_write_string(io, ",") - || __guac_write_length_int(io, y) - || guac_write_string(io, ",") - || __guac_write_length_png(io, surface) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "3.png,") + || __guac_socket_write_length_int(io, mode) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, layer->index) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, x) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, y) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_png(io, surface) + || guac_socket_write_string(io, ";"); } -int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface) { +int guac_protocol_send_cursor(guac_socket* io, int x, int y, cairo_surface_t* surface) { return - guac_write_string(io, "6.cursor,") - || __guac_write_length_int(io, x) - || guac_write_string(io, ",") - || __guac_write_length_int(io, y) - || guac_write_string(io, ",") - || __guac_write_length_png(io, surface) - || guac_write_string(io, ";"); + guac_socket_write_string(io, "6.cursor,") + || __guac_socket_write_length_int(io, x) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_int(io, y) + || guac_socket_write_string(io, ",") + || __guac_socket_write_length_png(io, surface) + || guac_socket_write_string(io, ";"); } -int __guac_fill_instructionbuf(GUACIO* io) { +int __guac_fill_instructionbuf(guac_socket* io) { int retval; @@ -357,7 +357,7 @@ int __guac_fill_instructionbuf(GUACIO* io) { } /* Returns new instruction if one exists, or NULL if no more instructions. */ -guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout) { +guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeout) { int retval; int i = io->__instructionbuf_parse_start; @@ -482,7 +482,7 @@ guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout) { } /* No instruction yet? Get more data ... */ - retval = guac_select(io, usec_timeout); + retval = guac_socket_select(io, usec_timeout); if (retval <= 0) return NULL; @@ -503,28 +503,54 @@ guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout) { } -void guac_free_instruction_data(guac_instruction* instruction) { +guac_instruction* guac_protocol_expect_instruction(guac_socket* io, int usec_timeout, + const char* opcode) { + + guac_instruction* instruction; + + /* Wait for data until timeout */ + if (guac_protocol_instructions_waiting(io, usec_timeout) <= 0) + return NULL; + + /* Read available instruction */ + instruction = guac_protocol_read_instruction(io, usec_timeout); + if (instruction == NULL) + return NULL; + + /* Validate instruction */ + if (strcmp(instruction->opcode, opcode) != 0) { + guac_error = GUAC_STATUS_BAD_STATE; + guac_instruction_free(instruction); + return NULL; + } + + /* Return instruction if valid */ + return instruction; + +} + +void guac_instruction_free_data(guac_instruction* instruction) { free(instruction->opcode); if (instruction->argv) free(instruction->argv); } -void guac_free_instruction(guac_instruction* instruction) { - guac_free_instruction_data(instruction); +void guac_instruction_free(guac_instruction* instruction) { + guac_instruction_free_data(instruction); free(instruction); } -int guac_instructions_waiting(GUACIO* io, int usec_timeout) { +int guac_protocol_instructions_waiting(guac_socket* io, int usec_timeout) { if (io->__instructionbuf_used_length > 0) return 1; - return guac_select(io, usec_timeout); + return guac_socket_select(io, usec_timeout); } -guac_timestamp guac_current_timestamp() { +guac_timestamp guac_protocol_get_timestamp() { #ifdef HAVE_CLOCK_GETTIME diff --git a/libguac/src/guacio.c b/libguac/src/socket.c similarity index 75% rename from libguac/src/guacio.c rename to libguac/src/socket.c index cd523c17..66f5c050 100644 --- a/libguac/src/guacio.c +++ b/libguac/src/socket.c @@ -52,19 +52,19 @@ #include #include -#include "guacio.h" +#include "socket.h" #include "error.h" -char __GUACIO_BASE64_CHARACTERS[64] = { +char __guac_socket_BASE64_CHARACTERS[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', }; -GUACIO* guac_open(int fd) { +guac_socket* guac_socket_open(int fd) { - GUACIO* io = malloc(sizeof(GUACIO)); + guac_socket* io = malloc(sizeof(guac_socket)); /* If no memory available, return with error */ if (io == NULL) { @@ -96,14 +96,14 @@ GUACIO* guac_open(int fd) { } -void guac_close(GUACIO* io) { - guac_flush(io); +void guac_socket_close(guac_socket* io) { + guac_socket_flush(io); free(io->__instructionbuf); free(io); } /* Write bytes, limit rate */ -ssize_t __guac_write(GUACIO* io, const char* buf, int count) { +ssize_t __guac_socket_write(guac_socket* io, const char* buf, int count) { int retval; @@ -140,15 +140,15 @@ int64_t guac_parse_int(const char* str) { } -ssize_t guac_write_int(GUACIO* io, int64_t i) { +ssize_t guac_socket_write_int(guac_socket* io, int64_t i) { char buffer[128]; snprintf(buffer, sizeof(buffer), "%"PRIi64, i); - return guac_write_string(io, buffer); + return guac_socket_write_string(io, buffer); } -ssize_t guac_write_string(GUACIO* io, const char* str) { +ssize_t guac_socket_write_string(guac_socket* io, const char* str) { char* __out_buf = io->__out_buf; @@ -161,7 +161,7 @@ ssize_t guac_write_string(GUACIO* io, const char* str) { /* Flush when necessary, return on error */ if (io->__written > 8188 /* sizeof(__out_buf) - 4 */) { - retval = __guac_write(io, __out_buf, io->__written); + retval = __guac_socket_write(io, __out_buf, io->__written); if (retval < 0) return retval; @@ -175,29 +175,29 @@ ssize_t guac_write_string(GUACIO* io, const char* str) { } -ssize_t __guac_write_base64_triplet(GUACIO* io, int a, int b, int c) { +ssize_t __guac_socket_write_base64_triplet(guac_socket* io, int a, int b, int c) { char* __out_buf = io->__out_buf; int retval; /* Byte 1 */ - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[(a & 0xFC) >> 2]; /* [AAAAAA]AABBBB BBBBCC CCCCCC */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[(a & 0xFC) >> 2]; /* [AAAAAA]AABBBB BBBBCC CCCCCC */ if (b >= 0) { - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4) | ((b & 0xF0) >> 4)]; /* AAAAAA[AABBBB]BBBBCC CCCCCC */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((a & 0x03) << 4) | ((b & 0xF0) >> 4)]; /* AAAAAA[AABBBB]BBBBCC CCCCCC */ if (c >= 0) { - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)]; /* AAAAAA AABBBB[BBBBCC]CCCCCC */ - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[c & 0x3F]; /* AAAAAA AABBBB BBBBCC[CCCCCC] */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)]; /* AAAAAA AABBBB[BBBBCC]CCCCCC */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[c & 0x3F]; /* AAAAAA AABBBB BBBBCC[CCCCCC] */ } else { - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((b & 0x0F) << 2)]; /* AAAAAA AABBBB[BBBB--]------ */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((b & 0x0F) << 2)]; /* AAAAAA AABBBB[BBBB--]------ */ __out_buf[io->__written++] = '='; /* AAAAAA AABBBB BBBB--[------] */ } } else { - __out_buf[io->__written++] = __GUACIO_BASE64_CHARACTERS[((a & 0x03) << 4)]; /* AAAAAA[AA----]------ ------ */ + __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((a & 0x03) << 4)]; /* AAAAAA[AA----]------ ------ */ __out_buf[io->__written++] = '='; /* AAAAAA AA----[------]------ */ __out_buf[io->__written++] = '='; /* AAAAAA AA---- ------[------] */ } @@ -206,7 +206,7 @@ ssize_t __guac_write_base64_triplet(GUACIO* io, int a, int b, int c) { /* Flush when necessary, return on error */ if (io->__written > 8188 /* sizeof(__out_buf) - 4 */) { - retval = __guac_write(io, __out_buf, io->__written); + retval = __guac_socket_write(io, __out_buf, io->__written); if (retval < 0) return retval; @@ -223,7 +223,7 @@ ssize_t __guac_write_base64_triplet(GUACIO* io, int a, int b, int c) { } -ssize_t __guac_write_base64_byte(GUACIO* io, char buf) { +ssize_t __guac_socket_write_base64_byte(guac_socket* io, char buf) { int* __ready_buf = io->__ready_buf; @@ -233,7 +233,7 @@ ssize_t __guac_write_base64_byte(GUACIO* io, char buf) { /* Flush triplet */ if (io->__ready == 3) { - retval = __guac_write_base64_triplet(io, __ready_buf[0], __ready_buf[1], __ready_buf[2]); + retval = __guac_socket_write_base64_triplet(io, __ready_buf[0], __ready_buf[1], __ready_buf[2]); if (retval < 0) return retval; @@ -243,7 +243,7 @@ ssize_t __guac_write_base64_byte(GUACIO* io, char buf) { return 1; } -ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count) { +ssize_t guac_socket_write_base64(guac_socket* io, const void* buf, size_t count) { int retval; @@ -252,7 +252,7 @@ ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count) { while (char_buf < end) { - retval = __guac_write_base64_byte(io, *(char_buf++)); + retval = __guac_socket_write_base64_byte(io, *(char_buf++)); if (retval < 0) return retval; @@ -262,13 +262,13 @@ ssize_t guac_write_base64(GUACIO* io, const void* buf, size_t count) { } -ssize_t guac_flush(GUACIO* io) { +ssize_t guac_socket_flush(guac_socket* io) { int retval; /* Flush remaining bytes in buffer */ if (io->__written > 0) { - retval = __guac_write(io, io->__out_buf, io->__written); + retval = __guac_socket_write(io, io->__out_buf, io->__written); if (retval < 0) return retval; @@ -279,13 +279,13 @@ ssize_t guac_flush(GUACIO* io) { } -ssize_t guac_flush_base64(GUACIO* io) { +ssize_t guac_socket_flush_base64(guac_socket* io) { int retval; /* Flush triplet to output buffer */ while (io->__ready > 0) { - retval = __guac_write_base64_byte(io, -1); + retval = __guac_socket_write_base64_byte(io, -1); if (retval < 0) return retval; } @@ -295,7 +295,7 @@ ssize_t guac_flush_base64(GUACIO* io) { } -int guac_select(GUACIO* io, int usec_timeout) { +int guac_socket_select(guac_socket* io, int usec_timeout) { fd_set fds; struct timeval timeout; From 5428aef91265470a634e3a3af4f1675801215b27 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 25 Nov 2011 12:22:12 -0800 Subject: [PATCH 117/330] Implemented logging functions. --- libguac/src/client.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/libguac/src/client.c b/libguac/src/client.c index 0ba54118..7fc5c473 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -348,3 +348,43 @@ int guac_client_handle_instruction(guac_client* client, guac_instruction* instru } +void vguac_client_log_info(guac_client* client, const char* format, + va_list ap) { + + /* Call handler if defined */ + if (client->log_info_handler != NULL) + client->log_info_handler(client, format, ap); + +} + +void vguac_client_log_error(guac_client* client, const char* format, + va_list ap) { + + /* Call handler if defined */ + if (client->log_error_handler != NULL) + client->log_error_handler(client, format, ap); + +} + +void guac_client_log_info(guac_client* client, const char* format, ...) { + + va_list args; + va_start(args, format); + + vguac_client_log_info(client, format, args); + + va_end(args); + +} + +void guac_client_log_error(guac_client* client, const char* format, ...) { + + va_list args; + va_start(args, format); + + vguac_client_log_error(client, format, args); + + va_end(args); + +} + From ae33a4ca485b5cb8f39e3909c2398e9000ab8746 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 25 Nov 2011 13:04:59 -0800 Subject: [PATCH 118/330] Converted to new guac_client_plugin API --- libguac/include/client.h | 70 ++++++---- libguac/src/client.c | 272 +++++++++++++-------------------------- 2 files changed, 137 insertions(+), 205 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index d3aa7e0a..ce59e00d 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -51,6 +51,7 @@ */ typedef struct guac_client guac_client; +typedef struct guac_client_plugin guac_client_plugin; /** * Handler for server messages (where "server" refers to the server that @@ -84,6 +85,11 @@ typedef int guac_client_free_handler(guac_client* client); */ typedef void guac_client_log_handler(guac_client* client, const char* format, va_list args); +/** + * Handler which should initialize the given guac_client. + */ +typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); + /** * Possible current states of the Guacamole client. Currently, the only * two states are RUNNING and STOPPING. @@ -104,6 +110,33 @@ typedef enum guac_client_state { } guac_client_state; +/** + * A handle to a client plugin, containing enough information about the + * plugin to complete the initial protocol handshake and instantiate a new + * client supporting the protocol provided by the client plugin. + */ +struct guac_client_plugin { + + /** + * Reference to dlopen'd client plugin. + */ + void* __client_plugin_handle; + + /** + * Reference to the init handler of this client plugin. This + * function will be called when the client plugin is started. + */ + guac_client_init_handler* init_handler; + + /** + * NULL-terminated array of all arguments accepted by this client + * plugin, in order. The values of these arguments will be passed + * to the init_handler if the client plugin is started. + */ + const char** args; + +}; + /** * Guacamole proxy client. * @@ -113,10 +146,11 @@ typedef enum guac_client_state { struct guac_client { /** - * The guac_socket structure to be used to communicate with the web-client. It is - * expected that the implementor of any Guacamole proxy client will provide - * their own mechanism of I/O for their protocol. The guac_socket structure is - * used only to communicate conveniently with the Guacamole web-client. + * The guac_socket structure to be used to communicate with the web-client. + * It is expected that the implementor of any Guacamole proxy client will + * provide their own mechanism of I/O for their protocol. The guac_socket + * structure is used only to communicate conveniently with the Guacamole + * web-client. */ guac_socket* io; @@ -157,11 +191,6 @@ struct guac_client { */ guac_timestamp last_sent_timestamp; - /** - * Reference to dlopen'd client plugin. - */ - void* __client_plugin_handle; - /** * Arbitrary reference to proxy client-specific data. Implementors of a * Guacamole proxy client can store any data they want here, which can then @@ -288,7 +317,7 @@ struct guac_client { * * void function_of_daemon() { * - * guac_client* client = [client from guac_get_client()]; + * guac_client* client = [client from guac_client_plugin_get_client()]; * * client->log_info_handler = log_handler; * @@ -315,7 +344,7 @@ struct guac_client { * * void function_of_daemon() { * - * guac_client* client = [client from guac_get_client()]; + * guac_client* client = [client from guac_client_plugin_get_client()]; * * client->log_error_handler = log_handler; * @@ -327,23 +356,18 @@ struct guac_client { }; -/** - * Handler which should initialize the given guac_client. - */ -typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); - /** * Initialize and return a new guac_client. The pluggable client will be - * chosen based on the first connect message received on the given file - * descriptor. + * initialized using the arguments provided. * - * @param client_fd The file descriptor associated with the socket associated - * with the connection to the web-client tunnel. - * @param usec_timeout The maximum number of microseconds to wait for each - * instruction during the initial client handshake. + * @param plugin The client plugin to use to create the new client. + * @param io The guac_socket the client should use for communication. + * @param argc The number of arguments being passed to the client. + * @param argv All arguments to be passed to the client. * @return A pointer to the newly initialized client. */ -guac_client* guac_get_client(int client_fd, int usec_timeout); +guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, + guac_socket* io, int argc, char** argv); /** * Free all resources associated with the given client. diff --git a/libguac/src/client.c b/libguac/src/client.c index 7fc5c473..85f9c72c 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -44,6 +44,7 @@ #include "protocol.h" #include "client.h" #include "client-handlers.h" +#include "error.h" #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) @@ -56,25 +57,6 @@ guac_layer __GUAC_DEFAULT_LAYER = { const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; -guac_client* __guac_alloc_client(guac_socket* io) { - - /* Allocate new client (not handoff) */ - guac_client* client = malloc(sizeof(guac_client)); - memset(client, 0, sizeof(guac_client)); - - /* Init new client */ - client->io = io; - client->last_received_timestamp = client->last_sent_timestamp = guac_protocol_get_timestamp(); - client->state = RUNNING; - - client->__all_layers = NULL; - client->__available_buffers = NULL; - - client->__next_buffer_index = -1; - - return client; -} - guac_layer* guac_client_alloc_layer(guac_client* client, int index) { guac_layer* allocd_layer; @@ -127,10 +109,15 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) { } -guac_client* guac_get_client(int client_fd, int usec_timeout) { +guac_client_plugin* guac_client_plugin_open(const char* protocol) { - guac_client* client; - guac_socket* io = guac_socket_open(client_fd); + guac_client_plugin* plugin; + + /* Reference to dlopen()'d plugin */ + void* client_plugin_handle; + + /* Client args description */ + const char** client_args; /* Pluggable client */ char protocol_lib[256] = "libguac-client-"; @@ -140,179 +127,100 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) { void* obj; } alias; - char* error; - - /* Client args description */ - const char** client_args; - - /* Client arguments */ - int argc; - char** argv; - - /* Instruction */ - guac_instruction* instruction; - - /* Wait for select instruction */ - for (;;) { - - int result; - - /* Wait for data until timeout */ - result = guac_protocol_instructions_waiting(io, usec_timeout); - if (result == 0) { - guac_protocol_send_error(io, "Select timeout."); - guac_socket_close(io); - return NULL; - } - - /* If error occurs while waiting, exit with failure */ - if (result < 0) { - guac_socket_close(io); - return NULL; - } - - instruction = guac_protocol_read_instruction(io, usec_timeout); - if (instruction == NULL) { - guac_socket_close(io); - return NULL; - } - - /* Select instruction read */ - else { - - if (strcmp(instruction->opcode, "select") == 0) { - - /* Get protocol from message */ - char* protocol = instruction->argv[0]; - - strcat(protocol_lib, protocol); - strcat(protocol_lib, ".so"); - - /* Create new client */ - client = __guac_alloc_client(io); - - /* Load client plugin */ - client->__client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); - if (!(client->__client_plugin_handle)) { - guac_client_log_error(client, "Could not open client plugin for protocol \"%s\": %s\n", protocol, dlerror()); - guac_protocol_send_error(io, "Could not load server-side client plugin."); - guac_socket_flush(io); - guac_socket_close(io); - guac_instruction_free(instruction); - return NULL; - } - - dlerror(); /* Clear errors */ - - /* Get init function */ - alias.obj = dlsym(client->__client_plugin_handle, "guac_client_init"); - - if ((error = dlerror()) != NULL) { - guac_client_log_error(client, "Could not get guac_client_init in plugin: %s\n", error); - guac_protocol_send_error(io, "Invalid server-side client plugin."); - guac_socket_flush(io); - guac_socket_close(io); - guac_instruction_free(instruction); - return NULL; - } - - /* Get usage strig */ - client_args = (const char**) dlsym(client->__client_plugin_handle, "GUAC_CLIENT_ARGS"); - - if ((error = dlerror()) != NULL) { - guac_client_log_error(client, "Could not get GUAC_CLIENT_ARGS in plugin: %s\n", error); - guac_protocol_send_error(io, "Invalid server-side client plugin."); - guac_socket_flush(io); - guac_socket_close(io); - guac_instruction_free(instruction); - return NULL; - } - - if ( /* Send args */ - guac_protocol_send_args(io, client_args) - || guac_socket_flush(io) - ) { - guac_socket_close(io); - guac_instruction_free(instruction); - return NULL; - } - - guac_instruction_free(instruction); - break; - - } /* end if select */ - - guac_instruction_free(instruction); - } - + /* Load client plugin */ + client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); + if (!client_plugin_handle) { + guac_error = GUAC_STATUS_BAD_ARGUMENT; + return NULL; } - /* Wait for connect instruction */ - for (;;) { + dlerror(); /* Clear errors */ - int result; - - /* Wait for data until timeout */ - result = guac_protocol_instructions_waiting(io, usec_timeout); - if (result == 0) { - guac_protocol_send_error(io, "Connect timeout."); - guac_socket_close(io); - return NULL; - } - - /* If error occurs while waiting, exit with failure */ - if (result < 0) { - guac_socket_close(io); - return NULL; - } - - instruction = guac_protocol_read_instruction(io, usec_timeout); - if (instruction == NULL) { - guac_client_log_error(client, "Error reading instruction while waiting for connect"); - guac_socket_close(io); - return NULL; - } - - /* Connect instruction read */ - else { - - if (strcmp(instruction->opcode, "connect") == 0) { - - /* Initialize client arguments */ - argc = instruction->argc; - argv = instruction->argv; - - if (alias.client_init(client, argc, argv) != 0) { - /* NOTE: On error, proxy client will send appropriate error message */ - guac_instruction_free(instruction); - guac_socket_close(io); - return NULL; - } - - guac_instruction_free(instruction); - return client; - - } /* end if connect */ - - guac_instruction_free(instruction); - } + /* Get init function */ + alias.obj = dlsym(client_plugin_handle, "guac_client_init"); + /* Fail if cannot find guac_client_init */ + if (dlerror() != NULL) { + guac_error = GUAC_STATUS_BAD_ARGUMENT; + return NULL; } + /* Get usage strig */ + client_args = (const char**) dlsym(client_plugin_handle, "GUAC_CLIENT_ARGS"); + + /* Fail if cannot find GUAC_CLIENT_ARGS */ + if (dlerror() != NULL) { + guac_error = GUAC_STATUS_BAD_ARGUMENT; + return NULL; + } + + /* Allocate plugin */ + plugin = malloc(sizeof(guac_client_plugin)); + if (plugin == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + return NULL; + } + + /* Init and return plugin */ + plugin->__client_plugin_handle = client_plugin_handle; + plugin->init_handler = alias.client_init; + plugin->args = client_args; + return plugin; + +} + +int guac_client_plugin_close(guac_client_plugin* plugin) { + + /* Unload client plugin */ + if (dlclose(plugin->__client_plugin_handle)) { + guac_error = GUAC_STATUS_BAD_STATE; + return -1; + } + + return 0; + +} + +guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, + guac_socket* io, int argc, char** argv) { + + /* Allocate new client */ + guac_client* client = malloc(sizeof(guac_client)); + if (client == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + return NULL; + } + + /* Init new client */ + memset(client, 0, sizeof(guac_client)); + + client->io = io; + client->last_received_timestamp = + client->last_sent_timestamp = guac_protocol_get_timestamp(); + + client->state = RUNNING; + + client->__all_layers = NULL; + client->__available_buffers = NULL; + + client->__next_buffer_index = -1; + + if (plugin->init_handler(client, argc, argv) != 0) { + guac_client_free(client); + return NULL; + } + + return client; + } void guac_client_free(guac_client* client) { if (client->free_handler) { - if (client->free_handler(client)) - guac_client_log_error(client, "Error calling client free handler"); - } - guac_socket_close(client->io); + /* FIXME: Errors currently ignored... */ + client->free_handler(client); - /* Unload client plugin */ - if (dlclose(client->__client_plugin_handle)) { - guac_client_log_error(client, "Could not close client plugin while unloading client: %s", dlerror()); } /* Free all layers */ From 6bd9c00faeec1bbc88a743828ee59fc2ff5eee5c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 25 Nov 2011 13:13:32 -0800 Subject: [PATCH 119/330] Prototypes and docs for plugin functions --- libguac/include/client.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libguac/include/client.h b/libguac/include/client.h index ce59e00d..8d080c6d 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -356,6 +356,27 @@ struct guac_client { }; +/** + * Open the plugin which provides support for the given protocol, if it + * exists. + * + * @param protocol The name of the protocol to retrieve the client plugin + * for. + * @return The client plugin supporting the given protocol, or NULL if + * an error occurs or no such plugin exists. + */ +guac_client_plugin* guac_client_plugin_open(const char* protocol); + +/** + * Close the given plugin, releasing all associated resources. This function + * must be called after use of a client plugin is finished. + * + * @param plugin The client plugin to close. + * @return Zero on success, non-zero if an error occurred while releasing + * the resources associated with the plugin. + */ +int guac_client_plugin_close(guac_client_plugin* plugin); + /** * Initialize and return a new guac_client. The pluggable client will be * initialized using the arguments provided. From c4c30af6a4db953d9f3baf7aae82a999ac32f1e5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 25 Nov 2011 13:18:00 -0800 Subject: [PATCH 120/330] Migrated guac_parse_int to __guac_parse_int, out of socket.h --- libguac/include/socket.h | 11 ----------- libguac/src/client-handlers.c | 21 ++++++++++++++++++++- libguac/src/socket.c | 18 ------------------ 3 files changed, 20 insertions(+), 30 deletions(-) diff --git a/libguac/include/socket.h b/libguac/include/socket.h index 38f8108a..8fd1a113 100644 --- a/libguac/include/socket.h +++ b/libguac/include/socket.h @@ -130,17 +130,6 @@ typedef struct guac_socket { */ guac_socket* guac_socket_open(int fd); -/** - * Parses the given string as a decimal number, returning the result as - * a 64-bit signed value. This value will be 64-bit regardless of platform. - * - * @param str The string to parse into a 64-bit integer. - * @return The 64-bit integer representation of the number in the given - * string, undefined if the string does not contain a properly - * formatted number. - */ -int64_t guac_parse_int(const char* str); - /** * Writes the given unsigned int to the given guac_socket object. The data * written may be buffered until the buffer is flushed automatically or diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index 91e533a2..a6a144f3 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -53,10 +53,29 @@ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { {NULL, NULL} }; +int64_t __guac_parse_int(const char* str) { + + int sign = 1; + int64_t num = 0; + + for (; *str != '\0'; str++) { + + if (*str == '-') + sign = -sign; + else + num = num * 10 + (*str - '0'); + + } + + return num * sign; + +} + + /* Guacamole instruction handlers */ int __guac_handle_sync(guac_client* client, guac_instruction* instruction) { - guac_timestamp timestamp = guac_parse_int(instruction->argv[0]); + guac_timestamp timestamp = __guac_parse_int(instruction->argv[0]); /* Error if timestamp is in future */ if (timestamp > client->last_sent_timestamp) diff --git a/libguac/src/socket.c b/libguac/src/socket.c index 66f5c050..6e247984 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -122,24 +122,6 @@ ssize_t __guac_socket_write(guac_socket* io, const char* buf, int count) { return retval; } -int64_t guac_parse_int(const char* str) { - - int sign = 1; - int64_t num = 0; - - for (; *str != '\0'; str++) { - - if (*str == '-') - sign = -sign; - else - num = num * 10 + (*str - '0'); - - } - - return num * sign; - -} - ssize_t guac_socket_write_int(guac_socket* io, int64_t i) { char buffer[128]; From 8cffca4f137f289e50b491d293e082b417ec8528 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 25 Nov 2011 13:20:41 -0800 Subject: [PATCH 121/330] Removed guac_sleep --- libguac/include/protocol.h | 8 -------- libguac/src/protocol.c | 17 ----------------- 2 files changed, 25 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 302c71e2..adcd4289 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -380,13 +380,5 @@ guac_instruction* guac_protocol_expect_instruction(guac_socket* io, int usec_tim */ guac_timestamp guac_protocol_get_timestamp(); -/** - * Suspends execution of the current thread for the given number of - * milliseconds. - * - * @param millis The number of milliseconds to sleep. - */ -void guac_sleep(int millis); - #endif diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index faafe65d..1f4b2653 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -576,20 +576,3 @@ guac_timestamp guac_protocol_get_timestamp() { } -void guac_sleep(int millis) { - -#ifdef HAVE_NANOSLEEP - struct timespec sleep_period; - - sleep_period.tv_sec = millis / 1000; - sleep_period.tv_nsec = (millis % 1000) * 1000000L; - - nanosleep(&sleep_period, NULL); -#elif defined(__MINGW32__) - Sleep(millis); -#else -#warning No sleep/nanosleep function available. Clients may not perform as expected. Consider patching libguac to add support for your platform. -#endif - -} - From 059ddc0448af12f0264564c26ca5b17b2bb6d430 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 25 Nov 2011 15:15:22 -0800 Subject: [PATCH 122/330] Added version number to Doxyfile --- libguac/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/Doxyfile b/libguac/Doxyfile index 0bfde8d4..812ee0c9 100644 --- a/libguac/Doxyfile +++ b/libguac/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = libguac # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = +PROJECT_NUMBER = 0.5.0 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. From 24a2ad6d129389f60b929eab62b4ca6efd12c2c4 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 25 Nov 2011 16:34:43 -0800 Subject: [PATCH 123/330] Renamed io to socket (in vars) --- libguac/include/client.h | 6 +- libguac/include/protocol.h | 56 +++---- libguac/include/socket.h | 28 ++-- libguac/src/client.c | 4 +- libguac/src/protocol.c | 290 ++++++++++++++++++------------------- libguac/src/socket.c | 124 ++++++++-------- 6 files changed, 254 insertions(+), 254 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 8d080c6d..9ee187ef 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -152,7 +152,7 @@ struct guac_client { * structure is used only to communicate conveniently with the Guacamole * web-client. */ - guac_socket* io; + guac_socket* socket; /** * The current state of the client. When the client is first allocated, @@ -382,13 +382,13 @@ int guac_client_plugin_close(guac_client_plugin* plugin); * initialized using the arguments provided. * * @param plugin The client plugin to use to create the new client. - * @param io The guac_socket the client should use for communication. + * @param socket The guac_socket the client should use for communication. * @param argc The number of arguments being passed to the client. * @param argv All arguments to be passed to the client. * @return A pointer to the newly initialized client. */ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, - guac_socket* io, int argc, char** argv); + guac_socket* socket, int argc, char** argv); /** * Free all resources associated with the given client. diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index adcd4289..f075f8c5 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -155,20 +155,20 @@ void guac_instruction_free(guac_instruction* instruction); * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param args The NULL-terminated array of argument names (strings). * @return Zero on success, non-zero on error. */ -int guac_protocol_send_args(guac_socket* io, const char** name); +int guac_protocol_send_args(guac_socket* socket, const char** name); /** * Sends a name instruction over the given guac_socket connection. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param name The name to send within the name instruction. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_name(guac_socket* io, const char* name); +int guac_protocol_send_name(guac_socket* socket, const char* name); /** * Sends a sync instruction over the given guac_socket connection. The @@ -177,11 +177,11 @@ int guac_protocol_send_name(guac_socket* io, const char* name); * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param timestamp The current timestamp (in milliseconds). * @return Zero on success, non-zero on error. */ -int guac_protocol_send_sync(guac_socket* io, guac_timestamp timestamp); +int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp); /** * Sends an error instruction over the given guac_socket connection. @@ -189,11 +189,11 @@ int guac_protocol_send_sync(guac_socket* io, guac_timestamp timestamp); * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param error The description associated with the error. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_error(guac_socket* io, const char* error); +int guac_protocol_send_error(guac_socket* socket, const char* error); /** * Sends a clipboard instruction over the given guac_socket connection. @@ -201,11 +201,11 @@ int guac_protocol_send_error(guac_socket* io, const char* error); * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param data The clipboard data to send. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_clipboard(guac_socket* io, const char* data); +int guac_protocol_send_clipboard(guac_socket* socket, const char* data); /** * Sends a size instruction over the given guac_socket connection. @@ -213,12 +213,12 @@ int guac_protocol_send_clipboard(guac_socket* io, const char* data); * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param w The width of the display. * @param h The height of the display. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_size(guac_socket* io, int w, int h); +int guac_protocol_send_size(guac_socket* socket, int w, int h); /** * Sends a copy instruction over the given guac_socket connection. @@ -226,7 +226,7 @@ int guac_protocol_send_size(guac_socket* io, int w, int h); * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param srcl The source layer. * @param srcx The X coordinate of the source rectangle. * @param srcy The Y coordinate of the source rectangle. @@ -240,7 +240,7 @@ int guac_protocol_send_size(guac_socket* io, int w, int h); * should be copied. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_copy(guac_socket* io, +int guac_protocol_send_copy(guac_socket* socket, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty); @@ -250,7 +250,7 @@ int guac_protocol_send_copy(guac_socket* io, * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. * @param x The X coordinate of the rectangle. @@ -263,7 +263,7 @@ int guac_protocol_send_copy(guac_socket* io, * @param a The alpha (transparency) component of the color of the rectangle. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_rect(guac_socket* io, +int guac_protocol_send_rect(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, int width, int height, int r, int g, int b, int a); @@ -274,7 +274,7 @@ int guac_protocol_send_rect(guac_socket* io, * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param layer The layer to set the clipping region of. * @param x The X coordinate of the clipping rectangle. * @param y The Y coordinate of the clipping rectangle. @@ -282,7 +282,7 @@ int guac_protocol_send_rect(guac_socket* io, * @param height The height of the clipping rectangle. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_clip(guac_socket* io, const guac_layer* layer, +int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer, int x, int y, int width, int height); /** @@ -292,7 +292,7 @@ int guac_protocol_send_clip(guac_socket* io, const guac_layer* layer, * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. * @param x The destination X coordinate. @@ -300,7 +300,7 @@ int guac_protocol_send_clip(guac_socket* io, const guac_layer* layer, * @param surface A cairo surface containing the image data to send. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_png(guac_socket* io, guac_composite_mode mode, +int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface); /** @@ -310,25 +310,25 @@ int guac_protocol_send_png(guac_socket* io, guac_composite_mode mode, * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param x The X coordinate of the cursor hotspot. * @param y The Y coordinate of the cursor hotspot. * @param surface A cairo surface containing the image data to send. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_cursor(guac_socket* io, int x, int y, cairo_surface_t* surface); +int guac_protocol_send_cursor(guac_socket* socket, int x, int y, cairo_surface_t* surface); /** * Returns whether new instruction data is available on the given guac_socket * connection for parsing. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param usec_timeout The maximum number of microseconds to wait before * giving up. * @return A positive value if data is available, negative on error, or * zero if no data is currently available. */ -int guac_protocol_instructions_waiting(guac_socket* io, int usec_timeout); +int guac_protocol_instructions_waiting(guac_socket* socket, int usec_timeout); /** * Reads a single instruction from the given guac_socket connection. @@ -336,7 +336,7 @@ int guac_protocol_instructions_waiting(guac_socket* io, int usec_timeout); * If an error occurs reading the instruction, NULL is returned, * and guac_error is set appropriately. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param usec_timeout The maximum number of microseconds to wait before * giving up. * @return A new instruction if data was successfully read, NULL on @@ -346,7 +346,7 @@ int guac_protocol_instructions_waiting(guac_socket* io, int usec_timeout); * guac_protocol_read_instruction() will return the parsed instruction once * enough data is available. */ -guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeout); +guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_timeout); /** * Reads a single instruction with the given opcode from the given guac_socket @@ -358,7 +358,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeo * If the instruction read is not the expected instruction, NULL is returned, * and guac_error is set to GUAC_STATUS_BAD_STATE. * - * @param io The guac_socket connection to use. + * @param socket The guac_socket connection to use. * @param usec_timeout The maximum number of microseconds to wait before * giving up. * @param opcode The opcode of the instruction to read. @@ -367,7 +367,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeo * a different opcode, NULL is returned and guac_error is set to * GUAC_STATUS_BAD_STATE. */ -guac_instruction* guac_protocol_expect_instruction(guac_socket* io, int usec_timeout, +guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, int usec_timeout, const char* opcode); /** diff --git a/libguac/include/socket.h b/libguac/include/socket.h index 8fd1a113..dbf745f1 100644 --- a/libguac/include/socket.h +++ b/libguac/include/socket.h @@ -138,11 +138,11 @@ guac_socket* guac_socket_open(int fd); * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The guac_socket object to write to. + * @param socket The guac_socket object to write to. * @param i The unsigned int to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_socket_write_int(guac_socket* io, int64_t i); +ssize_t guac_socket_write_int(guac_socket* socket, int64_t i); /** * Writes the given string to the given guac_socket object. The data @@ -154,11 +154,11 @@ ssize_t guac_socket_write_int(guac_socket* io, int64_t i); * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The guac_socket object to write to. + * @param socket The guac_socket object to write to. * @param str The string to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_socket_write_string(guac_socket* io, const char* str); +ssize_t guac_socket_write_string(guac_socket* socket, const char* str); /** * Writes the given binary data to the given guac_socket object as base64-encoded @@ -171,12 +171,12 @@ ssize_t guac_socket_write_string(guac_socket* io, const char* str); * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The guac_socket object to write to. + * @param socket The guac_socket object to write to. * @param buf A buffer containing the data to write. * @param count The number of bytes to write. * @return Zero on success, or non-zero if an error occurs while writing. */ -ssize_t guac_socket_write_base64(guac_socket* io, const void* buf, size_t count); +ssize_t guac_socket_write_base64(guac_socket* socket, const void* buf, size_t count); /** * Flushes the base64 buffer, writing padding characters as necessary. @@ -184,10 +184,10 @@ ssize_t guac_socket_write_base64(guac_socket* io, const void* buf, size_t count) * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The guac_socket object to flush + * @param socket The guac_socket object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ -ssize_t guac_socket_flush_base64(guac_socket* io); +ssize_t guac_socket_flush_base64(guac_socket* socket); /** * Flushes the write buffer. @@ -195,10 +195,10 @@ ssize_t guac_socket_flush_base64(guac_socket* io); * If an error occurs while writing, a non-zero value is returned, and * guac_error is set appropriately. * - * @param io The guac_socket object to flush + * @param socket The guac_socket object to flush * @return Zero on success, or non-zero if an error occurs during flush. */ -ssize_t guac_socket_flush(guac_socket* io); +ssize_t guac_socket_flush(guac_socket* socket); /** @@ -211,22 +211,22 @@ ssize_t guac_socket_flush(guac_socket* io); * If a timeout occurs while waiting, zero value is returned, and * guac_error is set to GUAC_STATUS_INPUT_TIMEOUT. * - * @param io The guac_socket object to wait for. + * @param socket The guac_socket object to wait for. * @param usec_timeout The maximum number of microseconds to wait for data, or * -1 to potentially wait forever. * @return Positive on success, zero if the timeout elapsed and no data is * available, negative on error. */ -int guac_socket_select(guac_socket* io, int usec_timeout); +int guac_socket_select(guac_socket* socket, int usec_timeout); /** * Frees resources allocated to the given guac_socket object. Note that this * implicitly flush all buffers, but will NOT close the associated file * descriptor. * - * @param io The guac_socket object to close. + * @param socket The guac_socket object to close. */ -void guac_socket_close(guac_socket* io); +void guac_socket_close(guac_socket* socket); #endif diff --git a/libguac/src/client.c b/libguac/src/client.c index 85f9c72c..0ad18a27 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -182,7 +182,7 @@ int guac_client_plugin_close(guac_client_plugin* plugin) { } guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, - guac_socket* io, int argc, char** argv) { + guac_socket* socket, int argc, char** argv) { /* Allocate new client */ guac_client* client = malloc(sizeof(guac_client)); @@ -194,7 +194,7 @@ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, /* Init new client */ memset(client, 0, sizeof(guac_client)); - client->io = io; + client->socket = socket; client->last_received_timestamp = client->last_sent_timestamp = guac_protocol_get_timestamp(); diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 1f4b2653..0b2884ca 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -64,167 +64,167 @@ #include "protocol.h" #include "error.h" -ssize_t __guac_socket_write_length_string(guac_socket* io, const char* str) { +ssize_t __guac_socket_write_length_string(guac_socket* socket, const char* str) { return - guac_socket_write_int(io, strlen(str)) - || guac_socket_write_string(io, ".") - || guac_socket_write_string(io, str); + guac_socket_write_int(socket, strlen(str)) + || guac_socket_write_string(socket, ".") + || guac_socket_write_string(socket, str); } -ssize_t __guac_socket_write_length_int(guac_socket* io, int64_t i) { +ssize_t __guac_socket_write_length_int(guac_socket* socket, int64_t i) { char buffer[128]; snprintf(buffer, sizeof(buffer), "%"PRIi64, i); - return __guac_socket_write_length_string(io, buffer); + return __guac_socket_write_length_string(socket, buffer); } -int guac_protocol_send_args(guac_socket* io, const char** args) { +int guac_protocol_send_args(guac_socket* socket, const char** args) { int i; - if (guac_socket_write_string(io, "4.args")) return -1; + if (guac_socket_write_string(socket, "4.args")) return -1; for (i=0; args[i] != NULL; i++) { - if (guac_socket_write_string(io, ",")) + if (guac_socket_write_string(socket, ",")) return -1; - if (__guac_socket_write_length_string(io, args[i])) + if (__guac_socket_write_length_string(socket, args[i])) return -1; } - return guac_socket_write_string(io, ";"); + return guac_socket_write_string(socket, ";"); } -int guac_protocol_send_name(guac_socket* io, const char* name) { +int guac_protocol_send_name(guac_socket* socket, const char* name) { return - guac_socket_write_string(io, "4.name,") - || __guac_socket_write_length_string(io, name) - || guac_socket_write_string(io, ";"); + guac_socket_write_string(socket, "4.name,") + || __guac_socket_write_length_string(socket, name) + || guac_socket_write_string(socket, ";"); } -int guac_protocol_send_size(guac_socket* io, int w, int h) { +int guac_protocol_send_size(guac_socket* socket, int w, int h) { return - guac_socket_write_string(io, "4.size,") - || __guac_socket_write_length_int(io, w) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, h) - || guac_socket_write_string(io, ";"); + guac_socket_write_string(socket, "4.size,") + || __guac_socket_write_length_int(socket, w) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, h) + || guac_socket_write_string(socket, ";"); } -int guac_protocol_send_clipboard(guac_socket* io, const char* data) { +int guac_protocol_send_clipboard(guac_socket* socket, const char* data) { return - guac_socket_write_string(io, "9.clipboard,") - || __guac_socket_write_length_string(io, data) - || guac_socket_write_string(io, ";"); + guac_socket_write_string(socket, "9.clipboard,") + || __guac_socket_write_length_string(socket, data) + || guac_socket_write_string(socket, ";"); } -int guac_protocol_send_error(guac_socket* io, const char* error) { +int guac_protocol_send_error(guac_socket* socket, const char* error) { return - guac_socket_write_string(io, "5.error,") - || __guac_socket_write_length_string(io, error) - || guac_socket_write_string(io, ";"); + guac_socket_write_string(socket, "5.error,") + || __guac_socket_write_length_string(socket, error) + || guac_socket_write_string(socket, ";"); } -int guac_protocol_send_sync(guac_socket* io, guac_timestamp timestamp) { +int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp) { return - guac_socket_write_string(io, "4.sync,") - || __guac_socket_write_length_int(io, timestamp) - || guac_socket_write_string(io, ";"); + guac_socket_write_string(socket, "4.sync,") + || __guac_socket_write_length_int(socket, timestamp) + || guac_socket_write_string(socket, ";"); } -int guac_protocol_send_copy(guac_socket* io, +int guac_protocol_send_copy(guac_socket* socket, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty) { return - guac_socket_write_string(io, "4.copy,") - || __guac_socket_write_length_int(io, srcl->index) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, srcx) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, srcy) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, w) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, h) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, mode) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, dstl->index) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, dstx) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, dsty) - || guac_socket_write_string(io, ";"); + guac_socket_write_string(socket, "4.copy,") + || __guac_socket_write_length_int(socket, srcl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcy) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, w) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, h) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, mode) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dstl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dstx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dsty) + || guac_socket_write_string(socket, ";"); } -int guac_protocol_send_rect(guac_socket* io, +int guac_protocol_send_rect(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, int width, int height, int r, int g, int b, int a) { return - guac_socket_write_string(io, "4.rect,") - || __guac_socket_write_length_int(io, mode) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, layer->index) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, x) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, y) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, width) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, height) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, r) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, g) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, b) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, a) - || guac_socket_write_string(io, ";"); + guac_socket_write_string(socket, "4.rect,") + || __guac_socket_write_length_int(socket, mode) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, width) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, height) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, r) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, g) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, b) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, a) + || guac_socket_write_string(socket, ";"); } -int guac_protocol_send_clip(guac_socket* io, const guac_layer* layer, +int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer, int x, int y, int width, int height) { return - guac_socket_write_string(io, "4.clip,") - || __guac_socket_write_length_int(io, layer->index) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, x) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, y) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, width) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, height) - || guac_socket_write_string(io, ";"); + guac_socket_write_string(socket, "4.clip,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, width) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, height) + || guac_socket_write_string(socket, ";"); } typedef struct __guac_socket_write_png_data { - guac_socket* io; + guac_socket* socket; char* buffer; int buffer_size; @@ -262,14 +262,14 @@ cairo_status_t __guac_socket_write_png(void* closure, const unsigned char* data, } -int __guac_socket_write_length_png(guac_socket* io, cairo_surface_t* surface) { +int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface) { __guac_socket_write_png_data png_data; int base64_length; /* Write surface */ - png_data.io = io; + png_data.socket = socket; png_data.buffer_size = 8192; png_data.buffer = malloc(png_data.buffer_size); png_data.data_size = 0; @@ -282,10 +282,10 @@ int __guac_socket_write_length_png(guac_socket* io, cairo_surface_t* surface) { /* Write length and data */ if ( - guac_socket_write_int(io, base64_length) - || guac_socket_write_string(io, ".") - || guac_socket_write_base64(io, png_data.buffer, png_data.data_size) - || guac_socket_flush_base64(io)) { + guac_socket_write_int(socket, base64_length) + || guac_socket_write_string(socket, ".") + || guac_socket_write_base64(socket, png_data.buffer, png_data.data_size) + || guac_socket_flush_base64(socket)) { free(png_data.buffer); return -1; } @@ -296,60 +296,60 @@ int __guac_socket_write_length_png(guac_socket* io, cairo_surface_t* surface) { } -int guac_protocol_send_png(guac_socket* io, guac_composite_mode mode, +int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface) { return - guac_socket_write_string(io, "3.png,") - || __guac_socket_write_length_int(io, mode) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, layer->index) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, x) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, y) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_png(io, surface) - || guac_socket_write_string(io, ";"); + guac_socket_write_string(socket, "3.png,") + || __guac_socket_write_length_int(socket, mode) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_png(socket, surface) + || guac_socket_write_string(socket, ";"); } -int guac_protocol_send_cursor(guac_socket* io, int x, int y, cairo_surface_t* surface) { +int guac_protocol_send_cursor(guac_socket* socket, int x, int y, cairo_surface_t* surface) { return - guac_socket_write_string(io, "6.cursor,") - || __guac_socket_write_length_int(io, x) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_int(io, y) - || guac_socket_write_string(io, ",") - || __guac_socket_write_length_png(io, surface) - || guac_socket_write_string(io, ";"); + guac_socket_write_string(socket, "6.cursor,") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_png(socket, surface) + || guac_socket_write_string(socket, ";"); } -int __guac_fill_instructionbuf(guac_socket* io) { +int __guac_fill_instructionbuf(guac_socket* socket) { int retval; /* Attempt to fill buffer */ retval = recv( - io->fd, - io->__instructionbuf + io->__instructionbuf_used_length, - io->__instructionbuf_size - io->__instructionbuf_used_length, + socket->fd, + socket->__instructionbuf + socket->__instructionbuf_used_length, + socket->__instructionbuf_size - socket->__instructionbuf_used_length, 0 ); if (retval < 0) return retval; - io->__instructionbuf_used_length += retval; + socket->__instructionbuf_used_length += retval; /* Expand buffer if necessary */ - if (io->__instructionbuf_used_length > io->__instructionbuf_size / 2) { - io->__instructionbuf_size *= 2; - io->__instructionbuf = realloc(io->__instructionbuf, io->__instructionbuf_size); + if (socket->__instructionbuf_used_length > socket->__instructionbuf_size / 2) { + socket->__instructionbuf_size *= 2; + socket->__instructionbuf = realloc(socket->__instructionbuf, socket->__instructionbuf_size); } return retval; @@ -357,10 +357,10 @@ int __guac_fill_instructionbuf(guac_socket* io) { } /* Returns new instruction if one exists, or NULL if no more instructions. */ -guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeout) { +guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_timeout) { int retval; - int i = io->__instructionbuf_parse_start; + int i = socket->__instructionbuf_parse_start; /* Loop until a instruction is read */ for (;;) { @@ -369,10 +369,10 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeo int element_length = 0; /* Parse instruction in buffe */ - while (i < io->__instructionbuf_used_length) { + while (i < socket->__instructionbuf_used_length) { /* Read character from buffer */ - char c = io->__instructionbuf[i++]; + char c = socket->__instructionbuf[i++]; /* If digit, calculate element length */ if (c >= '0' && c <= '9') @@ -382,10 +382,10 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeo else if (c == '.') { /* Verify element is fully read */ - if (i + element_length < io->__instructionbuf_used_length) { + if (i + element_length < socket->__instructionbuf_used_length) { /* Get element value */ - char* elementv = &(io->__instructionbuf[i]); + char* elementv = &(socket->__instructionbuf[i]); /* Get terminator, set null terminator of elementv */ char terminator = elementv[element_length]; @@ -399,10 +399,10 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeo /* As element has been read successfully, update * parse start */ - io->__instructionbuf_parse_start = i; + socket->__instructionbuf_parse_start = i; /* Save element */ - io->__instructionbuf_elementv[io->__instructionbuf_elementc++] = elementv; + socket->__instructionbuf_elementv[socket->__instructionbuf_elementc++] = elementv; /* Finish parse if terminator is a semicolon */ if (terminator == ';') { @@ -418,7 +418,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeo } /* Init parsed instruction */ - parsed_instruction->argc = io->__instructionbuf_elementc - 1; + parsed_instruction->argc = socket->__instructionbuf_elementc - 1; parsed_instruction->argv = malloc(sizeof(char*) * parsed_instruction->argc); /* Fail if memory could not be alloc'd for argv */ @@ -429,7 +429,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeo } /* Set opcode */ - parsed_instruction->opcode = strdup(io->__instructionbuf_elementv[0]); + parsed_instruction->opcode = strdup(socket->__instructionbuf_elementv[0]); /* Fail if memory could not be alloc'd for opcode */ if (parsed_instruction->opcode == NULL) { @@ -442,7 +442,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeo /* Copy element values to parsed instruction */ for (j=0; jargc; j++) { - parsed_instruction->argv[j] = strdup(io->__instructionbuf_elementv[j+1]); + parsed_instruction->argv[j] = strdup(socket->__instructionbuf_elementv[j+1]); /* Free memory and fail if out of mem */ if (parsed_instruction->argv[j] == NULL) { @@ -461,10 +461,10 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeo } /* Reset buffer */ - memmove(io->__instructionbuf, io->__instructionbuf + i + 1, io->__instructionbuf_used_length - i - 1); - io->__instructionbuf_used_length -= i + 1; - io->__instructionbuf_parse_start = 0; - io->__instructionbuf_elementc = 0; + memmove(socket->__instructionbuf, socket->__instructionbuf + i + 1, socket->__instructionbuf_used_length - i - 1); + socket->__instructionbuf_used_length -= i + 1; + socket->__instructionbuf_parse_start = 0; + socket->__instructionbuf_elementc = 0; /* Done */ return parsed_instruction; @@ -482,12 +482,12 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeo } /* No instruction yet? Get more data ... */ - retval = guac_socket_select(io, usec_timeout); + retval = guac_socket_select(socket, usec_timeout); if (retval <= 0) return NULL; /* If more data is available, fill into buffer */ - retval = __guac_fill_instructionbuf(io); + retval = __guac_fill_instructionbuf(socket); /* Error, guac_error already set */ if (retval < 0) @@ -503,17 +503,17 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* io, int usec_timeo } -guac_instruction* guac_protocol_expect_instruction(guac_socket* io, int usec_timeout, +guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, int usec_timeout, const char* opcode) { guac_instruction* instruction; /* Wait for data until timeout */ - if (guac_protocol_instructions_waiting(io, usec_timeout) <= 0) + if (guac_protocol_instructions_waiting(socket, usec_timeout) <= 0) return NULL; /* Read available instruction */ - instruction = guac_protocol_read_instruction(io, usec_timeout); + instruction = guac_protocol_read_instruction(socket, usec_timeout); if (instruction == NULL) return NULL; @@ -542,12 +542,12 @@ void guac_instruction_free(guac_instruction* instruction) { } -int guac_protocol_instructions_waiting(guac_socket* io, int usec_timeout) { +int guac_protocol_instructions_waiting(guac_socket* socket, int usec_timeout) { - if (io->__instructionbuf_used_length > 0) + if (socket->__instructionbuf_used_length > 0) return 1; - return guac_socket_select(io, usec_timeout); + return guac_socket_select(socket, usec_timeout); } guac_timestamp guac_protocol_get_timestamp() { diff --git a/libguac/src/socket.c b/libguac/src/socket.c index 6e247984..edda22ec 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -64,55 +64,55 @@ char __guac_socket_BASE64_CHARACTERS[64] = { guac_socket* guac_socket_open(int fd) { - guac_socket* io = malloc(sizeof(guac_socket)); + guac_socket* socket = malloc(sizeof(guac_socket)); /* If no memory available, return with error */ - if (io == NULL) { + if (socket == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; return NULL; } - io->__ready = 0; - io->__written = 0; - io->fd = fd; + socket->__ready = 0; + socket->__written = 0; + socket->fd = fd; /* Allocate instruction buffer */ - io->__instructionbuf_size = 1024; - io->__instructionbuf = malloc(io->__instructionbuf_size); + socket->__instructionbuf_size = 1024; + socket->__instructionbuf = malloc(socket->__instructionbuf_size); /* If no memory available, return with error */ - if (io->__instructionbuf == NULL) { + if (socket->__instructionbuf == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; - free(io); + free(socket); return NULL; } /* Init members */ - io->__instructionbuf_used_length = 0; - io->__instructionbuf_parse_start = 0; - io->__instructionbuf_elementc = 0; + socket->__instructionbuf_used_length = 0; + socket->__instructionbuf_parse_start = 0; + socket->__instructionbuf_elementc = 0; - return io; + return socket; } -void guac_socket_close(guac_socket* io) { - guac_socket_flush(io); - free(io->__instructionbuf); - free(io); +void guac_socket_close(guac_socket* socket) { + guac_socket_flush(socket); + free(socket->__instructionbuf); + free(socket); } /* Write bytes, limit rate */ -ssize_t __guac_socket_write(guac_socket* io, const char* buf, int count) { +ssize_t __guac_socket_write(guac_socket* socket, const char* buf, int count) { int retval; #ifdef __MINGW32__ /* MINGW32 WINSOCK only works with send() */ - retval = send(io->fd, buf, count, 0); + retval = send(socket->fd, buf, count, 0); #else /* Use write() for all other platforms */ - retval = write(io->fd, buf, count); + retval = write(socket->fd, buf, count); #endif /* Record errors in guac_error */ @@ -122,33 +122,33 @@ ssize_t __guac_socket_write(guac_socket* io, const char* buf, int count) { return retval; } -ssize_t guac_socket_write_int(guac_socket* io, int64_t i) { +ssize_t guac_socket_write_int(guac_socket* socket, int64_t i) { char buffer[128]; snprintf(buffer, sizeof(buffer), "%"PRIi64, i); - return guac_socket_write_string(io, buffer); + return guac_socket_write_string(socket, buffer); } -ssize_t guac_socket_write_string(guac_socket* io, const char* str) { +ssize_t guac_socket_write_string(guac_socket* socket, const char* str) { - char* __out_buf = io->__out_buf; + char* __out_buf = socket->__out_buf; int retval; for (; *str != '\0'; str++) { - __out_buf[io->__written++] = *str; + __out_buf[socket->__written++] = *str; /* Flush when necessary, return on error */ - if (io->__written > 8188 /* sizeof(__out_buf) - 4 */) { + if (socket->__written > 8188 /* sizeof(__out_buf) - 4 */) { - retval = __guac_socket_write(io, __out_buf, io->__written); + retval = __guac_socket_write(socket, __out_buf, socket->__written); if (retval < 0) return retval; - io->__written = 0; + socket->__written = 0; } } @@ -157,42 +157,42 @@ ssize_t guac_socket_write_string(guac_socket* io, const char* str) { } -ssize_t __guac_socket_write_base64_triplet(guac_socket* io, int a, int b, int c) { +ssize_t __guac_socket_write_base64_triplet(guac_socket* socket, int a, int b, int c) { - char* __out_buf = io->__out_buf; + char* __out_buf = socket->__out_buf; int retval; /* Byte 1 */ - __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[(a & 0xFC) >> 2]; /* [AAAAAA]AABBBB BBBBCC CCCCCC */ + __out_buf[socket->__written++] = __guac_socket_BASE64_CHARACTERS[(a & 0xFC) >> 2]; /* [AAAAAA]AABBBB BBBBCC CCCCCC */ if (b >= 0) { - __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((a & 0x03) << 4) | ((b & 0xF0) >> 4)]; /* AAAAAA[AABBBB]BBBBCC CCCCCC */ + __out_buf[socket->__written++] = __guac_socket_BASE64_CHARACTERS[((a & 0x03) << 4) | ((b & 0xF0) >> 4)]; /* AAAAAA[AABBBB]BBBBCC CCCCCC */ if (c >= 0) { - __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)]; /* AAAAAA AABBBB[BBBBCC]CCCCCC */ - __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[c & 0x3F]; /* AAAAAA AABBBB BBBBCC[CCCCCC] */ + __out_buf[socket->__written++] = __guac_socket_BASE64_CHARACTERS[((b & 0x0F) << 2) | ((c & 0xC0) >> 6)]; /* AAAAAA AABBBB[BBBBCC]CCCCCC */ + __out_buf[socket->__written++] = __guac_socket_BASE64_CHARACTERS[c & 0x3F]; /* AAAAAA AABBBB BBBBCC[CCCCCC] */ } else { - __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((b & 0x0F) << 2)]; /* AAAAAA AABBBB[BBBB--]------ */ - __out_buf[io->__written++] = '='; /* AAAAAA AABBBB BBBB--[------] */ + __out_buf[socket->__written++] = __guac_socket_BASE64_CHARACTERS[((b & 0x0F) << 2)]; /* AAAAAA AABBBB[BBBB--]------ */ + __out_buf[socket->__written++] = '='; /* AAAAAA AABBBB BBBB--[------] */ } } else { - __out_buf[io->__written++] = __guac_socket_BASE64_CHARACTERS[((a & 0x03) << 4)]; /* AAAAAA[AA----]------ ------ */ - __out_buf[io->__written++] = '='; /* AAAAAA AA----[------]------ */ - __out_buf[io->__written++] = '='; /* AAAAAA AA---- ------[------] */ + __out_buf[socket->__written++] = __guac_socket_BASE64_CHARACTERS[((a & 0x03) << 4)]; /* AAAAAA[AA----]------ ------ */ + __out_buf[socket->__written++] = '='; /* AAAAAA AA----[------]------ */ + __out_buf[socket->__written++] = '='; /* AAAAAA AA---- ------[------] */ } - /* At this point, 4 bytes have been io->__written */ + /* At this point, 4 bytes have been socket->__written */ /* Flush when necessary, return on error */ - if (io->__written > 8188 /* sizeof(__out_buf) - 4 */) { - retval = __guac_socket_write(io, __out_buf, io->__written); + if (socket->__written > 8188 /* sizeof(__out_buf) - 4 */) { + retval = __guac_socket_write(socket, __out_buf, socket->__written); if (retval < 0) return retval; - io->__written = 0; + socket->__written = 0; } if (b < 0) @@ -205,27 +205,27 @@ ssize_t __guac_socket_write_base64_triplet(guac_socket* io, int a, int b, int c) } -ssize_t __guac_socket_write_base64_byte(guac_socket* io, char buf) { +ssize_t __guac_socket_write_base64_byte(guac_socket* socket, char buf) { - int* __ready_buf = io->__ready_buf; + int* __ready_buf = socket->__ready_buf; int retval; - __ready_buf[io->__ready++] = buf & 0xFF; + __ready_buf[socket->__ready++] = buf & 0xFF; /* Flush triplet */ - if (io->__ready == 3) { - retval = __guac_socket_write_base64_triplet(io, __ready_buf[0], __ready_buf[1], __ready_buf[2]); + if (socket->__ready == 3) { + retval = __guac_socket_write_base64_triplet(socket, __ready_buf[0], __ready_buf[1], __ready_buf[2]); if (retval < 0) return retval; - io->__ready = 0; + socket->__ready = 0; } return 1; } -ssize_t guac_socket_write_base64(guac_socket* io, const void* buf, size_t count) { +ssize_t guac_socket_write_base64(guac_socket* socket, const void* buf, size_t count) { int retval; @@ -234,7 +234,7 @@ ssize_t guac_socket_write_base64(guac_socket* io, const void* buf, size_t count) while (char_buf < end) { - retval = __guac_socket_write_base64_byte(io, *(char_buf++)); + retval = __guac_socket_write_base64_byte(socket, *(char_buf++)); if (retval < 0) return retval; @@ -244,30 +244,30 @@ ssize_t guac_socket_write_base64(guac_socket* io, const void* buf, size_t count) } -ssize_t guac_socket_flush(guac_socket* io) { +ssize_t guac_socket_flush(guac_socket* socket) { int retval; /* Flush remaining bytes in buffer */ - if (io->__written > 0) { - retval = __guac_socket_write(io, io->__out_buf, io->__written); + if (socket->__written > 0) { + retval = __guac_socket_write(socket, socket->__out_buf, socket->__written); if (retval < 0) return retval; - io->__written = 0; + socket->__written = 0; } return 0; } -ssize_t guac_socket_flush_base64(guac_socket* io) { +ssize_t guac_socket_flush_base64(guac_socket* socket) { int retval; /* Flush triplet to output buffer */ - while (io->__ready > 0) { - retval = __guac_socket_write_base64_byte(io, -1); + while (socket->__ready > 0) { + retval = __guac_socket_write_base64_byte(socket, -1); if (retval < 0) return retval; } @@ -277,7 +277,7 @@ ssize_t guac_socket_flush_base64(guac_socket* io) { } -int guac_socket_select(guac_socket* io, int usec_timeout) { +int guac_socket_select(guac_socket* socket, int usec_timeout) { fd_set fds; struct timeval timeout; @@ -285,7 +285,7 @@ int guac_socket_select(guac_socket* io, int usec_timeout) { /* No timeout if usec_timeout is negative */ if (usec_timeout < 0) - retval = select(io->fd + 1, &fds, NULL, NULL, NULL); + retval = select(socket->fd + 1, &fds, NULL, NULL, NULL); /* Handle timeout if specified */ else { @@ -293,9 +293,9 @@ int guac_socket_select(guac_socket* io, int usec_timeout) { timeout.tv_usec = usec_timeout%1000000; FD_ZERO(&fds); - FD_SET(io->fd, &fds); + FD_SET(socket->fd, &fds); - retval = select(io->fd + 1, &fds, NULL, NULL, &timeout); + retval = select(socket->fd + 1, &fds, NULL, NULL, &timeout); } /* Properly set guac_error */ From e99b470f717cd3dda3b88fa6691c7501649e78ec Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 25 Nov 2011 17:51:15 -0800 Subject: [PATCH 124/330] Stripping include from file paths. --- libguac/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/Doxyfile b/libguac/Doxyfile index 812ee0c9..6dc51a74 100644 --- a/libguac/Doxyfile +++ b/libguac/Doxyfile @@ -114,7 +114,7 @@ FULL_PATH_NAMES = YES # If left blank the directory from which doxygen is run is used as the # path to strip. -STRIP_FROM_PATH = +STRIP_FROM_PATH = include # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells From 7bca78c7a89be170e74d432034f9be154d5bdaa5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 25 Nov 2011 23:48:45 -0800 Subject: [PATCH 125/330] Reject invalid instructions. --- libguac/src/protocol.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 0b2884ca..3585b3c8 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -368,7 +368,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t /* Length of element */ int element_length = 0; - /* Parse instruction in buffe */ + /* Parse instruction in buffer */ while (i < socket->__instructionbuf_used_length) { /* Read character from buffer */ @@ -391,8 +391,8 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t char terminator = elementv[element_length]; elementv[element_length] = '\0'; - /* Move to terminator of element */ - i += element_length; + /* Move to char after terminator of element */ + i += element_length+1; /* Reset element length */ element_length = 0; @@ -471,6 +471,12 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t } /* end if terminator */ + /* Error if expected comma is not present */ + else if (terminator != ',') { + guac_error = GUAC_STATUS_BAD_ARGUMENT; + return NULL; + } + } /* end if element fully read */ /* Otherwise, read more data */ @@ -479,6 +485,12 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t } + /* Error if length is non-numeric or does not end in a period */ + else { + guac_error = GUAC_STATUS_BAD_ARGUMENT; + return NULL; + } + } /* No instruction yet? Get more data ... */ From 61579bd9b7de0ec6cb12baa1527f269d4e92eac1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 26 Nov 2011 00:28:43 -0800 Subject: [PATCH 126/330] Fix library name generation, fix instruction parsing. --- libguac/src/client.c | 4 ++++ libguac/src/protocol.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index 0ad18a27..db53b224 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -127,6 +127,10 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol) { void* obj; } alias; + /* Add protocol and .so suffix to protocol_lib */ + strcat(protocol_lib, protocol); + strcat(protocol_lib, ".so"); + /* Load client plugin */ client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); if (!client_plugin_handle) { diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 3585b3c8..e80d94c7 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -461,8 +461,8 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t } /* Reset buffer */ - memmove(socket->__instructionbuf, socket->__instructionbuf + i + 1, socket->__instructionbuf_used_length - i - 1); - socket->__instructionbuf_used_length -= i + 1; + memmove(socket->__instructionbuf, socket->__instructionbuf + i, socket->__instructionbuf_used_length - i); + socket->__instructionbuf_used_length -= i; socket->__instructionbuf_parse_start = 0; socket->__instructionbuf_elementc = 0; From 989f24be2b06c65b3db7cae3d7630e4b1f065ed8 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 26 Nov 2011 14:50:03 -0800 Subject: [PATCH 127/330] Do not call free handler for client if init does not complete. --- libguac/include/client.h | 3 +++ libguac/src/client.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 9ee187ef..899093ba 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -287,6 +287,9 @@ struct guac_client { * by the proxy, and any data allocated by the proxy client should be * freed. * + * Note that this handler will NOT be called if the client's + * guac_client_init() function fails. + * * Implement this handler if you store data inside the client. * * Example: diff --git a/libguac/src/client.c b/libguac/src/client.c index db53b224..22bb24c5 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -210,7 +210,7 @@ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, client->__next_buffer_index = -1; if (plugin->init_handler(client, argc, argv) != 0) { - guac_client_free(client); + free(client); return NULL; } From 7fdb236001116ccbafa44459eda59623bedebc64 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 26 Nov 2011 16:11:00 -0800 Subject: [PATCH 128/330] Exclude client-handlers.h from generated doc. --- libguac/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/Doxyfile b/libguac/Doxyfile index 6dc51a74..f5ae26bd 100644 --- a/libguac/Doxyfile +++ b/libguac/Doxyfile @@ -603,7 +603,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = +EXCLUDE = include/client-handlers.h # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded From 29d42d0012778b9bac5ba3e8e598a377a190a9ff Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 26 Nov 2011 17:28:12 -0800 Subject: [PATCH 129/330] Improved doc layout --- libguac/.gitignore | 3 +++ libguac/{ => doc}/Doxyfile | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) rename libguac/{ => doc}/Doxyfile (99%) diff --git a/libguac/.gitignore b/libguac/.gitignore index e37f9166..b566155e 100644 --- a/libguac/.gitignore +++ b/libguac/.gitignore @@ -33,3 +33,6 @@ libtool ltmain.sh missing +# Generated docs +doc/doxygen-output + diff --git a/libguac/Doxyfile b/libguac/doc/Doxyfile similarity index 99% rename from libguac/Doxyfile rename to libguac/doc/Doxyfile index f5ae26bd..177293d0 100644 --- a/libguac/Doxyfile +++ b/libguac/doc/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NUMBER = 0.5.0 # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. -OUTPUT_DIRECTORY = doc +OUTPUT_DIRECTORY = doxygen-output # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output @@ -114,7 +114,7 @@ FULL_PATH_NAMES = YES # If left blank the directory from which doxygen is run is used as the # path to strip. -STRIP_FROM_PATH = include +STRIP_FROM_PATH = ../include ../src # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells @@ -574,7 +574,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = +INPUT = ../include ../src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -603,7 +603,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = include/client-handlers.h +EXCLUDE = ../include/client-handlers.h # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded From 2d02a0f3bda014175077a3f9489e07a37804c919 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 26 Nov 2011 20:10:52 -0800 Subject: [PATCH 130/330] Removed guac_instruction_free_data() --- libguac/src/protocol.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index e80d94c7..1f9c7345 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -541,16 +541,19 @@ guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, int usec } -void guac_instruction_free_data(guac_instruction* instruction) { - free(instruction->opcode); - - if (instruction->argv) - free(instruction->argv); -} void guac_instruction_free(guac_instruction* instruction) { - guac_instruction_free_data(instruction); + + /* Free opcode */ + free(instruction->opcode); + + /* Free argv if set (may be NULL of argc is 0) */ + if (instruction->argv) + free(instruction->argv); + + /* Free instruction */ free(instruction); + } From f935075aecffd98e92d6b5d69ac6dd3b5604df74 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 27 Nov 2011 15:57:43 -0800 Subject: [PATCH 131/330] Added guac_error_message. Added error messages to all functions. --- libguac/include/error.h | 13 ++++++++++++ libguac/src/client.c | 6 ++++++ libguac/src/error.c | 45 ++++++++++++++++++++++++++++++++++++++--- libguac/src/protocol.c | 8 ++++++++ libguac/src/socket.c | 17 +++++++++++++--- 5 files changed, 83 insertions(+), 6 deletions(-) diff --git a/libguac/include/error.h b/libguac/include/error.h index af62dcfb..85eabf3c 100644 --- a/libguac/include/error.h +++ b/libguac/include/error.h @@ -116,4 +116,17 @@ const char* guac_status_string(guac_status status); guac_status* __guac_error(); +/** + * Returns a message describing the error which occurred during the last + * function call. If an error occurred, but no message is associated with it, + * NULL is returned. This value is undefined if no error occurred. + * + * The storage of this value is thread-local. Assignment of a message to + * guac_error_message in one thread will not affect its value in another + * thread. + */ +#define guac_error_message (*__guac_error_message()) + +const char** __guac_error_message(); + #endif diff --git a/libguac/src/client.c b/libguac/src/client.c index 22bb24c5..2607d12a 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -135,6 +135,7 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol) { client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); if (!client_plugin_handle) { guac_error = GUAC_STATUS_BAD_ARGUMENT; + guac_error_message = "Client plugin not found"; return NULL; } @@ -146,6 +147,7 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol) { /* Fail if cannot find guac_client_init */ if (dlerror() != NULL) { guac_error = GUAC_STATUS_BAD_ARGUMENT; + guac_error_message = dlerror(); return NULL; } @@ -155,6 +157,7 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol) { /* Fail if cannot find GUAC_CLIENT_ARGS */ if (dlerror() != NULL) { guac_error = GUAC_STATUS_BAD_ARGUMENT; + guac_error_message = dlerror(); return NULL; } @@ -162,6 +165,7 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol) { plugin = malloc(sizeof(guac_client_plugin)); if (plugin == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for client plugin"; return NULL; } @@ -178,6 +182,7 @@ int guac_client_plugin_close(guac_client_plugin* plugin) { /* Unload client plugin */ if (dlclose(plugin->__client_plugin_handle)) { guac_error = GUAC_STATUS_BAD_STATE; + guac_error_message = dlerror(); return -1; } @@ -192,6 +197,7 @@ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, guac_client* client = malloc(sizeof(guac_client)); if (client == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for client"; return NULL; } diff --git a/libguac/src/error.c b/libguac/src/error.c index 67ef367c..869259fe 100644 --- a/libguac/src/error.c +++ b/libguac/src/error.c @@ -107,17 +107,27 @@ const char* guac_status_string(guac_status status) { static pthread_key_t __guac_error_key; static pthread_once_t __guac_error_key_init = PTHREAD_ONCE_INIT; -static void __guac_free_error(void* status) { +static pthread_key_t __guac_error_message_key; +static pthread_once_t __guac_error_message_key_init = PTHREAD_ONCE_INIT; + +static void __guac_free_pointer(void* pointer) { /* Free memory allocated to status variable */ - free(status); + free(pointer); } static void __guac_alloc_error_key() { /* Create key, destroy any allocated variable on thread exit */ - pthread_key_create(&__guac_error_key, __guac_free_error); + pthread_key_create(&__guac_error_key, __guac_free_pointer); + +} + +static void __guac_alloc_error_message_key() { + + /* Create key, destroy any allocated variable on thread exit */ + pthread_key_create(&__guac_error_message_key, __guac_free_pointer); } @@ -142,15 +152,44 @@ guac_status* __guac_error() { } +const char** __guac_error_message() { + + /* Pointer for thread-local data */ + const char** message; + + /* Init error message key, if not already initialized */ + pthread_once( + &__guac_error_message_key_init, + __guac_alloc_error_message_key + ); + + /* Retrieve thread-local message variable */ + message = (const char**) pthread_getspecific(__guac_error_message_key); + + /* Allocate thread-local message variable if not already allocated */ + if (message == NULL) { + message = malloc(sizeof(const char*)); + pthread_setspecific(__guac_error_message_key, message); + } + + return message; + +} + #else /* Default (not-threadsafe) implementation */ static guac_status __guac_error_unsafe_storage; +static const char** __guac_error_message_unsafe_storage; guac_status* __guac_error() { return &__guac_error_unsafe_storage; } +const char** __guac_error_message() { + return &__guac_error_message_unsafe_storage; +} + /* Warn about threadsafety */ #warn No threadsafe implementation of __guac_error exists for your platform, so a default non-threadsafe implementation has been used instead. This may lead to incorrect status codes being reported for failures. Please consider adding support for your platform, or filing a bug report with the Guacamole project. diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 1f9c7345..0ff61bbc 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -414,6 +414,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t parsed_instruction = malloc(sizeof(guac_instruction)); if (parsed_instruction == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for parsed instruction"; return NULL; } @@ -424,6 +425,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t /* Fail if memory could not be alloc'd for argv */ if (parsed_instruction->argv == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for arguments of parsed instruction"; free(parsed_instruction); return NULL; } @@ -434,6 +436,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t /* Fail if memory could not be alloc'd for opcode */ if (parsed_instruction->opcode == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for opcode of parsed instruction"; free(parsed_instruction->argv); free(parsed_instruction); return NULL; @@ -447,6 +450,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t /* Free memory and fail if out of mem */ if (parsed_instruction->argv[j] == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for single argument of parsed instruction"; /* Free all alloc'd argv values */ while (--j >= 0) @@ -474,6 +478,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t /* Error if expected comma is not present */ else if (terminator != ',') { guac_error = GUAC_STATUS_BAD_ARGUMENT; + guac_error_message = "Element terminator of instructioni was not ';' nor ','"; return NULL; } @@ -488,6 +493,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t /* Error if length is non-numeric or does not end in a period */ else { guac_error = GUAC_STATUS_BAD_ARGUMENT; + guac_error_message = "Non-numeric character in element length"; return NULL; } @@ -508,6 +514,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t /* EOF */ if (retval == 0) { guac_error = GUAC_STATUS_NO_INPUT; + guac_error_message = "End of stream reached while reading instruction"; return NULL; } @@ -532,6 +539,7 @@ guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, int usec /* Validate instruction */ if (strcmp(instruction->opcode, opcode) != 0) { guac_error = GUAC_STATUS_BAD_STATE; + guac_error_message = "Instruction read did not have expected opcode"; guac_instruction_free(instruction); return NULL; } diff --git a/libguac/src/socket.c b/libguac/src/socket.c index edda22ec..5b1a3f00 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -69,6 +69,7 @@ guac_socket* guac_socket_open(int fd) { /* If no memory available, return with error */ if (socket == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for socket"; return NULL; } @@ -83,6 +84,7 @@ guac_socket* guac_socket_open(int fd) { /* If no memory available, return with error */ if (socket->__instructionbuf == NULL) { guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for instruction buffer"; free(socket); return NULL; } @@ -116,8 +118,10 @@ ssize_t __guac_socket_write(guac_socket* socket, const char* buf, int count) { #endif /* Record errors in guac_error */ - if (retval < 0) + if (retval < 0) { guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Error writing data to socket"; + } return retval; } @@ -299,8 +303,15 @@ int guac_socket_select(guac_socket* socket, int usec_timeout) { } /* Properly set guac_error */ - if (retval < 0) guac_error = GUAC_STATUS_SEE_ERRNO; - if (retval == 0) guac_error = GUAC_STATUS_INPUT_TIMEOUT; + if (retval < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Error while waiting for data on socket"; + } + + if (retval == 0) { + guac_error = GUAC_STATUS_INPUT_TIMEOUT; + guac_error_message = "Timeout while waiting for data on socket"; + } return retval; From 81bea52e4db9b2eafac1bf10cd0c099a72187922 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 27 Nov 2011 23:38:38 -0800 Subject: [PATCH 132/330] Reset position in buffer each reparse (otherwise, stream will be read corrupt as parser is in wrong state). --- libguac/src/protocol.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 0ff61bbc..71cc0a9f 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -360,14 +360,16 @@ int __guac_fill_instructionbuf(guac_socket* socket) { guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_timeout) { int retval; - int i = socket->__instructionbuf_parse_start; - + /* Loop until a instruction is read */ for (;;) { /* Length of element */ int element_length = 0; + /* Position within buffer */ + int i = socket->__instructionbuf_parse_start; + /* Parse instruction in buffer */ while (i < socket->__instructionbuf_used_length) { From 3c5a54e3031cf5d2e98579e5787bd8e4a58b9429 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 1 Dec 2011 22:57:34 -0800 Subject: [PATCH 133/330] Restored guac_client_stop. --- libguac/include/client.h | 9 +++++++++ libguac/src/client.c | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/libguac/include/client.h b/libguac/include/client.h index 899093ba..2d53d074 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -490,6 +490,15 @@ void vguac_client_log_info(guac_client* client, const char* format, va_list ap); */ void vguac_client_log_error(guac_client* client, const char* format, va_list ap); +/** + * Signals the given client to stop gracefully. This is a completely + * cooperative signal, and can be ignored by the client or the hosting + * daemon. + * + * @param client The proxy client to signal to stop. + */ +void guac_client_stop(guac_client* client); + /** * The default Guacamole client layer, layer 0. */ diff --git a/libguac/src/client.c b/libguac/src/client.c index 2607d12a..3b5eceb1 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -306,3 +306,7 @@ void guac_client_log_error(guac_client* client, const char* format, ...) { } +void guac_client_stop(guac_client* client) { + client->state = STOPPING; +} + From 55f00483e27e4abb02dd239b7ab31066554346d4 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 6 Dec 2011 12:52:18 -0800 Subject: [PATCH 134/330] Should check for cairo/cairo.h, not cairo.h --- libguac/configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/configure.in b/libguac/configure.in index 193dde7e..633f7717 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -56,7 +56,7 @@ AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([wsock32], [main]) # Checks for header files. -AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h time.h sys/time.h syslog.h unistd.h cairo.h]) +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h time.h sys/time.h syslog.h unistd.h cairo/cairo.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T From 1f041e9cee8ccf15fe49337d750ca2ec64cc939b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 11 Dec 2011 14:49:34 -0800 Subject: [PATCH 135/330] Updated README to point to new Trac. --- libguac/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/README b/libguac/README index 221f63a5..01ec4065 100644 --- a/libguac/README +++ b/libguac/README @@ -75,5 +75,5 @@ configure script. Please report any bugs encountered by opening a new ticket at the Trac system hosted at: - http://sourceforge.net/apps/trac/guacamole/ + http://guac-dev.org/trac/ From c8d2f232d6ac2faa9c0f4d1378d9b0b0ec56d02c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 11 Dec 2011 15:00:19 -0800 Subject: [PATCH 136/330] Update changelog --- libguac/ChangeLog | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libguac/ChangeLog b/libguac/ChangeLog index ccbd5d4f..544da378 100644 --- a/libguac/ChangeLog +++ b/libguac/ChangeLog @@ -1,3 +1,14 @@ +2011-12-11 Michael Jumper + + * Added functions for alloc/free of layers and buffers + * Added "clip" instruction + * New, more efficient instruction format + * Fixed guac_write_base64 to match docs + * Added guac_error for error reporting and logging + * Consistent naming conventions + * Migrated daemon-specific functionality to guacd + * Made private members of structs private (using double-underscore prefix) + 2011-03-14 Michael Jumper * Lag control ("sync" message) From a1b93e0802ba15b8772223a216f82778491b7032 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 20 Dec 2011 20:07:31 -0800 Subject: [PATCH 137/330] Bumped version numbers to 0.5.0. --- libguac/configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/configure.in b/libguac/configure.in index 633f7717..174df1bc 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -35,7 +35,7 @@ # ***** END LICENSE BLOCK ***** AC_INIT(src/client.c) -AM_INIT_AUTOMAKE(libguac, 0.4.0) +AM_INIT_AUTOMAKE(libguac, 0.5.0) AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. From 05b0a09a8ab776f0d3e624ce3c5048b092f5a40e Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 21 Dec 2011 01:35:16 -0800 Subject: [PATCH 138/330] Fixed memory leak in guac_instruction_free() --- libguac/src/protocol.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 71cc0a9f..89fe785a 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -554,13 +554,23 @@ guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, int usec void guac_instruction_free(guac_instruction* instruction) { + int argc = instruction->argc; + /* Free opcode */ free(instruction->opcode); /* Free argv if set (may be NULL of argc is 0) */ - if (instruction->argv) + if (instruction->argv) { + + /* All argument values */ + while (argc > 0) + free(instruction->argv[--argc]); + + /* Free actual array */ free(instruction->argv); + } + /* Free instruction */ free(instruction); From 966cdd72711aa025a015b89964b10f84665d59c4 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 21 Dec 2011 01:44:30 -0800 Subject: [PATCH 139/330] Fixed memory leak in guac_client_plugin_close() --- libguac/src/client.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libguac/src/client.c b/libguac/src/client.c index 3b5eceb1..d2df605b 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -186,6 +186,8 @@ int guac_client_plugin_close(guac_client_plugin* plugin) { return -1; } + /* Free plugin handle */ + free(plugin); return 0; } From 27c4e62756da2e570761762eb357f4db40a707bd Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 24 Dec 2011 22:48:15 -0800 Subject: [PATCH 140/330] Renamed RUNNING and STOPPING to GUAC_CLIENT_RUNNING and GUAC_CLIENT_STOPPING. Added GUAC_CLIENT_MOUSE_* masks. --- libguac/include/client.h | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 2d53d074..641d62fc 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -90,9 +90,34 @@ typedef void guac_client_log_handler(guac_client* client, const char* format, va */ typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); +/** + * Button mask value for the left mouse button. + */ +#define GUAC_CLIENT_MOUSE_LEFT 0x01 + +/** + * Button mask value for the middle mouse button. + */ +#define GUAC_CLIENT_MOUSE_MIDDLE 0x02 + +/** + * Button mask value for the right mouse button. + */ +#define GUAC_CLIENT_MOUSE_RIGHT 0x04 + +/** + * Button mask value for scrolling the mouse scrollwheel up. + */ +#define GUAC_CLIENT_MOUSE_SCROLL_UP 0x08 + +/** + * Button mask value for scrolling the mouse scrollwheel down. + */ +#define GUAC_CLIENT_MOUSE_SCROLL_DOWN 0x10 + /** * Possible current states of the Guacamole client. Currently, the only - * two states are RUNNING and STOPPING. + * two states are GUAC_CLIENT_RUNNING and GUAC_CLIENT_STOPPING. */ typedef enum guac_client_state { @@ -100,13 +125,13 @@ typedef enum guac_client_state { * The state of the client from when it has been allocated by the main * daemon until it is killed or disconnected. */ - RUNNING, + GUAC_CLIENT_RUNNING, /** * The state of the client when a stop has been requested, signalling the * I/O threads to shutdown. */ - STOPPING + GUAC_CLIENT_STOPPING } guac_client_state; @@ -156,9 +181,9 @@ struct guac_client { /** * The current state of the client. When the client is first allocated, - * this will be initialized to RUNNING. It will remain at RUNNING until - * an event occurs which requires the client to shutdown, at which point - * the state becomes STOPPING. + * this will be initialized to GUAC_CLIENT_RUNNING. It will remain at + * GUAC_CLIENT_RUNNING until an event occurs which requires the client to + * shutdown, at which point the state becomes GUAC_CLIENT_STOPPING. */ guac_client_state state; From 549c6d4515ae5d30c94848375f3f59d0a001cc19 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 24 Dec 2011 22:49:27 -0800 Subject: [PATCH 141/330] Fixed broken rename. --- libguac/src/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index d2df605b..812f9c60 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -210,7 +210,7 @@ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, client->last_received_timestamp = client->last_sent_timestamp = guac_protocol_get_timestamp(); - client->state = RUNNING; + client->state = GUAC_CLIENT_RUNNING; client->__all_layers = NULL; client->__available_buffers = NULL; @@ -309,6 +309,6 @@ void guac_client_log_error(guac_client* client, const char* format, ...) { } void guac_client_stop(guac_client* client) { - client->state = STOPPING; + client->state = GUAC_CLIENT_STOPPING; } From 5c91834998d57e09408a9a3e8035f0316888311c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 29 Dec 2011 16:40:00 -0800 Subject: [PATCH 142/330] Clarified flag nature of GUAC_CLIENT_MOUSE_* --- libguac/include/client.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 641d62fc..c6d4e86b 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -91,27 +91,35 @@ typedef void guac_client_log_handler(guac_client* client, const char* format, va typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); /** - * Button mask value for the left mouse button. + * The flag set in the mouse button mask when the left mouse button is down. */ #define GUAC_CLIENT_MOUSE_LEFT 0x01 /** - * Button mask value for the middle mouse button. + * The flag set in the mouse button mask when the middle mouse button is down. */ #define GUAC_CLIENT_MOUSE_MIDDLE 0x02 /** - * Button mask value for the right mouse button. + * The flag set in the mouse button mask when the right mouse button is down. */ #define GUAC_CLIENT_MOUSE_RIGHT 0x04 /** - * Button mask value for scrolling the mouse scrollwheel up. + * The flag set in the mouse button mask when the mouse scrollwheel is scrolled + * up. Note that mouse scrollwheels are actually sets of two buttons. One + * button is pressed and released for an upward scroll, and the other is + * pressed and released for a downward scroll. Some mice may actually implement + * these as separate buttons, not a wheel. */ #define GUAC_CLIENT_MOUSE_SCROLL_UP 0x08 /** - * Button mask value for scrolling the mouse scrollwheel down. + * The flag set in the mouse button mask when the mouse scrollwheel is scrolled + * down. Note that mouse scrollwheels are actually sets of two buttons. One + * button is pressed and released for an upward scroll, and the other is + * pressed and released for a downward scroll. Some mice may actually implement + * these as separate buttons, not a wheel. */ #define GUAC_CLIENT_MOUSE_SCROLL_DOWN 0x10 From 180216159f559ebbd3bb487a42201a0e2aba4c70 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 3 Jan 2012 00:03:24 -0800 Subject: [PATCH 143/330] Use dlerror() for errors opening client plugin. --- libguac/src/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index 812f9c60..8e777614 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -135,7 +135,7 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol) { client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); if (!client_plugin_handle) { guac_error = GUAC_STATUS_BAD_ARGUMENT; - guac_error_message = "Client plugin not found"; + guac_error_message = dlerror(); return NULL; } From da27927a3ffe890a0c131320b8ebed94320ba815 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 12 Jan 2012 09:57:34 -0800 Subject: [PATCH 144/330] Require a minimum number of buffers before old free'd buffers are reused, implement LRU strategy for reuse of buffers (oldest free'd buffer). --- libguac/include/client.h | 13 +++++++++++++ libguac/src/client.c | 17 +++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index c6d4e86b..c79c4bc3 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -123,6 +123,14 @@ typedef int guac_client_init_handler(guac_client* client, int argc, char** argv) */ #define GUAC_CLIENT_MOUSE_SCROLL_DOWN 0x10 +/** + * The minimum number of buffers to create before allowing free'd buffers to + * be reclaimed. In the case a protocol rapidly creates, uses, and destroys + * buffers, this can prevent unnecessary reuse of the same buffer (which + * would make draw operations unnecessarily synchronous). + */ +#define GUAC_BUFFER_POOL_INITIAL_SIZE 1024 + /** * Possible current states of the Guacamole client. Currently, the only * two states are GUAC_CLIENT_RUNNING and GUAC_CLIENT_STOPPING. @@ -206,6 +214,11 @@ struct guac_client { */ guac_layer* __available_buffers; + /** + * Pointer to the last buffer in the list of all available buffers. + */ + guac_layer* __last_available_buffer; + /** * The head pointer of the list of all allocated layers, regardless of use * status. diff --git a/libguac/src/client.c b/libguac/src/client.c index 8e777614..ac073535 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -78,10 +78,17 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { guac_layer* allocd_layer; /* If available layers, pop off first available buffer */ - if (client->__available_buffers != NULL) { + if (client->__next_buffer_index <= -GUAC_BUFFER_POOL_INITIAL_SIZE && + client->__available_buffers != NULL) { + allocd_layer = client->__available_buffers; client->__available_buffers = client->__available_buffers->__next_available; allocd_layer->__next_available = NULL; + + /* If last buffer, reset last available buffer pointer */ + if (allocd_layer == client->__last_available_buffer) + client->__last_available_buffer = NULL; + } /* If no available buffer, allocate new buffer, add to __all_layers list */ @@ -103,9 +110,11 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { void guac_client_free_buffer(guac_client* client, guac_layer* layer) { - /* Add layer to pool of available buffers */ - layer->__next_available = client->__available_buffers; - client->__available_buffers = layer; + /* Add layer to tail of pool of available buffers */ + if (client->__last_available_buffer != NULL) + client->__last_available_buffer->__next_available = layer; + + client->__last_available_buffer = layer; } From c339b1299bd6bfb187d5aa5750f1313d9ab65c43 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 12 Jan 2012 10:11:45 -0800 Subject: [PATCH 145/330] Move private struct members to bottom such that public interface is not distrubed when internal changes are made (avoid being forced to increment version, as done now). --- libguac/Makefile.am | 2 +- libguac/include/client.h | 43 ++++++++++++++++++++-------------------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index fff061c1..41bbc815 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -46,5 +46,5 @@ lib_LTLIBRARIES = libguac.la libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handlers.c src/error.c -libguac_la_LDFLAGS = -version-info 2:0:0 +libguac_la_LDFLAGS = -version-info 3:0:0 diff --git a/libguac/include/client.h b/libguac/include/client.h index c79c4bc3..b5d6682d 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -203,28 +203,6 @@ struct guac_client { */ guac_client_state state; - /** - * The index of the next available buffer. - */ - int __next_buffer_index; - - /** - * The head pointer of the list of all available (allocated but not used) - * buffers. - */ - guac_layer* __available_buffers; - - /** - * Pointer to the last buffer in the list of all available buffers. - */ - guac_layer* __last_available_buffer; - - /** - * The head pointer of the list of all allocated layers, regardless of use - * status. - */ - guac_layer* __all_layers; - /** * The time (in milliseconds) of receipt of the last sync message from * the client. @@ -402,6 +380,27 @@ struct guac_client { */ guac_client_log_handler* log_error_handler; + /** + * The index of the next available buffer. + */ + int __next_buffer_index; + + /** + * The head pointer of the list of all available (allocated but not used) + * buffers. + */ + guac_layer* __available_buffers; + + /** + * Pointer to the last buffer in the list of all available buffers. + */ + guac_layer* __last_available_buffer; + + /** + * The head pointer of the list of all allocated layers, regardless of use + * status. + */ + guac_layer* __all_layers; }; From a17cd6202ba0896148ba8492391726c10bd5b895 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 11 Feb 2012 19:00:55 -0800 Subject: [PATCH 146/330] Modified size to be layer-specific, adding layer move instruction. --- libguac/configure.in | 2 +- libguac/include/protocol.h | 26 +++++++++++++++++++++++--- libguac/src/protocol.c | 23 ++++++++++++++++++++++- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index 174df1bc..28cb34bd 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -35,7 +35,7 @@ # ***** END LICENSE BLOCK ***** AC_INIT(src/client.c) -AM_INIT_AUTOMAKE(libguac, 0.5.0) +AM_INIT_AUTOMAKE(libguac, 0.6.0) AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index f075f8c5..da5b7c7d 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -214,11 +214,31 @@ int guac_protocol_send_clipboard(guac_socket* socket, const char* data); * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. - * @param w The width of the display. - * @param h The height of the display. + * @param layer The layer to resize. + * @param w The new width of the layer. + * @param h The new height of the layer. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_size(guac_socket* socket, int w, int h); +int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, + int w, int h); + +/** + * Sends a move instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to move. + * @param parent The parent layer the specified layer will be positioned + * relative to. + * @param x The X coordinate of the layer. + * @param y The Y coordinate of the layer. + * @param z The Z index of the layer, relative to other layers in its parent. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, + const guac_layer* parent, int x, int y, int z); /** * Sends a copy instruction over the given guac_socket connection. diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 89fe785a..4f5c0678 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -110,10 +110,13 @@ int guac_protocol_send_name(guac_socket* socket, const char* name) { } -int guac_protocol_send_size(guac_socket* socket, int w, int h) { +int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, + int w, int h) { return guac_socket_write_string(socket, "4.size,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, w) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, h) @@ -121,6 +124,24 @@ int guac_protocol_send_size(guac_socket* socket, int w, int h) { } +int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, + const guac_layer* parent, int x, int y, int z) { + + return + guac_socket_write_string(socket, "4.move,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, parent->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, z) + || guac_socket_write_string(socket, ";"); + +} + int guac_protocol_send_clipboard(guac_socket* socket, const char* data) { return From 124460b5d9e88579dd52a6a0a0aab577da05d948 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 15 Feb 2012 10:04:31 -0800 Subject: [PATCH 147/330] New cursor instruction format (allowing buffering of cursors). --- libguac/include/protocol.h | 9 +++++++-- libguac/src/protocol.c | 14 +++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index da5b7c7d..d7d282ed 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -333,10 +333,15 @@ int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, * @param socket The guac_socket connection to use. * @param x The X coordinate of the cursor hotspot. * @param y The Y coordinate of the cursor hotspot. - * @param surface A cairo surface containing the image data to send. + * @param srcl The source layer. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_cursor(guac_socket* socket, int x, int y, cairo_surface_t* surface); +int guac_protocol_send_cursor(guac_socket* socket, int x, int y, + const guac_layer* srcl, int srcx, int srcy, int w, int h); /** * Returns whether new instruction data is available on the given guac_socket diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 4f5c0678..6039494c 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -336,15 +336,23 @@ int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, } -int guac_protocol_send_cursor(guac_socket* socket, int x, int y, cairo_surface_t* surface) { - +int guac_protocol_send_cursor(guac_socket* socket, int x, int y, + const guac_layer* srcl, int srcx, int srcy, int w, int h) { return guac_socket_write_string(socket, "6.cursor,") || __guac_socket_write_length_int(socket, x) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, y) || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_png(socket, surface) + || __guac_socket_write_length_int(socket, srcl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcy) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, w) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, h) || guac_socket_write_string(socket, ";"); } From 28e2d41e163a1046aeca337d55f220125f3e61cd Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 20 Feb 2012 12:41:23 -0800 Subject: [PATCH 148/330] Added dispose instruction. --- libguac/include/protocol.h | 12 ++++++++++++ libguac/src/protocol.c | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index d7d282ed..77a0c6a4 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -240,6 +240,18 @@ int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, const guac_layer* parent, int x, int y, int z); +/** + * Sends a dispose instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to dispose. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer); + /** * Sends a copy instruction over the given guac_socket connection. * diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 6039494c..1075e46c 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -142,6 +142,15 @@ int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, } +int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer) { + + return + guac_socket_write_string(socket, "7.dispose,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ";"); + +} + int guac_protocol_send_clipboard(guac_socket* socket, const char* data) { return From 7d7a0260bf778a2c3134ad2c04330c006474bc16 Mon Sep 17 00:00:00 2001 From: Matt Hortman Date: Tue, 21 Feb 2012 11:20:32 -0500 Subject: [PATCH 149/330] added constants for raster operations --- libguac/include/protocol.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) mode change 100644 => 100755 libguac/include/protocol.h diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h old mode 100644 new mode 100755 index d7d282ed..822b0566 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -90,7 +90,12 @@ typedef enum guac_composite_mode { GUAC_COMP_IN = 0x4, /* 0100 */ GUAC_COMP_OUT = 0x8, /* 1000 */ GUAC_COMP_RATOP = 0x9, /* 1001 */ - GUAC_COMP_SRC = 0xC /* 1100 */ + GUAC_COMP_SRC = 0xC, /* 1100 */ + + GUAC_COMP_OR = 0xF0, /* perform OR ternary raster operation */ + GUAC_COMP_AND = 0xF1, /* perform AND ternary raster operation */ + GUAC_COMP_XOR2 = 0xF2, /* perform XOR ternary raster operation */ + GUAC_COMP_NOR = 0xF3 /* perform NOR ternary raster operation */ } guac_composite_mode; From 8348900db9b3945be41bf154936a73176ec9747e Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 23 Feb 2012 14:41:33 -0800 Subject: [PATCH 150/330] Prototypes for new instruction functions. --- libguac/include/protocol.h | 170 +++++++++++++++++++++++++++++++++++-- 1 file changed, 161 insertions(+), 9 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 77a0c6a4..1c37a3af 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -283,23 +283,144 @@ int guac_protocol_send_copy(guac_socket* socket, * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. - * @param mode The composite mode to use. * @param layer The destination layer. * @param x The X coordinate of the rectangle. * @param y The Y coordinate of the rectangle. * @param width The width of the rectangle. * @param height The height of the rectangle. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_rect(guac_socket* socket, const guac_layer* layer, + int x, int y, int width, int height); + +/** + * Sends an lpath instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @param x The X coordinate of the point to add to the path. + * @param y The Y coordinate of the point to add to the path. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_lpath(guac_socket* socket, const guac_layer* layer, + int x, int y); + +/** + * Sends a qpath instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @param x The X coordinate of the point to add to the path. + * @param y The Y coordinate of the point to add to the path. + * @param cpx The X coordinate of the control point. + * @param cpy The Y coordinate of the control point. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_qpath(guac_socket* socket, const guac_layer* layer, + +/** + * Sends a cpath instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @param x The X coordinate of the point to add to the path. + * @param y The Y coordinate of the point to add to the path. + * @param cp1x The X coordinate of the first control point. + * @param cp1y The Y coordinate of the first control point. + * @param cp2x The X coordinate of the second control point. + * @param cp2y The Y coordinate of the second control point. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_cpath(guac_socket* socket, const guac_layer* layer, + int x, int y, int cp1x, int cp1y, int cp2x, int cp2y); + +/** + * Sends a cfill instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. * @param r The red component of the color of the rectangle. * @param g The green component of the color of the rectangle. * @param b The blue component of the color of the rectangle. * @param a The alpha (transparency) component of the color of the rectangle. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_rect(guac_socket* socket, +int guac_protocol_send_cfill(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, - int x, int y, int width, int height, int r, int g, int b, int a); +/** + * Sends an rfill instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param srcl The source layer. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_rfill(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + const guac_layer* srcl, int srcx, int srcy, int w, int h); + +/** + * Sends a cstroke instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param r The red component of the color of the rectangle. + * @param g The green component of the color of the rectangle. + * @param b The blue component of the color of the rectangle. + * @param a The alpha (transparency) component of the color of the rectangle. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_cstroke(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + int r, int g, int b, int a); + +/** + * Sends an rstroke instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param srcl The source layer. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_rstroke(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + const guac_layer* srcl, int srcx, int srcy, int w, int h); + /** * Sends a clip instruction over the given guac_socket connection. * @@ -308,14 +429,45 @@ int guac_protocol_send_rect(guac_socket* socket, * * @param socket The guac_socket connection to use. * @param layer The layer to set the clipping region of. - * @param x The X coordinate of the clipping rectangle. - * @param y The Y coordinate of the clipping rectangle. - * @param width The width of the clipping rectangle. - * @param height The height of the clipping rectangle. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer, - int x, int y, int width, int height); +int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer); + +/** + * Sends a push instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to set the clipping region of. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_push(guac_socket* socket, const guac_layer* layer); + +/** + * Sends a pop instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to set the clipping region of. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_pop(guac_socket* socket, const guac_layer* layer); + +/** + * Sends a reset instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to set the clipping region of. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer); /** * Sends a png instruction over the given guac_socket connection. The PNG image data From e110b9ce92dbfeeee68b6cb50ffeba21f3399235 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 23 Feb 2012 14:44:48 -0800 Subject: [PATCH 151/330] LICENSE and Doxyfile should be present in source tarball (fixes ticket #84). --- libguac/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 41bbc815..a0b2f5bd 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -48,3 +48,5 @@ libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handler libguac_la_LDFLAGS = -version-info 3:0:0 +EXTRA_DIST = LICENSE doc/Doxyfile + From f77e0dbcc8e1a10dddb76402ed492a11ca79783b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Feb 2012 01:02:04 -0800 Subject: [PATCH 152/330] Fully enumerate raster operations. --- libguac/include/protocol.h | 44 ++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 8b6db447..5a13a65d 100755 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -92,10 +92,46 @@ typedef enum guac_composite_mode { GUAC_COMP_RATOP = 0x9, /* 1001 */ GUAC_COMP_SRC = 0xC, /* 1100 */ - GUAC_COMP_OR = 0xF0, /* perform OR ternary raster operation */ - GUAC_COMP_AND = 0xF1, /* perform AND ternary raster operation */ - GUAC_COMP_XOR2 = 0xF2, /* perform XOR ternary raster operation */ - GUAC_COMP_NOR = 0xF3 /* perform NOR ternary raster operation */ + /* Bitwise composite operations (binary) */ + + /* + * A: S' & D' + * B: S' & D + * C: S & D' + * D: S & D + * + * 0 = Active, 1 = Inactive + */ + + /* ABCD */ + GUAC_COMP_BINARY_BLACK = 0x10, /* 0000 */ + GUAC_COMP_BINARY_WHITE = 0x1F, /* 1111 */ + + GUAC_COMP_BINARY_SRC = 0x13, /* 0011 */ + GUAC_COMP_BINARY_DEST = 0x15, /* 0101 */ + GUAC_COMP_BINARY_NSRC = 0x1C, /* 1100 */ + GUAC_COMP_BINARY_NDEST = 0x1A, /* 1010 */ + + GUAC_COMP_BINARY_AND = 0x11, /* 0001 */ + GUAC_COMP_BINARY_NAND = 0x1E, /* 1110 */ + + GUAC_COMP_BINARY_OR = 0x17, /* 0111 */ + GUAC_COMP_BINARY_NOR = 0x18, /* 1000 */ + + GUAC_COMP_BINARY_XOR = 0x16, /* 0110 */ + GUAC_COMP_BINARY_XNOR = 0x19, /* 1001 */ + + GUAC_COMP_BINARY_NSRC_AND = 0x14, /* 0100 */ + GUAC_COMP_BINARY_NSRC_NAND = 0x1B, /* 1011 */ + + GUAC_COMP_BINARY_NSRC_OR = 0x1D, /* 1101 */ + GUAC_COMP_BINARY_NSRC_NOR = 0x12, /* 0010 */ + + GUAC_COMP_BINARY_NDEST_AND = 0x12, /* 0010 */ + GUAC_COMP_BINARY_NDEST_NAND = 0x1D, /* 1101 */ + + GUAC_COMP_BINARY_NDEST_OR = 0x1B, /* 1011 */ + GUAC_COMP_BINARY_NDEST_NOR = 0x14 /* 0100 */ } guac_composite_mode; From 3942cabfd027cc0bd4d4e81968faabc2b54054c2 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Feb 2012 10:26:58 -0800 Subject: [PATCH 153/330] Improved comments for raster ops. --- libguac/include/protocol.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 5a13a65d..5c957819 100755 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -103,33 +103,41 @@ typedef enum guac_composite_mode { * 0 = Active, 1 = Inactive */ - /* ABCD */ + /* Constant functions */ /* ABCD */ GUAC_COMP_BINARY_BLACK = 0x10, /* 0000 */ GUAC_COMP_BINARY_WHITE = 0x1F, /* 1111 */ + /* Copy functions */ GUAC_COMP_BINARY_SRC = 0x13, /* 0011 */ GUAC_COMP_BINARY_DEST = 0x15, /* 0101 */ GUAC_COMP_BINARY_NSRC = 0x1C, /* 1100 */ GUAC_COMP_BINARY_NDEST = 0x1A, /* 1010 */ + /* AND / NAND */ GUAC_COMP_BINARY_AND = 0x11, /* 0001 */ GUAC_COMP_BINARY_NAND = 0x1E, /* 1110 */ + /* OR / NOR */ GUAC_COMP_BINARY_OR = 0x17, /* 0111 */ GUAC_COMP_BINARY_NOR = 0x18, /* 1000 */ + /* XOR / XNOR */ GUAC_COMP_BINARY_XOR = 0x16, /* 0110 */ GUAC_COMP_BINARY_XNOR = 0x19, /* 1001 */ + /* AND / NAND with inverted source */ GUAC_COMP_BINARY_NSRC_AND = 0x14, /* 0100 */ GUAC_COMP_BINARY_NSRC_NAND = 0x1B, /* 1011 */ + /* OR / NOR with inverted source */ GUAC_COMP_BINARY_NSRC_OR = 0x1D, /* 1101 */ GUAC_COMP_BINARY_NSRC_NOR = 0x12, /* 0010 */ + /* AND / NAND with inverted destination */ GUAC_COMP_BINARY_NDEST_AND = 0x12, /* 0010 */ GUAC_COMP_BINARY_NDEST_NAND = 0x1D, /* 1101 */ + /* OR / NOR with inverted destination */ GUAC_COMP_BINARY_NDEST_OR = 0x1B, /* 1011 */ GUAC_COMP_BINARY_NDEST_NOR = 0x14 /* 0100 */ From 13db6307b65cc1fa946bab6bde9aaaf397f2bb93 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Feb 2012 10:27:46 -0800 Subject: [PATCH 154/330] Changed tabs to spaces. --- libguac/include/protocol.h | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 5c957819..2b347b1c 100755 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -104,42 +104,42 @@ typedef enum guac_composite_mode { */ /* Constant functions */ /* ABCD */ - GUAC_COMP_BINARY_BLACK = 0x10, /* 0000 */ - GUAC_COMP_BINARY_WHITE = 0x1F, /* 1111 */ + GUAC_COMP_BINARY_BLACK = 0x10, /* 0000 */ + GUAC_COMP_BINARY_WHITE = 0x1F, /* 1111 */ /* Copy functions */ - GUAC_COMP_BINARY_SRC = 0x13, /* 0011 */ - GUAC_COMP_BINARY_DEST = 0x15, /* 0101 */ - GUAC_COMP_BINARY_NSRC = 0x1C, /* 1100 */ - GUAC_COMP_BINARY_NDEST = 0x1A, /* 1010 */ + GUAC_COMP_BINARY_SRC = 0x13, /* 0011 */ + GUAC_COMP_BINARY_DEST = 0x15, /* 0101 */ + GUAC_COMP_BINARY_NSRC = 0x1C, /* 1100 */ + GUAC_COMP_BINARY_NDEST = 0x1A, /* 1010 */ /* AND / NAND */ - GUAC_COMP_BINARY_AND = 0x11, /* 0001 */ - GUAC_COMP_BINARY_NAND = 0x1E, /* 1110 */ + GUAC_COMP_BINARY_AND = 0x11, /* 0001 */ + GUAC_COMP_BINARY_NAND = 0x1E, /* 1110 */ /* OR / NOR */ - GUAC_COMP_BINARY_OR = 0x17, /* 0111 */ - GUAC_COMP_BINARY_NOR = 0x18, /* 1000 */ + GUAC_COMP_BINARY_OR = 0x17, /* 0111 */ + GUAC_COMP_BINARY_NOR = 0x18, /* 1000 */ /* XOR / XNOR */ - GUAC_COMP_BINARY_XOR = 0x16, /* 0110 */ - GUAC_COMP_BINARY_XNOR = 0x19, /* 1001 */ + GUAC_COMP_BINARY_XOR = 0x16, /* 0110 */ + GUAC_COMP_BINARY_XNOR = 0x19, /* 1001 */ /* AND / NAND with inverted source */ - GUAC_COMP_BINARY_NSRC_AND = 0x14, /* 0100 */ - GUAC_COMP_BINARY_NSRC_NAND = 0x1B, /* 1011 */ + GUAC_COMP_BINARY_NSRC_AND = 0x14, /* 0100 */ + GUAC_COMP_BINARY_NSRC_NAND = 0x1B, /* 1011 */ /* OR / NOR with inverted source */ - GUAC_COMP_BINARY_NSRC_OR = 0x1D, /* 1101 */ - GUAC_COMP_BINARY_NSRC_NOR = 0x12, /* 0010 */ + GUAC_COMP_BINARY_NSRC_OR = 0x1D, /* 1101 */ + GUAC_COMP_BINARY_NSRC_NOR = 0x12, /* 0010 */ /* AND / NAND with inverted destination */ - GUAC_COMP_BINARY_NDEST_AND = 0x12, /* 0010 */ - GUAC_COMP_BINARY_NDEST_NAND = 0x1D, /* 1101 */ + GUAC_COMP_BINARY_NDEST_AND = 0x12, /* 0010 */ + GUAC_COMP_BINARY_NDEST_NAND = 0x1D, /* 1101 */ /* OR / NOR with inverted destination */ - GUAC_COMP_BINARY_NDEST_OR = 0x1B, /* 1011 */ - GUAC_COMP_BINARY_NDEST_NOR = 0x14 /* 0100 */ + GUAC_COMP_BINARY_NDEST_OR = 0x1B, /* 1011 */ + GUAC_COMP_BINARY_NDEST_NOR = 0x14 /* 0100 */ } guac_composite_mode; From 54cc87093a1cb8f63ddd2e85b9607a4b025bb176 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Feb 2012 10:36:46 -0800 Subject: [PATCH 155/330] Removed execute permissions from source. --- libguac/include/protocol.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 libguac/include/protocol.h diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h old mode 100755 new mode 100644 From 554d6e1ec1c86ba75c12187fe693864c9bcb4435 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Feb 2012 12:28:12 -0800 Subject: [PATCH 156/330] Implemented transfer instruction, initial transfer function definitions. --- libguac/include/protocol.h | 77 +++++++++++++++++++++++++++----------- libguac/src/protocol.c | 27 +++++++++++++ 2 files changed, 82 insertions(+), 22 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 2b347b1c..1539c323 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -103,45 +103,54 @@ typedef enum guac_composite_mode { * 0 = Active, 1 = Inactive */ - /* Constant functions */ /* ABCD */ - GUAC_COMP_BINARY_BLACK = 0x10, /* 0000 */ - GUAC_COMP_BINARY_WHITE = 0x1F, /* 1111 */ +} guac_composite_mode; + + +/** + * Default transfer functions. There is no current facility in the + * Guacamole protocol to define custom transfer functions. + */ +typedef enum guac_transfer_function { + + /* Constant functions */ /* ABCD */ + GUAC_TRANSFER_BINARY_BLACK = 0x10, /* 0000 */ + GUAC_TRANSFER_BINARY_WHITE = 0x1F, /* 1111 */ /* Copy functions */ - GUAC_COMP_BINARY_SRC = 0x13, /* 0011 */ - GUAC_COMP_BINARY_DEST = 0x15, /* 0101 */ - GUAC_COMP_BINARY_NSRC = 0x1C, /* 1100 */ - GUAC_COMP_BINARY_NDEST = 0x1A, /* 1010 */ + GUAC_TRANSFER_BINARY_SRC = 0x13, /* 0011 */ + GUAC_TRANSFER_BINARY_DEST = 0x15, /* 0101 */ + GUAC_TRANSFER_BINARY_NSRC = 0x1C, /* 1100 */ + GUAC_TRANSFER_BINARY_NDEST = 0x1A, /* 1010 */ /* AND / NAND */ - GUAC_COMP_BINARY_AND = 0x11, /* 0001 */ - GUAC_COMP_BINARY_NAND = 0x1E, /* 1110 */ + GUAC_TRANSFER_BINARY_AND = 0x11, /* 0001 */ + GUAC_TRANSFER_BINARY_NAND = 0x1E, /* 1110 */ /* OR / NOR */ - GUAC_COMP_BINARY_OR = 0x17, /* 0111 */ - GUAC_COMP_BINARY_NOR = 0x18, /* 1000 */ + GUAC_TRANSFER_BINARY_OR = 0x17, /* 0111 */ + GUAC_TRANSFER_BINARY_NOR = 0x18, /* 1000 */ /* XOR / XNOR */ - GUAC_COMP_BINARY_XOR = 0x16, /* 0110 */ - GUAC_COMP_BINARY_XNOR = 0x19, /* 1001 */ + GUAC_TRANSFER_BINARY_XOR = 0x16, /* 0110 */ + GUAC_TRANSFER_BINARY_XNOR = 0x19, /* 1001 */ /* AND / NAND with inverted source */ - GUAC_COMP_BINARY_NSRC_AND = 0x14, /* 0100 */ - GUAC_COMP_BINARY_NSRC_NAND = 0x1B, /* 1011 */ + GUAC_TRANSFER_BINARY_NSRC_AND = 0x14, /* 0100 */ + GUAC_TRANSFER_BINARY_NSRC_NAND = 0x1B, /* 1011 */ /* OR / NOR with inverted source */ - GUAC_COMP_BINARY_NSRC_OR = 0x1D, /* 1101 */ - GUAC_COMP_BINARY_NSRC_NOR = 0x12, /* 0010 */ + GUAC_TRANSFER_BINARY_NSRC_OR = 0x1D, /* 1101 */ + GUAC_TRANSFER_BINARY_NSRC_NOR = 0x12, /* 0010 */ /* AND / NAND with inverted destination */ - GUAC_COMP_BINARY_NDEST_AND = 0x12, /* 0010 */ - GUAC_COMP_BINARY_NDEST_NAND = 0x1D, /* 1101 */ + GUAC_TRANSFER_BINARY_NDEST_AND = 0x12, /* 0010 */ + GUAC_TRANSFER_BINARY_NDEST_NAND = 0x1D, /* 1101 */ /* OR / NOR with inverted destination */ - GUAC_COMP_BINARY_NDEST_OR = 0x1B, /* 1011 */ - GUAC_COMP_BINARY_NDEST_NOR = 0x14 /* 0100 */ + GUAC_TRANSFER_BINARY_NDEST_OR = 0x1B, /* 1011 */ + GUAC_TRANSFER_BINARY_NDEST_NOR = 0x14 /* 0100 */ -} guac_composite_mode; +} guac_transfer_function; typedef struct guac_layer guac_layer; @@ -325,6 +334,30 @@ int guac_protocol_send_copy(guac_socket* socket, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty); +/** + * Sends a transfer instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param srcl The source layer. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. + * @param fn The transfer function to use. + * @param dstl The destination layer. + * @param dstx The X coordinate of the destination, where the source rectangle + * should be copied. + * @param dsty The Y coordinate of the destination, where the source rectangle + * should be copied. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_transfer(guac_socket* socket, + const guac_layer* srcl, int srcx, int srcy, int w, int h, + guac_transfer_function fn, const guac_layer* dstl, int dstx, int dsty); + /** * Sends a rect instruction over the given guac_socket connection. * diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 1075e46c..58e1d7f7 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -204,6 +204,33 @@ int guac_protocol_send_copy(guac_socket* socket, } +int guac_protocol_send_transfer(guac_socket* socket, + const guac_layer* srcl, int srcx, int srcy, int w, int h, + guac_transfer_function fn, const guac_layer* dstl, int dstx, int dsty) { + + return + guac_socket_write_string(socket, "8.transfer,") + || __guac_socket_write_length_int(socket, srcl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcy) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, w) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, h) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, fn) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dstl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dstx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dsty) + || guac_socket_write_string(socket, ";"); + +} + int guac_protocol_send_rect(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, int width, int height, From c55bef0c4144a5efc9ca864392b3e8da23b34928 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Feb 2012 13:14:19 -0800 Subject: [PATCH 157/330] Fix transfer function indices. --- libguac/include/protocol.h | 42 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 1539c323..11727fec 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -112,43 +112,43 @@ typedef enum guac_composite_mode { */ typedef enum guac_transfer_function { - /* Constant functions */ /* ABCD */ - GUAC_TRANSFER_BINARY_BLACK = 0x10, /* 0000 */ - GUAC_TRANSFER_BINARY_WHITE = 0x1F, /* 1111 */ + /* Constant functions */ /* ABCD */ + GUAC_TRANSFER_BINARY_BLACK = 0x0, /* 0000 */ + GUAC_TRANSFER_BINARY_WHITE = 0xF, /* 1111 */ /* Copy functions */ - GUAC_TRANSFER_BINARY_SRC = 0x13, /* 0011 */ - GUAC_TRANSFER_BINARY_DEST = 0x15, /* 0101 */ - GUAC_TRANSFER_BINARY_NSRC = 0x1C, /* 1100 */ - GUAC_TRANSFER_BINARY_NDEST = 0x1A, /* 1010 */ + GUAC_TRANSFER_BINARY_SRC = 0x3, /* 0011 */ + GUAC_TRANSFER_BINARY_DEST = 0x5, /* 0101 */ + GUAC_TRANSFER_BINARY_NSRC = 0xC, /* 1100 */ + GUAC_TRANSFER_BINARY_NDEST = 0xA, /* 1010 */ /* AND / NAND */ - GUAC_TRANSFER_BINARY_AND = 0x11, /* 0001 */ - GUAC_TRANSFER_BINARY_NAND = 0x1E, /* 1110 */ + GUAC_TRANSFER_BINARY_AND = 0x1, /* 0001 */ + GUAC_TRANSFER_BINARY_NAND = 0xE, /* 1110 */ /* OR / NOR */ - GUAC_TRANSFER_BINARY_OR = 0x17, /* 0111 */ - GUAC_TRANSFER_BINARY_NOR = 0x18, /* 1000 */ + GUAC_TRANSFER_BINARY_OR = 0x7, /* 0111 */ + GUAC_TRANSFER_BINARY_NOR = 0x8, /* 1000 */ /* XOR / XNOR */ - GUAC_TRANSFER_BINARY_XOR = 0x16, /* 0110 */ - GUAC_TRANSFER_BINARY_XNOR = 0x19, /* 1001 */ + GUAC_TRANSFER_BINARY_XOR = 0x6, /* 0110 */ + GUAC_TRANSFER_BINARY_XNOR = 0x9, /* 1001 */ /* AND / NAND with inverted source */ - GUAC_TRANSFER_BINARY_NSRC_AND = 0x14, /* 0100 */ - GUAC_TRANSFER_BINARY_NSRC_NAND = 0x1B, /* 1011 */ + GUAC_TRANSFER_BINARY_NSRC_AND = 0x4, /* 0100 */ + GUAC_TRANSFER_BINARY_NSRC_NAND = 0xB, /* 1011 */ /* OR / NOR with inverted source */ - GUAC_TRANSFER_BINARY_NSRC_OR = 0x1D, /* 1101 */ - GUAC_TRANSFER_BINARY_NSRC_NOR = 0x12, /* 0010 */ + GUAC_TRANSFER_BINARY_NSRC_OR = 0xD, /* 1101 */ + GUAC_TRANSFER_BINARY_NSRC_NOR = 0x2, /* 0010 */ /* AND / NAND with inverted destination */ - GUAC_TRANSFER_BINARY_NDEST_AND = 0x12, /* 0010 */ - GUAC_TRANSFER_BINARY_NDEST_NAND = 0x1D, /* 1101 */ + GUAC_TRANSFER_BINARY_NDEST_AND = 0x2, /* 0010 */ + GUAC_TRANSFER_BINARY_NDEST_NAND = 0xD, /* 1101 */ /* OR / NOR with inverted destination */ - GUAC_TRANSFER_BINARY_NDEST_OR = 0x1B, /* 1011 */ - GUAC_TRANSFER_BINARY_NDEST_NOR = 0x14 /* 0100 */ + GUAC_TRANSFER_BINARY_NDEST_OR = 0xB, /* 1011 */ + GUAC_TRANSFER_BINARY_NDEST_NOR = 0x4 /* 0100 */ } guac_transfer_function; From ee324aed69651f3f498537f0b77fc64d24245c2f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Feb 2012 16:01:02 -0800 Subject: [PATCH 158/330] Fixed merge of unstable, refactored rect and clip. --- libguac/include/protocol.h | 5 +++-- libguac/src/protocol.c | 25 ++----------------------- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 24459a39..70e3e8b7 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -405,6 +405,7 @@ int guac_protocol_send_lpath(guac_socket* socket, const guac_layer* layer, * @return Zero on success, non-zero on error. */ int guac_protocol_send_qpath(guac_socket* socket, const guac_layer* layer, + int x, int y, int cpx, int cpy); /** * Sends a cpath instruction over the given guac_socket connection. @@ -638,8 +639,8 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t * a different opcode, NULL is returned and guac_error is set to * GUAC_STATUS_BAD_STATE. */ -guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, int usec_timeout, - const char* opcode); +guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, + int usec_timeout, const char* opcode); /** * Returns an arbitrary timestamp. The difference between return values of any diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 58e1d7f7..fae8ed67 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -232,14 +232,10 @@ int guac_protocol_send_transfer(guac_socket* socket, } int guac_protocol_send_rect(guac_socket* socket, - guac_composite_mode mode, const guac_layer* layer, - int x, int y, int width, int height, - int r, int g, int b, int a) { + const guac_layer* layer, int x, int y, int width, int height) { return guac_socket_write_string(socket, "4.rect,") - || __guac_socket_write_length_int(socket, mode) - || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, layer->index) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, x) @@ -249,32 +245,15 @@ int guac_protocol_send_rect(guac_socket* socket, || __guac_socket_write_length_int(socket, width) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, height) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, r) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, g) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, b) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, a) || guac_socket_write_string(socket, ";"); } -int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer, - int x, int y, int width, int height) { +int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer) { return guac_socket_write_string(socket, "4.clip,") || __guac_socket_write_length_int(socket, layer->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, x) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, y) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, width) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, height) || guac_socket_write_string(socket, ";"); } From 33e028f1f4adf7462ce58b4f2c70676ae4a99a99 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Feb 2012 22:56:38 -0800 Subject: [PATCH 159/330] Refactored guac_client_alloc_layer(), implement guac_client_free_layer(). --- libguac/include/client.h | 33 ++++++++++++++++++++++++---- libguac/src/client.c | 47 +++++++++++++++++++++++++++++++++------- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index b5d6682d..3f4a4a1d 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -396,6 +396,22 @@ struct guac_client { */ guac_layer* __last_available_buffer; + /** + * The index of the next available layer. + */ + int __next_layer_index; + + /** + * The head pointer of the list of all available (allocated but not used) + * layers. + */ + guac_layer* __available_layers; + + /** + * Pointer to the last layer in the list of all available layers. + */ + guac_layer* __last_available_layer; + /** * The head pointer of the list of all allocated layers, regardless of use * status. @@ -467,14 +483,13 @@ int guac_client_handle_instruction(guac_client* client, guac_instruction* instru guac_layer* guac_client_alloc_buffer(guac_client* client); /** - * Allocates a new layer. The layer will be given the specified index, - * even if the layer returned was a previously used (and free'd) layer. + * Allocates a new layer. An arbitrary index is automatically assigned + * if no existing layer is available for use. * * @param client The proxy client to allocate the layer buffer for. - * @param index The index of the layer to allocate. * @return The next available layer, or a newly allocated layer. */ -guac_layer* guac_client_alloc_layer(guac_client* client, int index); +guac_layer* guac_client_alloc_layer(guac_client* client); /** * Returns the given buffer to the pool of available buffers, such that it @@ -485,6 +500,16 @@ guac_layer* guac_client_alloc_layer(guac_client* client, int index); */ void guac_client_free_buffer(guac_client* client, guac_layer* layer); +/** + * Returns the given layer to the pool of available layers, such that it + * can be reused by any subsequent call to guac_client_allow_layer(). + * + * @param client The proxy client to return the layer to. + * @param layer The buffer to return to the pool of available layer. + */ +void guac_client_free_layer(guac_client* client, guac_layer* layer); + + /** * Logs an informational message in the log used by the given client. The * logger used will normally be defined by guacd (or whichever program loads diff --git a/libguac/src/client.c b/libguac/src/client.c index ac073535..f247bf0b 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -57,18 +57,37 @@ guac_layer __GUAC_DEFAULT_LAYER = { const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; -guac_layer* guac_client_alloc_layer(guac_client* client, int index) { +guac_layer* guac_client_alloc_layer(guac_client* client) { guac_layer* allocd_layer; - /* Init new layer */ - allocd_layer = malloc(sizeof(guac_layer)); + /* If available layers, pop off first available layer */ + if (client->__next_layer_index >= GUAC_BUFFER_POOL_INITIAL_SIZE && + client->__available_layers != NULL) { - /* Add to __all_layers list */ - allocd_layer->__next = client->__all_layers; - client->__all_layers = allocd_layer; + allocd_layer = client->__available_layers; + client->__available_layers = client->__available_layers->__next_available; + allocd_layer->__next_available = NULL; + + /* If last layer, reset last available layer pointer */ + if (allocd_layer == client->__last_available_layer) + client->__last_available_layer = NULL; + + } + + /* If no available layer, allocate new layer, add to __all_layers list */ + else { + + /* Init new layer */ + allocd_layer = malloc(sizeof(guac_layer)); + allocd_layer->index = client->__next_layer_index++; + + /* Add to __all_layers list */ + allocd_layer->__next = client->__all_layers; + client->__all_layers = allocd_layer; + + } - allocd_layer->index = index; return allocd_layer; } @@ -118,6 +137,16 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) { } +void guac_client_free_layer(guac_client* client, guac_layer* layer) { + + /* Add layer to tail of pool of available layers */ + if (client->__last_available_layer != NULL) + client->__last_available_layer->__next_available = layer; + + client->__last_available_layer = layer; + +} + guac_client_plugin* guac_client_plugin_open(const char* protocol) { guac_client_plugin* plugin; @@ -222,9 +251,11 @@ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, client->state = GUAC_CLIENT_RUNNING; client->__all_layers = NULL; - client->__available_buffers = NULL; + client->__available_buffers = client->__last_available_buffer = NULL; + client->__available_layers = client->__last_available_layer = NULL; client->__next_buffer_index = -1; + client->__next_layer_index = 1; if (plugin->init_handler(client, argc, argv) != 0) { free(client); From 878d8a406ce5d87ff5d2cd6d13747d16b8c37801 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 6 Mar 2012 12:42:38 -0800 Subject: [PATCH 160/330] Add line cap and join styles. --- libguac/include/protocol.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 70e3e8b7..adcb8644 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -152,6 +152,24 @@ typedef enum guac_transfer_function { } guac_transfer_function; +/** + * Supported line cap styles + */ +typedef enum guac_line_cap_style { + GUAC_LINE_CAP_BUTT = 0x0, + GUAC_LINE_CAP_ROUND = 0x1, + GUAC_LINE_CAP_SQUARE = 0x2, +} guac_line_cap; + +/** + * Supported line join styles + */ +typedef enum guac_line_join_style { + GUAC_LINE_JOIN_BEVEL = 0x0, + GUAC_LINE_JOIN_MITRE = 0x1, + GUAC_LINE_JOIN_ROUND = 0x2, +} guac_line_join; + typedef struct guac_layer guac_layer; /** @@ -474,6 +492,9 @@ int guac_protocol_send_rfill(guac_socket* socket, * @param socket The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. + * @param cap The style of line cap to use when drawing the stroke. + * @param join The style of line join to use when drawing the stroke. + * @param thickness The thickness of the stroke in pixels. * @param r The red component of the color of the rectangle. * @param g The green component of the color of the rectangle. * @param b The blue component of the color of the rectangle. @@ -482,6 +503,7 @@ int guac_protocol_send_rfill(guac_socket* socket, */ int guac_protocol_send_cstroke(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, + guac_line_cap_style cap, guac_line_join_style join, int thickness, int r, int g, int b, int a); /** @@ -493,6 +515,9 @@ int guac_protocol_send_cstroke(guac_socket* socket, * @param socket The guac_socket connection to use. * @param mode The composite mode to use. * @param layer The destination layer. + * @param cap The style of line cap to use when drawing the stroke. + * @param join The style of line join to use when drawing the stroke. + * @param thickness The thickness of the stroke in pixels. * @param srcl The source layer. * @param srcx The X coordinate of the source rectangle. * @param srcy The Y coordinate of the source rectangle. @@ -502,6 +527,7 @@ int guac_protocol_send_cstroke(guac_socket* socket, */ int guac_protocol_send_rstroke(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, + guac_line_cap_style cap, guac_line_join_style join, int thickness, const guac_layer* srcl, int srcx, int srcy, int w, int h); /** From 4595ed51f373ee4b196bb3e686234a5c9e3b704e Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 10 Mar 2012 12:56:59 -0800 Subject: [PATCH 161/330] Alphabetized and organized instruction functions, reformatted and fixed comments. --- libguac/include/protocol.h | 780 ++++++++++++++++++------------------- 1 file changed, 384 insertions(+), 396 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index adcb8644..7577cd04 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -159,7 +159,7 @@ typedef enum guac_line_cap_style { GUAC_LINE_CAP_BUTT = 0x0, GUAC_LINE_CAP_ROUND = 0x1, GUAC_LINE_CAP_SQUARE = 0x2, -} guac_line_cap; +} guac_line_cap_style; /** * Supported line join styles @@ -168,7 +168,7 @@ typedef enum guac_line_join_style { GUAC_LINE_JOIN_BEVEL = 0x0, GUAC_LINE_JOIN_MITRE = 0x1, GUAC_LINE_JOIN_ROUND = 0x2, -} guac_line_join; +} guac_line_join_style; typedef struct guac_layer guac_layer; @@ -225,397 +225,6 @@ typedef struct guac_instruction { */ void guac_instruction_free(guac_instruction* instruction); -/** - * Sends an args instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param args The NULL-terminated array of argument names (strings). - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_args(guac_socket* socket, const char** name); - -/** - * Sends a name instruction over the given guac_socket connection. - * - * @param socket The guac_socket connection to use. - * @param name The name to send within the name instruction. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_name(guac_socket* socket, const char* name); - -/** - * Sends a sync instruction over the given guac_socket connection. The - * current time in milliseconds should be passed in as the timestamp. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param timestamp The current timestamp (in milliseconds). - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp); - -/** - * Sends an error instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param error The description associated with the error. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_error(guac_socket* socket, const char* error); - -/** - * Sends a clipboard instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param data The clipboard data to send. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_clipboard(guac_socket* socket, const char* data); - -/** - * Sends a size instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The layer to resize. - * @param w The new width of the layer. - * @param h The new height of the layer. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, - int w, int h); - -/** - * Sends a move instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The layer to move. - * @param parent The parent layer the specified layer will be positioned - * relative to. - * @param x The X coordinate of the layer. - * @param y The Y coordinate of the layer. - * @param z The Z index of the layer, relative to other layers in its parent. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, - const guac_layer* parent, int x, int y, int z); - -/** - * Sends a dispose instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The layer to dispose. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer); - -/** - * Sends a copy instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param srcl The source layer. - * @param srcx The X coordinate of the source rectangle. - * @param srcy The Y coordinate of the source rectangle. - * @param w The width of the source rectangle. - * @param h The height of the source rectangle. - * @param mode The composite mode to use. - * @param dstl The destination layer. - * @param dstx The X coordinate of the destination, where the source rectangle - * should be copied. - * @param dsty The Y coordinate of the destination, where the source rectangle - * should be copied. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_copy(guac_socket* socket, - const guac_layer* srcl, int srcx, int srcy, int w, int h, - guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty); - -/** - * Sends a transfer instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param srcl The source layer. - * @param srcx The X coordinate of the source rectangle. - * @param srcy The Y coordinate of the source rectangle. - * @param w The width of the source rectangle. - * @param h The height of the source rectangle. - * @param fn The transfer function to use. - * @param dstl The destination layer. - * @param dstx The X coordinate of the destination, where the source rectangle - * should be copied. - * @param dsty The Y coordinate of the destination, where the source rectangle - * should be copied. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_transfer(guac_socket* socket, - const guac_layer* srcl, int srcx, int srcy, int w, int h, - guac_transfer_function fn, const guac_layer* dstl, int dstx, int dsty); - -/** - * Sends a rect instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The destination layer. - * @param x The X coordinate of the rectangle. - * @param y The Y coordinate of the rectangle. - * @param width The width of the rectangle. - * @param height The height of the rectangle. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_rect(guac_socket* socket, const guac_layer* layer, - int x, int y, int width, int height); - -/** - * Sends an lpath instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The destination layer. - * @param x The X coordinate of the point to add to the path. - * @param y The Y coordinate of the point to add to the path. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_lpath(guac_socket* socket, const guac_layer* layer, - int x, int y); - -/** - * Sends a qpath instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The destination layer. - * @param x The X coordinate of the point to add to the path. - * @param y The Y coordinate of the point to add to the path. - * @param cpx The X coordinate of the control point. - * @param cpy The Y coordinate of the control point. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_qpath(guac_socket* socket, const guac_layer* layer, - int x, int y, int cpx, int cpy); - -/** - * Sends a cpath instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The destination layer. - * @param x The X coordinate of the point to add to the path. - * @param y The Y coordinate of the point to add to the path. - * @param cp1x The X coordinate of the first control point. - * @param cp1y The Y coordinate of the first control point. - * @param cp2x The X coordinate of the second control point. - * @param cp2y The Y coordinate of the second control point. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_cpath(guac_socket* socket, const guac_layer* layer, - int x, int y, int cp1x, int cp1y, int cp2x, int cp2y); - -/** - * Sends a cfill instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param mode The composite mode to use. - * @param layer The destination layer. - * @param r The red component of the color of the rectangle. - * @param g The green component of the color of the rectangle. - * @param b The blue component of the color of the rectangle. - * @param a The alpha (transparency) component of the color of the rectangle. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_cfill(guac_socket* socket, - guac_composite_mode mode, const guac_layer* layer, - int r, int g, int b, int a); - -/** - * Sends an rfill instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param mode The composite mode to use. - * @param layer The destination layer. - * @param srcl The source layer. - * @param srcx The X coordinate of the source rectangle. - * @param srcy The Y coordinate of the source rectangle. - * @param w The width of the source rectangle. - * @param h The height of the source rectangle. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_rfill(guac_socket* socket, - guac_composite_mode mode, const guac_layer* layer, - const guac_layer* srcl, int srcx, int srcy, int w, int h); - -/** - * Sends a cstroke instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param mode The composite mode to use. - * @param layer The destination layer. - * @param cap The style of line cap to use when drawing the stroke. - * @param join The style of line join to use when drawing the stroke. - * @param thickness The thickness of the stroke in pixels. - * @param r The red component of the color of the rectangle. - * @param g The green component of the color of the rectangle. - * @param b The blue component of the color of the rectangle. - * @param a The alpha (transparency) component of the color of the rectangle. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_cstroke(guac_socket* socket, - guac_composite_mode mode, const guac_layer* layer, - guac_line_cap_style cap, guac_line_join_style join, int thickness, - int r, int g, int b, int a); - -/** - * Sends an rstroke instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param mode The composite mode to use. - * @param layer The destination layer. - * @param cap The style of line cap to use when drawing the stroke. - * @param join The style of line join to use when drawing the stroke. - * @param thickness The thickness of the stroke in pixels. - * @param srcl The source layer. - * @param srcx The X coordinate of the source rectangle. - * @param srcy The Y coordinate of the source rectangle. - * @param w The width of the source rectangle. - * @param h The height of the source rectangle. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_rstroke(guac_socket* socket, - guac_composite_mode mode, const guac_layer* layer, - guac_line_cap_style cap, guac_line_join_style join, int thickness, - const guac_layer* srcl, int srcx, int srcy, int w, int h); - -/** - * Sends a clip instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The layer to set the clipping region of. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer); - -/** - * Sends a push instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The layer to set the clipping region of. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_push(guac_socket* socket, const guac_layer* layer); - -/** - * Sends a pop instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The layer to set the clipping region of. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_pop(guac_socket* socket, const guac_layer* layer); - -/** - * Sends a reset instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The layer to set the clipping region of. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer); - -/** - * Sends a png instruction over the given guac_socket connection. The PNG image data - * given will be automatically base64-encoded for transmission. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param mode The composite mode to use. - * @param layer The destination layer. - * @param x The destination X coordinate. - * @param y The destination Y coordinate. - * @param surface A cairo surface containing the image data to send. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, - const guac_layer* layer, int x, int y, cairo_surface_t* surface); - -/** - * Sends a cursor instruction over the given guac_socket connection. The PNG image - * data given will be automatically base64-encoded for transmission. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param x The X coordinate of the cursor hotspot. - * @param y The Y coordinate of the cursor hotspot. - * @param srcl The source layer. - * @param srcx The X coordinate of the source rectangle. - * @param srcy The Y coordinate of the source rectangle. - * @param w The width of the source rectangle. - * @param h The height of the source rectangle. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_cursor(guac_socket* socket, int x, int y, - const guac_layer* srcl, int srcx, int srcy, int w, int h); - /** * Returns whether new instruction data is available on the given guac_socket * connection for parsing. @@ -641,10 +250,11 @@ int guac_protocol_instructions_waiting(guac_socket* socket, int usec_timeout); * error or if the instruction could not be read completely * because the timeout elapsed, in which case guac_error will be * set to GUAC_STATUS_INPUT_TIMEOUT and subsequent calls to - * guac_protocol_read_instruction() will return the parsed instruction once - * enough data is available. + * guac_protocol_read_instruction() will return the parsed instruction + * once enough data is available. */ -guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_timeout); +guac_instruction* guac_protocol_read_instruction(guac_socket* socket, + int usec_timeout); /** * Reads a single instruction with the given opcode from the given guac_socket @@ -678,5 +288,383 @@ guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, */ guac_timestamp guac_protocol_get_timestamp(); +/* CONTROL INSTRUCTIONS */ + +/** + * Sends an args instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param args The NULL-terminated array of argument names (strings). + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_args(guac_socket* socket, const char** args); + +/* TODO: guac_protocol_send_connect */ +/* TODO: guac_protocol_send_disconnect */ + +/** + * Sends an error instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param error The description associated with the error. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_error(guac_socket* socket, const char* error); + +/* TODO: guac_protocol_send_set */ +/* TODO: guac_protocol_send_select */ + +/** + * Sends a sync instruction over the given guac_socket connection. The + * current time in milliseconds should be passed in as the timestamp. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param timestamp The current timestamp (in milliseconds). + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp); + +/* DRAWING INSTRUCTIONS */ + +/** + * Sends a cfill instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param r The red component of the color of the rectangle. + * @param g The green component of the color of the rectangle. + * @param b The blue component of the color of the rectangle. + * @param a The alpha (transparency) component of the color of the rectangle. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_cfill(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + int r, int g, int b, int a); + +/** + * Sends a clip instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to set the clipping region of. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer); + +/** + * Sends a copy instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param srcl The source layer. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. + * @param mode The composite mode to use. + * @param dstl The destination layer. + * @param dstx The X coordinate of the destination, where the source rectangle + * should be copied. + * @param dsty The Y coordinate of the destination, where the source rectangle + * should be copied. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_copy(guac_socket* socket, + const guac_layer* srcl, int srcx, int srcy, int w, int h, + guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty); + +/** + * Sends a cstroke instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param cap The style of line cap to use when drawing the stroke. + * @param join The style of line join to use when drawing the stroke. + * @param thickness The thickness of the stroke in pixels. + * @param r The red component of the color of the rectangle. + * @param g The green component of the color of the rectangle. + * @param b The blue component of the color of the rectangle. + * @param a The alpha (transparency) component of the color of the rectangle. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_cstroke(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + guac_line_cap_style cap, guac_line_join_style join, int thickness, + int r, int g, int b, int a); + +/** + * Sends a cursor instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param x The X coordinate of the cursor hotspot. + * @param y The Y coordinate of the cursor hotspot. + * @param srcl The source layer. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_cursor(guac_socket* socket, int x, int y, + const guac_layer* srcl, int srcx, int srcy, int w, int h); + +/** + * Sends a path instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @param x The X coordinate of the point to add to the path. + * @param y The Y coordinate of the point to add to the path. + * @param cp1x The X coordinate of the first control point. + * @param cp1y The Y coordinate of the first control point. + * @param cp2x The X coordinate of the second control point. + * @param cp2y The Y coordinate of the second control point. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_path(guac_socket* socket, const guac_layer* layer, + int x, int y, int cp1x, int cp1y, int cp2x, int cp2y); + +/** + * Sends a png instruction over the given guac_socket connection. The PNG image + * data given will be automatically base64-encoded for transmission. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param x The destination X coordinate. + * @param y The destination Y coordinate. + * @param surface A cairo surface containing the image data to send. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, + const guac_layer* layer, int x, int y, cairo_surface_t* surface); + +/** + * Sends a pop instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to set the clipping region of. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_pop(guac_socket* socket, const guac_layer* layer); + +/** + * Sends a push instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to set the clipping region of. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_push(guac_socket* socket, const guac_layer* layer); + +/** + * Sends a rect instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @param x The X coordinate of the rectangle. + * @param y The Y coordinate of the rectangle. + * @param width The width of the rectangle. + * @param height The height of the rectangle. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_rect(guac_socket* socket, const guac_layer* layer, + int x, int y, int width, int height); + +/** + * Sends a reset instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to set the clipping region of. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer); + +/** + * Sends an rfill instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param srcl The source layer. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_rfill(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + const guac_layer* srcl, int srcx, int srcy, int w, int h); + +/** + * Sends an rstroke instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param cap The style of line cap to use when drawing the stroke. + * @param join The style of line join to use when drawing the stroke. + * @param thickness The thickness of the stroke in pixels. + * @param srcl The source layer. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_rstroke(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + guac_line_cap_style cap, guac_line_join_style join, int thickness, + const guac_layer* srcl, int srcx, int srcy, int w, int h); + +/** + * Sends a transfer instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param srcl The source layer. + * @param srcx The X coordinate of the source rectangle. + * @param srcy The Y coordinate of the source rectangle. + * @param w The width of the source rectangle. + * @param h The height of the source rectangle. + * @param fn The transfer function to use. + * @param dstl The destination layer. + * @param dstx The X coordinate of the destination, where the source rectangle + * should be copied. + * @param dsty The Y coordinate of the destination, where the source rectangle + * should be copied. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_transfer(guac_socket* socket, + const guac_layer* srcl, int srcx, int srcy, int w, int h, + guac_transfer_function fn, const guac_layer* dstl, int dstx, int dsty); + +/* TODO: guac_protocol_send_transform */ + +/* LAYER INSTRUCTIONS */ + +/** + * Sends a dispose instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to dispose. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer); + +/* TODO: guac_protocol_send_distort */ + +/** + * Sends a move instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to move. + * @param parent The parent layer the specified layer will be positioned + * relative to. + * @param x The X coordinate of the layer. + * @param y The Y coordinate of the layer. + * @param z The Z index of the layer, relative to other layers in its parent. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, + const guac_layer* parent, int x, int y, int z); + +/* TODO: guac_protocol_send_shade */ + +/** + * Sends a size instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to resize. + * @param w The new width of the layer. + * @param h The new height of the layer. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, + int w, int h); + +/* TEXT INSTRUCTIONS */ + +/** + * Sends a clipboard instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param data The clipboard data to send. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_clipboard(guac_socket* socket, const char* data); + +/** + * Sends a name instruction over the given guac_socket connection. + * + * @param socket The guac_socket connection to use. + * @param name The name to send within the name instruction. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_name(guac_socket* socket, const char* name); + #endif From 1a9521074cbfe6024d117f8f0aeec53933f65a25 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 10 Mar 2012 20:56:00 -0800 Subject: [PATCH 162/330] Added prototypes for TODO functions. --- libguac/include/protocol.h | 107 ++++++++++++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 7 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 7577cd04..c7f23ddd 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -302,8 +302,28 @@ guac_timestamp guac_protocol_get_timestamp(); */ int guac_protocol_send_args(guac_socket* socket, const char** args); -/* TODO: guac_protocol_send_connect */ -/* TODO: guac_protocol_send_disconnect */ +/** + * Sends a connect instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param args The NULL-terminated array of argument values (strings). + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_connect(guac_socket* socket, const char** args); + +/** + * Sends a disconnect instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_disconnect(guac_socket* socket); /** * Sends an error instruction over the given guac_socket connection. @@ -317,8 +337,31 @@ int guac_protocol_send_args(guac_socket* socket, const char** args); */ int guac_protocol_send_error(guac_socket* socket, const char* error); -/* TODO: guac_protocol_send_set */ -/* TODO: guac_protocol_send_select */ +/** + * Sends a set instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param name The name of the parameter to set. + * @param value The value to set the parameter to. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_set(guac_socket* socket, const char* name, + const char* value); + +/** + * Sends a select instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param protocol The protocol to request. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_select(guac_socket* socket, const char* protocol); /** * Sends a sync instruction over the given guac_socket connection. The @@ -590,7 +633,26 @@ int guac_protocol_send_transfer(guac_socket* socket, const guac_layer* srcl, int srcx, int srcy, int w, int h, guac_transfer_function fn, const guac_layer* dstl, int dstx, int dsty); -/* TODO: guac_protocol_send_transform */ +/** + * Sends a transform instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to apply the given transform matrix to. + * @param a The first value of the affine transform matrix. + * @param b The second value of the affine transform matrix. + * @param c The third value of the affine transform matrix. + * @param d The fourth value of the affine transform matrix. + * @param e The fifth value of the affine transform matrix. + * @param f The sixth value of the affine transform matrix. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_transform(guac_socket* socket, + const guac_layer* layer, + double a, double b, double c, + double d, double e, double f); /* LAYER INSTRUCTIONS */ @@ -606,7 +668,26 @@ int guac_protocol_send_transfer(guac_socket* socket, */ int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer); -/* TODO: guac_protocol_send_distort */ +/** + * Sends a distort instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to distort with the given transform matrix. + * @param a The first value of the affine transform matrix. + * @param b The second value of the affine transform matrix. + * @param c The third value of the affine transform matrix. + * @param d The fourth value of the affine transform matrix. + * @param e The fifth value of the affine transform matrix. + * @param f The sixth value of the affine transform matrix. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_distort(guac_socket* socket, + const guac_layer* layer, + double a, double b, double c, + double d, double e, double f); /** * Sends a move instruction over the given guac_socket connection. @@ -626,7 +707,19 @@ int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer); int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, const guac_layer* parent, int x, int y, int z); -/* TODO: guac_protocol_send_shade */ +/** + * Sends a shade instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The layer to shade. + * @param a The alpha value of the layer. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_shade(guac_socket* socket, const guac_layer* layer, + int a); /** * Sends a size instruction over the given guac_socket connection. From d93108767bda46dc41eb1ea8b6f6d051b7f5783a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 10 Mar 2012 21:34:42 -0800 Subject: [PATCH 163/330] Reorganized functions, alphabetized. --- libguac/src/protocol.c | 461 ++++++++++++++++++++++------------------- 1 file changed, 245 insertions(+), 216 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index fae8ed67..8e1b9000 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -64,6 +64,8 @@ #include "protocol.h" #include "error.h" +/* Output formatting functions */ + ssize_t __guac_socket_write_length_string(guac_socket* socket, const char* str) { return @@ -73,6 +75,7 @@ ssize_t __guac_socket_write_length_string(guac_socket* socket, const char* str) } + ssize_t __guac_socket_write_length_int(guac_socket* socket, int64_t i) { char buffer[128]; @@ -81,182 +84,8 @@ ssize_t __guac_socket_write_length_int(guac_socket* socket, int64_t i) { } -int guac_protocol_send_args(guac_socket* socket, const char** args) { - int i; - - if (guac_socket_write_string(socket, "4.args")) return -1; - - for (i=0; args[i] != NULL; i++) { - - if (guac_socket_write_string(socket, ",")) - return -1; - - if (__guac_socket_write_length_string(socket, args[i])) - return -1; - - } - - return guac_socket_write_string(socket, ";"); - -} - -int guac_protocol_send_name(guac_socket* socket, const char* name) { - - return - guac_socket_write_string(socket, "4.name,") - || __guac_socket_write_length_string(socket, name) - || guac_socket_write_string(socket, ";"); - -} - -int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, - int w, int h) { - - return - guac_socket_write_string(socket, "4.size,") - || __guac_socket_write_length_int(socket, layer->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, w) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, h) - || guac_socket_write_string(socket, ";"); - -} - -int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, - const guac_layer* parent, int x, int y, int z) { - - return - guac_socket_write_string(socket, "4.move,") - || __guac_socket_write_length_int(socket, layer->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, parent->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, x) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, y) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, z) - || guac_socket_write_string(socket, ";"); - -} - -int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer) { - - return - guac_socket_write_string(socket, "7.dispose,") - || __guac_socket_write_length_int(socket, layer->index) - || guac_socket_write_string(socket, ";"); - -} - -int guac_protocol_send_clipboard(guac_socket* socket, const char* data) { - - return - guac_socket_write_string(socket, "9.clipboard,") - || __guac_socket_write_length_string(socket, data) - || guac_socket_write_string(socket, ";"); - -} - -int guac_protocol_send_error(guac_socket* socket, const char* error) { - - return - guac_socket_write_string(socket, "5.error,") - || __guac_socket_write_length_string(socket, error) - || guac_socket_write_string(socket, ";"); -} - -int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp) { - - return - guac_socket_write_string(socket, "4.sync,") - || __guac_socket_write_length_int(socket, timestamp) - || guac_socket_write_string(socket, ";"); - -} - -int guac_protocol_send_copy(guac_socket* socket, - const guac_layer* srcl, int srcx, int srcy, int w, int h, - guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty) { - - return - guac_socket_write_string(socket, "4.copy,") - || __guac_socket_write_length_int(socket, srcl->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcx) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcy) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, w) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, h) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, mode) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, dstl->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, dstx) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, dsty) - || guac_socket_write_string(socket, ";"); - -} - -int guac_protocol_send_transfer(guac_socket* socket, - const guac_layer* srcl, int srcx, int srcy, int w, int h, - guac_transfer_function fn, const guac_layer* dstl, int dstx, int dsty) { - - return - guac_socket_write_string(socket, "8.transfer,") - || __guac_socket_write_length_int(socket, srcl->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcx) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcy) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, w) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, h) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, fn) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, dstl->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, dstx) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, dsty) - || guac_socket_write_string(socket, ";"); - -} - -int guac_protocol_send_rect(guac_socket* socket, - const guac_layer* layer, int x, int y, int width, int height) { - - return - guac_socket_write_string(socket, "4.rect,") - || __guac_socket_write_length_int(socket, layer->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, x) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, y) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, width) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, height) - || guac_socket_write_string(socket, ";"); - -} - -int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer) { - - return - guac_socket_write_string(socket, "4.clip,") - || __guac_socket_write_length_int(socket, layer->index) - || guac_socket_write_string(socket, ";"); - -} +/* PNG output formatting */ typedef struct __guac_socket_write_png_data { @@ -266,7 +95,8 @@ typedef struct __guac_socket_write_png_data { int buffer_size; int data_size; -} __guac_socket_write_png_data; +} + __guac_socket_write_png_data; cairo_status_t __guac_socket_write_png(void* closure, const unsigned char* data, unsigned int length) { @@ -298,6 +128,7 @@ cairo_status_t __guac_socket_write_png(void* closure, const unsigned char* data, } + int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface) { __guac_socket_write_png_data png_data; @@ -332,46 +163,7 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface } -int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, - const guac_layer* layer, int x, int y, cairo_surface_t* surface) { - - return - guac_socket_write_string(socket, "3.png,") - || __guac_socket_write_length_int(socket, mode) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, layer->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, x) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, y) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_png(socket, surface) - || guac_socket_write_string(socket, ";"); - -} - - -int guac_protocol_send_cursor(guac_socket* socket, int x, int y, - const guac_layer* srcl, int srcx, int srcy, int w, int h) { - return - guac_socket_write_string(socket, "6.cursor,") - || __guac_socket_write_length_int(socket, x) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, y) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcl->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcx) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcy) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, w) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, h) - || guac_socket_write_string(socket, ";"); - -} - +/* Instruction I/O */ int __guac_fill_instructionbuf(guac_socket* socket) { @@ -400,6 +192,7 @@ int __guac_fill_instructionbuf(guac_socket* socket) { } + /* Returns new instruction if one exists, or NULL if no more instructions. */ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_timeout) { @@ -568,6 +361,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t } + guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, int usec_timeout, const char* opcode) { @@ -629,6 +423,7 @@ int guac_protocol_instructions_waiting(guac_socket* socket, int usec_timeout) { return guac_socket_select(socket, usec_timeout); } + guac_timestamp guac_protocol_get_timestamp() { #ifdef HAVE_CLOCK_GETTIME @@ -655,3 +450,237 @@ guac_timestamp guac_protocol_get_timestamp() { } + +/* Protocol functions */ + +int guac_protocol_send_args(guac_socket* socket, const char** args) { + + int i; + + if (guac_socket_write_string(socket, "4.args")) return -1; + + for (i=0; args[i] != NULL; i++) { + + if (guac_socket_write_string(socket, ",")) + return -1; + + if (__guac_socket_write_length_string(socket, args[i])) + return -1; + + } + + return guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer) { + + return + guac_socket_write_string(socket, "4.clip,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_clipboard(guac_socket* socket, const char* data) { + + return + guac_socket_write_string(socket, "9.clipboard,") + || __guac_socket_write_length_string(socket, data) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_copy(guac_socket* socket, + const guac_layer* srcl, int srcx, int srcy, int w, int h, + guac_composite_mode mode, const guac_layer* dstl, int dstx, int dsty) { + + return + guac_socket_write_string(socket, "4.copy,") + || __guac_socket_write_length_int(socket, srcl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcy) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, w) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, h) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, mode) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dstl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dstx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dsty) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_cursor(guac_socket* socket, int x, int y, + const guac_layer* srcl, int srcx, int srcy, int w, int h) { + return + guac_socket_write_string(socket, "6.cursor,") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcy) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, w) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, h) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer) { + + return + guac_socket_write_string(socket, "7.dispose,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_error(guac_socket* socket, const char* error) { + + return + guac_socket_write_string(socket, "5.error,") + || __guac_socket_write_length_string(socket, error) + || guac_socket_write_string(socket, ";"); +} + + + +int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, + const guac_layer* parent, int x, int y, int z) { + + return + guac_socket_write_string(socket, "4.move,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, parent->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, z) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_name(guac_socket* socket, const char* name) { + + return + guac_socket_write_string(socket, "4.name,") + || __guac_socket_write_length_string(socket, name) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, + const guac_layer* layer, int x, int y, cairo_surface_t* surface) { + + return + guac_socket_write_string(socket, "3.png,") + || __guac_socket_write_length_int(socket, mode) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_png(socket, surface) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_rect(guac_socket* socket, + const guac_layer* layer, int x, int y, int width, int height) { + + return + guac_socket_write_string(socket, "4.rect,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, width) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, height) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, + int w, int h) { + + return + guac_socket_write_string(socket, "4.size,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, w) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, h) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp) { + + return + guac_socket_write_string(socket, "4.sync,") + || __guac_socket_write_length_int(socket, timestamp) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_transfer(guac_socket* socket, + const guac_layer* srcl, int srcx, int srcy, int w, int h, + guac_transfer_function fn, const guac_layer* dstl, int dstx, int dsty) { + + return + guac_socket_write_string(socket, "8.transfer,") + || __guac_socket_write_length_int(socket, srcl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcy) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, w) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, h) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, fn) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dstl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dstx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, dsty) + || guac_socket_write_string(socket, ";"); + +} + + From 55ac0eee0b2b6cb16d37be8990270ed5c9ac4776 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 11 Mar 2012 12:57:15 -0700 Subject: [PATCH 164/330] Implemented around 1/3 of all new instructions. --- libguac/src/protocol.c | 100 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 8e1b9000..e499f322 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -474,6 +474,49 @@ int guac_protocol_send_args(guac_socket* socket, const char** args) { } +int guac_protocol_send_cfill(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + int r, int g, int b, int a) { + + return + guac_socket_write_string(socket, "5.cfill,") + || __guac_socket_write_length_int(socket, mode) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, r) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, g) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, b) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, a) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_connect(guac_socket* socket, const char** args) { + + int i; + + if (guac_socket_write_string(socket, "7.connect")) return -1; + + for (i=0; args[i] != NULL; i++) { + + if (guac_socket_write_string(socket, ",")) + return -1; + + if (__guac_socket_write_length_string(socket, args[i])) + return -1; + + } + + return guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer) { return @@ -522,6 +565,35 @@ int guac_protocol_send_copy(guac_socket* socket, } +int guac_protocol_send_cstroke(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + guac_line_cap_style cap, guac_line_join_style join, int thickness, + int r, int g, int b, int a) { + + return + guac_socket_write_string(socket, "7.cstroke,") + || __guac_socket_write_length_int(socket, mode) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, cap) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, join) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, thickness) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, r) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, g) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, b) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, a) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_cursor(guac_socket* socket, int x, int y, const guac_layer* srcl, int srcx, int srcy, int w, int h) { return @@ -544,6 +616,11 @@ int guac_protocol_send_cursor(guac_socket* socket, int x, int y, } +int guac_protocol_send_disconnect(guac_socket* socket) { + return guac_socket_write_string(socket, "10.disconnect;"); +} + + int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer) { return @@ -631,6 +708,29 @@ int guac_protocol_send_rect(guac_socket* socket, } +int guac_protocol_send_set(guac_socket* socket, const char* name, + const char* value) { + + return + guac_socket_write_string(socket, "3.set,") + || __guac_socket_write_length_string(socket, name) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_string(socket, value) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_select(guac_socket* socket, const char* protocol) { + + return + guac_socket_write_string(socket, "6.select,") + || __guac_socket_write_length_string(socket, protocol) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, int w, int h) { From 0479d71563415adb5f057f53dd79f774588276fa Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 11 Mar 2012 13:15:45 -0700 Subject: [PATCH 165/330] Added all remaining new instructions (and old client-only instructions) --- libguac/src/protocol.c | 179 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index e499f322..0ccc8018 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -85,6 +85,15 @@ ssize_t __guac_socket_write_length_int(guac_socket* socket, int64_t i) { } +ssize_t __guac_socket_write_length_double(guac_socket* socket, double d) { + + char buffer[128]; + snprintf(buffer, sizeof(buffer), "%g", d); + return __guac_socket_write_length_string(socket, buffer); + +} + + /* PNG output formatting */ typedef struct __guac_socket_write_png_data { @@ -631,6 +640,30 @@ int guac_protocol_send_dispose(guac_socket* socket, const guac_layer* layer) { } +int guac_protocol_send_distort(guac_socket* socket, const guac_layer* layer, + double a, double b, double c, + double d, double e, double f) { + + return + guac_socket_write_string(socket, "7.distort,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, a) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, b) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, c) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, d) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, e) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, f) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_error(guac_socket* socket, const char* error) { return @@ -670,6 +703,29 @@ int guac_protocol_send_name(guac_socket* socket, const char* name) { } +int guac_protocol_send_path(guac_socket* socket, const guac_layer* layer, + int x, int y, int cp1x, int cp1y, int cp2x, int cp2y) { + + return + guac_socket_write_string(socket, "4.path,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, cp1x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, cp1y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, cp2x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, cp2y) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface) { @@ -689,6 +745,26 @@ int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, } +int guac_protocol_send_pop(guac_socket* socket, const guac_layer* layer) { + + return + guac_socket_write_string(socket, "3.pop,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_push(guac_socket* socket, const guac_layer* layer) { + + return + guac_socket_write_string(socket, "4.push,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_rect(guac_socket* socket, const guac_layer* layer, int x, int y, int width, int height) { @@ -708,6 +784,71 @@ int guac_protocol_send_rect(guac_socket* socket, } +int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer) { + + return + guac_socket_write_string(socket, "5.reset,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_rfill(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + const guac_layer* srcl, int srcx, int srcy, int w, int h) { + + return + guac_socket_write_string(socket, "5.rfill,") + || __guac_socket_write_length_int(socket, mode) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcy) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, w) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, h) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_rstroke(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + guac_line_cap_style cap, guac_line_join_style join, int thickness, + const guac_layer* srcl, int srcx, int srcy, int w, int h) { + + return + guac_socket_write_string(socket, "7.rstroke,") + || __guac_socket_write_length_int(socket, mode) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, cap) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, join) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, thickness) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcl->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcx) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcy) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, w) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, h) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_set(guac_socket* socket, const char* name, const char* value) { @@ -731,6 +872,20 @@ int guac_protocol_send_select(guac_socket* socket, const char* protocol) { } +int guac_protocol_send_shade(guac_socket* socket, const guac_layer* layer, + int a) { + + return + guac_socket_write_string(socket, "5.shade,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, a) + || guac_socket_write_string(socket, ";"); + +} + + + int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, int w, int h) { @@ -784,3 +939,27 @@ int guac_protocol_send_transfer(guac_socket* socket, } +int guac_protocol_send_transform(guac_socket* socket, const guac_layer* layer, + double a, double b, double c, + double d, double e, double f) { + + return + guac_socket_write_string(socket, "9.transform,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, a) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, b) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, c) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, d) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, e) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, f) + || guac_socket_write_string(socket, ";"); + +} + + From eee3fc4fd748b4c66e1b416aa30bbed53bda76a3 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 11 Mar 2012 19:19:42 -0700 Subject: [PATCH 166/330] Removed commas at end of last entries in enums. --- libguac/include/protocol.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index c7f23ddd..fd64b773 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -90,7 +90,7 @@ typedef enum guac_composite_mode { GUAC_COMP_IN = 0x4, /* 0100 */ GUAC_COMP_OUT = 0x8, /* 1000 */ GUAC_COMP_RATOP = 0x9, /* 1001 */ - GUAC_COMP_SRC = 0xC, /* 1100 */ + GUAC_COMP_SRC = 0xC /* 1100 */ /* Bitwise composite operations (binary) */ @@ -158,7 +158,7 @@ typedef enum guac_transfer_function { typedef enum guac_line_cap_style { GUAC_LINE_CAP_BUTT = 0x0, GUAC_LINE_CAP_ROUND = 0x1, - GUAC_LINE_CAP_SQUARE = 0x2, + GUAC_LINE_CAP_SQUARE = 0x2 } guac_line_cap_style; /** @@ -167,7 +167,7 @@ typedef enum guac_line_cap_style { typedef enum guac_line_join_style { GUAC_LINE_JOIN_BEVEL = 0x0, GUAC_LINE_JOIN_MITRE = 0x1, - GUAC_LINE_JOIN_ROUND = 0x2, + GUAC_LINE_JOIN_ROUND = 0x2 } guac_line_join_style; typedef struct guac_layer guac_layer; From fbe43e917e6bb6f470cedf8a5e1659a722212f82 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 11 Mar 2012 21:05:34 -0700 Subject: [PATCH 167/330] Refactored rstroke/rfill to lstroke/lfill. --- libguac/include/protocol.h | 80 +++++++++++++++----------------- libguac/src/protocol.c | 93 ++++++++++++++++---------------------- 2 files changed, 74 insertions(+), 99 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index fd64b773..32416a7b 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -475,6 +475,42 @@ int guac_protocol_send_cstroke(guac_socket* socket, int guac_protocol_send_cursor(guac_socket* socket, int x, int y, const guac_layer* srcl, int srcx, int srcy, int w, int h); +/** + * Sends an lfill instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param srcl The source layer. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_lfill(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + const guac_layer* srcl); + +/** + * Sends an lstroke instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param mode The composite mode to use. + * @param layer The destination layer. + * @param cap The style of line cap to use when drawing the stroke. + * @param join The style of line join to use when drawing the stroke. + * @param thickness The thickness of the stroke in pixels. + * @param srcl The source layer. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_lstroke(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + guac_line_cap_style cap, guac_line_join_style join, int thickness, + const guac_layer* srcl); + /** * Sends a path instruction over the given guac_socket connection. * @@ -565,50 +601,6 @@ int guac_protocol_send_rect(guac_socket* socket, const guac_layer* layer, */ int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer); -/** - * Sends an rfill instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param mode The composite mode to use. - * @param layer The destination layer. - * @param srcl The source layer. - * @param srcx The X coordinate of the source rectangle. - * @param srcy The Y coordinate of the source rectangle. - * @param w The width of the source rectangle. - * @param h The height of the source rectangle. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_rfill(guac_socket* socket, - guac_composite_mode mode, const guac_layer* layer, - const guac_layer* srcl, int srcx, int srcy, int w, int h); - -/** - * Sends an rstroke instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param mode The composite mode to use. - * @param layer The destination layer. - * @param cap The style of line cap to use when drawing the stroke. - * @param join The style of line join to use when drawing the stroke. - * @param thickness The thickness of the stroke in pixels. - * @param srcl The source layer. - * @param srcx The X coordinate of the source rectangle. - * @param srcy The Y coordinate of the source rectangle. - * @param w The width of the source rectangle. - * @param h The height of the source rectangle. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_rstroke(guac_socket* socket, - guac_composite_mode mode, const guac_layer* layer, - guac_line_cap_style cap, guac_line_join_style join, int thickness, - const guac_layer* srcl, int srcx, int srcy, int w, int h); - /** * Sends a transfer instruction over the given guac_socket connection. * diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 0ccc8018..59f8cf7e 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -673,6 +673,44 @@ int guac_protocol_send_error(guac_socket* socket, const char* error) { } +int guac_protocol_send_lfill(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + const guac_layer* srcl) { + + return + guac_socket_write_string(socket, "5.lfill,") + || __guac_socket_write_length_int(socket, mode) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcl->index) + || guac_socket_write_string(socket, ";"); + +} + + +int guac_protocol_send_lstroke(guac_socket* socket, + guac_composite_mode mode, const guac_layer* layer, + guac_line_cap_style cap, guac_line_join_style join, int thickness, + const guac_layer* srcl) { + + return + guac_socket_write_string(socket, "7.lstroke,") + || __guac_socket_write_length_int(socket, mode) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, cap) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, join) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, thickness) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, srcl->index) + || guac_socket_write_string(socket, ";"); + +} + int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer, const guac_layer* parent, int x, int y, int z) { @@ -794,61 +832,6 @@ int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer) { } -int guac_protocol_send_rfill(guac_socket* socket, - guac_composite_mode mode, const guac_layer* layer, - const guac_layer* srcl, int srcx, int srcy, int w, int h) { - - return - guac_socket_write_string(socket, "5.rfill,") - || __guac_socket_write_length_int(socket, mode) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, layer->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcl->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcx) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcy) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, w) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, h) - || guac_socket_write_string(socket, ";"); - -} - - -int guac_protocol_send_rstroke(guac_socket* socket, - guac_composite_mode mode, const guac_layer* layer, - guac_line_cap_style cap, guac_line_join_style join, int thickness, - const guac_layer* srcl, int srcx, int srcy, int w, int h) { - - return - guac_socket_write_string(socket, "7.rstroke,") - || __guac_socket_write_length_int(socket, mode) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, layer->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, cap) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, join) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, thickness) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcl->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcx) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, srcy) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, w) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, h) - || guac_socket_write_string(socket, ";"); - -} - - int guac_protocol_send_set(guac_socket* socket, const char* name, const char* value) { From 39c0977b9df14ca19cc34951339cd7da2cced4f4 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 11 Mar 2012 23:17:16 -0700 Subject: [PATCH 168/330] Corrected spelling of miter. --- libguac/include/protocol.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 32416a7b..70063f29 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -166,7 +166,7 @@ typedef enum guac_line_cap_style { */ typedef enum guac_line_join_style { GUAC_LINE_JOIN_BEVEL = 0x0, - GUAC_LINE_JOIN_MITRE = 0x1, + GUAC_LINE_JOIN_MITER = 0x1, GUAC_LINE_JOIN_ROUND = 0x2 } guac_line_join_style; From e3c3eea764b9b0cd3a06ec60ae8cbb900257e886 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 12 Mar 2012 17:22:04 -0700 Subject: [PATCH 169/330] Refactored path into curve, added line, arc, and start instructions. Added close instruction. Added identity instruction. --- libguac/include/protocol.h | 110 ++++++++++++++++++++++++++++------ libguac/src/protocol.c | 118 +++++++++++++++++++++++++++++-------- 2 files changed, 185 insertions(+), 43 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 70063f29..28608f19 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -378,6 +378,24 @@ int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp); /* DRAWING INSTRUCTIONS */ +/** + * Sends an arc instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @param x The X coordinate of the center of the circle containing the arc. + * @param y The Y coordinate of the center of the circle containing the arc. + * @param radius The radius of the circle containing the arc. + * @param startAngle The starting angle, in radians. + * @param endAngle The ending angle, in radians. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, + int x, int y, int radius, double startAngle, double endAngle); + /** * Sends a cfill instruction over the given guac_socket connection. * @@ -409,6 +427,18 @@ int guac_protocol_send_cfill(guac_socket* socket, */ int guac_protocol_send_clip(guac_socket* socket, const guac_layer* layer); +/** + * Sends a close instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_close(guac_socket* socket, const guac_layer* layer); + /** * Sends a copy instruction over the given guac_socket connection. * @@ -475,6 +505,37 @@ int guac_protocol_send_cstroke(guac_socket* socket, int guac_protocol_send_cursor(guac_socket* socket, int x, int y, const guac_layer* srcl, int srcx, int srcy, int w, int h); +/** + * Sends a curve instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @param cp1x The X coordinate of the first control point. + * @param cp1y The Y coordinate of the first control point. + * @param cp2x The X coordinate of the second control point. + * @param cp2y The Y coordinate of the second control point. + * @param x The X coordinate of the endpoint of the curve. + * @param y The Y coordinate of the endpoint of the curve. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_curve(guac_socket* socket, const guac_layer* layer, + int cp1x, int cp1y, int cp2x, int cp2y, int x, int y); + +/** + * Sends an identity instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_identity(guac_socket* socket, const guac_layer* layer); + /** * Sends an lfill instruction over the given guac_socket connection. * @@ -491,6 +552,21 @@ int guac_protocol_send_lfill(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, const guac_layer* srcl); +/** + * Sends a line instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @param x The X coordinate of the endpoint of the line. + * @param y The Y coordinate of the endpoint of the line. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_line(guac_socket* socket, const guac_layer* layer, + int x, int y); + /** * Sends an lstroke instruction over the given guac_socket connection. * @@ -511,25 +587,6 @@ int guac_protocol_send_lstroke(guac_socket* socket, guac_line_cap_style cap, guac_line_join_style join, int thickness, const guac_layer* srcl); -/** - * Sends a path instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param layer The destination layer. - * @param x The X coordinate of the point to add to the path. - * @param y The Y coordinate of the point to add to the path. - * @param cp1x The X coordinate of the first control point. - * @param cp1y The Y coordinate of the first control point. - * @param cp2x The X coordinate of the second control point. - * @param cp2y The Y coordinate of the second control point. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_path(guac_socket* socket, const guac_layer* layer, - int x, int y, int cp1x, int cp1y, int cp2x, int cp2y); - /** * Sends a png instruction over the given guac_socket connection. The PNG image * data given will be automatically base64-encoded for transmission. @@ -601,6 +658,21 @@ int guac_protocol_send_rect(guac_socket* socket, const guac_layer* layer, */ int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer); +/** + * Sends a start instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @param x The X coordinate of the first point of the subpath. + * @param y The Y coordinate of the first point of the subpath. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_start(guac_socket* socket, const guac_layer* layer, + int x, int y); + /** * Sends a transfer instruction over the given guac_socket connection. * diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 59f8cf7e..86dd40d7 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -483,6 +483,27 @@ int guac_protocol_send_args(guac_socket* socket, const char** args) { } +int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, + int x, int y, int radius, double startAngle, double endAngle) { + + return + guac_socket_write_string(socket, "3.arc,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, radius) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, startAngle) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_double(socket, endAngle) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_cfill(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int r, int g, int b, int a) { @@ -505,6 +526,16 @@ int guac_protocol_send_cfill(guac_socket* socket, } +int guac_protocol_send_close(guac_socket* socket, const guac_layer* layer) { + + return + guac_socket_write_string(socket, "5.close,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_connect(guac_socket* socket, const char** args) { int i; @@ -625,6 +656,29 @@ int guac_protocol_send_cursor(guac_socket* socket, int x, int y, } +int guac_protocol_send_curve(guac_socket* socket, const guac_layer* layer, + int cp1x, int cp1y, int cp2x, int cp2y, int x, int y) { + + return + guac_socket_write_string(socket, "5.curve,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, cp1x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, cp1y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, cp2x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, cp2y) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_disconnect(guac_socket* socket) { return guac_socket_write_string(socket, "10.disconnect;"); } @@ -673,6 +727,16 @@ int guac_protocol_send_error(guac_socket* socket, const char* error) { } +int guac_protocol_send_identity(guac_socket* socket, const guac_layer* layer) { + + return + guac_socket_write_string(socket, "8.identity,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_lfill(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, const guac_layer* srcl) { @@ -689,6 +753,21 @@ int guac_protocol_send_lfill(guac_socket* socket, } +int guac_protocol_send_line(guac_socket* socket, const guac_layer* layer, + int x, int y) { + + return + guac_socket_write_string(socket, "4.line,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_lstroke(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, guac_line_cap_style cap, guac_line_join_style join, int thickness, @@ -741,29 +820,6 @@ int guac_protocol_send_name(guac_socket* socket, const char* name) { } -int guac_protocol_send_path(guac_socket* socket, const guac_layer* layer, - int x, int y, int cp1x, int cp1y, int cp2x, int cp2y) { - - return - guac_socket_write_string(socket, "4.path,") - || __guac_socket_write_length_int(socket, layer->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, x) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, y) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, cp1x) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, cp1y) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, cp2x) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, cp2y) - || guac_socket_write_string(socket, ";"); - -} - - int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface) { @@ -868,7 +924,6 @@ int guac_protocol_send_shade(guac_socket* socket, const guac_layer* layer, } - int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, int w, int h) { @@ -884,6 +939,21 @@ int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer, } +int guac_protocol_send_start(guac_socket* socket, const guac_layer* layer, + int x, int y) { + + return + guac_socket_write_string(socket, "5.start,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, x) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, y) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp) { return From fa27d7b11e775d47d0001c3946f80f57a9ea3785 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 13 Mar 2012 12:06:11 -0700 Subject: [PATCH 170/330] Added layer to set instruction. --- libguac/include/protocol.h | 5 +++-- libguac/src/protocol.c | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 28608f19..aeb4b109 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -344,12 +344,13 @@ int guac_protocol_send_error(guac_socket* socket, const char* error); * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. + * @param layer The layer to set the parameter of. * @param name The name of the parameter to set. * @param value The value to set the parameter to. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_set(guac_socket* socket, const char* name, - const char* value); +int guac_protocol_send_set(guac_socket* socket, const guac_layer* layer, + const char* name, const char* value); /** * Sends a select instruction over the given guac_socket connection. diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 86dd40d7..6ec0d069 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -888,11 +888,13 @@ int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer) { } -int guac_protocol_send_set(guac_socket* socket, const char* name, - const char* value) { +int guac_protocol_send_set(guac_socket* socket, const guac_layer* layer, + const char* name, const char* value) { return guac_socket_write_string(socket, "3.set,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, name) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, value) From 7f293df34cf8956f8ccdae20e57b50be92bbebea Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 13 Mar 2012 15:45:22 -0700 Subject: [PATCH 171/330] Modify guac_client_plugin_get_client() to allow logging to be set up before guac_client_init is called (fixes ticket #85). --- libguac/include/client.h | 8 +++++++- libguac/src/client.c | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 3f4a4a1d..6f6f768e 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -449,10 +449,16 @@ int guac_client_plugin_close(guac_client_plugin* plugin); * @param socket The guac_socket the client should use for communication. * @param argc The number of arguments being passed to the client. * @param argv All arguments to be passed to the client. + * @param log_info_handler Info logging handler to provide to the client before + * initializing. + * @param log_error_handler Error logging handler to provide to the client + * before initializing. * @return A pointer to the newly initialized client. */ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, - guac_socket* socket, int argc, char** argv); + guac_socket* socket, int argc, char** argv, + guac_client_log_handler* log_info_handler, + guac_client_log_handler* log_error_handler); /** * Free all resources associated with the given client. diff --git a/libguac/src/client.c b/libguac/src/client.c index f247bf0b..1451c034 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -231,7 +231,9 @@ int guac_client_plugin_close(guac_client_plugin* plugin) { } guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, - guac_socket* socket, int argc, char** argv) { + guac_socket* socket, int argc, char** argv, + guac_client_log_handler* log_info_handler, + guac_client_log_handler* log_error_handler) { /* Allocate new client */ guac_client* client = malloc(sizeof(guac_client)); @@ -257,6 +259,10 @@ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, client->__next_buffer_index = -1; client->__next_layer_index = 1; + /* Set up logging in client */ + client->log_info_handler = log_info_handler; + client->log_error_handler = log_error_handler; + if (plugin->init_handler(client, argc, argv) != 0) { free(client); return NULL; From a5fdb711c5028c39b8cd1b54b4a1ea08e7145187 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 13 Mar 2012 15:54:55 -0700 Subject: [PATCH 172/330] Fix documentation of log handlers. --- libguac/include/client.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 6f6f768e..57852c5d 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -344,9 +344,7 @@ struct guac_client { * * void function_of_daemon() { * - * guac_client* client = [client from guac_client_plugin_get_client()]; - * - * client->log_info_handler = log_handler; + * guac_client* client = [pass log_handler to guac_client_plugin_get_client()]; * * } * @endcode @@ -371,9 +369,7 @@ struct guac_client { * * void function_of_daemon() { * - * guac_client* client = [client from guac_client_plugin_get_client()]; - * - * client->log_error_handler = log_handler; + * guac_client* client = [pass log_handler to guac_client_plugin_get_client()]; * * } * @endcode From b71eca8183d81b59865bba23e83c5c9b130b526b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 13 Mar 2012 19:07:24 -0700 Subject: [PATCH 173/330] Add new negative parameter to arc. --- libguac/include/protocol.h | 5 ++++- libguac/src/protocol.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index aeb4b109..e73db9a1 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -392,10 +392,13 @@ int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp); * @param radius The radius of the circle containing the arc. * @param startAngle The starting angle, in radians. * @param endAngle The ending angle, in radians. + * @param negative Zero if the arc should be drawn in order of increasing + * angle, non-zero otherwise. * @return Zero on success, non-zero on error. */ int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, - int x, int y, int radius, double startAngle, double endAngle); + int x, int y, int radius, double startAngle, double endAngle, + int negative); /** * Sends a cfill instruction over the given guac_socket connection. diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 6ec0d069..4b7bcbd9 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -484,7 +484,8 @@ int guac_protocol_send_args(guac_socket* socket, const char** args) { int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, - int x, int y, int radius, double startAngle, double endAngle) { + int x, int y, int radius, double startAngle, double endAngle, + int negative) { return guac_socket_write_string(socket, "3.arc,") @@ -499,6 +500,8 @@ int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, || __guac_socket_write_length_double(socket, startAngle) || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, endAngle) + || guac_socket_write_string(socket, ",") + || guac_socket_write_string(socket, negative ? "1" : "0") || guac_socket_write_string(socket, ";"); } From eb73b52e69101a706d1384f007f5d8641fa68714 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 13 Mar 2012 19:12:37 -0700 Subject: [PATCH 174/330] Fix output of arc instruction. --- libguac/src/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 4b7bcbd9..9644aa4f 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -501,7 +501,7 @@ int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, || guac_socket_write_string(socket, ",") || __guac_socket_write_length_double(socket, endAngle) || guac_socket_write_string(socket, ",") - || guac_socket_write_string(socket, negative ? "1" : "0") + || guac_socket_write_string(socket, negative ? "1.1" : "1.0") || guac_socket_write_string(socket, ";"); } From 1aa594bd8b8e56b24f61adb718d68082f271f8fe Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 15 Mar 2012 11:30:52 -0700 Subject: [PATCH 175/330] __guac_fill_instructionbuf() should report errors. --- libguac/src/protocol.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 9644aa4f..47da5860 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -180,21 +180,28 @@ int __guac_fill_instructionbuf(guac_socket* socket) { /* Attempt to fill buffer */ retval = recv( - socket->fd, - socket->__instructionbuf + socket->__instructionbuf_used_length, - socket->__instructionbuf_size - socket->__instructionbuf_used_length, - 0 + socket->fd, + socket->__instructionbuf + socket->__instructionbuf_used_length, + socket->__instructionbuf_size - socket->__instructionbuf_used_length, + 0 ); - if (retval < 0) + /* Set guac_error if recv() unsuccessful */ + if (retval < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Error filling instruction buffer"; return retval; + } socket->__instructionbuf_used_length += retval; /* Expand buffer if necessary */ - if (socket->__instructionbuf_used_length > socket->__instructionbuf_size / 2) { + if (socket->__instructionbuf_used_length > + socket->__instructionbuf_size / 2) { + socket->__instructionbuf_size *= 2; - socket->__instructionbuf = realloc(socket->__instructionbuf, socket->__instructionbuf_size); + socket->__instructionbuf = realloc(socket->__instructionbuf, + socket->__instructionbuf_size); } return retval; @@ -203,7 +210,8 @@ int __guac_fill_instructionbuf(guac_socket* socket) { /* Returns new instruction if one exists, or NULL if no more instructions. */ -guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_timeout) { +guac_instruction* guac_protocol_read_instruction(guac_socket* socket, + int usec_timeout) { int retval; From 9118f593b3b2bc09772a5989acaddccae734792c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 19:22:26 -0700 Subject: [PATCH 176/330] Restore checks for libpng. --- libguac/configure.in | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index 28cb34bd..ba84bb59 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -51,12 +51,13 @@ AC_DEFINE(_BSD_SOURCE) # Checks for libraries. AC_CHECK_LIB([dl], [dlopen],, AC_MSG_ERROR("libdl is required for loading client plugins")) +AC_CHECK_LIB([png], [png_write_png],, AC_MSG_ERROR("libpng is required for writing png messages")) AC_CHECK_LIB([cairo], [cairo_create],, AC_MSG_ERROR("cairo is required for drawing instructions")) AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([wsock32], [main]) # Checks for header files. -AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h time.h sys/time.h syslog.h unistd.h cairo/cairo.h]) +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h time.h sys/time.h syslog.h unistd.h cairo/cairo.h pngstruct.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_SIZE_T @@ -65,7 +66,7 @@ AC_TYPE_SSIZE_T # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_REALLOC -AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup nanosleep]) +AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup png_get_io_ptr nanosleep]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT From bd864f3f8f3775afdbe51752515834f6a2b40b20 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 19:25:33 -0700 Subject: [PATCH 177/330] Check for pngstruct.h --- libguac/src/protocol.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 47da5860..9176c491 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -50,6 +50,10 @@ #include #include +#ifdef HAVE_PNGSTRUCT_H +#include +#endif + #include #include From 3cae4f016f8274269076c307dd744f2e358f1c6e Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 20:19:12 -0700 Subject: [PATCH 178/330] Use libpng for writing of PNGs (currently only works with RGB/RGBA surfaces, and only writes RGB) --- libguac/src/protocol.c | 113 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 103 insertions(+), 10 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 9176c491..3f99fb68 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -54,6 +54,8 @@ #include #endif +#include + #include #include @@ -108,12 +110,18 @@ typedef struct __guac_socket_write_png_data { int buffer_size; int data_size; -} - __guac_socket_write_png_data; +} __guac_socket_write_png_data; -cairo_status_t __guac_socket_write_png(void* closure, const unsigned char* data, unsigned int length) { +void __guac_socket_write_png(png_structp png, + png_bytep data, png_size_t length) { - __guac_socket_write_png_data* png_data = (__guac_socket_write_png_data*) closure; + /* Get png buffer structure */ + __guac_socket_write_png_data* png_data; +#ifdef HAVE_PNG_GET_IO_PTR + png_data = (__guac_socket_write_png_data*) png_get_io_ptr(png); +#else + png_data = (__guac_socket_write_png_data*) png->io_ptr; +#endif /* Calculate next buffer size */ int next_size = png_data->data_size + length; @@ -137,26 +145,111 @@ cairo_status_t __guac_socket_write_png(void* closure, const unsigned char* data, memcpy(png_data->buffer + png_data->data_size, data, length); png_data->data_size += length; - return CAIRO_STATUS_SUCCESS; - } +void __guac_socket_flush_png(png_structp png) { + /* Dummy function */ +} int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface) { + png_structp png; + png_infop png_info; + png_byte** png_rows; + + int x, y; + __guac_socket_write_png_data png_data; int base64_length; - /* Write surface */ + /* Get image surface properties and data */ + /*cairo_format_t format = cairo_image_surface_get_format(surface);*/ + int width = cairo_image_surface_get_width(surface); + int height = cairo_image_surface_get_height(surface); + int stride = cairo_image_surface_get_stride(surface); + unsigned char* data = cairo_image_surface_get_data(surface); + /* Flush pending operations to surface */ + cairo_surface_flush(surface); + + /* If not an image surface, fail */ + if (data == NULL) { + return -1; /* FIXME: Set guac_error, etc? */ + } + + /* Copy data from surface into PNG data */ + png_rows = (png_byte**) malloc(sizeof(png_byte*) * height); + for (y=0; y Date: Sun, 1 Apr 2012 21:20:08 -0700 Subject: [PATCH 179/330] Handle formats, basic palette mapping implementation. --- libguac/src/protocol.c | 159 +++++++++++++++++++++++++++++++++++------ 1 file changed, 136 insertions(+), 23 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 3f99fb68..00c34097 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -151,45 +151,111 @@ void __guac_socket_flush_png(png_structp png) { /* Dummy function */ } -int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface) { +typedef struct __guac_palette { - png_structp png; - png_infop png_info; - png_byte** png_rows; + int index; + int color; + +} __guac_palette; + +void __guac_create_palette(cairo_surface_t* surface) { int x, y; - __guac_socket_write_png_data png_data; - int base64_length; - - /* Get image surface properties and data */ - /*cairo_format_t format = cairo_image_surface_get_format(surface);*/ int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); int stride = cairo_image_surface_get_stride(surface); unsigned char* data = cairo_image_surface_get_data(surface); - /* Flush pending operations to surface */ - cairo_surface_flush(surface); + /* Simple palette map */ + __guac_palette palette[0xFFF] = {{0}}; + int colors = 0; + + for (y=0; y> 12) ^ (color & 0xFFF); + + __guac_palette* entry; + + /* Search for open palette entry */ + for (;;) { + + entry = &palette[hash]; + + /* If we've found a free space, use it */ + if (entry->index == 0) { + + /* Stop if already at capacity */ + if (colors == 256) + return; + + /* Add color to map, done */ + entry->index = ++colors; + entry->color = color; + break; + + } + + /* Otherwise, if already stored here, done */ + if (entry->color == color) + break; + + /* Otherwise, collision. Move on to another bucket */ + hash = (hash+1) & 0xFFF; + + } + + } + + /* Advance to next data row */ + data += stride; - /* If not an image surface, fail */ - if (data == NULL) { - return -1; /* FIXME: Set guac_error, etc? */ } + fprintf(stderr, "%i colors!\n", colors); + +} + +png_byte** __guac_create_png_rgb(cairo_surface_t* surface, int alpha) { + + png_byte** png_rows; + int x, y; + + int width = cairo_image_surface_get_width(surface); + int height = cairo_image_surface_get_height(surface); + int stride = cairo_image_surface_get_stride(surface); + unsigned char* data = cairo_image_surface_get_data(surface); + + /* Fail if not an image surface */ + if (data == NULL) + return NULL; + + int bpp; + if (alpha) bpp = 4; + else bpp = 3; + /* Copy data from surface into PNG data */ png_rows = (png_byte**) malloc(sizeof(png_byte*) * height); for (y=0; y Date: Sun, 1 Apr 2012 21:49:15 -0700 Subject: [PATCH 180/330] Move palette functions into own files. --- libguac/Makefile.am | 6 +- libguac/include/palette.h | 62 ++++++++++++++++++++ libguac/src/palette.c | 117 ++++++++++++++++++++++++++++++++++++++ libguac/src/protocol.c | 72 +---------------------- 4 files changed, 184 insertions(+), 73 deletions(-) create mode 100644 libguac/include/palette.h create mode 100644 libguac/src/palette.c diff --git a/libguac/Makefile.am b/libguac/Makefile.am index a0b2f5bd..20a0ee44 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -40,13 +40,15 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -Iinclude libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/socket.h include/protocol.h include/client-handlers.h include/error.h +libguacinc_HEADERS = include/client.h include/socket.h include/protocol.h include/client-handlers.h include/error.h include/palette.h lib_LTLIBRARIES = libguac.la -libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handlers.c src/error.c +libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handlers.c src/error.c src/palette.c libguac_la_LDFLAGS = -version-info 3:0:0 +noinst_HEADERS = include/palette.h + EXTRA_DIST = LICENSE doc/Doxyfile diff --git a/libguac/include/palette.h b/libguac/include/palette.h new file mode 100644 index 00000000..ed210a08 --- /dev/null +++ b/libguac/include/palette.h @@ -0,0 +1,62 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef __GUAC_PALETTE_H +#define __GUAC_PALETTE_H + +#include + +typedef struct guac_palette_entry { + + int index; + int color; + +} guac_palette_entry; + + +typedef struct guac_palette { + + guac_palette_entry entries[0xFFF]; + int colors; + +} guac_palette; + +guac_palette* __guac_create_palette(cairo_surface_t* surface); +void __guac_free_palette(guac_palette* palette); + +#endif + diff --git a/libguac/src/palette.c b/libguac/src/palette.c new file mode 100644 index 00000000..4672b574 --- /dev/null +++ b/libguac/src/palette.c @@ -0,0 +1,117 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include +#include + +#include + +#include + +#include "palette.h" + +guac_palette* __guac_create_palette(cairo_surface_t* surface) { + + int x, y; + + int width = cairo_image_surface_get_width(surface); + int height = cairo_image_surface_get_height(surface); + int stride = cairo_image_surface_get_stride(surface); + unsigned char* data = cairo_image_surface_get_data(surface); + + /* Allocate palette */ + guac_palette* palette = (guac_palette*) malloc(sizeof(guac_palette)); + memset(palette, 0, sizeof(guac_palette)); + + for (y=0; y> 12) ^ (color & 0xFFF); + + guac_palette_entry* entry; + + /* Search for open palette entry */ + for (;;) { + + entry = &(palette->entries[hash]); + + /* If we've found a free space, use it */ + if (entry->index == 0) { + + /* Stop if already at capacity */ + if (palette->colors == 256) { + __guac_free_palette(palette); + return NULL; + } + + /* Add color to map, done */ + entry->index = ++palette->colors; + entry->color = color; + break; + + } + + /* Otherwise, if already stored here, done */ + if (entry->color == color) + break; + + /* Otherwise, collision. Move on to another bucket */ + hash = (hash+1) & 0xFFF; + + } + } + + /* Advance to next data row */ + data += stride; + + } + + return palette; + +} + +void __guac_free_palette(guac_palette* palette) { + free(palette); +} + diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 00c34097..7f2d7a4d 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -69,6 +69,7 @@ #include "socket.h" #include "protocol.h" #include "error.h" +#include "palette.h" /* Output formatting functions */ @@ -151,77 +152,6 @@ void __guac_socket_flush_png(png_structp png) { /* Dummy function */ } -typedef struct __guac_palette { - - int index; - int color; - -} __guac_palette; - -void __guac_create_palette(cairo_surface_t* surface) { - - int x, y; - - int width = cairo_image_surface_get_width(surface); - int height = cairo_image_surface_get_height(surface); - int stride = cairo_image_surface_get_stride(surface); - unsigned char* data = cairo_image_surface_get_data(surface); - - /* Simple palette map */ - __guac_palette palette[0xFFF] = {{0}}; - int colors = 0; - - for (y=0; y> 12) ^ (color & 0xFFF); - - __guac_palette* entry; - - /* Search for open palette entry */ - for (;;) { - - entry = &palette[hash]; - - /* If we've found a free space, use it */ - if (entry->index == 0) { - - /* Stop if already at capacity */ - if (colors == 256) - return; - - /* Add color to map, done */ - entry->index = ++colors; - entry->color = color; - break; - - } - - /* Otherwise, if already stored here, done */ - if (entry->color == color) - break; - - /* Otherwise, collision. Move on to another bucket */ - hash = (hash+1) & 0xFFF; - - } - - } - - /* Advance to next data row */ - data += stride; - - } - - fprintf(stderr, "%i colors!\n", colors); - -} - png_byte** __guac_create_png_rgb(cairo_surface_t* surface, int alpha) { png_byte** png_rows; From e22323c4d9dd9f34af93530fcffbf3581ab84744 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 21:54:03 -0700 Subject: [PATCH 181/330] Function rename + palette alloc test. --- libguac/include/palette.h | 4 ++-- libguac/src/palette.c | 6 +++--- libguac/src/protocol.c | 10 +++++++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/libguac/include/palette.h b/libguac/include/palette.h index ed210a08..fc3cc3dd 100644 --- a/libguac/include/palette.h +++ b/libguac/include/palette.h @@ -55,8 +55,8 @@ typedef struct guac_palette { } guac_palette; -guac_palette* __guac_create_palette(cairo_surface_t* surface); -void __guac_free_palette(guac_palette* palette); +guac_palette* guac_palette_alloc(cairo_surface_t* surface); +void guac_palette_free(guac_palette* palette); #endif diff --git a/libguac/src/palette.c b/libguac/src/palette.c index 4672b574..2add6b1a 100644 --- a/libguac/src/palette.c +++ b/libguac/src/palette.c @@ -47,7 +47,7 @@ #include "palette.h" -guac_palette* __guac_create_palette(cairo_surface_t* surface) { +guac_palette* guac_palette_alloc(cairo_surface_t* surface) { int x, y; @@ -81,7 +81,7 @@ guac_palette* __guac_create_palette(cairo_surface_t* surface) { /* Stop if already at capacity */ if (palette->colors == 256) { - __guac_free_palette(palette); + guac_palette_free(palette); return NULL; } @@ -111,7 +111,7 @@ guac_palette* __guac_create_palette(cairo_surface_t* surface) { } -void __guac_free_palette(guac_palette* palette) { +void guac_palette_free(guac_palette* palette) { free(palette); } diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 7f2d7a4d..fffce3fa 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -227,7 +227,15 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface cairo_surface_flush(surface); if (format == CAIRO_FORMAT_RGB24) { - __guac_create_palette(surface); + + guac_palette* palette = guac_palette_alloc(surface); + if (palette != NULL) { + fprintf(stderr, + "Created palette with %i entries.\n", + palette->colors); + guac_palette_free(palette); + } + png_rows = __guac_create_png_rgb(surface, 0); png_format = PNG_COLOR_TYPE_RGB; } From 314e8c9222f64b1520e384ca7a0e03a2c51d44c5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 21:57:19 -0700 Subject: [PATCH 182/330] Add palette find function. --- libguac/include/palette.h | 1 + libguac/src/palette.c | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/libguac/include/palette.h b/libguac/include/palette.h index fc3cc3dd..fb30066e 100644 --- a/libguac/include/palette.h +++ b/libguac/include/palette.h @@ -56,6 +56,7 @@ typedef struct guac_palette { } guac_palette; guac_palette* guac_palette_alloc(cairo_surface_t* surface); +int guac_palette_find(guac_palette* palette, int color); void guac_palette_free(guac_palette* palette); #endif diff --git a/libguac/src/palette.c b/libguac/src/palette.c index 2add6b1a..dc18ebb8 100644 --- a/libguac/src/palette.c +++ b/libguac/src/palette.c @@ -111,6 +111,33 @@ guac_palette* guac_palette_alloc(cairo_surface_t* surface) { } +int guac_palette_find(guac_palette* palette, int color) { + + /* Calculate hash code */ + int hash = ((color & 0xFFF000) >> 12) ^ (color & 0xFFF); + + guac_palette_entry* entry; + + /* Search for palette entry */ + for (;;) { + + entry = &(palette->entries[hash]); + + /* If we've found a free space, color not stored. */ + if (entry->index == 0) + return -1; + + /* Otherwise, if color indeed stored here, done */ + if (entry->color == color) + return entry->index; + + /* Otherwise, collision. Move on to another bucket */ + hash = (hash+1) & 0xFFF; + + } + +} + void guac_palette_free(guac_palette* palette) { free(palette); } From 1489ae902da03fc60d04e80af8664c3403e86a19 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 22:06:34 -0700 Subject: [PATCH 183/330] Store sequential array of colors in palette. --- libguac/include/palette.h | 3 ++- libguac/src/palette.c | 5 +++-- libguac/src/protocol.c | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libguac/include/palette.h b/libguac/include/palette.h index fb30066e..d2263e95 100644 --- a/libguac/include/palette.h +++ b/libguac/include/palette.h @@ -51,7 +51,8 @@ typedef struct guac_palette_entry { typedef struct guac_palette { guac_palette_entry entries[0xFFF]; - int colors; + int colors[256]; + int size; } guac_palette; diff --git a/libguac/src/palette.c b/libguac/src/palette.c index dc18ebb8..8d38c771 100644 --- a/libguac/src/palette.c +++ b/libguac/src/palette.c @@ -80,13 +80,14 @@ guac_palette* guac_palette_alloc(cairo_surface_t* surface) { if (entry->index == 0) { /* Stop if already at capacity */ - if (palette->colors == 256) { + if (palette->size == 256) { guac_palette_free(palette); return NULL; } /* Add color to map, done */ - entry->index = ++palette->colors; + palette->colors[palette->size] = color; + entry->index = ++palette->size; entry->color = color; break; diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index fffce3fa..18647c97 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -230,9 +230,11 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface guac_palette* palette = guac_palette_alloc(surface); if (palette != NULL) { + fprintf(stderr, "Created palette with %i entries.\n", - palette->colors); + palette->size); + guac_palette_free(palette); } From 969f96f1b7e32ac41586e4fa47d3412aaf328a5b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 22:28:45 -0700 Subject: [PATCH 184/330] Use libpng if palette possible, otherwise use Cairo (stub). --- libguac/src/protocol.c | 131 ++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 80 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 18647c97..160b91d6 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -152,59 +152,10 @@ void __guac_socket_flush_png(png_structp png) { /* Dummy function */ } -png_byte** __guac_create_png_rgb(cairo_surface_t* surface, int alpha) { +int __guac_socket_write_length_png_cairo(guac_socket* socket, cairo_surface_t* surface) { - png_byte** png_rows; - int x, y; - - int width = cairo_image_surface_get_width(surface); - int height = cairo_image_surface_get_height(surface); - int stride = cairo_image_surface_get_stride(surface); - unsigned char* data = cairo_image_surface_get_data(surface); - - /* Fail if not an image surface */ - if (data == NULL) - return NULL; - - int bpp; - if (alpha) bpp = 4; - else bpp = 3; - - /* Copy data from surface into PNG data */ - png_rows = (png_byte**) malloc(sizeof(png_byte*) * height); - for (y=0; ysize); - - guac_palette_free(palette); - } - - png_rows = __guac_create_png_rgb(surface, 0); - png_format = PNG_COLOR_TYPE_RGB; - } - else if (format == CAIRO_FORMAT_ARGB32) { - png_rows = __guac_create_png_rgb(surface, 1); - png_format = PNG_COLOR_TYPE_RGB_ALPHA; - } - else - return -1; /* FIXME: Format not yet supported */ - - /* If not an image surface, fail */ - if (png_rows == NULL) { - return -1; /* FIXME: Set guac_error, etc? */ - } + /* If not possible, resort to Cairo PNG writer */ + if (palette == NULL) + return __guac_socket_write_length_png_cairo(socket, surface); /* Set up PNG writer */ png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); @@ -282,6 +220,36 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface __guac_socket_write_png, __guac_socket_flush_png); + /* Copy data from surface into PNG data */ + png_rows = (png_byte**) malloc(sizeof(png_byte*) * height); + for (y=0; ysize); + + guac_palette_free(palette); + /* Write image info */ png_set_IHDR( png, @@ -289,7 +257,7 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface width, height, 8, - png_format, + PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT @@ -302,7 +270,10 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface /* Finish write */ png_destroy_write_struct(&png, &png_info); - __guac_free_png(png_rows, height); + /* Free PNG data */ + for (y=0; y Date: Sun, 1 Apr 2012 22:36:55 -0700 Subject: [PATCH 185/330] Store palette in libpng format, add PLTE section. --- libguac/include/palette.h | 3 ++- libguac/src/palette.c | 12 ++++++++++-- libguac/src/protocol.c | 3 +++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libguac/include/palette.h b/libguac/include/palette.h index d2263e95..ce6256f0 100644 --- a/libguac/include/palette.h +++ b/libguac/include/palette.h @@ -38,6 +38,7 @@ #ifndef __GUAC_PALETTE_H #define __GUAC_PALETTE_H +#include #include typedef struct guac_palette_entry { @@ -51,7 +52,7 @@ typedef struct guac_palette_entry { typedef struct guac_palette { guac_palette_entry entries[0xFFF]; - int colors[256]; + png_color colors[256]; int size; } guac_palette; diff --git a/libguac/src/palette.c b/libguac/src/palette.c index 8d38c771..be1a6518 100644 --- a/libguac/src/palette.c +++ b/libguac/src/palette.c @@ -79,16 +79,24 @@ guac_palette* guac_palette_alloc(cairo_surface_t* surface) { /* If we've found a free space, use it */ if (entry->index == 0) { + png_color* c; + /* Stop if already at capacity */ if (palette->size == 256) { guac_palette_free(palette); return NULL; } - /* Add color to map, done */ - palette->colors[palette->size] = color; + /* Store in palette */ + c = &(palette->colors[palette->size]); + c->blue = (color & 0x0000FF); + c->green = (color & 0x00FF00) >> 8; + c->red = (color & 0xFF0000) >> 16; + + /* Add color to map */ entry->index = ++palette->size; entry->color = color; + break; } diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 160b91d6..3e93f3b5 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -263,6 +263,9 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface PNG_FILTER_TYPE_DEFAULT ); + /* Write palette */ + png_set_PLTE(png, png_info, palette->colors, palette->size); + /* Write image */ png_set_rows(png, png_info, png_rows); png_write_png(png, png_info, PNG_TRANSFORM_IDENTITY, NULL); From e8833857b9fb802018a708ec808e188ef38899a0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 22:37:25 -0700 Subject: [PATCH 186/330] Removed debug fprintf. --- libguac/src/protocol.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 3e93f3b5..56502171 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -244,10 +244,6 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface } - fprintf(stderr, - "Created palette with %i entries.\n", - palette->size); - guac_palette_free(palette); /* Write image info */ From d300688a5b7778798b96ecce9337fd224ac7343f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 23:01:53 -0700 Subject: [PATCH 187/330] Fix palette find. --- libguac/src/palette.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libguac/src/palette.c b/libguac/src/palette.c index be1a6518..b04d1ae9 100644 --- a/libguac/src/palette.c +++ b/libguac/src/palette.c @@ -89,9 +89,9 @@ guac_palette* guac_palette_alloc(cairo_surface_t* surface) { /* Store in palette */ c = &(palette->colors[palette->size]); - c->blue = (color & 0x0000FF); - c->green = (color & 0x00FF00) >> 8; - c->red = (color & 0xFF0000) >> 16; + c->blue = (color ) & 0xFF; + c->green = (color >> 8 ) & 0xFF; + c->red = (color >> 16) & 0xFF; /* Add color to map */ entry->index = ++palette->size; @@ -138,7 +138,7 @@ int guac_palette_find(guac_palette* palette, int color) { /* Otherwise, if color indeed stored here, done */ if (entry->color == color) - return entry->index; + return entry->index - 1; /* Otherwise, collision. Move on to another bucket */ hash = (hash+1) & 0xFFF; From b4ad24ccd6c3273f9e1cfa188c4416d9a75fbfdb Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 23:10:52 -0700 Subject: [PATCH 188/330] Use appropriate BPP and packing. --- libguac/src/protocol.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 56502171..f0b17d18 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -164,6 +164,7 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface png_structp png; png_infop png_info; png_byte** png_rows; + int bpp; int x, y; @@ -191,6 +192,12 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface if (palette == NULL) return __guac_socket_write_length_png_cairo(socket, surface); + /* Calculate BPP from palette size */ + if (palette->size <= 2) bpp = 1; + else if (palette->size <= 4) bpp = 2; + else if (palette->size <= 16) bpp = 4; + else bpp = 8; + /* Set up PNG writer */ png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { @@ -252,7 +259,7 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface png_info, width, height, - 8, + bpp, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, @@ -264,7 +271,7 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface /* Write image */ png_set_rows(png, png_info, png_rows); - png_write_png(png, png_info, PNG_TRANSFORM_IDENTITY, NULL); + png_write_png(png, png_info, PNG_TRANSFORM_PACKING, NULL); /* Finish write */ png_destroy_write_struct(&png, &png_info); From d2523c062c9b28526d74e6533468b66cafd3dc03 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 23:16:58 -0700 Subject: [PATCH 189/330] Restore Cairo PNG support. --- libguac/src/protocol.c | 71 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index f0b17d18..e5ab832c 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -113,6 +113,70 @@ typedef struct __guac_socket_write_png_data { } __guac_socket_write_png_data; +cairo_status_t __guac_socket_write_png_cairo(void* closure, const unsigned char* data, unsigned int length) { + + __guac_socket_write_png_data* png_data = (__guac_socket_write_png_data*) closure; + + /* Calculate next buffer size */ + int next_size = png_data->data_size + length; + + /* If need resizing, double buffer size until big enough */ + if (next_size > png_data->buffer_size) { + + char* new_buffer; + + do { + png_data->buffer_size <<= 1; + } while (next_size > png_data->buffer_size); + + /* Resize buffer */ + new_buffer = realloc(png_data->buffer, png_data->buffer_size); + png_data->buffer = new_buffer; + + } + + /* Append data to buffer */ + memcpy(png_data->buffer + png_data->data_size, data, length); + png_data->data_size += length; + + return CAIRO_STATUS_SUCCESS; + +} + + +int __guac_socket_write_length_png_cairo(guac_socket* socket, cairo_surface_t* surface) { + + __guac_socket_write_png_data png_data; + int base64_length; + + /* Write surface */ + + png_data.socket = socket; + png_data.buffer_size = 8192; + png_data.buffer = malloc(png_data.buffer_size); + png_data.data_size = 0; + + if (cairo_surface_write_to_png_stream(surface, __guac_socket_write_png_cairo, &png_data) != CAIRO_STATUS_SUCCESS) { + return -1; + } + + base64_length = (png_data.data_size + 2) / 3 * 4; + + /* Write length and data */ + if ( + guac_socket_write_int(socket, base64_length) + || guac_socket_write_string(socket, ".") + || guac_socket_write_base64(socket, png_data.buffer, png_data.data_size) + || guac_socket_flush_base64(socket)) { + free(png_data.buffer); + return -1; + } + + free(png_data.buffer); + return 0; + +} + void __guac_socket_write_png(png_structp png, png_bytep data, png_size_t length) { @@ -152,13 +216,6 @@ void __guac_socket_flush_png(png_structp png) { /* Dummy function */ } -int __guac_socket_write_length_png_cairo(guac_socket* socket, cairo_surface_t* surface) { - - /* STUB */ - return guac_socket_write_string(socket, "0."); - -} - int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface) { png_structp png; From 71de5606bfc1669ed60b92dcad565bbf5756af0c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 1 Apr 2012 23:27:57 -0700 Subject: [PATCH 190/330] Should not install palette.h --- libguac/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 20a0ee44..372907f5 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -40,7 +40,7 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -Iinclude libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/socket.h include/protocol.h include/client-handlers.h include/error.h include/palette.h +libguacinc_HEADERS = include/client.h include/socket.h include/protocol.h include/client-handlers.h include/error.h lib_LTLIBRARIES = libguac.la From ecec3a109968437e41c3fa2fe9addbc33c3f6b4e Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 2 Apr 2012 13:27:28 -0700 Subject: [PATCH 191/330] Fix size of palette hash table (should be 0x1000, not 0xFFF), don't free palette until AFTER done... --- libguac/include/palette.h | 2 +- libguac/src/protocol.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libguac/include/palette.h b/libguac/include/palette.h index ce6256f0..7db3379e 100644 --- a/libguac/include/palette.h +++ b/libguac/include/palette.h @@ -51,7 +51,7 @@ typedef struct guac_palette_entry { typedef struct guac_palette { - guac_palette_entry entries[0xFFF]; + guac_palette_entry entries[0x1000]; png_color colors[256]; int size; diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index e5ab832c..5e0bdbaf 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -308,8 +308,6 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface } - guac_palette_free(palette); - /* Write image info */ png_set_IHDR( png, @@ -333,6 +331,9 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface /* Finish write */ png_destroy_write_struct(&png, &png_info); + /* Free palette */ + guac_palette_free(palette); + /* Free PNG data */ for (y=0; y Date: Tue, 10 Apr 2012 11:08:52 -0700 Subject: [PATCH 192/330] Properly add layers/buffers to available layer/buffer pool. --- libguac/src/client.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libguac/src/client.c b/libguac/src/client.c index 1451c034..d1f715af 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -133,6 +133,9 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) { if (client->__last_available_buffer != NULL) client->__last_available_buffer->__next_available = layer; + if (client->__available_buffers == NULL) + client->__available_buffers = layer; + client->__last_available_buffer = layer; } @@ -143,6 +146,9 @@ void guac_client_free_layer(guac_client* client, guac_layer* layer) { if (client->__last_available_layer != NULL) client->__last_available_layer->__next_available = layer; + if (client->__available_layers == NULL) + client->__available_layers = layer; + client->__last_available_layer = layer; } From 844afb647836c3df89244aa24a67aea94245ce40 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 10 Apr 2012 16:12:03 -0700 Subject: [PATCH 193/330] Fix segfault in layer/buffer alloc. --- libguac/src/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index d1f715af..759c4f3e 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -67,7 +67,6 @@ guac_layer* guac_client_alloc_layer(guac_client* client) { allocd_layer = client->__available_layers; client->__available_layers = client->__available_layers->__next_available; - allocd_layer->__next_available = NULL; /* If last layer, reset last available layer pointer */ if (allocd_layer == client->__last_available_layer) @@ -102,7 +101,6 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { allocd_layer = client->__available_buffers; client->__available_buffers = client->__available_buffers->__next_available; - allocd_layer->__next_available = NULL; /* If last buffer, reset last available buffer pointer */ if (allocd_layer == client->__last_available_buffer) @@ -137,6 +135,7 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) { client->__available_buffers = layer; client->__last_available_buffer = layer; + layer->__next_available = NULL; } @@ -150,6 +149,7 @@ void guac_client_free_layer(guac_client* client, guac_layer* layer) { client->__available_layers = layer; client->__last_available_layer = layer; + layer->__next_available = NULL; } From 7bc4c199b61c4f76df740743179eb85050a18c3c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 19 Apr 2012 21:05:07 -0700 Subject: [PATCH 194/330] Add error handling to png. --- libguac/src/protocol.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 5e0bdbaf..9f961199 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -157,6 +157,8 @@ int __guac_socket_write_length_png_cairo(guac_socket* socket, cairo_surface_t* s png_data.data_size = 0; if (cairo_surface_write_to_png_stream(surface, __guac_socket_write_png_cairo, &png_data) != CAIRO_STATUS_SUCCESS) { + guac_error = GUAC_STATUS_OUTPUT_ERROR; + guac_error_message = "Cairo PNG backend failed"; return -1; } @@ -258,19 +260,25 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface /* Set up PNG writer */ png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { - return -1; /* FIXME: Set guac_error, etc? */ + guac_error = GUAC_STATUS_OUTPUT_ERROR; + guac_error_message = "libpng failed to create write structure"; + return -1; } png_info = png_create_info_struct(png); if (!png_info) { png_destroy_write_struct(&png, NULL); - return -1; /* FIXME: Set guac_error, etc? */ + guac_error = GUAC_STATUS_OUTPUT_ERROR; + guac_error_message = "libpng failed to create info structure"; + return -1; } /* Set error handler */ if (setjmp(png_jmpbuf(png))) { png_destroy_write_struct(&png, &png_info); - return -1; /* FIXME: Set guac_error, etc? */ + guac_error = GUAC_STATUS_OUTPUT_ERROR; + guac_error_message = "libpng output error"; + return -1; } /* Set up buffer structure */ From 75d3a3e15c553e7004145781d660c2f7a2d42a1b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 4 May 2012 19:07:29 -0700 Subject: [PATCH 195/330] Updated ChangeLog --- libguac/ChangeLog | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libguac/ChangeLog b/libguac/ChangeLog index 544da378..e948c9e1 100644 --- a/libguac/ChangeLog +++ b/libguac/ChangeLog @@ -1,3 +1,14 @@ +2011-05-04 Michael Jumper + + * Buffer/layer allocation and pooling fixes + * Automatic PNG palletization + * Fix error reporting + * Add log handlers for guac_client_plugin_get_client() + * Add layer and drawing instructions + * Reorganized source + * Raster operations + * Cacheable cursors + 2011-12-11 Michael Jumper * Added functions for alloc/free of layers and buffers From ae9f20b896391ed787a24ebe4196aa094be614e8 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 11 May 2012 14:35:38 -0700 Subject: [PATCH 196/330] Fix documentation version, add palette to excludes. --- libguac/doc/Doxyfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libguac/doc/Doxyfile b/libguac/doc/Doxyfile index 177293d0..88065b4e 100644 --- a/libguac/doc/Doxyfile +++ b/libguac/doc/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = libguac # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 0.5.0 +PROJECT_NUMBER = 0.6.0 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. @@ -603,7 +603,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = ../include/client-handlers.h +EXCLUDE = ../include/client-handlers.h ../include/palette.h # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded @@ -617,7 +617,7 @@ EXCLUDE_SYMLINKS = NO # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -625,7 +625,7 @@ EXCLUDE_PATTERNS = # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test -EXCLUDE_SYMBOLS = __* +EXCLUDE_SYMBOLS = __* guac_palette* # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see From 6259381d92c276067390a9ec2dc200b0b4471be4 Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Wed, 23 May 2012 11:59:48 +0200 Subject: [PATCH 197/330] Corrected padding in base64 encoding Signed-off-by: Michael Jumper --- libguac/src/socket.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libguac/src/socket.c b/libguac/src/socket.c index 5b1a3f00..e2b9a490 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -209,13 +209,13 @@ ssize_t __guac_socket_write_base64_triplet(guac_socket* socket, int a, int b, in } -ssize_t __guac_socket_write_base64_byte(guac_socket* socket, char buf) { +ssize_t __guac_socket_write_base64_byte(guac_socket* socket, int buf) { int* __ready_buf = socket->__ready_buf; int retval; - __ready_buf[socket->__ready++] = buf & 0xFF; + __ready_buf[socket->__ready++] = buf; /* Flush triplet */ if (socket->__ready == 3) { @@ -233,8 +233,8 @@ ssize_t guac_socket_write_base64(guac_socket* socket, const void* buf, size_t co int retval; - const char* char_buf = (const char*) buf; - const char* end = char_buf + count; + const unsigned char* char_buf = (const unsigned char*) buf; + const unsigned char* end = char_buf + count; while (char_buf < end) { From 8f9eac1d33d0db76947c44a1114fb171ce4a00e5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 24 May 2012 23:57:30 -0700 Subject: [PATCH 198/330] Updated contributors. --- libguac/src/socket.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libguac/src/socket.c b/libguac/src/socket.c index e2b9a490..bb35393f 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * David PHAM-VAN Ulteo SAS - http://www.ulteo.com * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or From 675dec46d39b39338100718e00e759c04fa3a5fb Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 3 Jun 2012 20:42:04 -0700 Subject: [PATCH 199/330] Updated/fixed ChangeLog. --- libguac/ChangeLog | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libguac/ChangeLog b/libguac/ChangeLog index e948c9e1..7febb4fe 100644 --- a/libguac/ChangeLog +++ b/libguac/ChangeLog @@ -1,4 +1,8 @@ -2011-05-04 Michael Jumper +2012-05-23 David Pham-Van + + * Corrected padding in base64 encoding + +2012-05-04 Michael Jumper * Buffer/layer allocation and pooling fixes * Automatic PNG palletization From 7382bacc813313cb1227ac88435a38d893169a35 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 3 Jun 2012 20:47:45 -0700 Subject: [PATCH 200/330] Bump version to 0.6.1 --- libguac/configure.in | 2 +- libguac/doc/Doxyfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index ba84bb59..a9c0644b 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -35,7 +35,7 @@ # ***** END LICENSE BLOCK ***** AC_INIT(src/client.c) -AM_INIT_AUTOMAKE(libguac, 0.6.0) +AM_INIT_AUTOMAKE(libguac, 0.6.1) AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. diff --git a/libguac/doc/Doxyfile b/libguac/doc/Doxyfile index 88065b4e..10c337e8 100644 --- a/libguac/doc/Doxyfile +++ b/libguac/doc/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = libguac # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 0.6.0 +PROJECT_NUMBER = 0.6.1 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. From 79185d52f54f73ffe8a7f35115f017b5e0971b49 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 3 Jun 2012 20:52:11 -0700 Subject: [PATCH 201/330] Update version info. --- libguac/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 372907f5..5bb7efc8 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -46,7 +46,7 @@ lib_LTLIBRARIES = libguac.la libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handlers.c src/error.c src/palette.c -libguac_la_LDFLAGS = -version-info 3:0:0 +libguac_la_LDFLAGS = -version-info 3:1:0 noinst_HEADERS = include/palette.h From fb5b4af5ef3ea5de2243eab8715a86e3f253e722 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 20 Jun 2012 13:21:05 -0700 Subject: [PATCH 202/330] client-handlers.h should not be installed. --- libguac/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 5bb7efc8..25bb04b2 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -40,7 +40,7 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -Iinclude libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/socket.h include/protocol.h include/client-handlers.h include/error.h +libguacinc_HEADERS = include/client.h include/socket.h include/protocol.h include/error.h lib_LTLIBRARIES = libguac.la @@ -48,7 +48,7 @@ libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handler libguac_la_LDFLAGS = -version-info 3:1:0 -noinst_HEADERS = include/palette.h +noinst_HEADERS = include/palette.h include/client-handlers.h EXTRA_DIST = LICENSE doc/Doxyfile From 6b7fd035038054889bc4975e13ad4ec046bcce16 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 19 Jul 2012 20:03:28 -0700 Subject: [PATCH 203/330] Measure string output in UTF-8 characters. --- libguac/src/protocol.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 9f961199..85c4e422 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -73,10 +73,46 @@ /* Output formatting functions */ +ssize_t __guac_utf8_strlen(const char* str) { + + /* The current length of the string */ + int length = 0; + + /* Number of characters before start of next character */ + int skip = 0; + + while (*str != 0) { + + /* If skipping, then skip */ + if (skip > 0) skip--; + + /* Otherwise, determine next skip value, and increment length */ + else { + + /* Get next character */ + unsigned char c = (unsigned char) *str; + + /* Determine skip value (size in bytes of rest of character) */ + if ((c >>= 1) == 0x7E) skip = 5; + else if ((c >>= 1) == 0x3E) skip = 4; + else if ((c >>= 1) == 0x1E) skip = 3; + else if ((c >>= 1) == 0x0E) skip = 2; + else if ((c >>= 1) == 0x06) skip = 1; + + length++; + } + + str++; + } + + return length; + +} + ssize_t __guac_socket_write_length_string(guac_socket* socket, const char* str) { return - guac_socket_write_int(socket, strlen(str)) + guac_socket_write_int(socket, __guac_utf8_strlen(str)) || guac_socket_write_string(socket, ".") || guac_socket_write_string(socket, str); From 466fb36fd4187c8aec565da8c80e593b897e18fa Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 19 Jul 2012 23:32:49 -0700 Subject: [PATCH 204/330] Split unicode functions into own files. --- libguac/Makefile.am | 2 +- libguac/include/unicode.h | 60 +++++++++++++++++++++++++++ libguac/src/protocol.c | 39 +----------------- libguac/src/unicode.c | 85 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+), 38 deletions(-) create mode 100644 libguac/include/unicode.h create mode 100644 libguac/src/unicode.c diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 25bb04b2..3c69a92d 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -48,7 +48,7 @@ libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handler libguac_la_LDFLAGS = -version-info 3:1:0 -noinst_HEADERS = include/palette.h include/client-handlers.h +noinst_HEADERS = include/palette.h include/client-handlers.h include/unicode.h EXTRA_DIST = LICENSE doc/Doxyfile diff --git a/libguac/include/unicode.h b/libguac/include/unicode.h new file mode 100644 index 00000000..d9abd849 --- /dev/null +++ b/libguac/include/unicode.h @@ -0,0 +1,60 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_UNICODE_H +#define _GUAC_UNICODE_H + +/** + * Given the initial byte of a single UTF-8 character, returns the overall + * byte size of the entire character. + * + * @param c The initial byte of the character to check. + * @return The number of bytes in the given character overall. + */ +size_t guac_utf8_charsize(unsigned char c); + +/** + * Given a UTF-8-encoded string, returns the length of the string in characters + * (not bytes). + * + * @param str The UTF-8 string to calculate the length of. + * @return The length in characters of the given UTF-8 string. + */ +size_t guac_utf8_strlen(const char* str); + +#endif + diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 85c4e422..0ace2ac6 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -70,49 +70,14 @@ #include "protocol.h" #include "error.h" #include "palette.h" +#include "unicode.h" /* Output formatting functions */ -ssize_t __guac_utf8_strlen(const char* str) { - - /* The current length of the string */ - int length = 0; - - /* Number of characters before start of next character */ - int skip = 0; - - while (*str != 0) { - - /* If skipping, then skip */ - if (skip > 0) skip--; - - /* Otherwise, determine next skip value, and increment length */ - else { - - /* Get next character */ - unsigned char c = (unsigned char) *str; - - /* Determine skip value (size in bytes of rest of character) */ - if ((c >>= 1) == 0x7E) skip = 5; - else if ((c >>= 1) == 0x3E) skip = 4; - else if ((c >>= 1) == 0x1E) skip = 3; - else if ((c >>= 1) == 0x0E) skip = 2; - else if ((c >>= 1) == 0x06) skip = 1; - - length++; - } - - str++; - } - - return length; - -} - ssize_t __guac_socket_write_length_string(guac_socket* socket, const char* str) { return - guac_socket_write_int(socket, __guac_utf8_strlen(str)) + guac_socket_write_int(socket, guac_utf8_strlen(str)) || guac_socket_write_string(socket, ".") || guac_socket_write_string(socket, str); diff --git a/libguac/src/unicode.c b/libguac/src/unicode.c new file mode 100644 index 00000000..de80c8ed --- /dev/null +++ b/libguac/src/unicode.c @@ -0,0 +1,85 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "unicode.h" + +size_t guac_utf8_charsize(unsigned char c) { + + /* Determine size in bytes of character */ + if ((c >>= 1) == 0x7E) return 6; + if ((c >>= 1) == 0x3E) return 5; + if ((c >>= 1) == 0x1E) return 4; + if ((c >>= 1) == 0x0E) return 3; + if ((c >>= 1) == 0x06) return 2; + + /* Default to one character */ + return 1; + +} + +size_t guac_utf8_strlen(const char* str) { + + /* The current length of the string */ + int length = 0; + + /* Number of characters before start of next character */ + int skip = 0; + + while (*str != 0) { + + /* If skipping, then skip */ + if (skip > 0) skip--; + + /* Otherwise, determine next skip value, and increment length */ + else { + + /* Get next character */ + unsigned char c = (unsigned char) *str; + + /* Determine skip value (size in bytes of rest of character) */ + skip = guac_utf8_charsize(c) - 1; + + length++; + } + + str++; + } + + return length; + +} + From b76a53fe624831533f8d9d3090e09ce18fb13612 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Jul 2012 10:00:00 -0700 Subject: [PATCH 205/330] Walk element content to determine character length (NOTE: need to save state between walks to avoid rewalking old characters and turning a linear-time parse into quadratic-time). --- libguac/src/protocol.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 0ace2ac6..c0c93034 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -412,9 +412,15 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, /* Loop until a instruction is read */ for (;;) { - /* Length of element */ + /* Length of element, in Unicode characters */ int element_length = 0; + /* Length of element, in bytes */ + int element_byte_length = 0; + + /* Current position within the element, in Unicode characters */ + int current_unicode_length = 0; + /* Position within buffer */ int i = socket->__instructionbuf_parse_start; @@ -431,21 +437,34 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, /* Otherwise, if end of length */ else if (c == '.') { + /* Calculate element byte length by walking buffer */ + while (i + element_byte_length < + socket->__instructionbuf_used_length) { + + /* Get next byte */ + c = socket->__instructionbuf[i + element_byte_length]; + + /* Update byte and character lengths */ + element_byte_length += guac_utf8_charsize((unsigned) c); + current_unicode_length++; + + } + /* Verify element is fully read */ - if (i + element_length < socket->__instructionbuf_used_length) { + if (current_unicode_length == element_length) { /* Get element value */ char* elementv = &(socket->__instructionbuf[i]); /* Get terminator, set null terminator of elementv */ - char terminator = elementv[element_length]; - elementv[element_length] = '\0'; + char terminator = elementv[element_byte_length]; + elementv[element_byte_length] = '\0'; /* Move to char after terminator of element */ - i += element_length+1; + i += element_byte_length+1; /* Reset element length */ - element_length = 0; + element_length = element_byte_length = 0; /* As element has been read successfully, update * parse start */ From a7843cc30f052d39981e3a96e944447922200385 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 21 Jul 2012 12:15:59 -0700 Subject: [PATCH 206/330] Fix makefile and includes. --- libguac/Makefile.am | 2 +- libguac/include/unicode.h | 2 ++ libguac/src/unicode.c | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 3c69a92d..ae919670 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -44,7 +44,7 @@ libguacinc_HEADERS = include/client.h include/socket.h include/protocol.h includ lib_LTLIBRARIES = libguac.la -libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handlers.c src/error.c src/palette.c +libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handlers.c src/error.c src/palette.c src/unicode.c libguac_la_LDFLAGS = -version-info 3:1:0 diff --git a/libguac/include/unicode.h b/libguac/include/unicode.h index d9abd849..3364641e 100644 --- a/libguac/include/unicode.h +++ b/libguac/include/unicode.h @@ -38,6 +38,8 @@ #ifndef _GUAC_UNICODE_H #define _GUAC_UNICODE_H +#include + /** * Given the initial byte of a single UTF-8 character, returns the overall * byte size of the entire character. diff --git a/libguac/src/unicode.c b/libguac/src/unicode.c index de80c8ed..f634c10c 100644 --- a/libguac/src/unicode.c +++ b/libguac/src/unicode.c @@ -35,6 +35,8 @@ * * ***** END LICENSE BLOCK ***** */ +#include + #include "unicode.h" size_t guac_utf8_charsize(unsigned char c) { From a365f0813ba0a69608ac6dc3a31a682cbfe6cb79 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Jul 2012 13:57:13 -0700 Subject: [PATCH 207/330] Fix element walk. Reset all char counters. --- libguac/src/protocol.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index c0c93034..bc9ba68c 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -439,7 +439,8 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, /* Calculate element byte length by walking buffer */ while (i + element_byte_length < - socket->__instructionbuf_used_length) { + socket->__instructionbuf_used_length + && current_unicode_length < element_length) { /* Get next byte */ c = socket->__instructionbuf[i + element_byte_length]; @@ -464,7 +465,9 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, i += element_byte_length+1; /* Reset element length */ - element_length = element_byte_length = 0; + element_length = + element_byte_length = + current_unicode_length = 0; /* As element has been read successfully, update * parse start */ From 2c66cc4a40931015995bdaad082432a88b048995 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Jul 2012 15:21:10 -0700 Subject: [PATCH 208/330] Separate Makefile.am for src --- libguac/Makefile.am | 12 +--------- libguac/configure.in | 4 +++- libguac/src/Makefile.am | 51 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 libguac/src/Makefile.am diff --git a/libguac/Makefile.am b/libguac/Makefile.am index ae919670..2f9546f1 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -37,18 +37,8 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 -AM_CFLAGS = -Werror -Wall -pedantic -Iinclude -libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = include/client.h include/socket.h include/protocol.h include/error.h - -lib_LTLIBRARIES = libguac.la - -libguac_la_SOURCES = src/client.c src/socket.c src/protocol.c src/client-handlers.c src/error.c src/palette.c src/unicode.c - -libguac_la_LDFLAGS = -version-info 3:1:0 - -noinst_HEADERS = include/palette.h include/client-handlers.h include/unicode.h +SUBDIRS = src EXTRA_DIST = LICENSE doc/Doxyfile diff --git a/libguac/configure.in b/libguac/configure.in index a9c0644b..f7cb711f 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -68,5 +68,7 @@ AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup png_get_io_ptr nanosleep]) -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([Makefile + src/Makefile]) + AC_OUTPUT diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am new file mode 100644 index 00000000..bafff8b9 --- /dev/null +++ b/libguac/src/Makefile.am @@ -0,0 +1,51 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is libguac. +# +# The Initial Developer of the Original Code is +# Michael Jumper. +# Portions created by the Initial Developer are Copyright (C) 2010 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +AUTOMAKE_OPTIONS = foreign +ACLOCAL_AMFLAGS = -I m4 +AM_CFLAGS = -Werror -Wall -pedantic -I../include + +libguacincdir = $(includedir)/guacamole +libguacinc_HEADERS = ../include/client.h ../include/socket.h ../include/protocol.h ../include/error.h + +lib_LTLIBRARIES = libguac.la + +libguac_la_SOURCES = client.c socket.c protocol.c client-handlers.c error.c palette.c unicode.c + +libguac_la_LDFLAGS = -version-info 3:1:0 + +noinst_HEADERS = ../include/palette.h ../include/client-handlers.h ../include/unicode.h + From c21604e2cd2924778f53838376eae69761fe67ac Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Jul 2012 15:34:36 -0700 Subject: [PATCH 209/330] Cleaned up Makefile.am's --- libguac/Makefile.am | 1 - libguac/src/Makefile.am | 25 +++++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 2f9546f1..18c97410 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -35,7 +35,6 @@ # ***** END LICENSE BLOCK ***** AUTOMAKE_OPTIONS = foreign - ACLOCAL_AMFLAGS = -I m4 SUBDIRS = src diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index bafff8b9..ecd7c7f5 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -39,13 +39,26 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -I../include libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = ../include/client.h ../include/socket.h ../include/protocol.h ../include/error.h +libguacinc_HEADERS = \ + ../include/client.h \ + ../include/socket.h \ + ../include/protocol.h \ + ../include/error.h + +noinst_HEADERS = \ + ../include/palette.h \ + ../include/client-handlers.h \ + ../include/unicode.h + +libguac_la_SOURCES = \ + client.c \ + socket.c \ + protocol.c \ + client-handlers.c \ + error.c \ + palette.c \ + unicode.c lib_LTLIBRARIES = libguac.la - -libguac_la_SOURCES = client.c socket.c protocol.c client-handlers.c error.c palette.c unicode.c - libguac_la_LDFLAGS = -version-info 3:1:0 -noinst_HEADERS = ../include/palette.h ../include/client-handlers.h ../include/unicode.h - From 2f0d2f37e6aa081a43fe74e9161eeb49acd59787 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Jul 2012 17:57:31 -0700 Subject: [PATCH 210/330] Use Check for unit tests, add unit test stub. --- libguac/.gitignore | 4 ++++ libguac/Makefile.am | 2 +- libguac/configure.in | 6 ++++- libguac/tests/Makefile.am | 46 ++++++++++++++++++++++++++++++++++++ libguac/tests/test_unicode.c | 5 ++++ 5 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 libguac/tests/Makefile.am create mode 100644 libguac/tests/test_unicode.c diff --git a/libguac/.gitignore b/libguac/.gitignore index b566155e..e2b1ec0b 100644 --- a/libguac/.gitignore +++ b/libguac/.gitignore @@ -5,6 +5,10 @@ *.lo *.la +# Test binaries +tests/test_* +!tests/test_*.[ch] + # Backup files *~ diff --git a/libguac/Makefile.am b/libguac/Makefile.am index 18c97410..0b85b25c 100644 --- a/libguac/Makefile.am +++ b/libguac/Makefile.am @@ -37,7 +37,7 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src +SUBDIRS = src . tests EXTRA_DIST = LICENSE doc/Doxyfile diff --git a/libguac/configure.in b/libguac/configure.in index f7cb711f..bfcd41f4 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -68,7 +68,11 @@ AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup png_get_io_ptr nanosleep]) +# Check for "Check" (for unit tests) +PKG_CHECK_MODULES([CHECK], [check >= 0.9.4]) + AC_CONFIG_FILES([Makefile - src/Makefile]) + src/Makefile + tests/Makefile]) AC_OUTPUT diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am new file mode 100644 index 00000000..3856e475 --- /dev/null +++ b/libguac/tests/Makefile.am @@ -0,0 +1,46 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is libguac. +# +# The Initial Developer of the Original Code is +# Michael Jumper. +# Portions created by the Initial Developer are Copyright (C) 2010 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +AUTOMAKE_OPTIONS = foreign +ACLOCAL_AMFLAGS = -I m4 + +TESTS = test_unicode +check_PROGRAMS = test_unicode +test_unicode_SOURCES = test_unicode.c +test_unicode_CFLAGS = @CHECK_CFLAGS@ +test_unicode_LDADD = $(top_builddir)/src/libguac.la @CHECK_LIBS@ + + diff --git a/libguac/tests/test_unicode.c b/libguac/tests/test_unicode.c new file mode 100644 index 00000000..b0475e48 --- /dev/null +++ b/libguac/tests/test_unicode.c @@ -0,0 +1,5 @@ + +int main() { + return 0; +} + From 2650f1e4a5876b44c993a74cf02d65f6e2611c67 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Jul 2012 18:00:59 -0700 Subject: [PATCH 211/330] Add license comment to unit test source. --- libguac/tests/test_unicode.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/libguac/tests/test_unicode.c b/libguac/tests/test_unicode.c index b0475e48..053312be 100644 --- a/libguac/tests/test_unicode.c +++ b/libguac/tests/test_unicode.c @@ -1,4 +1,40 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + int main() { return 0; } From caf2349a649b7263cc223658134e94ee8fdddef8 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Jul 2012 19:40:11 -0700 Subject: [PATCH 212/330] Renamed test. --- libguac/tests/Makefile.am | 11 +++++------ libguac/tests/{test_unicode.c => test_protocol.c} | 0 2 files changed, 5 insertions(+), 6 deletions(-) rename libguac/tests/{test_unicode.c => test_protocol.c} (100%) diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index 3856e475..1027b5d7 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -37,10 +37,9 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 -TESTS = test_unicode -check_PROGRAMS = test_unicode -test_unicode_SOURCES = test_unicode.c -test_unicode_CFLAGS = @CHECK_CFLAGS@ -test_unicode_LDADD = $(top_builddir)/src/libguac.la @CHECK_LIBS@ - +TESTS = test_protocol +check_PROGRAMS = test_protocol +test_protocol_SOURCES = test_protocol.c +test_protocol_CFLAGS = @CHECK_CFLAGS@ +test_protocol_LDADD = $(top_builddir)/src/libguac.la @CHECK_LIBS@ diff --git a/libguac/tests/test_unicode.c b/libguac/tests/test_protocol.c similarity index 100% rename from libguac/tests/test_unicode.c rename to libguac/tests/test_protocol.c From 3cca318f8ed45e65f39ff0bb4e1009ce38089311 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 22 Jul 2012 22:08:01 -0700 Subject: [PATCH 213/330] Protocol test stub. --- libguac/configure.in | 5 +++-- libguac/tests/Makefile.am | 3 +-- libguac/tests/test_protocol.c | 42 ++++++++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index bfcd41f4..000bc3b3 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -68,8 +68,9 @@ AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([clock_gettime gettimeofday memmove memset select strdup png_get_io_ptr nanosleep]) -# Check for "Check" (for unit tests) -PKG_CHECK_MODULES([CHECK], [check >= 0.9.4]) +# Check for unit testing library +AC_CHECK_LIB([cunit], [CU_run_test], [CUNIT_LIBS=-lcunit]) +AC_SUBST(CUNIT_LIBS) AC_CONFIG_FILES([Makefile src/Makefile diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index 1027b5d7..d09a89c9 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -40,6 +40,5 @@ ACLOCAL_AMFLAGS = -I m4 TESTS = test_protocol check_PROGRAMS = test_protocol test_protocol_SOURCES = test_protocol.c -test_protocol_CFLAGS = @CHECK_CFLAGS@ -test_protocol_LDADD = $(top_builddir)/src/libguac.la @CHECK_LIBS@ +test_protocol_LDADD = $(top_builddir)/src/libguac.la @CUNIT_LIBS@ diff --git a/libguac/tests/test_protocol.c b/libguac/tests/test_protocol.c index 053312be..6bff4a8b 100644 --- a/libguac/tests/test_protocol.c +++ b/libguac/tests/test_protocol.c @@ -35,7 +35,47 @@ * * ***** END LICENSE BLOCK ***** */ -int main() { +#include + +int init_suite() { return 0; } +int cleanup_suite() { + return 0; +} + +void test_unicode() { +} + +int main() { + + CU_pSuite pSuite; + + /* Init registry */ + if (CU_initialize_registry() != CUE_SUCCESS) + return CU_get_error(); + + /* Add protocol test suite */ + pSuite = CU_add_suite("protocol", init_suite, cleanup_suite); + if (pSuite == NULL) { + CU_cleanup_registry(); + return CU_get_error(); + } + + /* Add tests */ + if ( + CU_add_test(pSuite, "unicode-support", test_unicode) == NULL + ) { + CU_cleanup_registry(); + return CU_get_error(); + } + + /* Run tests */ + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + CU_cleanup_registry(); + return CU_get_error(); + +} + From 5bd42295cae9c97eade906f2f56c1eb96ea198cf Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Jul 2012 01:41:50 -0700 Subject: [PATCH 214/330] Use read() instead of recv() such that non-sockets can be used for reads. --- libguac/src/protocol.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index bc9ba68c..ec72be25 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -373,11 +373,10 @@ int __guac_fill_instructionbuf(guac_socket* socket) { int retval; /* Attempt to fill buffer */ - retval = recv( + retval = read( socket->fd, socket->__instructionbuf + socket->__instructionbuf_used_length, - socket->__instructionbuf_size - socket->__instructionbuf_used_length, - 0 + socket->__instructionbuf_size - socket->__instructionbuf_used_length ); /* Set guac_error if recv() unsuccessful */ From e1715cc40cbc1fa262a7136e0a0e8891615f5abe Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Jul 2012 01:42:15 -0700 Subject: [PATCH 215/330] Actual unit test of unicode use. --- libguac/tests/Makefile.am | 1 + libguac/tests/test_protocol.c | 76 +++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index d09a89c9..bd2cc225 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -36,6 +36,7 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 +AM_CFLAGS = -Werror -Wall -pedantic -I../include TESTS = test_protocol check_PROGRAMS = test_protocol diff --git a/libguac/tests/test_protocol.c b/libguac/tests/test_protocol.c index 6bff4a8b..a9d53899 100644 --- a/libguac/tests/test_protocol.c +++ b/libguac/tests/test_protocol.c @@ -35,8 +35,17 @@ * * ***** END LICENSE BLOCK ***** */ +#include +#include +#include #include +#include "socket.h" +#include "protocol.h" +#include "error.h" + +#define UTF8_DOG "\xe7\x8a\xac" + int init_suite() { return 0; } @@ -46,6 +55,73 @@ int cleanup_suite() { } void test_unicode() { + + int rfd, wfd; + int fd[2], childpid; + + char test_string[] = "4.test,3.a" UTF8_DOG "b," + "5.12345,4.a" UTF8_DOG UTF8_DOG "c;" + "5.test2,10.hellohello,15.worldworldworld;"; + + /* Create pipe */ + pipe(fd); + + /* File descriptors */ + rfd = fd[0]; + wfd = fd[1]; + + /* Fork */ + if ((childpid = fork()) == -1) { + /* ERROR */ + perror("fork"); + return; + } + + /* Child (pipe writer) */ + if (childpid != 0) { + close(rfd); + write(wfd, test_string, sizeof(test_string)); + exit(0); + } + + /* Parent (unit test) */ + else { + + guac_socket* socket; + guac_instruction* instruction; + + close(wfd); + + /* Open guac socket */ + socket = guac_socket_open(rfd); + CU_ASSERT_PTR_NOT_NULL_FATAL(socket); + + /* Read instruction */ + instruction = guac_protocol_read_instruction(socket, 1000000); + CU_ASSERT_PTR_NOT_NULL_FATAL(instruction); + + /* Validate contents */ + CU_ASSERT_STRING_EQUAL(instruction->opcode, "test"); + CU_ASSERT_EQUAL_FATAL(instruction->argc, 3); + CU_ASSERT_STRING_EQUAL(instruction->argv[0], "a" UTF8_DOG "b"); + CU_ASSERT_STRING_EQUAL(instruction->argv[1], "12345"); + CU_ASSERT_STRING_EQUAL(instruction->argv[2], "a" UTF8_DOG UTF8_DOG "c"); + + /* Read another instruction */ + guac_instruction_free(instruction); + instruction = guac_protocol_read_instruction(socket, 1000000); + + /* Validate contents */ + CU_ASSERT_STRING_EQUAL(instruction->opcode, "test2"); + CU_ASSERT_EQUAL_FATAL(instruction->argc, 2); + CU_ASSERT_STRING_EQUAL(instruction->argv[0], "hellohello"); + CU_ASSERT_STRING_EQUAL(instruction->argv[1], "worldworldworld"); + + guac_instruction_free(instruction); + guac_socket_close(socket); + + } + } int main() { From 24c7898ffe1879ab09a58f80cf4653b5dfee2e55 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Jul 2012 02:20:12 -0700 Subject: [PATCH 216/330] Rename test function. --- libguac/tests/test_protocol.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libguac/tests/test_protocol.c b/libguac/tests/test_protocol.c index a9d53899..e273075f 100644 --- a/libguac/tests/test_protocol.c +++ b/libguac/tests/test_protocol.c @@ -54,7 +54,7 @@ int cleanup_suite() { return 0; } -void test_unicode() { +void test_instruction_parse() { int rfd, wfd; int fd[2], childpid; @@ -126,22 +126,22 @@ void test_unicode() { int main() { - CU_pSuite pSuite; + CU_pSuite suite; /* Init registry */ if (CU_initialize_registry() != CUE_SUCCESS) return CU_get_error(); /* Add protocol test suite */ - pSuite = CU_add_suite("protocol", init_suite, cleanup_suite); - if (pSuite == NULL) { + suite = CU_add_suite("protocol", init_suite, cleanup_suite); + if (suite == NULL) { CU_cleanup_registry(); return CU_get_error(); } /* Add tests */ if ( - CU_add_test(pSuite, "unicode-support", test_unicode) == NULL + CU_add_test(suite, "instruction-parse", test_instruction_parse) == NULL ) { CU_cleanup_registry(); return CU_get_error(); From 4170f781a5ec6f78fc27df6a5a51876bba45d216 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Jul 2012 02:25:06 -0700 Subject: [PATCH 217/330] More renaming. --- libguac/tests/test_protocol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/tests/test_protocol.c b/libguac/tests/test_protocol.c index e273075f..4ddccc30 100644 --- a/libguac/tests/test_protocol.c +++ b/libguac/tests/test_protocol.c @@ -54,7 +54,7 @@ int cleanup_suite() { return 0; } -void test_instruction_parse() { +void test_instruction_read() { int rfd, wfd; int fd[2], childpid; @@ -141,7 +141,7 @@ int main() { /* Add tests */ if ( - CU_add_test(suite, "instruction-parse", test_instruction_parse) == NULL + CU_add_test(suite, "instruction-read", test_instruction_read) == NULL ) { CU_cleanup_registry(); return CU_get_error(); From af4cb160cb3f8b0c895841143c4a99eb3be69ad1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Jul 2012 12:38:53 -0700 Subject: [PATCH 218/330] Add instruction writing test. --- libguac/tests/test_protocol.c | 71 +++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/libguac/tests/test_protocol.c b/libguac/tests/test_protocol.c index 4ddccc30..fe4e0e2e 100644 --- a/libguac/tests/test_protocol.c +++ b/libguac/tests/test_protocol.c @@ -54,6 +54,76 @@ int cleanup_suite() { return 0; } +void test_instruction_write() { + + int rfd, wfd; + int fd[2], childpid; + + /* Create pipe */ + pipe(fd); + + /* File descriptors */ + rfd = fd[0]; + wfd = fd[1]; + + /* Fork */ + if ((childpid = fork()) == -1) { + /* ERROR */ + perror("fork"); + return; + } + + /* Child (pipe writer) */ + if (childpid != 0) { + + guac_socket* socket; + + close(rfd); + + /* Open guac socket */ + socket = guac_socket_open(wfd); + + /* Write instruction */ + guac_protocol_send_clipboard(socket, "a" UTF8_DOG "b" UTF8_DOG "c"); + guac_protocol_send_sync(socket, 12345); + guac_socket_flush(socket); + + guac_socket_close(socket); + exit(0); + } + + /* Parent (unit test) */ + else { + + char expected[] = + "9.clipboard,5.a" UTF8_DOG "b" UTF8_DOG "c;" + "4.sync,5.12345;"; + + int numread; + char buffer[1024]; + int offset = 0; + + close(wfd); + + /* Read everything available into buffer */ + while ((numread = + read(rfd, + &(buffer[offset]), + sizeof(buffer)-offset)) != 0) { + offset += numread; + } + + /* Add NULL terminator */ + buffer[offset] = '\0'; + + /* Read value should be equal to expected value */ + CU_ASSERT_STRING_EQUAL(buffer, expected); + + } + +} + + void test_instruction_read() { int rfd, wfd; @@ -142,6 +212,7 @@ int main() { /* Add tests */ if ( CU_add_test(suite, "instruction-read", test_instruction_read) == NULL + || CU_add_test(suite, "instruction-write", test_instruction_write) == NULL ) { CU_cleanup_registry(); return CU_get_error(); From f8eb590ea33bde46ec85c5ae733f0fa6e45962e0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Jul 2012 15:37:36 -0700 Subject: [PATCH 219/330] Split test_protocol.c into multiple files, one per test. --- libguac/tests/Makefile.am | 8 +- libguac/tests/protocol/instruction_read.c | 118 ++++++++++++++ libguac/tests/protocol/instruction_write.c | 117 ++++++++++++++ libguac/tests/protocol/suite.c | 72 +++++++++ libguac/tests/protocol/suite.h | 49 ++++++ libguac/tests/test_protocol.c | 176 +-------------------- 6 files changed, 366 insertions(+), 174 deletions(-) create mode 100644 libguac/tests/protocol/instruction_read.c create mode 100644 libguac/tests/protocol/instruction_write.c create mode 100644 libguac/tests/protocol/suite.c create mode 100644 libguac/tests/protocol/suite.h diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index bd2cc225..c3ff77df 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -40,6 +40,12 @@ AM_CFLAGS = -Werror -Wall -pedantic -I../include TESTS = test_protocol check_PROGRAMS = test_protocol -test_protocol_SOURCES = test_protocol.c + +test_protocol_SOURCES = \ + test_protocol.c \ + protocol/suite.c \ + protocol/instruction_read.c \ + protocol/instruction_write.c + test_protocol_LDADD = $(top_builddir)/src/libguac.la @CUNIT_LIBS@ diff --git a/libguac/tests/protocol/instruction_read.c b/libguac/tests/protocol/instruction_read.c new file mode 100644 index 00000000..19d75ffd --- /dev/null +++ b/libguac/tests/protocol/instruction_read.c @@ -0,0 +1,118 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include + +#include "socket.h" +#include "protocol.h" +#include "error.h" + +#include "suite.h" + +void test_instruction_read() { + + int rfd, wfd; + int fd[2], childpid; + + char test_string[] = "4.test,3.a" UTF8_DOG "b," + "5.12345,4.a" UTF8_DOG UTF8_DOG "c;" + "5.test2,10.hellohello,15.worldworldworld;"; + + /* Create pipe */ + pipe(fd); + + /* File descriptors */ + rfd = fd[0]; + wfd = fd[1]; + + /* Fork */ + if ((childpid = fork()) == -1) { + /* ERROR */ + perror("fork"); + return; + } + + /* Child (pipe writer) */ + if (childpid != 0) { + close(rfd); + write(wfd, test_string, sizeof(test_string)); + exit(0); + } + + /* Parent (unit test) */ + else { + + guac_socket* socket; + guac_instruction* instruction; + + close(wfd); + + /* Open guac socket */ + socket = guac_socket_open(rfd); + CU_ASSERT_PTR_NOT_NULL_FATAL(socket); + + /* Read instruction */ + instruction = guac_protocol_read_instruction(socket, 1000000); + CU_ASSERT_PTR_NOT_NULL_FATAL(instruction); + + /* Validate contents */ + CU_ASSERT_STRING_EQUAL(instruction->opcode, "test"); + CU_ASSERT_EQUAL_FATAL(instruction->argc, 3); + CU_ASSERT_STRING_EQUAL(instruction->argv[0], "a" UTF8_DOG "b"); + CU_ASSERT_STRING_EQUAL(instruction->argv[1], "12345"); + CU_ASSERT_STRING_EQUAL(instruction->argv[2], "a" UTF8_DOG UTF8_DOG "c"); + + /* Read another instruction */ + guac_instruction_free(instruction); + instruction = guac_protocol_read_instruction(socket, 1000000); + + /* Validate contents */ + CU_ASSERT_STRING_EQUAL(instruction->opcode, "test2"); + CU_ASSERT_EQUAL_FATAL(instruction->argc, 2); + CU_ASSERT_STRING_EQUAL(instruction->argv[0], "hellohello"); + CU_ASSERT_STRING_EQUAL(instruction->argv[1], "worldworldworld"); + + guac_instruction_free(instruction); + guac_socket_close(socket); + + } + +} + diff --git a/libguac/tests/protocol/instruction_write.c b/libguac/tests/protocol/instruction_write.c new file mode 100644 index 00000000..3331226f --- /dev/null +++ b/libguac/tests/protocol/instruction_write.c @@ -0,0 +1,117 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include + +#include "socket.h" +#include "protocol.h" +#include "error.h" + +#include "suite.h" + +void test_instruction_write() { + + int rfd, wfd; + int fd[2], childpid; + + /* Create pipe */ + pipe(fd); + + /* File descriptors */ + rfd = fd[0]; + wfd = fd[1]; + + /* Fork */ + if ((childpid = fork()) == -1) { + /* ERROR */ + perror("fork"); + return; + } + + /* Child (pipe writer) */ + if (childpid != 0) { + + guac_socket* socket; + + close(rfd); + + /* Open guac socket */ + socket = guac_socket_open(wfd); + + /* Write instruction */ + guac_protocol_send_clipboard(socket, "a" UTF8_DOG "b" UTF8_DOG "c"); + guac_protocol_send_sync(socket, 12345); + guac_socket_flush(socket); + + guac_socket_close(socket); + exit(0); + } + + /* Parent (unit test) */ + else { + + char expected[] = + "9.clipboard,5.a" UTF8_DOG "b" UTF8_DOG "c;" + "4.sync,5.12345;"; + + int numread; + char buffer[1024]; + int offset = 0; + + close(wfd); + + /* Read everything available into buffer */ + while ((numread = + read(rfd, + &(buffer[offset]), + sizeof(buffer)-offset)) != 0) { + offset += numread; + } + + /* Add NULL terminator */ + buffer[offset] = '\0'; + + /* Read value should be equal to expected value */ + CU_ASSERT_STRING_EQUAL(buffer, expected); + + } + +} + diff --git a/libguac/tests/protocol/suite.c b/libguac/tests/protocol/suite.c new file mode 100644 index 00000000..6c7cca25 --- /dev/null +++ b/libguac/tests/protocol/suite.c @@ -0,0 +1,72 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include + +#include "suite.h" + +int protocol_suite_init() { + return 0; +} + +int protocol_suite_cleanup() { + return 0; +} + +int register_protocol_suite() { + + /* Add protocol test suite */ + CU_pSuite suite = CU_add_suite("protocol", + protocol_suite_init, protocol_suite_cleanup); + if (suite == NULL) { + CU_cleanup_registry(); + return CU_get_error(); + } + + /* Add tests */ + if ( + CU_add_test(suite, "instruction-read", test_instruction_read) == NULL + || CU_add_test(suite, "instruction-write", test_instruction_write) == NULL + ) { + CU_cleanup_registry(); + return CU_get_error(); + } + + return 0; + +} + diff --git a/libguac/tests/protocol/suite.h b/libguac/tests/protocol/suite.h new file mode 100644 index 00000000..b551e3a5 --- /dev/null +++ b/libguac/tests/protocol/suite.h @@ -0,0 +1,49 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_TEST_PROTOCOL_SUITE_H +#define _GUAC_TEST_PROTOCOL_SUITE_H + +#define UTF8_DOG "\xe7\x8a\xac" + +int register_protocol_suite(); + +void test_instruction_read(); +void test_instruction_write(); + +#endif + diff --git a/libguac/tests/test_protocol.c b/libguac/tests/test_protocol.c index fe4e0e2e..dfccdd46 100644 --- a/libguac/tests/test_protocol.c +++ b/libguac/tests/test_protocol.c @@ -35,188 +35,18 @@ * * ***** END LICENSE BLOCK ***** */ -#include -#include -#include #include -#include "socket.h" -#include "protocol.h" -#include "error.h" - -#define UTF8_DOG "\xe7\x8a\xac" - -int init_suite() { - return 0; -} - -int cleanup_suite() { - return 0; -} - -void test_instruction_write() { - - int rfd, wfd; - int fd[2], childpid; - - /* Create pipe */ - pipe(fd); - - /* File descriptors */ - rfd = fd[0]; - wfd = fd[1]; - - /* Fork */ - if ((childpid = fork()) == -1) { - /* ERROR */ - perror("fork"); - return; - } - - /* Child (pipe writer) */ - if (childpid != 0) { - - guac_socket* socket; - - close(rfd); - - /* Open guac socket */ - socket = guac_socket_open(wfd); - - /* Write instruction */ - guac_protocol_send_clipboard(socket, "a" UTF8_DOG "b" UTF8_DOG "c"); - guac_protocol_send_sync(socket, 12345); - guac_socket_flush(socket); - - guac_socket_close(socket); - exit(0); - } - - /* Parent (unit test) */ - else { - - char expected[] = - "9.clipboard,5.a" UTF8_DOG "b" UTF8_DOG "c;" - "4.sync,5.12345;"; - - int numread; - char buffer[1024]; - int offset = 0; - - close(wfd); - - /* Read everything available into buffer */ - while ((numread = - read(rfd, - &(buffer[offset]), - sizeof(buffer)-offset)) != 0) { - offset += numread; - } - - /* Add NULL terminator */ - buffer[offset] = '\0'; - - /* Read value should be equal to expected value */ - CU_ASSERT_STRING_EQUAL(buffer, expected); - - } - -} - - -void test_instruction_read() { - - int rfd, wfd; - int fd[2], childpid; - - char test_string[] = "4.test,3.a" UTF8_DOG "b," - "5.12345,4.a" UTF8_DOG UTF8_DOG "c;" - "5.test2,10.hellohello,15.worldworldworld;"; - - /* Create pipe */ - pipe(fd); - - /* File descriptors */ - rfd = fd[0]; - wfd = fd[1]; - - /* Fork */ - if ((childpid = fork()) == -1) { - /* ERROR */ - perror("fork"); - return; - } - - /* Child (pipe writer) */ - if (childpid != 0) { - close(rfd); - write(wfd, test_string, sizeof(test_string)); - exit(0); - } - - /* Parent (unit test) */ - else { - - guac_socket* socket; - guac_instruction* instruction; - - close(wfd); - - /* Open guac socket */ - socket = guac_socket_open(rfd); - CU_ASSERT_PTR_NOT_NULL_FATAL(socket); - - /* Read instruction */ - instruction = guac_protocol_read_instruction(socket, 1000000); - CU_ASSERT_PTR_NOT_NULL_FATAL(instruction); - - /* Validate contents */ - CU_ASSERT_STRING_EQUAL(instruction->opcode, "test"); - CU_ASSERT_EQUAL_FATAL(instruction->argc, 3); - CU_ASSERT_STRING_EQUAL(instruction->argv[0], "a" UTF8_DOG "b"); - CU_ASSERT_STRING_EQUAL(instruction->argv[1], "12345"); - CU_ASSERT_STRING_EQUAL(instruction->argv[2], "a" UTF8_DOG UTF8_DOG "c"); - - /* Read another instruction */ - guac_instruction_free(instruction); - instruction = guac_protocol_read_instruction(socket, 1000000); - - /* Validate contents */ - CU_ASSERT_STRING_EQUAL(instruction->opcode, "test2"); - CU_ASSERT_EQUAL_FATAL(instruction->argc, 2); - CU_ASSERT_STRING_EQUAL(instruction->argv[0], "hellohello"); - CU_ASSERT_STRING_EQUAL(instruction->argv[1], "worldworldworld"); - - guac_instruction_free(instruction); - guac_socket_close(socket); - - } - -} +#include "protocol/suite.h" int main() { - CU_pSuite suite; - /* Init registry */ if (CU_initialize_registry() != CUE_SUCCESS) return CU_get_error(); - /* Add protocol test suite */ - suite = CU_add_suite("protocol", init_suite, cleanup_suite); - if (suite == NULL) { - CU_cleanup_registry(); - return CU_get_error(); - } - - /* Add tests */ - if ( - CU_add_test(suite, "instruction-read", test_instruction_read) == NULL - || CU_add_test(suite, "instruction-write", test_instruction_write) == NULL - ) { - CU_cleanup_registry(); - return CU_get_error(); - } + /* Register suites */ + register_protocol_suite(); /* Run tests */ CU_basic_set_mode(CU_BRM_VERBOSE); From a46e4f40ed1dcea21afb628c961d49909257c0bc Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Jul 2012 15:50:58 -0700 Subject: [PATCH 220/330] Define better set of UTF8 test strings, use instead of dog. --- libguac/tests/protocol/instruction_read.c | 8 ++++---- libguac/tests/protocol/instruction_write.c | 4 ++-- libguac/tests/protocol/suite.h | 8 +++++++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/libguac/tests/protocol/instruction_read.c b/libguac/tests/protocol/instruction_read.c index 19d75ffd..a763ad21 100644 --- a/libguac/tests/protocol/instruction_read.c +++ b/libguac/tests/protocol/instruction_read.c @@ -51,8 +51,8 @@ void test_instruction_read() { int rfd, wfd; int fd[2], childpid; - char test_string[] = "4.test,3.a" UTF8_DOG "b," - "5.12345,4.a" UTF8_DOG UTF8_DOG "c;" + char test_string[] = "4.test,6.a" UTF8_4 "b," + "5.12345,10.a" UTF8_8 "c;" "5.test2,10.hellohello,15.worldworldworld;"; /* Create pipe */ @@ -95,9 +95,9 @@ void test_instruction_read() { /* Validate contents */ CU_ASSERT_STRING_EQUAL(instruction->opcode, "test"); CU_ASSERT_EQUAL_FATAL(instruction->argc, 3); - CU_ASSERT_STRING_EQUAL(instruction->argv[0], "a" UTF8_DOG "b"); + CU_ASSERT_STRING_EQUAL(instruction->argv[0], "a" UTF8_4 "b"); CU_ASSERT_STRING_EQUAL(instruction->argv[1], "12345"); - CU_ASSERT_STRING_EQUAL(instruction->argv[2], "a" UTF8_DOG UTF8_DOG "c"); + CU_ASSERT_STRING_EQUAL(instruction->argv[2], "a" UTF8_8 "c"); /* Read another instruction */ guac_instruction_free(instruction); diff --git a/libguac/tests/protocol/instruction_write.c b/libguac/tests/protocol/instruction_write.c index 3331226f..1e003942 100644 --- a/libguac/tests/protocol/instruction_write.c +++ b/libguac/tests/protocol/instruction_write.c @@ -76,7 +76,7 @@ void test_instruction_write() { socket = guac_socket_open(wfd); /* Write instruction */ - guac_protocol_send_clipboard(socket, "a" UTF8_DOG "b" UTF8_DOG "c"); + guac_protocol_send_clipboard(socket, "a" UTF8_4 "b" UTF8_4 "c"); guac_protocol_send_sync(socket, 12345); guac_socket_flush(socket); @@ -88,7 +88,7 @@ void test_instruction_write() { else { char expected[] = - "9.clipboard,5.a" UTF8_DOG "b" UTF8_DOG "c;" + "9.clipboard,11.a" UTF8_4 "b" UTF8_4 "c;" "4.sync,5.12345;"; int numread; diff --git a/libguac/tests/protocol/suite.h b/libguac/tests/protocol/suite.h index b551e3a5..7e8b5b8c 100644 --- a/libguac/tests/protocol/suite.h +++ b/libguac/tests/protocol/suite.h @@ -38,7 +38,13 @@ #ifndef _GUAC_TEST_PROTOCOL_SUITE_H #define _GUAC_TEST_PROTOCOL_SUITE_H -#define UTF8_DOG "\xe7\x8a\xac" +/* Unicode (UTF-8) strings */ + +#define UTF8_1 "\xe7\x8a\xac" /* One character */ +#define UTF8_2 UTF8_1 "\xf0\x90\xac\x80" /* Two characters */ +#define UTF8_3 UTF8_2 "z" /* Three characters */ +#define UTF8_4 UTF8_3 "\xc3\xa1" /* Four characters */ +#define UTF8_8 UTF8_4 UTF8_4 /* Eight characters */ int register_protocol_suite(); From f22469ef312d7ae07c2836a9e6d15b6cb222c6ec Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 23 Jul 2012 20:08:14 -0700 Subject: [PATCH 221/330] Ignore gcov files. --- libguac/.gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libguac/.gitignore b/libguac/.gitignore index e2b1ec0b..bb414c4c 100644 --- a/libguac/.gitignore +++ b/libguac/.gitignore @@ -9,6 +9,11 @@ tests/test_* !tests/test_*.[ch] +# gcov files +*.gcda +*.gcov +*.gcno + # Backup files *~ From cf6c232054b32ac74c33bd39e2d06f46656e4825 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 11 Aug 2012 13:22:27 -0700 Subject: [PATCH 222/330] Ensure m4/ directory exists, while automatically-added files are not included in commits. --- libguac/.gitignore | 3 ++- libguac/m4/README | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 libguac/m4/README diff --git a/libguac/.gitignore b/libguac/.gitignore index bb414c4c..614f6795 100644 --- a/libguac/.gitignore +++ b/libguac/.gitignore @@ -30,7 +30,8 @@ Makefile Makefile.in aclocal.m4 autom4te.cache/ -m4/ +m4/* +!README config.guess config.log config.status diff --git a/libguac/m4/README b/libguac/m4/README new file mode 100644 index 00000000..c9c9cbc4 --- /dev/null +++ b/libguac/m4/README @@ -0,0 +1,12 @@ +This file exists such that the m4/ directory will be created when cloning the +git repository. + +The m4/ directory is not directly used by this project, but libtoolize +populates this directory with files, recommending that the directory be +included in the macro search path for aclocal. + +Because autoreconf runs aclocal before libtoolize, this directory will not +exist when autoreconf is run, triggering an error from aclocal. + +Creating this directory (and keeping this file in it as a placeholder) +prevents this error. From 905c6039f41ff7ba11939d404b9a1f295aac3b5f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 11 Aug 2012 13:47:50 -0700 Subject: [PATCH 223/330] Update ChangeLog. --- libguac/ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libguac/ChangeLog b/libguac/ChangeLog index 7febb4fe..a79100e5 100644 --- a/libguac/ChangeLog +++ b/libguac/ChangeLog @@ -1,3 +1,8 @@ +2012-07-23 Michael Jumper + + * Add unit tests for Unicode in protocol + * Fix handling of Unicode (UTF-8) characters in protocol + 2012-05-23 David Pham-Van * Corrected padding in base64 encoding From 014a627d1359bf9aced02754f583bcd0bcfe9627 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 11 Aug 2012 13:50:13 -0700 Subject: [PATCH 224/330] Update version information. --- libguac/configure.in | 2 +- libguac/src/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index 000bc3b3..4c90441f 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -35,7 +35,7 @@ # ***** END LICENSE BLOCK ***** AC_INIT(src/client.c) -AM_INIT_AUTOMAKE(libguac, 0.6.1) +AM_INIT_AUTOMAKE(libguac, 0.6.2) AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index ecd7c7f5..08c86876 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -60,5 +60,5 @@ libguac_la_SOURCES = \ unicode.c lib_LTLIBRARIES = libguac.la -libguac_la_LDFLAGS = -version-info 3:1:0 +libguac_la_LDFLAGS = -version-info 3:2:0 From fbca4e8b9a52c6118cc41496dc935252fd1b4018 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 12 Aug 2012 23:12:59 -0700 Subject: [PATCH 225/330] Ensure suite.h is included in source tarball. --- libguac/tests/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index c3ff77df..21f9530a 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -47,5 +47,8 @@ test_protocol_SOURCES = \ protocol/instruction_read.c \ protocol/instruction_write.c +noinst_HEADERS = \ + protocol/suite.h + test_protocol_LDADD = $(top_builddir)/src/libguac.la @CUNIT_LIBS@ From aaa463ec9fe1c8f55a3ef5fa6ca290ac196199b1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 12 Aug 2012 23:14:14 -0700 Subject: [PATCH 226/330] Assert return values. --- libguac/tests/protocol/instruction_read.c | 7 +++++-- libguac/tests/protocol/instruction_write.c | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libguac/tests/protocol/instruction_read.c b/libguac/tests/protocol/instruction_read.c index a763ad21..45e7083d 100644 --- a/libguac/tests/protocol/instruction_read.c +++ b/libguac/tests/protocol/instruction_read.c @@ -56,7 +56,7 @@ void test_instruction_read() { "5.test2,10.hellohello,15.worldworldworld;"; /* Create pipe */ - pipe(fd); + CU_ASSERT_EQUAL_FATAL(pipe(fd), 0); /* File descriptors */ rfd = fd[0]; @@ -72,7 +72,10 @@ void test_instruction_read() { /* Child (pipe writer) */ if (childpid != 0) { close(rfd); - write(wfd, test_string, sizeof(test_string)); + CU_ASSERT_EQUAL( + write(wfd, test_string, sizeof(test_string)), + sizeof(test_string) + ); exit(0); } diff --git a/libguac/tests/protocol/instruction_write.c b/libguac/tests/protocol/instruction_write.c index 1e003942..58b136a4 100644 --- a/libguac/tests/protocol/instruction_write.c +++ b/libguac/tests/protocol/instruction_write.c @@ -52,7 +52,7 @@ void test_instruction_write() { int fd[2], childpid; /* Create pipe */ - pipe(fd); + CU_ASSERT_EQUAL_FATAL(pipe(fd), 0); /* File descriptors */ rfd = fd[0]; From b0240f02abdf2a8e1fe6c24d1dd7b3f6790253dc Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 23 Aug 2012 11:50:06 -0700 Subject: [PATCH 227/330] Define library prefix/suffix with macros, explicitly define and enforce limit on protocol name length, and overall library name length. --- libguac/include/client.h | 32 ++++++++++++++++++++++++++++++++ libguac/src/client.c | 9 +++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 57852c5d..1ceafe9c 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -50,6 +50,38 @@ * @file client.h */ +/** + * String prefix which begins the library filename of all client plugins. + */ +#define GUAC_PROTOCOL_LIBRARY_PREFIX "libguac-client-" + +/** + * String suffix which ends the library filename of all client plugins. + */ +#define GUAC_PROTOCOL_LIBRARY_SUFFIX ".so" + +/** + * The maximum number of characters (COUNTING NULL TERMINATOR) to allow + * for protocol names within the library filename of client plugins. + */ +#define GUAC_PROTOCOL_NAME_LIMIT 256 + +/** + * The maximum number of characters (INCLUDING NULL TERMINATOR) that a + * character array containing the concatenation of the library prefix, + * protocol name, and suffix can contain, assuming the protocol name is + * limited to GUAC_PROTOCOL_NAME_LIMIT characters. + */ +#define GUAC_PROTOCOL_LIBRARY_LIMIT ( \ + \ + sizeof(GUAC_PROTOCOL_LIBRARY_PREFIX) - 1 /* "libguac-client-" */ \ + + GUAC_PROTOCOL_NAME_LIMIT - 1 /* [up to 256 chars] */ \ + + sizeof(GUAC_PROTOCOL_LIBRARY_SUFFIX) - 1 /* ".so" */ \ + + 1 /* NULL terminator */ \ + \ +) + + typedef struct guac_client guac_client; typedef struct guac_client_plugin guac_client_plugin; diff --git a/libguac/src/client.c b/libguac/src/client.c index 759c4f3e..90491b50 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -164,16 +164,17 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol) { const char** client_args; /* Pluggable client */ - char protocol_lib[256] = "libguac-client-"; - + char protocol_lib[GUAC_PROTOCOL_LIBRARY_LIMIT] = + GUAC_PROTOCOL_LIBRARY_PREFIX; + union { guac_client_init_handler* client_init; void* obj; } alias; /* Add protocol and .so suffix to protocol_lib */ - strcat(protocol_lib, protocol); - strcat(protocol_lib, ".so"); + strncat(protocol_lib, protocol, GUAC_PROTOCOL_NAME_LIMIT-1); + strcat(protocol_lib, GUAC_PROTOCOL_LIBRARY_SUFFIX); /* Load client plugin */ client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); From 928f3c545754d52c6fd86dd9ebb014db717a43d1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 26 Aug 2012 11:30:42 -0700 Subject: [PATCH 228/330] Bump version numbers. --- libguac/configure.in | 2 +- libguac/src/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index 4c90441f..a252bb9d 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -35,7 +35,7 @@ # ***** END LICENSE BLOCK ***** AC_INIT(src/client.c) -AM_INIT_AUTOMAKE(libguac, 0.6.2) +AM_INIT_AUTOMAKE(libguac, 0.6.3) AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index 08c86876..d3ca6d57 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -60,5 +60,5 @@ libguac_la_SOURCES = \ unicode.c lib_LTLIBRARIES = libguac.la -libguac_la_LDFLAGS = -version-info 3:2:0 +libguac_la_LDFLAGS = -version-info 3:3:0 From 6d5c9b6ddec8a8405fd0a2074962686dff8a4874 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Aug 2012 14:28:56 -0700 Subject: [PATCH 229/330] Refactor creation of client to NOT require plugin. --- libguac/include/client.h | 28 +++++++++++++++------------- libguac/src/client.c | 22 ++++++++-------------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 1ceafe9c..028a89d0 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -470,23 +470,25 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol); int guac_client_plugin_close(guac_client_plugin* plugin); /** - * Initialize and return a new guac_client. The pluggable client will be - * initialized using the arguments provided. + * Initializes the given guac_client using the initialization routing provided + * by the given guac_client_plugin. * - * @param plugin The client plugin to use to create the new client. - * @param socket The guac_socket the client should use for communication. + * @param client The guac_client to initialize. + * @param plugin The client plugin to use to initialize the new client. * @param argc The number of arguments being passed to the client. * @param argv All arguments to be passed to the client. - * @param log_info_handler Info logging handler to provide to the client before - * initializing. - * @param log_error_handler Error logging handler to provide to the client - * before initializing. - * @return A pointer to the newly initialized client. + * @return Zero if initialization was successful, non-zero otherwise. */ -guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, - guac_socket* socket, int argc, char** argv, - guac_client_log_handler* log_info_handler, - guac_client_log_handler* log_error_handler); +int guac_client_init(guac_client* client, + guac_client_plugin* plugin, int argc, char** argv); + +/** + * Returns a new, barebones guac_client. This new guac_client has no handlers + * set, but is otherwise usable. + * + * @return A pointer to the new client. + */ +guac_client* guac_client_alloc(); /** * Free all resources associated with the given client. diff --git a/libguac/src/client.c b/libguac/src/client.c index 90491b50..25e41428 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -237,10 +237,14 @@ int guac_client_plugin_close(guac_client_plugin* plugin) { } -guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, - guac_socket* socket, int argc, char** argv, - guac_client_log_handler* log_info_handler, - guac_client_log_handler* log_error_handler) { +int guac_client_init(guac_client* client, + guac_client_plugin* plugin, int argc, char** argv) { + + return plugin->init_handler(client, argc, argv); + +} + +guac_client* guac_client_alloc() { /* Allocate new client */ guac_client* client = malloc(sizeof(guac_client)); @@ -253,7 +257,6 @@ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, /* Init new client */ memset(client, 0, sizeof(guac_client)); - client->socket = socket; client->last_received_timestamp = client->last_sent_timestamp = guac_protocol_get_timestamp(); @@ -266,15 +269,6 @@ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin, client->__next_buffer_index = -1; client->__next_layer_index = 1; - /* Set up logging in client */ - client->log_info_handler = log_info_handler; - client->log_error_handler = log_error_handler; - - if (plugin->init_handler(client, argc, argv) != 0) { - free(client); - return NULL; - } - return client; } From 114ac20f25c916024cea571f16f1aa5139d0c734 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Aug 2012 14:41:23 -0700 Subject: [PATCH 230/330] Layer pool test stub. --- libguac/tests/Makefile.am | 20 +++++--- libguac/tests/client/client_suite.c | 71 +++++++++++++++++++++++++++++ libguac/tests/client/client_suite.h | 46 +++++++++++++++++++ libguac/tests/client/layer_pool.c | 43 +++++++++++++++++ libguac/tests/test_client.c | 58 +++++++++++++++++++++++ 5 files changed, 232 insertions(+), 6 deletions(-) create mode 100644 libguac/tests/client/client_suite.c create mode 100644 libguac/tests/client/client_suite.h create mode 100644 libguac/tests/client/layer_pool.c create mode 100644 libguac/tests/test_client.c diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index 21f9530a..b3a3cf4e 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -38,17 +38,25 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -I../include -TESTS = test_protocol -check_PROGRAMS = test_protocol +TESTS = test_protocol test_client +check_PROGRAMS = test_protocol test_client -test_protocol_SOURCES = \ +noinst_HEADERS = \ + protocol/suite.h \ + client/client_suite.h + +test_protocol_SOURCES = \ test_protocol.c \ protocol/suite.c \ protocol/instruction_read.c \ protocol/instruction_write.c -noinst_HEADERS = \ - protocol/suite.h - test_protocol_LDADD = $(top_builddir)/src/libguac.la @CUNIT_LIBS@ +test_client_SOURCES = \ + test_client.c \ + client/client_suite.c \ + client/layer_pool.c + +test_client_LDADD = $(top_builddir)/src/libguac.la @CUNIT_LIBS@ + diff --git a/libguac/tests/client/client_suite.c b/libguac/tests/client/client_suite.c new file mode 100644 index 00000000..9840e884 --- /dev/null +++ b/libguac/tests/client/client_suite.c @@ -0,0 +1,71 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include + +#include "client_suite.h" + +int client_suite_init() { + return 0; +} + +int client_suite_cleanup() { + return 0; +} + +int register_client_suite() { + + /* Add client test suite */ + CU_pSuite suite = CU_add_suite("client", + client_suite_init, client_suite_cleanup); + if (suite == NULL) { + CU_cleanup_registry(); + return CU_get_error(); + } + + /* Add tests */ + if ( + CU_add_test(suite, "layer-pool", test_layer_pool) == NULL + ) { + CU_cleanup_registry(); + return CU_get_error(); + } + + return 0; + +} + diff --git a/libguac/tests/client/client_suite.h b/libguac/tests/client/client_suite.h new file mode 100644 index 00000000..44a9017e --- /dev/null +++ b/libguac/tests/client/client_suite.h @@ -0,0 +1,46 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_TEST_CLIENT_SUITE_H +#define _GUAC_TEST_CLIENT_SUITE_H + +int register_client_suite(); + +void test_layer_pool(); + +#endif + diff --git a/libguac/tests/client/layer_pool.c b/libguac/tests/client/layer_pool.c new file mode 100644 index 00000000..bccf125c --- /dev/null +++ b/libguac/tests/client/layer_pool.c @@ -0,0 +1,43 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "client_suite.h" + +void test_layer_pool() { + +} + diff --git a/libguac/tests/test_client.c b/libguac/tests/test_client.c new file mode 100644 index 00000000..fc939167 --- /dev/null +++ b/libguac/tests/test_client.c @@ -0,0 +1,58 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include + +#include "client/client_suite.h" + +int main() { + + /* Init registry */ + if (CU_initialize_registry() != CUE_SUCCESS) + return CU_get_error(); + + /* Register suites */ + register_client_suite(); + + /* Run tests */ + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + CU_cleanup_registry(); + return CU_get_error(); + +} + From bc5065cda4f57596f6608dac0c1ae67ceb3b3fc6 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Aug 2012 14:44:17 -0700 Subject: [PATCH 231/330] Combined tests into single executable. --- libguac/tests/Makefile.am | 19 +++--- .../tests/{test_client.c => test_libguac.c} | 2 + libguac/tests/test_protocol.c | 58 ------------------- 3 files changed, 9 insertions(+), 70 deletions(-) rename libguac/tests/{test_client.c => test_libguac.c} (97%) delete mode 100644 libguac/tests/test_protocol.c diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index b3a3cf4e..28ccc9b4 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -38,25 +38,20 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -I../include -TESTS = test_protocol test_client -check_PROGRAMS = test_protocol test_client +TESTS = test_libguac +check_PROGRAMS = test_libguac noinst_HEADERS = \ protocol/suite.h \ client/client_suite.h -test_protocol_SOURCES = \ - test_protocol.c \ +test_libguac_SOURCES = \ + test_libguac.c \ protocol/suite.c \ protocol/instruction_read.c \ - protocol/instruction_write.c - -test_protocol_LDADD = $(top_builddir)/src/libguac.la @CUNIT_LIBS@ - -test_client_SOURCES = \ - test_client.c \ - client/client_suite.c \ + protocol/instruction_write.c \ + client/client_suite.c \ client/layer_pool.c -test_client_LDADD = $(top_builddir)/src/libguac.la @CUNIT_LIBS@ +test_libguac_LDADD = $(top_builddir)/src/libguac.la @CUNIT_LIBS@ diff --git a/libguac/tests/test_client.c b/libguac/tests/test_libguac.c similarity index 97% rename from libguac/tests/test_client.c rename to libguac/tests/test_libguac.c index fc939167..6549d73b 100644 --- a/libguac/tests/test_client.c +++ b/libguac/tests/test_libguac.c @@ -37,6 +37,7 @@ #include +#include "protocol/suite.h" #include "client/client_suite.h" int main() { @@ -46,6 +47,7 @@ int main() { return CU_get_error(); /* Register suites */ + register_protocol_suite(); register_client_suite(); /* Run tests */ diff --git a/libguac/tests/test_protocol.c b/libguac/tests/test_protocol.c deleted file mode 100644 index dfccdd46..00000000 --- a/libguac/tests/test_protocol.c +++ /dev/null @@ -1,58 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include - -#include "protocol/suite.h" - -int main() { - - /* Init registry */ - if (CU_initialize_registry() != CUE_SUCCESS) - return CU_get_error(); - - /* Register suites */ - register_protocol_suite(); - - /* Run tests */ - CU_basic_set_mode(CU_BRM_VERBOSE); - CU_basic_run_tests(); - CU_cleanup_registry(); - return CU_get_error(); - -} - From 3e96b85b22de8b5b4444ce67eed90d6a2182b2bc Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Aug 2012 15:02:13 -0700 Subject: [PATCH 232/330] Implement pool test. --- libguac/tests/client/layer_pool.c | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/libguac/tests/client/layer_pool.c b/libguac/tests/client/layer_pool.c index bccf125c..88cf8785 100644 --- a/libguac/tests/client/layer_pool.c +++ b/libguac/tests/client/layer_pool.c @@ -35,9 +35,51 @@ * * ***** END LICENSE BLOCK ***** */ +#include + +#include "client.h" #include "client_suite.h" void test_layer_pool() { + guac_client* client; + + int i; + int seen[GUAC_BUFFER_POOL_INITIAL_SIZE] = {0}; + + guac_layer* layer; + + /* Get client */ + client = guac_client_alloc(); + CU_ASSERT_PTR_NOT_NULL_FATAL(client); + + /* Fill pool */ + for (i=0; iindex > 0); + CU_ASSERT(layer->index < GUAC_BUFFER_POOL_INITIAL_SIZE); + + /* This should be a layer we have not seen yet */ + CU_ASSERT_FALSE(seen[layer->index]); + seen[layer->index] = 1; + + guac_client_free_layer(client, layer); + + } + + /* Now that pool is filled, we should get a previously seen layer */ + layer = guac_client_alloc_layer(client); + + CU_ASSERT(layer->index > 0); + CU_ASSERT(layer->index < GUAC_BUFFER_POOL_INITIAL_SIZE); + CU_ASSERT_TRUE(seen[layer->index]); + + /* Free client */ + guac_client_free(client); + } From 77a752a2ee19bbf543b862fa0d80246fc286f5d2 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Aug 2012 15:05:55 -0700 Subject: [PATCH 233/330] Fix test. --- libguac/tests/client/layer_pool.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libguac/tests/client/layer_pool.c b/libguac/tests/client/layer_pool.c index 88cf8785..1fac22de 100644 --- a/libguac/tests/client/layer_pool.c +++ b/libguac/tests/client/layer_pool.c @@ -58,14 +58,14 @@ void test_layer_pool() { layer = guac_client_alloc_layer(client); - /* Index should be less than pool size */ + /* Index should be within pool size */ CU_ASSERT_PTR_NOT_NULL_FATAL(layer); CU_ASSERT(layer->index > 0); - CU_ASSERT(layer->index < GUAC_BUFFER_POOL_INITIAL_SIZE); + CU_ASSERT(layer->index <= GUAC_BUFFER_POOL_INITIAL_SIZE); /* This should be a layer we have not seen yet */ - CU_ASSERT_FALSE(seen[layer->index]); - seen[layer->index] = 1; + CU_ASSERT_FALSE(seen[layer->index - 1]); + seen[layer->index - 1] = 1; guac_client_free_layer(client, layer); @@ -75,8 +75,8 @@ void test_layer_pool() { layer = guac_client_alloc_layer(client); CU_ASSERT(layer->index > 0); - CU_ASSERT(layer->index < GUAC_BUFFER_POOL_INITIAL_SIZE); - CU_ASSERT_TRUE(seen[layer->index]); + CU_ASSERT(layer->index <= GUAC_BUFFER_POOL_INITIAL_SIZE); + CU_ASSERT_TRUE(seen[layer->index - 1]); /* Free client */ guac_client_free(client); From 35ff24868740187e19cc99048632559797cae6bd Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Aug 2012 15:06:06 -0700 Subject: [PATCH 234/330] Fix pool bounds. --- libguac/src/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/src/client.c b/libguac/src/client.c index 25e41428..63ed56a5 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -62,7 +62,7 @@ guac_layer* guac_client_alloc_layer(guac_client* client) { guac_layer* allocd_layer; /* If available layers, pop off first available layer */ - if (client->__next_layer_index >= GUAC_BUFFER_POOL_INITIAL_SIZE && + if (client->__next_layer_index > GUAC_BUFFER_POOL_INITIAL_SIZE && client->__available_layers != NULL) { allocd_layer = client->__available_layers; @@ -96,7 +96,7 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { guac_layer* allocd_layer; /* If available layers, pop off first available buffer */ - if (client->__next_buffer_index <= -GUAC_BUFFER_POOL_INITIAL_SIZE && + if (client->__next_buffer_index < -GUAC_BUFFER_POOL_INITIAL_SIZE && client->__available_buffers != NULL) { allocd_layer = client->__available_buffers; From 3249d068d334b8ae61540bbe71bcce103b1f1c92 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 20 Jun 2012 13:45:15 -0700 Subject: [PATCH 235/330] Prototypes for streaming inructions. --- libguac/include/protocol.h | 66 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index e73db9a1..c1cbef3d 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -51,6 +51,21 @@ */ +/** + * Annotates a resource related to printing. + */ +#define GUAC_REL_PRINTER "printer" + +/** + * Annotates a resource related to file transfer. + */ +#define GUAC_REL_FILE "file" + +/** + * Annotates a resource related to audio. + */ +#define GUAC_REL_AUDIO "audio" + /** * An arbitrary timestamp denoting a relative time value in milliseconds. */ @@ -182,6 +197,13 @@ struct guac_layer { */ int index; + /** + * The string which must be passed via a resource instruction to denote + * a resource related to this layer. This value is automatically set + * upon allocation. + */ + const char* rel; + /** * The next allocated layer in the list of all layers. */ @@ -290,6 +312,20 @@ guac_timestamp guac_protocol_get_timestamp(); /* CONTROL INSTRUCTIONS */ +/** + * Sends an accept instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param uuid The UUID of the resource that is being accepted. + * @param mimetype The mimetype being accepted. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_accept(guac_socket* socket, const char* uuid, + const char* mimetype); + /** * Sends an args instruction over the given guac_socket connection. * @@ -337,6 +373,36 @@ int guac_protocol_send_disconnect(guac_socket* socket); */ int guac_protocol_send_error(guac_socket* socket, const char* error); +/** + * Sends a reject instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param uuid The UUID of the resource that is being rejected. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_reject(guac_socket* socket, const char* uuid); + +/** + * Sends a resource instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param rel What this resource is related to (see the GUAC_REL_* + * constants). + * @param uuid The UUID of the resource that will be exposed. + * @param mimetypes An array of strings, where each string is an available + * mimetype. + * @param length The number of elements in the array of mimetype strings. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_resource(guac_socket* socket, const char* rel, + const char* uuid, const char** mimetypes, int length); + /** * Sends a set instruction over the given guac_socket connection. * From 4ed87ecab5ca2aec69fef05d4ac0bcbbe7c0056b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 20 Jun 2012 13:46:17 -0700 Subject: [PATCH 236/330] Update select instruction semantics. --- libguac/include/protocol.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index c1cbef3d..df09fb17 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -425,7 +425,7 @@ int guac_protocol_send_set(guac_socket* socket, const guac_layer* layer, * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. - * @param protocol The protocol to request. + * @param protocol The protocol or resource UUID to request. * @return Zero on success, non-zero on error. */ int guac_protocol_send_select(guac_socket* socket, const char* protocol); From 376fbe64aba8c7cfbcf8d9b41a6e0217acbb61f5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 17 Jul 2012 22:57:46 -0700 Subject: [PATCH 237/330] Added handlers. --- libguac/include/client.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libguac/include/client.h b/libguac/include/client.h index 028a89d0..583c8a84 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -122,6 +122,18 @@ typedef void guac_client_log_handler(guac_client* client, const char* format, va */ typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); +/** + * Handler which will be called whenever a resource is being exposed. + */ +typedef int guac_client_resource_handler(guac_client* client, + guac_resource* resource); + +/** + * Handler which will be called whenever a valid resource is selected. + */ +typedef int guac_client_stream_handler(guac_client* client, + guac_resource* resource); + /** * The flag set in the mouse button mask when the left mouse button is down. */ From 9e2e1e4994fea9a7c0eade9f6fe8692a30c80b7e Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 24 Aug 2012 21:37:37 -0700 Subject: [PATCH 238/330] Define guac_resource, remove rel, use URI instead of rel. --- libguac/include/protocol.h | 42 ++++++++++++++++++++------------------ libguac/src/client.c | 6 ++++++ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index df09fb17..df49a2a5 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -51,21 +51,6 @@ */ -/** - * Annotates a resource related to printing. - */ -#define GUAC_REL_PRINTER "printer" - -/** - * Annotates a resource related to file transfer. - */ -#define GUAC_REL_FILE "file" - -/** - * Annotates a resource related to audio. - */ -#define GUAC_REL_AUDIO "audio" - /** * An arbitrary timestamp denoting a relative time value in milliseconds. */ @@ -185,6 +170,24 @@ typedef enum guac_line_join_style { GUAC_LINE_JOIN_ROUND = 0x2 } guac_line_join_style; +/** + * Represents a single resource which can be requested or exposed via + * the Guacamole protocol. + */ +typedef struct guac_resource { + + /** + * The UUID of this resource. + */ + const char* uuid; + + /** + * Arbitrary data associated with this resource. + */ + void* data; + +} guac_resource; + typedef struct guac_layer guac_layer; /** @@ -198,11 +201,11 @@ struct guac_layer { int index; /** - * The string which must be passed via a resource instruction to denote + * The URI which must be passed via a resource instruction to denote * a resource related to this layer. This value is automatically set * upon allocation. */ - const char* rel; + char* uri; /** * The next allocated layer in the list of all layers. @@ -392,15 +395,14 @@ int guac_protocol_send_reject(guac_socket* socket, const char* uuid); * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. - * @param rel What this resource is related to (see the GUAC_REL_* - * constants). + * @param uri The destination URI that this resource should be exposed through. * @param uuid The UUID of the resource that will be exposed. * @param mimetypes An array of strings, where each string is an available * mimetype. * @param length The number of elements in the array of mimetype strings. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_resource(guac_socket* socket, const char* rel, +int guac_protocol_send_resource(guac_socket* socket, const char* uri, const char* uuid, const char** mimetypes, int length); /** diff --git a/libguac/src/client.c b/libguac/src/client.c index 63ed56a5..3a685ec4 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -51,6 +51,7 @@ guac_layer __GUAC_DEFAULT_LAYER = { .index = 0, + .uri = "layer://0", .__next = NULL, .__next_available = NULL }; @@ -80,6 +81,8 @@ guac_layer* guac_client_alloc_layer(guac_client* client) { /* Init new layer */ allocd_layer = malloc(sizeof(guac_layer)); allocd_layer->index = client->__next_layer_index++; + allocd_layer->uri = malloc(64); + snprintf(allocd_layer->uri, 64, "layer://%i", allocd_layer->index); /* Add to __all_layers list */ allocd_layer->__next = client->__all_layers; @@ -114,6 +117,8 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { /* Init new layer */ allocd_layer = malloc(sizeof(guac_layer)); allocd_layer->index = client->__next_buffer_index--; + allocd_layer->uri = malloc(64); + snprintf(allocd_layer->uri, 64, "layer://%i", allocd_layer->index); /* Add to __all_layers list */ allocd_layer->__next = client->__all_layers; @@ -290,6 +295,7 @@ void guac_client_free(guac_client* client) { client->__all_layers = layer->__next; /* Free layer */ + free(layer->uri); free(layer); } From 5f1b67fb02621e96bdbd9a2e197879f75e2fad04 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Aug 2012 12:50:09 -0700 Subject: [PATCH 239/330] New resource API and corresponding stubs. --- libguac/include/client.h | 33 +++++++++++++++--- libguac/include/protocol.h | 71 +++++++++++++++++++------------------- 2 files changed, 63 insertions(+), 41 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 583c8a84..072f2680 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -123,17 +123,32 @@ typedef void guac_client_log_handler(guac_client* client, const char* format, va typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); /** - * Handler which will be called whenever a resource is being exposed. + * Handler which will be called whenever a resource has been accepted by the + * client. */ -typedef int guac_client_resource_handler(guac_client* client, - guac_resource* resource); +typedef int guac_client_accept_handler(guac_client* client, + guac_resource* resource, const char* mimetype); /** - * Handler which will be called whenever a valid resource is selected. + * Handler which will be called whenever a resource has been rejected by the + * client. */ -typedef int guac_client_stream_handler(guac_client* client, +typedef int guac_client_reject_handler(guac_client* client, guac_resource* resource); +/* + * NOTE: The data and end instructions are currently implemented client-side + * only, and allocation of resources must ALWAYS be server-side. + * + * Each resource is mono-directional. Two resources must be allocated for + * bidirectional communication. + * + * Exposure of client-side resources to the server will be accomplished + * over the same protocol (resource -> accept/reject -> data -> end). The + * mono-directional nature of resources will allow the index spaces of + * client and server resources to be independent. + */ + /** * The flag set in the mouse button mask when the left mouse button is down. */ @@ -557,6 +572,14 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer); */ void guac_client_free_layer(guac_client* client, guac_layer* layer); +/** + * Allocates a new resource. An arbitrary index is automatically assigned + * if no existing resource index is available for use. + * + * @param client The proxy client to allocate the resource for. + * @return The next available resource, or a newly allocated resource. + */ +guac_resource* guac_client_alloc_resource(guac_client* client); /** * Logs an informational message in the log used by the given client. The diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index df49a2a5..c4722b75 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -177,9 +177,9 @@ typedef enum guac_line_join_style { typedef struct guac_resource { /** - * The UUID of this resource. + * The index of this resource. */ - const char* uuid; + int index; /** * Arbitrary data associated with this resource. @@ -315,20 +315,6 @@ guac_timestamp guac_protocol_get_timestamp(); /* CONTROL INSTRUCTIONS */ -/** - * Sends an accept instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param uuid The UUID of the resource that is being accepted. - * @param mimetype The mimetype being accepted. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_accept(guac_socket* socket, const char* uuid, - const char* mimetype); - /** * Sends an args instruction over the given guac_socket connection. * @@ -353,6 +339,20 @@ int guac_protocol_send_args(guac_socket* socket, const char** args); */ int guac_protocol_send_connect(guac_socket* socket, const char** args); +/** + * Sends a data instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param resource The resource associated with the data being sent. + * @param data The data to send. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_data(guac_socket* socket, guac_resource* resource, + const unsigned char* data); + /** * Sends a disconnect instruction over the given guac_socket connection. * @@ -364,6 +364,18 @@ int guac_protocol_send_connect(guac_socket* socket, const char** args); */ int guac_protocol_send_disconnect(guac_socket* socket); +/** + * Sends an end instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param resource The resource being closed. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_end(guac_socket* socket, guac_resource* resource); + /** * Sends an error instruction over the given guac_socket connection. * @@ -376,18 +388,6 @@ int guac_protocol_send_disconnect(guac_socket* socket); */ int guac_protocol_send_error(guac_socket* socket, const char* error); -/** - * Sends a reject instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param uuid The UUID of the resource that is being rejected. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_reject(guac_socket* socket, const char* uuid); - /** * Sends a resource instruction over the given guac_socket connection. * @@ -395,15 +395,14 @@ int guac_protocol_send_reject(guac_socket* socket, const char* uuid); * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. - * @param uri The destination URI that this resource should be exposed through. - * @param uuid The UUID of the resource that will be exposed. - * @param mimetypes An array of strings, where each string is an available - * mimetype. - * @param length The number of elements in the array of mimetype strings. + * @param resource The resource being exposed. + * @param uri The URI this resource should be exposed to. + * @param mimetypes A NULL-terminated array of strings, where each string is + * an available mimetype. * @return Zero on success, non-zero on error. */ -int guac_protocol_send_resource(guac_socket* socket, const char* uri, - const char* uuid, const char** mimetypes, int length); +int guac_protocol_send_resource(guac_socket* socket, guac_resource* resource, + const char* uri, const char** mimetypes); /** * Sends a set instruction over the given guac_socket connection. @@ -427,7 +426,7 @@ int guac_protocol_send_set(guac_socket* socket, const guac_layer* layer, * returned, and guac_error is set appropriately. * * @param socket The guac_socket connection to use. - * @param protocol The protocol or resource UUID to request. + * @param protocol The protocol to request. * @return Zero on success, non-zero on error. */ int guac_protocol_send_select(guac_socket* socket, const char* protocol); From af490aafbeda3439995a3718d200cfd66bcf29c3 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Aug 2012 14:07:02 -0700 Subject: [PATCH 240/330] Implementations of server-side streaming instructions. --- libguac/include/protocol.h | 4 ++- libguac/src/protocol.c | 62 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index c4722b75..3ad1dc63 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -348,10 +348,12 @@ int guac_protocol_send_connect(guac_socket* socket, const char** args); * @param socket The guac_socket connection to use. * @param resource The resource associated with the data being sent. * @param data The data to send. + * @param size The number of bytes from the beginning of the given buffer + * of data to send. * @return Zero on success, non-zero on error. */ int guac_protocol_send_data(guac_socket* socket, guac_resource* resource, - const unsigned char* data); + const unsigned char* data, size_t size); /** * Sends a disconnect instruction over the given guac_socket connection. diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index ec72be25..3eddce77 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -905,6 +905,26 @@ int guac_protocol_send_curve(guac_socket* socket, const guac_layer* layer, } +int guac_protocol_send_data(guac_socket* socket, guac_resource* resource, + const unsigned char* data, size_t size) { + + /* Calculate base64 length */ + int base64_length = (size + 2) / 3 * 4; + + /* Send base64-encoded data */ + return + guac_socket_write_string(socket, "4.data,") + || __guac_socket_write_length_int(socket, resource->index) + || guac_socket_write_string(socket, ",") + || guac_socket_write_int(socket, base64_length) + || guac_socket_write_string(socket, ".") + || guac_socket_write_base64(socket, data, size) + || guac_socket_flush_base64(socket) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_disconnect(guac_socket* socket) { return guac_socket_write_string(socket, "10.disconnect;"); } @@ -944,6 +964,15 @@ int guac_protocol_send_distort(guac_socket* socket, const guac_layer* layer, } +int guac_protocol_send_end(guac_socket* socket, guac_resource* resource) { + + return + guac_socket_write_string(socket, "3.end,") + || __guac_socket_write_length_int(socket, resource->index) + || guac_socket_write_string(socket, ";"); +} + + int guac_protocol_send_error(guac_socket* socket, const char* error) { return @@ -1114,6 +1143,39 @@ int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer) { } +int guac_protocol_send_resource(guac_socket* socket, guac_resource* resource, + const char* uri, const char** mimetypes) { + + /* Write resource header */ + if ( + guac_socket_write_string(socket, "8.resource,") + || __guac_socket_write_length_int(socket, resource->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_string(socket, uri) + ) + return -1; + + /* Write each mimetype */ + while (*mimetypes != NULL) { + + /* Write mimetype */ + if ( + guac_socket_write_string(socket, ",") + || __guac_socket_write_length_string(socket, *mimetypes) + ) + return -1; + + /* Next mimetype */ + mimetypes++; + + } + + /* Finish instruction */ + return guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_set(guac_socket* socket, const guac_layer* layer, const char* name, const char* value) { From 1bcc1e7d5ad6a75d5ef7cf92820fa5fcdfad7088 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 27 Aug 2012 15:10:27 -0700 Subject: [PATCH 241/330] Ensure buffers do not hurt layer pool. --- libguac/tests/client/layer_pool.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libguac/tests/client/layer_pool.c b/libguac/tests/client/layer_pool.c index 1fac22de..7727d85b 100644 --- a/libguac/tests/client/layer_pool.c +++ b/libguac/tests/client/layer_pool.c @@ -56,6 +56,9 @@ void test_layer_pool() { /* Fill pool */ for (i=0; i Date: Tue, 28 Aug 2012 11:25:21 -0700 Subject: [PATCH 242/330] Add buffer pool test. --- libguac/tests/Makefile.am | 1 + libguac/tests/client/buffer_pool.c | 88 +++++++++++++++++++++++++++++ libguac/tests/client/client_suite.c | 1 + libguac/tests/client/client_suite.h | 1 + 4 files changed, 91 insertions(+) create mode 100644 libguac/tests/client/buffer_pool.c diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index 28ccc9b4..435258d3 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -51,6 +51,7 @@ test_libguac_SOURCES = \ protocol/instruction_read.c \ protocol/instruction_write.c \ client/client_suite.c \ + client/buffer_pool.c \ client/layer_pool.c test_libguac_LDADD = $(top_builddir)/src/libguac.la @CUNIT_LIBS@ diff --git a/libguac/tests/client/buffer_pool.c b/libguac/tests/client/buffer_pool.c new file mode 100644 index 00000000..2cd5f07f --- /dev/null +++ b/libguac/tests/client/buffer_pool.c @@ -0,0 +1,88 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include + +#include "client.h" +#include "client_suite.h" + +void test_buffer_pool() { + + guac_client* client; + + int i; + int seen[GUAC_BUFFER_POOL_INITIAL_SIZE] = {0}; + + guac_layer* layer; + + /* Get client */ + client = guac_client_alloc(); + CU_ASSERT_PTR_NOT_NULL_FATAL(client); + + /* Fill pool */ + for (i=0; iindex < 0); + CU_ASSERT(layer->index >= -GUAC_BUFFER_POOL_INITIAL_SIZE); + + /* This should be a layer we have not seen yet */ + CU_ASSERT_FALSE(seen[-layer->index - 1]); + seen[-layer->index - 1] = 1; + + guac_client_free_buffer(client, layer); + + } + + /* Now that pool is filled, we should get a previously seen layer */ + layer = guac_client_alloc_buffer(client); + + CU_ASSERT(layer->index < 0); + CU_ASSERT(layer->index >= -GUAC_BUFFER_POOL_INITIAL_SIZE); + CU_ASSERT_TRUE(seen[-layer->index - 1]); + + /* Free client */ + guac_client_free(client); + +} + diff --git a/libguac/tests/client/client_suite.c b/libguac/tests/client/client_suite.c index 9840e884..b2c83c72 100644 --- a/libguac/tests/client/client_suite.c +++ b/libguac/tests/client/client_suite.c @@ -60,6 +60,7 @@ int register_client_suite() { /* Add tests */ if ( CU_add_test(suite, "layer-pool", test_layer_pool) == NULL + || CU_add_test(suite, "buffer-pool", test_buffer_pool) == NULL ) { CU_cleanup_registry(); return CU_get_error(); diff --git a/libguac/tests/client/client_suite.h b/libguac/tests/client/client_suite.h index 44a9017e..804c85dd 100644 --- a/libguac/tests/client/client_suite.h +++ b/libguac/tests/client/client_suite.h @@ -41,6 +41,7 @@ int register_client_suite(); void test_layer_pool(); +void test_buffer_pool(); #endif From 68e3d1507b9e8eeea4d066511e55a633e8675f90 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 29 Aug 2012 10:00:14 -0700 Subject: [PATCH 243/330] Add resource free stub. --- libguac/include/client.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libguac/include/client.h b/libguac/include/client.h index 072f2680..842d549e 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -581,6 +581,17 @@ void guac_client_free_layer(guac_client* client, guac_layer* layer); */ guac_resource* guac_client_alloc_resource(guac_client* client); +/** + * Frees an existing resource, re-adding it to the client's resource + * pool, such that it can be reused by a subsequent call to + * guac_client_alloc_resource(). + * + * @param client The proxy client to free the resource for. + * @oaran resource The resource to return to the resource pool. + */ +void guac_client_free_resource(guac_client* client, guac_resource* resource); + + /** * Logs an informational message in the log used by the given client. The * logger used will normally be defined by guacd (or whichever program loads From 4af8d80653f811b0b927f48968fb3c0535155314 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 29 Aug 2012 11:23:19 -0700 Subject: [PATCH 244/330] Bump version numbers. --- libguac/configure.in | 2 +- libguac/src/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/configure.in b/libguac/configure.in index a252bb9d..b72b78f9 100644 --- a/libguac/configure.in +++ b/libguac/configure.in @@ -35,7 +35,7 @@ # ***** END LICENSE BLOCK ***** AC_INIT(src/client.c) -AM_INIT_AUTOMAKE(libguac, 0.6.3) +AM_INIT_AUTOMAKE(libguac, 0.7.0) AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index d3ca6d57..5eaf4699 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -60,5 +60,5 @@ libguac_la_SOURCES = \ unicode.c lib_LTLIBRARIES = libguac.la -libguac_la_LDFLAGS = -version-info 3:3:0 +libguac_la_LDFLAGS = -version-info 4:0:0 From a02befb6bfef34b0a037c87a67521dadf4aa90dc Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 29 Aug 2012 11:36:32 -0700 Subject: [PATCH 245/330] Rename plugin init. --- libguac/include/client.h | 8 ++++---- libguac/src/client.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 842d549e..e6abd1cc 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -497,17 +497,17 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol); int guac_client_plugin_close(guac_client_plugin* plugin); /** - * Initializes the given guac_client using the initialization routing provided + * Initializes the given guac_client using the initialization routine provided * by the given guac_client_plugin. * - * @param client The guac_client to initialize. * @param plugin The client plugin to use to initialize the new client. + * @param client The guac_client to initialize. * @param argc The number of arguments being passed to the client. * @param argv All arguments to be passed to the client. * @return Zero if initialization was successful, non-zero otherwise. */ -int guac_client_init(guac_client* client, - guac_client_plugin* plugin, int argc, char** argv); +int guac_client_plugin_init_client(guac_client_plugin* plugin, + guac_client* client, int argc, char** argv); /** * Returns a new, barebones guac_client. This new guac_client has no handlers diff --git a/libguac/src/client.c b/libguac/src/client.c index 3a685ec4..f5b6ccf1 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -242,8 +242,8 @@ int guac_client_plugin_close(guac_client_plugin* plugin) { } -int guac_client_init(guac_client* client, - guac_client_plugin* plugin, int argc, char** argv) { +int guac_client_plugin_init_client(guac_client_plugin* plugin, + guac_client* client, int argc, char** argv) { return plugin->init_handler(client, argc, argv); From 78e51759cb21c1ad891c63468fa29a77eaf2f0db Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 2 Sep 2012 18:08:17 -0700 Subject: [PATCH 246/330] Output xml for docs. --- libguac/doc/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/doc/Doxyfile b/libguac/doc/Doxyfile index 10c337e8..1a5ba0be 100644 --- a/libguac/doc/Doxyfile +++ b/libguac/doc/Doxyfile @@ -1171,7 +1171,7 @@ MAN_LINKS = NO # generate an XML file that captures the structure of # the code including all documentation. -GENERATE_XML = NO +GENERATE_XML = YES # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be From 23f799fa3357aabc429f6174c9204c49f52fb7a4 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 2 Sep 2012 20:50:50 -0700 Subject: [PATCH 247/330] Added XSLT for translating Doxygen XML to DocBook. --- libguac/doc/docbook.xslt | 99 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 libguac/doc/docbook.xslt diff --git a/libguac/doc/docbook.xslt b/libguac/doc/docbook.xslt new file mode 100644 index 00000000..16fa3672 --- /dev/null +++ b/libguac/doc/docbook.xslt @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Description + + + + + + + + + + Parameters + + + + + + + + + + + + + + + + + + + + + + + + + From a959dff6f6fbac675d6c0341f8f1cb8d76352706 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 2 Sep 2012 23:27:19 -0700 Subject: [PATCH 248/330] Only output parameter if it has a name. --- libguac/doc/docbook.xslt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libguac/doc/docbook.xslt b/libguac/doc/docbook.xslt index 16fa3672..f8ffd0e3 100644 --- a/libguac/doc/docbook.xslt +++ b/libguac/doc/docbook.xslt @@ -44,9 +44,11 @@ - - - + + + + + From f8fdc3f35ad7ca1d85bca0af31bd64f100e760a5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 3 Sep 2012 17:54:30 -0700 Subject: [PATCH 249/330] Refactor guac_resource functions into resource.h --- libguac/include/client.h | 47 ---------------- libguac/include/protocol.h | 18 ------ libguac/include/resource.h | 110 +++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 65 deletions(-) create mode 100644 libguac/include/resource.h diff --git a/libguac/include/client.h b/libguac/include/client.h index e6abd1cc..9dc650f1 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -122,33 +122,6 @@ typedef void guac_client_log_handler(guac_client* client, const char* format, va */ typedef int guac_client_init_handler(guac_client* client, int argc, char** argv); -/** - * Handler which will be called whenever a resource has been accepted by the - * client. - */ -typedef int guac_client_accept_handler(guac_client* client, - guac_resource* resource, const char* mimetype); - -/** - * Handler which will be called whenever a resource has been rejected by the - * client. - */ -typedef int guac_client_reject_handler(guac_client* client, - guac_resource* resource); - -/* - * NOTE: The data and end instructions are currently implemented client-side - * only, and allocation of resources must ALWAYS be server-side. - * - * Each resource is mono-directional. Two resources must be allocated for - * bidirectional communication. - * - * Exposure of client-side resources to the server will be accomplished - * over the same protocol (resource -> accept/reject -> data -> end). The - * mono-directional nature of resources will allow the index spaces of - * client and server resources to be independent. - */ - /** * The flag set in the mouse button mask when the left mouse button is down. */ @@ -572,26 +545,6 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer); */ void guac_client_free_layer(guac_client* client, guac_layer* layer); -/** - * Allocates a new resource. An arbitrary index is automatically assigned - * if no existing resource index is available for use. - * - * @param client The proxy client to allocate the resource for. - * @return The next available resource, or a newly allocated resource. - */ -guac_resource* guac_client_alloc_resource(guac_client* client); - -/** - * Frees an existing resource, re-adding it to the client's resource - * pool, such that it can be reused by a subsequent call to - * guac_client_alloc_resource(). - * - * @param client The proxy client to free the resource for. - * @oaran resource The resource to return to the resource pool. - */ -void guac_client_free_resource(guac_client* client, guac_resource* resource); - - /** * Logs an informational message in the log used by the given client. The * logger used will normally be defined by guacd (or whichever program loads diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 3ad1dc63..6d77107d 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -170,24 +170,6 @@ typedef enum guac_line_join_style { GUAC_LINE_JOIN_ROUND = 0x2 } guac_line_join_style; -/** - * Represents a single resource which can be requested or exposed via - * the Guacamole protocol. - */ -typedef struct guac_resource { - - /** - * The index of this resource. - */ - int index; - - /** - * Arbitrary data associated with this resource. - */ - void* data; - -} guac_resource; - typedef struct guac_layer guac_layer; /** diff --git a/libguac/include/resource.h b/libguac/include/resource.h new file mode 100644 index 00000000..eda0e204 --- /dev/null +++ b/libguac/include/resource.h @@ -0,0 +1,110 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#ifndef _GUAC_RESOURCE_H +#define _GUAC_RESOURCE_H + +#include "client.h" + +/** + * Provides functions and structures required for handling resources. + * + * NOTE: The data and end instructions are currently implemented client-side + * only, and allocation of resources must ALWAYS be server-side. + * + * Each resource is mono-directional. Two resources must be allocated for + * bidirectional communication. + * + * Exposure of client-side resources to the server will be accomplished + * over the same protocol (resource -> accept/reject -> data -> end). The + * mono-directional nature of resources will allow the index spaces of + * client and server resources to be independent. + * + * @file resource.h + */ + +/** + * Represents a single resource which can be requested or exposed via + * the Guacamole protocol. + */ +typedef struct guac_resource { + + /** + * The index of this resource. + */ + int index; + + /** + * Arbitrary data associated with this resource. + */ + void* data; + +} guac_resource; + +/** + * Handler which will be called whenever a resource has been accepted by the + * client. + */ +typedef int guac_resource_accept_handler(guac_resource* resource, const char* mimetype); + +/** + * Handler which will be called whenever a resource has been rejected by the + * client. + */ +typedef int guac_resource_reject_handler(guac_resource* resource); + +/** + * Allocates a new resource. An arbitrary index is automatically assigned + * if no existing resource index is available for use. + * + * @param client The proxy client to allocate the resource for. + * @return The next available resource, or a newly allocated resource. + */ +guac_resource* guac_client_alloc_resource(guac_client* client); + +/** + * Frees an existing resource, re-adding it to the client's resource + * pool, such that it can be reused by a subsequent call to + * guac_client_alloc_resource(). + * + * @param client The proxy client to free the resource for. + * @oaran resource The resource to return to the resource pool. + */ +void guac_client_free_resource(guac_client* client, guac_resource* resource); + +#endif From 373cab0be6db3aedfeda93237f2c81dc236c48d3 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 3 Sep 2012 17:58:43 -0700 Subject: [PATCH 250/330] Refactor layer struct and functions into layer.h --- libguac/include/client.h | 36 ------------ libguac/include/layer.h | 116 +++++++++++++++++++++++++++++++++++++ libguac/include/protocol.h | 32 ---------- 3 files changed, 116 insertions(+), 68 deletions(-) create mode 100644 libguac/include/layer.h diff --git a/libguac/include/client.h b/libguac/include/client.h index 9dc650f1..a7fa9d61 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -509,42 +509,6 @@ void guac_client_free(guac_client* client); */ int guac_client_handle_instruction(guac_client* client, guac_instruction* instruction); -/** - * Allocates a new buffer (invisible layer). An arbitrary index is - * automatically assigned if no existing buffer is available for use. - * - * @param client The proxy client to allocate the buffer for. - * @return The next available buffer, or a newly allocated buffer. - */ -guac_layer* guac_client_alloc_buffer(guac_client* client); - -/** - * Allocates a new layer. An arbitrary index is automatically assigned - * if no existing layer is available for use. - * - * @param client The proxy client to allocate the layer buffer for. - * @return The next available layer, or a newly allocated layer. - */ -guac_layer* guac_client_alloc_layer(guac_client* client); - -/** - * Returns the given buffer to the pool of available buffers, such that it - * can be reused by any subsequent call to guac_client_allow_buffer(). - * - * @param client The proxy client to return the buffer to. - * @param layer The buffer to return to the pool of available buffers. - */ -void guac_client_free_buffer(guac_client* client, guac_layer* layer); - -/** - * Returns the given layer to the pool of available layers, such that it - * can be reused by any subsequent call to guac_client_allow_layer(). - * - * @param client The proxy client to return the layer to. - * @param layer The buffer to return to the pool of available layer. - */ -void guac_client_free_layer(guac_client* client, guac_layer* layer); - /** * Logs an informational message in the log used by the given client. The * logger used will normally be defined by guacd (or whichever program loads diff --git a/libguac/include/layer.h b/libguac/include/layer.h new file mode 100644 index 00000000..732b53ee --- /dev/null +++ b/libguac/include/layer.h @@ -0,0 +1,116 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_LAYER_H +#define _GUAC_LAYER_H + +/** + * Provides functions and structures required for allocating and using layers. + * + * @file layer.h + */ + +typedef struct guac_layer guac_layer; + +/** + * Represents a single layer within the Guacamole protocol. + */ +struct guac_layer { + + /** + * The index of this layer. + */ + int index; + + /** + * The URI which must be passed via a resource instruction to denote + * a resource related to this layer. This value is automatically set + * upon allocation. + */ + char* uri; + + /** + * The next allocated layer in the list of all layers. + */ + guac_layer* __next; + + /** + * The next available (unused) layer in the list of + * allocated but free'd layers. + */ + guac_layer* __next_available; + +}; + +/** + * Allocates a new buffer (invisible layer). An arbitrary index is + * automatically assigned if no existing buffer is available for use. + * + * @param client The proxy client to allocate the buffer for. + * @return The next available buffer, or a newly allocated buffer. + */ +guac_layer* guac_client_alloc_buffer(guac_client* client); + +/** + * Allocates a new layer. An arbitrary index is automatically assigned + * if no existing layer is available for use. + * + * @param client The proxy client to allocate the layer buffer for. + * @return The next available layer, or a newly allocated layer. + */ +guac_layer* guac_client_alloc_layer(guac_client* client); + +/** + * Returns the given buffer to the pool of available buffers, such that it + * can be reused by any subsequent call to guac_client_allow_buffer(). + * + * @param client The proxy client to return the buffer to. + * @param layer The buffer to return to the pool of available buffers. + */ +void guac_client_free_buffer(guac_client* client, guac_layer* layer); + +/** + * Returns the given layer to the pool of available layers, such that it + * can be reused by any subsequent call to guac_client_allow_layer(). + * + * @param client The proxy client to return the layer to. + * @param layer The buffer to return to the pool of available layer. + */ +void guac_client_free_layer(guac_client* client, guac_layer* layer); + +#endif + diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 6d77107d..b4c571e6 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -170,38 +170,6 @@ typedef enum guac_line_join_style { GUAC_LINE_JOIN_ROUND = 0x2 } guac_line_join_style; -typedef struct guac_layer guac_layer; - -/** - * Represents a single layer within the Guacamole protocol. - */ -struct guac_layer { - - /** - * The index of this layer. - */ - int index; - - /** - * The URI which must be passed via a resource instruction to denote - * a resource related to this layer. This value is automatically set - * upon allocation. - */ - char* uri; - - /** - * The next allocated layer in the list of all layers. - */ - guac_layer* __next; - - /** - * The next available (unused) layer in the list of - * allocated but free'd layers. - */ - guac_layer* __next_available; - -}; - /** * Represents a single instruction within the Guacamole protocol. */ From 19cc6ccc010446e1db67ae1bee52572339df2f37 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 3 Sep 2012 18:03:24 -0700 Subject: [PATCH 251/330] Refactor functions into instruction.h - beware of renaming. --- libguac/include/instruction.h | 133 ++++++++++++++++++++++++++++++++++ libguac/include/protocol.h | 83 --------------------- 2 files changed, 133 insertions(+), 83 deletions(-) create mode 100644 libguac/include/instruction.h diff --git a/libguac/include/instruction.h b/libguac/include/instruction.h new file mode 100644 index 00000000..6eb2fd93 --- /dev/null +++ b/libguac/include/instruction.h @@ -0,0 +1,133 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_INSTRUCTION_H +#define _GUAC_INSTRUCTION_H + +#include "socket.h" + +/** + * Provides functions and structures for reading, writing, and manipulating + * Guacamole instructions. + * + * @file instruction.h + */ + +/** + * Represents a single instruction within the Guacamole protocol. + */ +typedef struct guac_instruction { + + /** + * The opcode of the instruction. + */ + char* opcode; + + /** + * The number of arguments passed to this instruction. + */ + int argc; + + /** + * Array of all arguments passed to this instruction. + */ + char** argv; + +} guac_instruction; + + +/** + * Frees all memory allocated to the given instruction. + * + * @param instruction The instruction to free. + */ +void guac_instruction_free(guac_instruction* instruction); + +/** + * Returns whether new instruction data is available on the given guac_socket + * connection for parsing. + * + * @param socket The guac_socket connection to use. + * @param usec_timeout The maximum number of microseconds to wait before + * giving up. + * @return A positive value if data is available, negative on error, or + * zero if no data is currently available. + */ +int guac_instruction_waiting(guac_socket* socket, int usec_timeout); + +/** + * Reads a single instruction from the given guac_socket connection. + * + * If an error occurs reading the instruction, NULL is returned, + * and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param usec_timeout The maximum number of microseconds to wait before + * giving up. + * @return A new instruction if data was successfully read, NULL on + * error or if the instruction could not be read completely + * because the timeout elapsed, in which case guac_error will be + * set to GUAC_STATUS_INPUT_TIMEOUT and subsequent calls to + * guac_protocol_read_instruction() will return the parsed instruction + * once enough data is available. + */ +guac_instruction* guac_instruction_read(guac_socket* socket, int usec_timeout); + +/** + * Reads a single instruction with the given opcode from the given guac_socket + * connection. + * + * If an error occurs reading the instruction, NULL is returned, + * and guac_error is set appropriately. + * + * If the instruction read is not the expected instruction, NULL is returned, + * and guac_error is set to GUAC_STATUS_BAD_STATE. + * + * @param socket The guac_socket connection to use. + * @param usec_timeout The maximum number of microseconds to wait before + * giving up. + * @param opcode The opcode of the instruction to read. + * @return A new instruction if an instruction with the given opcode was read, + * NULL otherwise. If an instruction was read, but the instruction had + * a different opcode, NULL is returned and guac_error is set to + * GUAC_STATUS_BAD_STATE. + */ +guac_instruction* guac_instruction_expect(guac_socket* socket, + int usec_timeout, const char* opcode); + +#endif + diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index b4c571e6..1a3a1d8a 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -170,89 +170,6 @@ typedef enum guac_line_join_style { GUAC_LINE_JOIN_ROUND = 0x2 } guac_line_join_style; -/** - * Represents a single instruction within the Guacamole protocol. - */ -typedef struct guac_instruction { - - /** - * The opcode of the instruction. - */ - char* opcode; - - /** - * The number of arguments passed to this instruction. - */ - int argc; - - /** - * Array of all arguments passed to this instruction. - */ - char** argv; - -} guac_instruction; - - -/** - * Frees all memory allocated to the given instruction. - * - * @param instruction The instruction to free. - */ -void guac_instruction_free(guac_instruction* instruction); - -/** - * Returns whether new instruction data is available on the given guac_socket - * connection for parsing. - * - * @param socket The guac_socket connection to use. - * @param usec_timeout The maximum number of microseconds to wait before - * giving up. - * @return A positive value if data is available, negative on error, or - * zero if no data is currently available. - */ -int guac_protocol_instructions_waiting(guac_socket* socket, int usec_timeout); - -/** - * Reads a single instruction from the given guac_socket connection. - * - * If an error occurs reading the instruction, NULL is returned, - * and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param usec_timeout The maximum number of microseconds to wait before - * giving up. - * @return A new instruction if data was successfully read, NULL on - * error or if the instruction could not be read completely - * because the timeout elapsed, in which case guac_error will be - * set to GUAC_STATUS_INPUT_TIMEOUT and subsequent calls to - * guac_protocol_read_instruction() will return the parsed instruction - * once enough data is available. - */ -guac_instruction* guac_protocol_read_instruction(guac_socket* socket, - int usec_timeout); - -/** - * Reads a single instruction with the given opcode from the given guac_socket - * connection. - * - * If an error occurs reading the instruction, NULL is returned, - * and guac_error is set appropriately. - * - * If the instruction read is not the expected instruction, NULL is returned, - * and guac_error is set to GUAC_STATUS_BAD_STATE. - * - * @param socket The guac_socket connection to use. - * @param usec_timeout The maximum number of microseconds to wait before - * giving up. - * @param opcode The opcode of the instruction to read. - * @return A new instruction if an instruction with the given opcode was read, - * NULL otherwise. If an instruction was read, but the instruction had - * a different opcode, NULL is returned and guac_error is set to - * GUAC_STATUS_BAD_STATE. - */ -guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, - int usec_timeout, const char* opcode); - /** * Returns an arbitrary timestamp. The difference between return values of any * two calls is equal to the amount of time in milliseconds between those From d2eed6963597373b6d23f27111d780d332067fd3 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 3 Sep 2012 18:07:13 -0700 Subject: [PATCH 252/330] Refactor time functions into time.h --- libguac/include/protocol.h | 16 ---------- libguac/include/time.h | 63 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 libguac/include/time.h diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 1a3a1d8a..27d95101 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -50,12 +50,6 @@ * @file protocol.h */ - -/** - * An arbitrary timestamp denoting a relative time value in milliseconds. - */ -typedef int64_t guac_timestamp; - /** * Composite modes used by Guacamole draw instructions. Each * composite mode maps to a unique channel mask integer. @@ -170,16 +164,6 @@ typedef enum guac_line_join_style { GUAC_LINE_JOIN_ROUND = 0x2 } guac_line_join_style; -/** - * Returns an arbitrary timestamp. The difference between return values of any - * two calls is equal to the amount of time in milliseconds between those - * calls. The return value from a single call will not have any useful - * (or defined) meaning. - * - * @return An arbitrary millisecond timestamp. - */ -guac_timestamp guac_protocol_get_timestamp(); - /* CONTROL INSTRUCTIONS */ /** diff --git a/libguac/include/time.h b/libguac/include/time.h new file mode 100644 index 00000000..21dfea05 --- /dev/null +++ b/libguac/include/time.h @@ -0,0 +1,63 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_TIME_H +#define _GUAC_TIME_H + +/** + * Provides functions and structures for creating timestamps. + * + * @file time.h + */ + +/** + * An arbitrary timestamp denoting a relative time value in milliseconds. + */ +typedef int64_t guac_timestamp; + +/** + * Returns an arbitrary timestamp. The difference between return values of any + * two calls is equal to the amount of time in milliseconds between those + * calls. The return value from a single call will not have any useful + * (or defined) meaning. + * + * @return An arbitrary millisecond timestamp. + */ +guac_timestamp guac_timestamp_current(); + +#endif + From 0f4ca62eedba2c4326bb0af072ea50b39ff8e5af Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 3 Sep 2012 18:16:16 -0700 Subject: [PATCH 253/330] Refactor plugin functions into plugin.h --- libguac/include/client.h | 94 -------------------------- libguac/include/plugin.h | 142 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 94 deletions(-) create mode 100644 libguac/include/plugin.h diff --git a/libguac/include/client.h b/libguac/include/client.h index a7fa9d61..35f8815d 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -50,40 +50,7 @@ * @file client.h */ -/** - * String prefix which begins the library filename of all client plugins. - */ -#define GUAC_PROTOCOL_LIBRARY_PREFIX "libguac-client-" - -/** - * String suffix which ends the library filename of all client plugins. - */ -#define GUAC_PROTOCOL_LIBRARY_SUFFIX ".so" - -/** - * The maximum number of characters (COUNTING NULL TERMINATOR) to allow - * for protocol names within the library filename of client plugins. - */ -#define GUAC_PROTOCOL_NAME_LIMIT 256 - -/** - * The maximum number of characters (INCLUDING NULL TERMINATOR) that a - * character array containing the concatenation of the library prefix, - * protocol name, and suffix can contain, assuming the protocol name is - * limited to GUAC_PROTOCOL_NAME_LIMIT characters. - */ -#define GUAC_PROTOCOL_LIBRARY_LIMIT ( \ - \ - sizeof(GUAC_PROTOCOL_LIBRARY_PREFIX) - 1 /* "libguac-client-" */ \ - + GUAC_PROTOCOL_NAME_LIMIT - 1 /* [up to 256 chars] */ \ - + sizeof(GUAC_PROTOCOL_LIBRARY_SUFFIX) - 1 /* ".so" */ \ - + 1 /* NULL terminator */ \ - \ -) - - typedef struct guac_client guac_client; -typedef struct guac_client_plugin guac_client_plugin; /** * Handler for server messages (where "server" refers to the server that @@ -183,33 +150,6 @@ typedef enum guac_client_state { } guac_client_state; -/** - * A handle to a client plugin, containing enough information about the - * plugin to complete the initial protocol handshake and instantiate a new - * client supporting the protocol provided by the client plugin. - */ -struct guac_client_plugin { - - /** - * Reference to dlopen'd client plugin. - */ - void* __client_plugin_handle; - - /** - * Reference to the init handler of this client plugin. This - * function will be called when the client plugin is started. - */ - guac_client_init_handler* init_handler; - - /** - * NULL-terminated array of all arguments accepted by this client - * plugin, in order. The values of these arguments will be passed - * to the init_handler if the client plugin is started. - */ - const char** args; - -}; - /** * Guacamole proxy client. * @@ -448,40 +388,6 @@ struct guac_client { }; -/** - * Open the plugin which provides support for the given protocol, if it - * exists. - * - * @param protocol The name of the protocol to retrieve the client plugin - * for. - * @return The client plugin supporting the given protocol, or NULL if - * an error occurs or no such plugin exists. - */ -guac_client_plugin* guac_client_plugin_open(const char* protocol); - -/** - * Close the given plugin, releasing all associated resources. This function - * must be called after use of a client plugin is finished. - * - * @param plugin The client plugin to close. - * @return Zero on success, non-zero if an error occurred while releasing - * the resources associated with the plugin. - */ -int guac_client_plugin_close(guac_client_plugin* plugin); - -/** - * Initializes the given guac_client using the initialization routine provided - * by the given guac_client_plugin. - * - * @param plugin The client plugin to use to initialize the new client. - * @param client The guac_client to initialize. - * @param argc The number of arguments being passed to the client. - * @param argv All arguments to be passed to the client. - * @return Zero if initialization was successful, non-zero otherwise. - */ -int guac_client_plugin_init_client(guac_client_plugin* plugin, - guac_client* client, int argc, char** argv); - /** * Returns a new, barebones guac_client. This new guac_client has no handlers * set, but is otherwise usable. diff --git a/libguac/include/plugin.h b/libguac/include/plugin.h new file mode 100644 index 00000000..aa64f65f --- /dev/null +++ b/libguac/include/plugin.h @@ -0,0 +1,142 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#ifndef _GUAC_PLUGIN_H +#define _GUAC_PLUGIN_H + +/** + * Provides functions and structures required for handling a client plugin. + * + * @file plugin.h + */ + +/** + * String prefix which begins the library filename of all client plugins. + */ +#define GUAC_PROTOCOL_LIBRARY_PREFIX "libguac-client-" + +/** + * String suffix which ends the library filename of all client plugins. + */ +#define GUAC_PROTOCOL_LIBRARY_SUFFIX ".so" + +/** + * The maximum number of characters (COUNTING NULL TERMINATOR) to allow + * for protocol names within the library filename of client plugins. + */ +#define GUAC_PROTOCOL_NAME_LIMIT 256 + +/** + * The maximum number of characters (INCLUDING NULL TERMINATOR) that a + * character array containing the concatenation of the library prefix, + * protocol name, and suffix can contain, assuming the protocol name is + * limited to GUAC_PROTOCOL_NAME_LIMIT characters. + */ +#define GUAC_PROTOCOL_LIBRARY_LIMIT ( \ + \ + sizeof(GUAC_PROTOCOL_LIBRARY_PREFIX) - 1 /* "libguac-client-" */ \ + + GUAC_PROTOCOL_NAME_LIMIT - 1 /* [up to 256 chars] */ \ + + sizeof(GUAC_PROTOCOL_LIBRARY_SUFFIX) - 1 /* ".so" */ \ + + 1 /* NULL terminator */ \ + \ +) + +typedef struct guac_client_plugin guac_client_plugin; + +/** + * A handle to a client plugin, containing enough information about the + * plugin to complete the initial protocol handshake and instantiate a new + * client supporting the protocol provided by the client plugin. + */ +struct guac_client_plugin { + + /** + * Reference to dlopen'd client plugin. + */ + void* __client_plugin_handle; + + /** + * Reference to the init handler of this client plugin. This + * function will be called when the client plugin is started. + */ + guac_client_init_handler* init_handler; + + /** + * NULL-terminated array of all arguments accepted by this client + * plugin, in order. The values of these arguments will be passed + * to the init_handler if the client plugin is started. + */ + const char** args; + +}; + +/** + * Open the plugin which provides support for the given protocol, if it + * exists. + * + * @param protocol The name of the protocol to retrieve the client plugin + * for. + * @return The client plugin supporting the given protocol, or NULL if + * an error occurs or no such plugin exists. + */ +guac_client_plugin* guac_client_plugin_open(const char* protocol); + +/** + * Close the given plugin, releasing all associated resources. This function + * must be called after use of a client plugin is finished. + * + * @param plugin The client plugin to close. + * @return Zero on success, non-zero if an error occurred while releasing + * the resources associated with the plugin. + */ +int guac_client_plugin_close(guac_client_plugin* plugin); + +/** + * Initializes the given guac_client using the initialization routine provided + * by the given guac_client_plugin. + * + * @param plugin The client plugin to use to initialize the new client. + * @param client The guac_client to initialize. + * @param argc The number of arguments being passed to the client. + * @param argv All arguments to be passed to the client. + * @return Zero if initialization was successful, non-zero otherwise. + */ +int guac_client_plugin_init_client(guac_client_plugin* plugin, + guac_client* client, int argc, char** argv); + +#endif From 8807914668fda695249e20975a5357f059142124 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 4 Sep 2012 19:06:14 -0700 Subject: [PATCH 254/330] Add missing includes. --- libguac/include/client-handlers.h | 2 +- libguac/include/client.h | 4 +++- libguac/include/plugin.h | 2 ++ libguac/include/protocol.h | 3 +++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libguac/include/client-handlers.h b/libguac/include/client-handlers.h index de7603ae..7db42e6f 100644 --- a/libguac/include/client-handlers.h +++ b/libguac/include/client-handlers.h @@ -39,7 +39,7 @@ #define _GUAC_CLIENT_HANDLERS__H #include "client.h" -#include "protocol.h" +#include "instruction.h" /** * Provides initial handler functions and a lookup structure for automatically diff --git a/libguac/include/client.h b/libguac/include/client.h index 35f8815d..8cf9a553 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -41,8 +41,10 @@ #include +#include "instruction.h" +#include "layer.h" #include "socket.h" -#include "protocol.h" +#include "time.h" /** * Provides functions and structures required for defining (and handling) a proxy client. diff --git a/libguac/include/plugin.h b/libguac/include/plugin.h index aa64f65f..f1398859 100644 --- a/libguac/include/plugin.h +++ b/libguac/include/plugin.h @@ -39,6 +39,8 @@ #ifndef _GUAC_PLUGIN_H #define _GUAC_PLUGIN_H +#include "client.h" + /** * Provides functions and structures required for handling a client plugin. * diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 27d95101..ba44aac3 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -40,7 +40,10 @@ #include +#include "layer.h" +#include "resource.h" #include "socket.h" +#include "time.h" /** * Provides functions and structures required for communicating using the From 63e39befef1f2a6debbaa02827d12f386e71b3db Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 4 Sep 2012 23:28:58 -0700 Subject: [PATCH 255/330] Fixed includes, update Makefile.am --- libguac/include/layer.h | 2 ++ libguac/include/time.h | 2 ++ libguac/src/Makefile.am | 17 +++++++++++------ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/libguac/include/layer.h b/libguac/include/layer.h index 732b53ee..b76f4301 100644 --- a/libguac/include/layer.h +++ b/libguac/include/layer.h @@ -38,6 +38,8 @@ #ifndef _GUAC_LAYER_H #define _GUAC_LAYER_H +#include "client.h" + /** * Provides functions and structures required for allocating and using layers. * diff --git a/libguac/include/time.h b/libguac/include/time.h index 21dfea05..08ac665d 100644 --- a/libguac/include/time.h +++ b/libguac/include/time.h @@ -38,6 +38,8 @@ #ifndef _GUAC_TIME_H #define _GUAC_TIME_H +#include + /** * Provides functions and structures for creating timestamps. * diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index 5eaf4699..21a8cc34 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -39,15 +39,20 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = -Werror -Wall -pedantic -I../include libguacincdir = $(includedir)/guacamole -libguacinc_HEADERS = \ - ../include/client.h \ - ../include/socket.h \ - ../include/protocol.h \ - ../include/error.h +libguacinc_HEADERS = \ + ../include/client.h \ + ../include/error.h \ + ../include/instruction.h \ + ../include/layer.h \ + ../include/plugin.h \ + ../include/protocol.h \ + ../include/resource.h \ + ../include/socket.h \ + ../include/time.h noinst_HEADERS = \ - ../include/palette.h \ ../include/client-handlers.h \ + ../include/palette.h \ ../include/unicode.h libguac_la_SOURCES = \ From 9c53b853939704c4a34772285739c60a43ed34d6 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 5 Sep 2012 00:47:21 -0700 Subject: [PATCH 256/330] Fix includes, renamed time.h to timestamp.h --- libguac/include/client.h | 58 ++++++++++++++++++++++++- libguac/include/layer.h | 38 ---------------- libguac/include/protocol.h | 2 +- libguac/include/resource.h | 21 --------- libguac/include/{time.h => timestamp.h} | 2 +- libguac/src/Makefile.am | 2 +- libguac/src/client.c | 15 ++++--- libguac/src/protocol.c | 8 ++-- 8 files changed, 74 insertions(+), 72 deletions(-) rename libguac/include/{time.h => timestamp.h} (99%) diff --git a/libguac/include/client.h b/libguac/include/client.h index 8cf9a553..9481ab5a 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -43,8 +43,9 @@ #include "instruction.h" #include "layer.h" +#include "resource.h" #include "socket.h" -#include "time.h" +#include "timestamp.h" /** * Provides functions and structures required for defining (and handling) a proxy client. @@ -476,6 +477,61 @@ void vguac_client_log_error(guac_client* client, const char* format, va_list ap) */ void guac_client_stop(guac_client* client); +/** + * Allocates a new buffer (invisible layer). An arbitrary index is + * automatically assigned if no existing buffer is available for use. + * + * @param client The proxy client to allocate the buffer for. + * @return The next available buffer, or a newly allocated buffer. + */ +guac_layer* guac_client_alloc_buffer(guac_client* client); + +/** + * Allocates a new layer. An arbitrary index is automatically assigned + * if no existing layer is available for use. + * + * @param client The proxy client to allocate the layer buffer for. + * @return The next available layer, or a newly allocated layer. + */ +guac_layer* guac_client_alloc_layer(guac_client* client); + +/** + * Returns the given buffer to the pool of available buffers, such that it + * can be reused by any subsequent call to guac_client_allow_buffer(). + * + * @param client The proxy client to return the buffer to. + * @param layer The buffer to return to the pool of available buffers. + */ +void guac_client_free_buffer(guac_client* client, guac_layer* layer); + +/** + * Returns the given layer to the pool of available layers, such that it + * can be reused by any subsequent call to guac_client_allow_layer(). + * + * @param client The proxy client to return the layer to. + * @param layer The buffer to return to the pool of available layer. + */ +void guac_client_free_layer(guac_client* client, guac_layer* layer); + +/** + * Allocates a new resource. An arbitrary index is automatically assigned + * if no existing resource index is available for use. + * + * @param client The proxy client to allocate the resource for. + * @return The next available resource, or a newly allocated resource. + */ +guac_resource* guac_client_alloc_resource(guac_client* client); + +/** + * Frees an existing resource, re-adding it to the client's resource + * pool, such that it can be reused by a subsequent call to + * guac_client_alloc_resource(). + * + * @param client The proxy client to free the resource for. + * @oaran resource The resource to return to the resource pool. + */ +void guac_client_free_resource(guac_client* client, guac_resource* resource); + /** * The default Guacamole client layer, layer 0. */ diff --git a/libguac/include/layer.h b/libguac/include/layer.h index b76f4301..b02ec6e3 100644 --- a/libguac/include/layer.h +++ b/libguac/include/layer.h @@ -38,8 +38,6 @@ #ifndef _GUAC_LAYER_H #define _GUAC_LAYER_H -#include "client.h" - /** * Provides functions and structures required for allocating and using layers. * @@ -78,41 +76,5 @@ struct guac_layer { }; -/** - * Allocates a new buffer (invisible layer). An arbitrary index is - * automatically assigned if no existing buffer is available for use. - * - * @param client The proxy client to allocate the buffer for. - * @return The next available buffer, or a newly allocated buffer. - */ -guac_layer* guac_client_alloc_buffer(guac_client* client); - -/** - * Allocates a new layer. An arbitrary index is automatically assigned - * if no existing layer is available for use. - * - * @param client The proxy client to allocate the layer buffer for. - * @return The next available layer, or a newly allocated layer. - */ -guac_layer* guac_client_alloc_layer(guac_client* client); - -/** - * Returns the given buffer to the pool of available buffers, such that it - * can be reused by any subsequent call to guac_client_allow_buffer(). - * - * @param client The proxy client to return the buffer to. - * @param layer The buffer to return to the pool of available buffers. - */ -void guac_client_free_buffer(guac_client* client, guac_layer* layer); - -/** - * Returns the given layer to the pool of available layers, such that it - * can be reused by any subsequent call to guac_client_allow_layer(). - * - * @param client The proxy client to return the layer to. - * @param layer The buffer to return to the pool of available layer. - */ -void guac_client_free_layer(guac_client* client, guac_layer* layer); - #endif diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index ba44aac3..62ade022 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -43,7 +43,7 @@ #include "layer.h" #include "resource.h" #include "socket.h" -#include "time.h" +#include "timestamp.h" /** * Provides functions and structures required for communicating using the diff --git a/libguac/include/resource.h b/libguac/include/resource.h index eda0e204..5e03cd0d 100644 --- a/libguac/include/resource.h +++ b/libguac/include/resource.h @@ -39,8 +39,6 @@ #ifndef _GUAC_RESOURCE_H #define _GUAC_RESOURCE_H -#include "client.h" - /** * Provides functions and structures required for handling resources. * @@ -88,23 +86,4 @@ typedef int guac_resource_accept_handler(guac_resource* resource, const char* mi */ typedef int guac_resource_reject_handler(guac_resource* resource); -/** - * Allocates a new resource. An arbitrary index is automatically assigned - * if no existing resource index is available for use. - * - * @param client The proxy client to allocate the resource for. - * @return The next available resource, or a newly allocated resource. - */ -guac_resource* guac_client_alloc_resource(guac_client* client); - -/** - * Frees an existing resource, re-adding it to the client's resource - * pool, such that it can be reused by a subsequent call to - * guac_client_alloc_resource(). - * - * @param client The proxy client to free the resource for. - * @oaran resource The resource to return to the resource pool. - */ -void guac_client_free_resource(guac_client* client, guac_resource* resource); - #endif diff --git a/libguac/include/time.h b/libguac/include/timestamp.h similarity index 99% rename from libguac/include/time.h rename to libguac/include/timestamp.h index 08ac665d..baff204c 100644 --- a/libguac/include/time.h +++ b/libguac/include/timestamp.h @@ -43,7 +43,7 @@ /** * Provides functions and structures for creating timestamps. * - * @file time.h + * @file timestamp.h */ /** diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index 21a8cc34..8779c50c 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -48,7 +48,7 @@ libguacinc_HEADERS = \ ../include/protocol.h \ ../include/resource.h \ ../include/socket.h \ - ../include/time.h + ../include/timestamp.h noinst_HEADERS = \ ../include/client-handlers.h \ diff --git a/libguac/src/client.c b/libguac/src/client.c index f5b6ccf1..13534d98 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -35,16 +35,19 @@ * * ***** END LICENSE BLOCK ***** */ -#include -#include -#include #include +#include +#include +#include -#include "socket.h" -#include "protocol.h" #include "client.h" #include "client-handlers.h" #include "error.h" +#include "layer.h" +#include "plugin.h" +#include "protocol.h" +#include "socket.h" +#include "time.h" #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) @@ -263,7 +266,7 @@ guac_client* guac_client_alloc() { memset(client, 0, sizeof(guac_client)); client->last_received_timestamp = - client->last_sent_timestamp = guac_protocol_get_timestamp(); + client->last_sent_timestamp = guac_timestamp_current(); client->state = GUAC_CLIENT_RUNNING; diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 3eddce77..19bbaaa3 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -66,10 +66,12 @@ #include #endif -#include "socket.h" -#include "protocol.h" #include "error.h" +#include "instruction.h" +#include "layer.h" #include "palette.h" +#include "protocol.h" +#include "socket.h" #include "unicode.h" /* Output formatting functions */ @@ -600,7 +602,7 @@ guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, int usec guac_instruction* instruction; /* Wait for data until timeout */ - if (guac_protocol_instructions_waiting(socket, usec_timeout) <= 0) + if (guac_instruction_waiting(socket, usec_timeout) <= 0) return NULL; /* Read available instruction */ From c57a61122b55aae82653d649e0d189943dc9779a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 5 Sep 2012 01:02:52 -0700 Subject: [PATCH 257/330] Add missing includes to tests, fix function naming in protocol.c --- libguac/src/protocol.c | 10 +++++----- libguac/tests/protocol/instruction_read.c | 9 +++++---- libguac/tests/protocol/instruction_write.c | 5 +++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 19bbaaa3..0846181e 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -405,7 +405,7 @@ int __guac_fill_instructionbuf(guac_socket* socket) { /* Returns new instruction if one exists, or NULL if no more instructions. */ -guac_instruction* guac_protocol_read_instruction(guac_socket* socket, +guac_instruction* guac_instruction_read(guac_socket* socket, int usec_timeout) { int retval; @@ -596,7 +596,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, } -guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, int usec_timeout, +guac_instruction* guac_instruction_expect(guac_socket* socket, int usec_timeout, const char* opcode) { guac_instruction* instruction; @@ -606,7 +606,7 @@ guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, int usec return NULL; /* Read available instruction */ - instruction = guac_protocol_read_instruction(socket, usec_timeout); + instruction = guac_instruction_read(socket, usec_timeout); if (instruction == NULL) return NULL; @@ -649,7 +649,7 @@ void guac_instruction_free(guac_instruction* instruction) { } -int guac_protocol_instructions_waiting(guac_socket* socket, int usec_timeout) { +int guac_instruction_waiting(guac_socket* socket, int usec_timeout) { if (socket->__instructionbuf_used_length > 0) return 1; @@ -658,7 +658,7 @@ int guac_protocol_instructions_waiting(guac_socket* socket, int usec_timeout) { } -guac_timestamp guac_protocol_get_timestamp() { +guac_timestamp guac_timestamp_current() { #ifdef HAVE_CLOCK_GETTIME diff --git a/libguac/tests/protocol/instruction_read.c b/libguac/tests/protocol/instruction_read.c index 45e7083d..ef65a0be 100644 --- a/libguac/tests/protocol/instruction_read.c +++ b/libguac/tests/protocol/instruction_read.c @@ -40,9 +40,10 @@ #include #include -#include "socket.h" -#include "protocol.h" #include "error.h" +#include "instruction.h" +#include "protocol.h" +#include "socket.h" #include "suite.h" @@ -92,7 +93,7 @@ void test_instruction_read() { CU_ASSERT_PTR_NOT_NULL_FATAL(socket); /* Read instruction */ - instruction = guac_protocol_read_instruction(socket, 1000000); + instruction = guac_instruction_read(socket, 1000000); CU_ASSERT_PTR_NOT_NULL_FATAL(instruction); /* Validate contents */ @@ -104,7 +105,7 @@ void test_instruction_read() { /* Read another instruction */ guac_instruction_free(instruction); - instruction = guac_protocol_read_instruction(socket, 1000000); + instruction = guac_instruction_read(socket, 1000000); /* Validate contents */ CU_ASSERT_STRING_EQUAL(instruction->opcode, "test2"); diff --git a/libguac/tests/protocol/instruction_write.c b/libguac/tests/protocol/instruction_write.c index 58b136a4..36a6838a 100644 --- a/libguac/tests/protocol/instruction_write.c +++ b/libguac/tests/protocol/instruction_write.c @@ -40,9 +40,10 @@ #include #include -#include "socket.h" -#include "protocol.h" #include "error.h" +#include "instruction.h" +#include "protocol.h" +#include "socket.h" #include "suite.h" From 9a812c673296e2fb990f733edb546f5ead4c9aa0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 5 Sep 2012 17:03:56 -0700 Subject: [PATCH 258/330] Fixed typo. --- libguac/src/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 0846181e..bfb7b1cd 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -551,7 +551,7 @@ guac_instruction* guac_instruction_read(guac_socket* socket, /* Error if expected comma is not present */ else if (terminator != ',') { guac_error = GUAC_STATUS_BAD_ARGUMENT; - guac_error_message = "Element terminator of instructioni was not ';' nor ','"; + guac_error_message = "Element terminator of instruction was not ';' nor ','"; return NULL; } From df2ab8384f703d308ba09211b4670b9896681b53 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 5 Sep 2012 17:13:05 -0700 Subject: [PATCH 259/330] Refactored instruction functions into instruction.c. --- libguac/src/Makefile.am | 5 +- libguac/src/instruction.c | 334 ++++++++++++++++++++++++++++++++++++++ libguac/src/protocol.c | 291 --------------------------------- 3 files changed, 337 insertions(+), 293 deletions(-) create mode 100644 libguac/src/instruction.c diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index 8779c50c..10d36873 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -57,11 +57,12 @@ noinst_HEADERS = \ libguac_la_SOURCES = \ client.c \ - socket.c \ - protocol.c \ client-handlers.c \ error.c \ + instruction.c \ palette.c \ + protocol.c \ + socket.c \ unicode.c lib_LTLIBRARIES = libguac.la diff --git a/libguac/src/instruction.c b/libguac/src/instruction.c new file mode 100644 index 00000000..6073a69d --- /dev/null +++ b/libguac/src/instruction.c @@ -0,0 +1,334 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include + +#include "error.h" +#include "instruction.h" +#include "protocol.h" +#include "socket.h" +#include "unicode.h" + +int __guac_fill_instructionbuf(guac_socket* socket) { + + int retval; + + /* Attempt to fill buffer */ + retval = read( + socket->fd, + socket->__instructionbuf + socket->__instructionbuf_used_length, + socket->__instructionbuf_size - socket->__instructionbuf_used_length + ); + + /* Set guac_error if recv() unsuccessful */ + if (retval < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Error filling instruction buffer"; + return retval; + } + + socket->__instructionbuf_used_length += retval; + + /* Expand buffer if necessary */ + if (socket->__instructionbuf_used_length > + socket->__instructionbuf_size / 2) { + + socket->__instructionbuf_size *= 2; + socket->__instructionbuf = realloc(socket->__instructionbuf, + socket->__instructionbuf_size); + } + + return retval; + +} + + +/* Returns new instruction if one exists, or NULL if no more instructions. */ +guac_instruction* guac_instruction_read(guac_socket* socket, + int usec_timeout) { + + int retval; + + /* Loop until a instruction is read */ + for (;;) { + + /* Length of element, in Unicode characters */ + int element_length = 0; + + /* Length of element, in bytes */ + int element_byte_length = 0; + + /* Current position within the element, in Unicode characters */ + int current_unicode_length = 0; + + /* Position within buffer */ + int i = socket->__instructionbuf_parse_start; + + /* Parse instruction in buffer */ + while (i < socket->__instructionbuf_used_length) { + + /* Read character from buffer */ + char c = socket->__instructionbuf[i++]; + + /* If digit, calculate element length */ + if (c >= '0' && c <= '9') + element_length = element_length * 10 + c - '0'; + + /* Otherwise, if end of length */ + else if (c == '.') { + + /* Calculate element byte length by walking buffer */ + while (i + element_byte_length < + socket->__instructionbuf_used_length + && current_unicode_length < element_length) { + + /* Get next byte */ + c = socket->__instructionbuf[i + element_byte_length]; + + /* Update byte and character lengths */ + element_byte_length += guac_utf8_charsize((unsigned) c); + current_unicode_length++; + + } + + /* Verify element is fully read */ + if (current_unicode_length == element_length) { + + /* Get element value */ + char* elementv = &(socket->__instructionbuf[i]); + + /* Get terminator, set null terminator of elementv */ + char terminator = elementv[element_byte_length]; + elementv[element_byte_length] = '\0'; + + /* Move to char after terminator of element */ + i += element_byte_length+1; + + /* Reset element length */ + element_length = + element_byte_length = + current_unicode_length = 0; + + /* As element has been read successfully, update + * parse start */ + socket->__instructionbuf_parse_start = i; + + /* Save element */ + socket->__instructionbuf_elementv[socket->__instructionbuf_elementc++] = elementv; + + /* Finish parse if terminator is a semicolon */ + if (terminator == ';') { + + guac_instruction* parsed_instruction; + int j; + + /* Allocate instruction */ + parsed_instruction = malloc(sizeof(guac_instruction)); + if (parsed_instruction == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for parsed instruction"; + return NULL; + } + + /* Init parsed instruction */ + parsed_instruction->argc = socket->__instructionbuf_elementc - 1; + parsed_instruction->argv = malloc(sizeof(char*) * parsed_instruction->argc); + + /* Fail if memory could not be alloc'd for argv */ + if (parsed_instruction->argv == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for arguments of parsed instruction"; + free(parsed_instruction); + return NULL; + } + + /* Set opcode */ + parsed_instruction->opcode = strdup(socket->__instructionbuf_elementv[0]); + + /* Fail if memory could not be alloc'd for opcode */ + if (parsed_instruction->opcode == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for opcode of parsed instruction"; + free(parsed_instruction->argv); + free(parsed_instruction); + return NULL; + } + + + /* Copy element values to parsed instruction */ + for (j=0; jargc; j++) { + parsed_instruction->argv[j] = strdup(socket->__instructionbuf_elementv[j+1]); + + /* Free memory and fail if out of mem */ + if (parsed_instruction->argv[j] == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for single argument of parsed instruction"; + + /* Free all alloc'd argv values */ + while (--j >= 0) + free(parsed_instruction->argv[j]); + + free(parsed_instruction->opcode); + free(parsed_instruction->argv); + free(parsed_instruction); + return NULL; + } + + } + + /* Reset buffer */ + memmove(socket->__instructionbuf, socket->__instructionbuf + i, socket->__instructionbuf_used_length - i); + socket->__instructionbuf_used_length -= i; + socket->__instructionbuf_parse_start = 0; + socket->__instructionbuf_elementc = 0; + + /* Done */ + return parsed_instruction; + + } /* end if terminator */ + + /* Error if expected comma is not present */ + else if (terminator != ',') { + guac_error = GUAC_STATUS_BAD_ARGUMENT; + guac_error_message = "Element terminator of instruction was not ';' nor ','"; + return NULL; + } + + } /* end if element fully read */ + + /* Otherwise, read more data */ + else + break; + + } + + /* Error if length is non-numeric or does not end in a period */ + else { + guac_error = GUAC_STATUS_BAD_ARGUMENT; + guac_error_message = "Non-numeric character in element length"; + return NULL; + } + + } + + /* No instruction yet? Get more data ... */ + retval = guac_socket_select(socket, usec_timeout); + if (retval <= 0) + return NULL; + + /* If more data is available, fill into buffer */ + retval = __guac_fill_instructionbuf(socket); + + /* Error, guac_error already set */ + if (retval < 0) + return NULL; + + /* EOF */ + if (retval == 0) { + guac_error = GUAC_STATUS_NO_INPUT; + guac_error_message = "End of stream reached while reading instruction"; + return NULL; + } + + } + +} + + +guac_instruction* guac_instruction_expect(guac_socket* socket, int usec_timeout, + const char* opcode) { + + guac_instruction* instruction; + + /* Wait for data until timeout */ + if (guac_instruction_waiting(socket, usec_timeout) <= 0) + return NULL; + + /* Read available instruction */ + instruction = guac_instruction_read(socket, usec_timeout); + if (instruction == NULL) + return NULL; + + /* Validate instruction */ + if (strcmp(instruction->opcode, opcode) != 0) { + guac_error = GUAC_STATUS_BAD_STATE; + guac_error_message = "Instruction read did not have expected opcode"; + guac_instruction_free(instruction); + return NULL; + } + + /* Return instruction if valid */ + return instruction; + +} + + +void guac_instruction_free(guac_instruction* instruction) { + + int argc = instruction->argc; + + /* Free opcode */ + free(instruction->opcode); + + /* Free argv if set (may be NULL of argc is 0) */ + if (instruction->argv) { + + /* All argument values */ + while (argc > 0) + free(instruction->argv[--argc]); + + /* Free actual array */ + free(instruction->argv); + + } + + /* Free instruction */ + free(instruction); + +} + + +int guac_instruction_waiting(guac_socket* socket, int usec_timeout) { + + if (socket->__instructionbuf_used_length > 0) + return 1; + + return guac_socket_select(socket, usec_timeout); +} + diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index bfb7b1cd..d3e9d5ff 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -67,7 +67,6 @@ #endif #include "error.h" -#include "instruction.h" #include "layer.h" #include "palette.h" #include "protocol.h" @@ -368,296 +367,6 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface } -/* Instruction I/O */ - -int __guac_fill_instructionbuf(guac_socket* socket) { - - int retval; - - /* Attempt to fill buffer */ - retval = read( - socket->fd, - socket->__instructionbuf + socket->__instructionbuf_used_length, - socket->__instructionbuf_size - socket->__instructionbuf_used_length - ); - - /* Set guac_error if recv() unsuccessful */ - if (retval < 0) { - guac_error = GUAC_STATUS_SEE_ERRNO; - guac_error_message = "Error filling instruction buffer"; - return retval; - } - - socket->__instructionbuf_used_length += retval; - - /* Expand buffer if necessary */ - if (socket->__instructionbuf_used_length > - socket->__instructionbuf_size / 2) { - - socket->__instructionbuf_size *= 2; - socket->__instructionbuf = realloc(socket->__instructionbuf, - socket->__instructionbuf_size); - } - - return retval; - -} - - -/* Returns new instruction if one exists, or NULL if no more instructions. */ -guac_instruction* guac_instruction_read(guac_socket* socket, - int usec_timeout) { - - int retval; - - /* Loop until a instruction is read */ - for (;;) { - - /* Length of element, in Unicode characters */ - int element_length = 0; - - /* Length of element, in bytes */ - int element_byte_length = 0; - - /* Current position within the element, in Unicode characters */ - int current_unicode_length = 0; - - /* Position within buffer */ - int i = socket->__instructionbuf_parse_start; - - /* Parse instruction in buffer */ - while (i < socket->__instructionbuf_used_length) { - - /* Read character from buffer */ - char c = socket->__instructionbuf[i++]; - - /* If digit, calculate element length */ - if (c >= '0' && c <= '9') - element_length = element_length * 10 + c - '0'; - - /* Otherwise, if end of length */ - else if (c == '.') { - - /* Calculate element byte length by walking buffer */ - while (i + element_byte_length < - socket->__instructionbuf_used_length - && current_unicode_length < element_length) { - - /* Get next byte */ - c = socket->__instructionbuf[i + element_byte_length]; - - /* Update byte and character lengths */ - element_byte_length += guac_utf8_charsize((unsigned) c); - current_unicode_length++; - - } - - /* Verify element is fully read */ - if (current_unicode_length == element_length) { - - /* Get element value */ - char* elementv = &(socket->__instructionbuf[i]); - - /* Get terminator, set null terminator of elementv */ - char terminator = elementv[element_byte_length]; - elementv[element_byte_length] = '\0'; - - /* Move to char after terminator of element */ - i += element_byte_length+1; - - /* Reset element length */ - element_length = - element_byte_length = - current_unicode_length = 0; - - /* As element has been read successfully, update - * parse start */ - socket->__instructionbuf_parse_start = i; - - /* Save element */ - socket->__instructionbuf_elementv[socket->__instructionbuf_elementc++] = elementv; - - /* Finish parse if terminator is a semicolon */ - if (terminator == ';') { - - guac_instruction* parsed_instruction; - int j; - - /* Allocate instruction */ - parsed_instruction = malloc(sizeof(guac_instruction)); - if (parsed_instruction == NULL) { - guac_error = GUAC_STATUS_NO_MEMORY; - guac_error_message = "Could not allocate memory for parsed instruction"; - return NULL; - } - - /* Init parsed instruction */ - parsed_instruction->argc = socket->__instructionbuf_elementc - 1; - parsed_instruction->argv = malloc(sizeof(char*) * parsed_instruction->argc); - - /* Fail if memory could not be alloc'd for argv */ - if (parsed_instruction->argv == NULL) { - guac_error = GUAC_STATUS_NO_MEMORY; - guac_error_message = "Could not allocate memory for arguments of parsed instruction"; - free(parsed_instruction); - return NULL; - } - - /* Set opcode */ - parsed_instruction->opcode = strdup(socket->__instructionbuf_elementv[0]); - - /* Fail if memory could not be alloc'd for opcode */ - if (parsed_instruction->opcode == NULL) { - guac_error = GUAC_STATUS_NO_MEMORY; - guac_error_message = "Could not allocate memory for opcode of parsed instruction"; - free(parsed_instruction->argv); - free(parsed_instruction); - return NULL; - } - - - /* Copy element values to parsed instruction */ - for (j=0; jargc; j++) { - parsed_instruction->argv[j] = strdup(socket->__instructionbuf_elementv[j+1]); - - /* Free memory and fail if out of mem */ - if (parsed_instruction->argv[j] == NULL) { - guac_error = GUAC_STATUS_NO_MEMORY; - guac_error_message = "Could not allocate memory for single argument of parsed instruction"; - - /* Free all alloc'd argv values */ - while (--j >= 0) - free(parsed_instruction->argv[j]); - - free(parsed_instruction->opcode); - free(parsed_instruction->argv); - free(parsed_instruction); - return NULL; - } - - } - - /* Reset buffer */ - memmove(socket->__instructionbuf, socket->__instructionbuf + i, socket->__instructionbuf_used_length - i); - socket->__instructionbuf_used_length -= i; - socket->__instructionbuf_parse_start = 0; - socket->__instructionbuf_elementc = 0; - - /* Done */ - return parsed_instruction; - - } /* end if terminator */ - - /* Error if expected comma is not present */ - else if (terminator != ',') { - guac_error = GUAC_STATUS_BAD_ARGUMENT; - guac_error_message = "Element terminator of instruction was not ';' nor ','"; - return NULL; - } - - } /* end if element fully read */ - - /* Otherwise, read more data */ - else - break; - - } - - /* Error if length is non-numeric or does not end in a period */ - else { - guac_error = GUAC_STATUS_BAD_ARGUMENT; - guac_error_message = "Non-numeric character in element length"; - return NULL; - } - - } - - /* No instruction yet? Get more data ... */ - retval = guac_socket_select(socket, usec_timeout); - if (retval <= 0) - return NULL; - - /* If more data is available, fill into buffer */ - retval = __guac_fill_instructionbuf(socket); - - /* Error, guac_error already set */ - if (retval < 0) - return NULL; - - /* EOF */ - if (retval == 0) { - guac_error = GUAC_STATUS_NO_INPUT; - guac_error_message = "End of stream reached while reading instruction"; - return NULL; - } - - } - -} - - -guac_instruction* guac_instruction_expect(guac_socket* socket, int usec_timeout, - const char* opcode) { - - guac_instruction* instruction; - - /* Wait for data until timeout */ - if (guac_instruction_waiting(socket, usec_timeout) <= 0) - return NULL; - - /* Read available instruction */ - instruction = guac_instruction_read(socket, usec_timeout); - if (instruction == NULL) - return NULL; - - /* Validate instruction */ - if (strcmp(instruction->opcode, opcode) != 0) { - guac_error = GUAC_STATUS_BAD_STATE; - guac_error_message = "Instruction read did not have expected opcode"; - guac_instruction_free(instruction); - return NULL; - } - - /* Return instruction if valid */ - return instruction; - -} - - -void guac_instruction_free(guac_instruction* instruction) { - - int argc = instruction->argc; - - /* Free opcode */ - free(instruction->opcode); - - /* Free argv if set (may be NULL of argc is 0) */ - if (instruction->argv) { - - /* All argument values */ - while (argc > 0) - free(instruction->argv[--argc]); - - /* Free actual array */ - free(instruction->argv); - - } - - /* Free instruction */ - free(instruction); - -} - - -int guac_instruction_waiting(guac_socket* socket, int usec_timeout) { - - if (socket->__instructionbuf_used_length > 0) - return 1; - - return guac_socket_select(socket, usec_timeout); -} - - guac_timestamp guac_timestamp_current() { #ifdef HAVE_CLOCK_GETTIME From 2af32ece373890135f1b29a88856f0bf297c9376 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 5 Sep 2012 17:17:18 -0700 Subject: [PATCH 260/330] Refactored timestamp functions into timestamp.c --- libguac/src/Makefile.am | 1 + libguac/src/protocol.c | 41 ----------------------- libguac/src/timestamp.c | 73 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 41 deletions(-) create mode 100644 libguac/src/timestamp.c diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index 10d36873..f5130a46 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -63,6 +63,7 @@ libguac_la_SOURCES = \ palette.c \ protocol.c \ socket.c \ + timestamp.c \ unicode.c lib_LTLIBRARIES = libguac.la diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index d3e9d5ff..42fe5f9c 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -35,14 +35,6 @@ * * ***** END LICENSE BLOCK ***** */ -#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_NANOSLEEP) -#include -#endif - -#ifndef HAVE_CLOCK_GETTIME -#include -#endif - #include #include #include @@ -60,12 +52,6 @@ #include -#ifdef __MINGW32__ -#include -#else -#include -#endif - #include "error.h" #include "layer.h" #include "palette.h" @@ -367,33 +353,6 @@ int __guac_socket_write_length_png(guac_socket* socket, cairo_surface_t* surface } -guac_timestamp guac_timestamp_current() { - -#ifdef HAVE_CLOCK_GETTIME - - struct timespec current; - - /* Get current time */ - clock_gettime(CLOCK_REALTIME, ¤t); - - /* Calculate milliseconds */ - return (guac_timestamp) current.tv_sec * 1000 + current.tv_nsec / 1000000; - -#else - - struct timeval current; - - /* Get current time */ - gettimeofday(¤t, NULL); - - /* Calculate milliseconds */ - return (guac_timestamp) current.tv_sec * 1000 + current.tv_usec / 1000; - -#endif - -} - - /* Protocol functions */ int guac_protocol_send_args(guac_socket* socket, const char** args) { diff --git a/libguac/src/timestamp.c b/libguac/src/timestamp.c new file mode 100644 index 00000000..a610d8f1 --- /dev/null +++ b/libguac/src/timestamp.c @@ -0,0 +1,73 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_NANOSLEEP) +#include +#endif + +#ifndef HAVE_CLOCK_GETTIME +#include +#endif + +#include "timestamp.h" + +guac_timestamp guac_timestamp_current() { + +#ifdef HAVE_CLOCK_GETTIME + + struct timespec current; + + /* Get current time */ + clock_gettime(CLOCK_REALTIME, ¤t); + + /* Calculate milliseconds */ + return (guac_timestamp) current.tv_sec * 1000 + current.tv_nsec / 1000000; + +#else + + struct timeval current; + + /* Get current time */ + gettimeofday(¤t, NULL); + + /* Calculate milliseconds */ + return (guac_timestamp) current.tv_sec * 1000 + current.tv_usec / 1000; + +#endif + +} + From dc1be17935a5dd0dfe6b3474d0e2014ac3b470b1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 5 Sep 2012 17:23:24 -0700 Subject: [PATCH 261/330] Refactored plugin functions into plugin.c --- libguac/src/Makefile.am | 1 + libguac/src/client.c | 95 --------------------------- libguac/src/plugin.c | 141 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 95 deletions(-) create mode 100644 libguac/src/plugin.c diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index f5130a46..ad0de776 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -61,6 +61,7 @@ libguac_la_SOURCES = \ error.c \ instruction.c \ palette.c \ + plugin.c \ protocol.c \ socket.c \ timestamp.c \ diff --git a/libguac/src/client.c b/libguac/src/client.c index 13534d98..4466b342 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -35,7 +35,6 @@ * * ***** END LICENSE BLOCK ***** */ -#include #include #include #include @@ -49,9 +48,6 @@ #include "socket.h" #include "time.h" -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) - guac_layer __GUAC_DEFAULT_LAYER = { .index = 0, .uri = "layer://0", @@ -161,97 +157,6 @@ void guac_client_free_layer(guac_client* client, guac_layer* layer) { } -guac_client_plugin* guac_client_plugin_open(const char* protocol) { - - guac_client_plugin* plugin; - - /* Reference to dlopen()'d plugin */ - void* client_plugin_handle; - - /* Client args description */ - const char** client_args; - - /* Pluggable client */ - char protocol_lib[GUAC_PROTOCOL_LIBRARY_LIMIT] = - GUAC_PROTOCOL_LIBRARY_PREFIX; - - union { - guac_client_init_handler* client_init; - void* obj; - } alias; - - /* Add protocol and .so suffix to protocol_lib */ - strncat(protocol_lib, protocol, GUAC_PROTOCOL_NAME_LIMIT-1); - strcat(protocol_lib, GUAC_PROTOCOL_LIBRARY_SUFFIX); - - /* Load client plugin */ - client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); - if (!client_plugin_handle) { - guac_error = GUAC_STATUS_BAD_ARGUMENT; - guac_error_message = dlerror(); - return NULL; - } - - dlerror(); /* Clear errors */ - - /* Get init function */ - alias.obj = dlsym(client_plugin_handle, "guac_client_init"); - - /* Fail if cannot find guac_client_init */ - if (dlerror() != NULL) { - guac_error = GUAC_STATUS_BAD_ARGUMENT; - guac_error_message = dlerror(); - return NULL; - } - - /* Get usage strig */ - client_args = (const char**) dlsym(client_plugin_handle, "GUAC_CLIENT_ARGS"); - - /* Fail if cannot find GUAC_CLIENT_ARGS */ - if (dlerror() != NULL) { - guac_error = GUAC_STATUS_BAD_ARGUMENT; - guac_error_message = dlerror(); - return NULL; - } - - /* Allocate plugin */ - plugin = malloc(sizeof(guac_client_plugin)); - if (plugin == NULL) { - guac_error = GUAC_STATUS_NO_MEMORY; - guac_error_message = "Could not allocate memory for client plugin"; - return NULL; - } - - /* Init and return plugin */ - plugin->__client_plugin_handle = client_plugin_handle; - plugin->init_handler = alias.client_init; - plugin->args = client_args; - return plugin; - -} - -int guac_client_plugin_close(guac_client_plugin* plugin) { - - /* Unload client plugin */ - if (dlclose(plugin->__client_plugin_handle)) { - guac_error = GUAC_STATUS_BAD_STATE; - guac_error_message = dlerror(); - return -1; - } - - /* Free plugin handle */ - free(plugin); - return 0; - -} - -int guac_client_plugin_init_client(guac_client_plugin* plugin, - guac_client* client, int argc, char** argv) { - - return plugin->init_handler(client, argc, argv); - -} - guac_client* guac_client_alloc() { /* Allocate new client */ diff --git a/libguac/src/plugin.c b/libguac/src/plugin.c new file mode 100644 index 00000000..5bf5826b --- /dev/null +++ b/libguac/src/plugin.c @@ -0,0 +1,141 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include + +#include "client.h" +#include "client-handlers.h" +#include "error.h" +#include "plugin.h" +#include "protocol.h" +#include "socket.h" +#include "time.h" + +guac_client_plugin* guac_client_plugin_open(const char* protocol) { + + guac_client_plugin* plugin; + + /* Reference to dlopen()'d plugin */ + void* client_plugin_handle; + + /* Client args description */ + const char** client_args; + + /* Pluggable client */ + char protocol_lib[GUAC_PROTOCOL_LIBRARY_LIMIT] = + GUAC_PROTOCOL_LIBRARY_PREFIX; + + union { + guac_client_init_handler* client_init; + void* obj; + } alias; + + /* Add protocol and .so suffix to protocol_lib */ + strncat(protocol_lib, protocol, GUAC_PROTOCOL_NAME_LIMIT-1); + strcat(protocol_lib, GUAC_PROTOCOL_LIBRARY_SUFFIX); + + /* Load client plugin */ + client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); + if (!client_plugin_handle) { + guac_error = GUAC_STATUS_BAD_ARGUMENT; + guac_error_message = dlerror(); + return NULL; + } + + dlerror(); /* Clear errors */ + + /* Get init function */ + alias.obj = dlsym(client_plugin_handle, "guac_client_init"); + + /* Fail if cannot find guac_client_init */ + if (dlerror() != NULL) { + guac_error = GUAC_STATUS_BAD_ARGUMENT; + guac_error_message = dlerror(); + return NULL; + } + + /* Get usage strig */ + client_args = (const char**) dlsym(client_plugin_handle, "GUAC_CLIENT_ARGS"); + + /* Fail if cannot find GUAC_CLIENT_ARGS */ + if (dlerror() != NULL) { + guac_error = GUAC_STATUS_BAD_ARGUMENT; + guac_error_message = dlerror(); + return NULL; + } + + /* Allocate plugin */ + plugin = malloc(sizeof(guac_client_plugin)); + if (plugin == NULL) { + guac_error = GUAC_STATUS_NO_MEMORY; + guac_error_message = "Could not allocate memory for client plugin"; + return NULL; + } + + /* Init and return plugin */ + plugin->__client_plugin_handle = client_plugin_handle; + plugin->init_handler = alias.client_init; + plugin->args = client_args; + return plugin; + +} + +int guac_client_plugin_close(guac_client_plugin* plugin) { + + /* Unload client plugin */ + if (dlclose(plugin->__client_plugin_handle)) { + guac_error = GUAC_STATUS_BAD_STATE; + guac_error_message = dlerror(); + return -1; + } + + /* Free plugin handle */ + free(plugin); + return 0; + +} + +int guac_client_plugin_init_client(guac_client_plugin* plugin, + guac_client* client, int argc, char** argv) { + + return plugin->init_handler(client, argc, argv); + +} + From 9493dc10f3c3160a8398bbbb8bc2983d35ed8a98 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 5 Sep 2012 18:11:48 -0700 Subject: [PATCH 262/330] Added resource handlers to guac_resource. --- libguac/include/resource.h | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/libguac/include/resource.h b/libguac/include/resource.h index 5e03cd0d..0260542c 100644 --- a/libguac/include/resource.h +++ b/libguac/include/resource.h @@ -56,6 +56,16 @@ * @file resource.h */ +/** + * Handler which begins resource transfer when the client accepts an exposed resource. + */ +typedef int guac_resource_accept_handler(guac_resource* resource, const char* mimetype); + +/** + * Handler which cancels resource transfer when the client rejects an exposed resource. + */ +typedef int guac_resource_reject_handler(guac_resource* resource); + /** * Represents a single resource which can be requested or exposed via * the Guacamole protocol. @@ -67,6 +77,16 @@ typedef struct guac_resource { */ int index; + /** + * Handler which will be called when this resource is accepted by the client. + */ + guac_resource_accept_handler* accept_handler; + + /** + * Handler which will be called when this resource is rejected by the client. + */ + guac_resource_reject_handler* reject_handler; + /** * Arbitrary data associated with this resource. */ @@ -74,16 +94,4 @@ typedef struct guac_resource { } guac_resource; -/** - * Handler which will be called whenever a resource has been accepted by the - * client. - */ -typedef int guac_resource_accept_handler(guac_resource* resource, const char* mimetype); - -/** - * Handler which will be called whenever a resource has been rejected by the - * client. - */ -typedef int guac_resource_reject_handler(guac_resource* resource); - #endif From 866d067bba325877f6b5ea1c8196cf993f811421 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 10:22:17 -0700 Subject: [PATCH 263/330] Add forward declaration for guac_resource --- libguac/include/resource.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libguac/include/resource.h b/libguac/include/resource.h index 0260542c..3663f29b 100644 --- a/libguac/include/resource.h +++ b/libguac/include/resource.h @@ -56,6 +56,8 @@ * @file resource.h */ +typedef struct guac_resource guac_resource; + /** * Handler which begins resource transfer when the client accepts an exposed resource. */ @@ -70,7 +72,7 @@ typedef int guac_resource_reject_handler(guac_resource* resource); * Represents a single resource which can be requested or exposed via * the Guacamole protocol. */ -typedef struct guac_resource { +struct guac_resource { /** * The index of this resource. @@ -92,6 +94,6 @@ typedef struct guac_resource { */ void* data; -} guac_resource; +}; #endif From fba2c37b6b146a10a5ff39a40d95f7eec91d403a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 11:15:23 -0700 Subject: [PATCH 264/330] Add prototypes and structs for generic integer pool (to ultimately replace the individually-implemented layer and buffer pools, and for use in implementing the resource pool). --- libguac/include/pool.h | 132 ++++++++++++++++++++++++++++++++++++++++ libguac/src/Makefile.am | 1 + 2 files changed, 133 insertions(+) create mode 100644 libguac/include/pool.h diff --git a/libguac/include/pool.h b/libguac/include/pool.h new file mode 100644 index 00000000..9300a0d7 --- /dev/null +++ b/libguac/include/pool.h @@ -0,0 +1,132 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_POOL_H +#define _GUAC_POOL_H + +/** + * Provides functions and structures for maintaining dynamically allocated and freed + * pools of integers. + * + * @file pool.h + */ + +typedef struct guac_pool_int guac_pool_int; + +typedef struct guac_pool { + + /** + * The minimum number of integers which must have been returned by guac_pool_next_int + * before previously-used and freed integers are allowed to be returned. + */ + int min_size; + + /** + * The next integer to be released (after no more integers remain in the pool. + */ + int __next_value; + + /** + * The first integer in the pool, if any. + */ + guac_pool_int* __head; + + /** + * The last integer in the pool, if any. + */ + guac_pool_int* __tail; + +} guac_pool; + +/** + * Represents a single layer within the Guacamole protocol. + */ +struct guac_pool_int { + + /** + * The integer value of this pool entry. + */ + int value; + + /** + * The next available (unused) guac_pool_int in the list of + * allocated but free'd ints. + */ + __guac_pool_int* __next; + +}; + +/** + * Allocates a new guac_pool having the given minimum size. + * + * @param size The minimum number of integers which must have been returned by + * guac_pool_next_int before freed integers (previously used integers) + * are allowed to be returned. + * @return A new, empty guac_pool, having the given minimum size. + */ +guac_pool* guac_pool_alloc(int size); + +/** + * Frees the given guac_pool. + * + * @param pool The guac_pool to free. + */ +void guac_pool_free(guac_pool* pool); + +/** + * Returns the next available integer from the given guac_pool. All integers returned are + * non-negative, and are returned in sequences, starting from 0. + * + * @param pool The guac_pool to retrieve an integer from. + * @return The next available integer, which may be either an integer not yet returned + * by a call to guac_pool_next_int, or an integer which was previosly returned, + * but has since been freed. + */ +int guac_pool_next_int(guac_pool* pool); + +/** + * Frees the given integer back into the given guac_pool. The integer given will be + * available for future calls to guac_pool_next_int. + * + * @param pool The guac_pool to free the given integer into. + * @param value The integer which should be readded to the given pool, such that it can + * be received by a future call to guac_pool_next_int. + */ +void guac_pool_free_int(guac_pool* pool, int value); + +#endif + diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index ad0de776..da2e4a68 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -53,6 +53,7 @@ libguacinc_HEADERS = \ noinst_HEADERS = \ ../include/client-handlers.h \ ../include/palette.h \ + ../include/pool.h \ ../include/unicode.h libguac_la_SOURCES = \ From 0e63f8667daa59e756fd98506a968ac95aafc6db Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 11:20:18 -0700 Subject: [PATCH 265/330] Added stubbed pool.c, fixed typo in pool.h. --- libguac/include/pool.h | 2 +- libguac/src/Makefile.am | 1 + libguac/src/pool.c | 61 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 libguac/src/pool.c diff --git a/libguac/include/pool.h b/libguac/include/pool.h index 9300a0d7..07b5e933 100644 --- a/libguac/include/pool.h +++ b/libguac/include/pool.h @@ -86,7 +86,7 @@ struct guac_pool_int { * The next available (unused) guac_pool_int in the list of * allocated but free'd ints. */ - __guac_pool_int* __next; + guac_pool_int* __next; }; diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index da2e4a68..8fc5ab8f 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -63,6 +63,7 @@ libguac_la_SOURCES = \ instruction.c \ palette.c \ plugin.c \ + pool.c \ protocol.c \ socket.c \ timestamp.c \ diff --git a/libguac/src/pool.c b/libguac/src/pool.c new file mode 100644 index 00000000..f95dd51d --- /dev/null +++ b/libguac/src/pool.c @@ -0,0 +1,61 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include + +#include "pool.h" + +guac_pool* guac_pool_alloc(int size) { + + /* STUB */ + return NULL; + +} + +void guac_pool_free(guac_pool* pool) { + /* STUB */ +} + +int guac_pool_next_int(guac_pool* pool) { + /* STUB */ + return 0; +} + +void guac_pool_free_int(guac_pool* pool, int value) { + /* STUB */ +} + From 4444690400de3c61ef66a1512047637dca4d857d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 11:24:01 -0700 Subject: [PATCH 266/330] Implement guac_pool alloc and free. --- libguac/src/pool.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libguac/src/pool.c b/libguac/src/pool.c index f95dd51d..d8469ed5 100644 --- a/libguac/src/pool.c +++ b/libguac/src/pool.c @@ -36,18 +36,30 @@ * ***** END LICENSE BLOCK ***** */ #include +#include #include "pool.h" guac_pool* guac_pool_alloc(int size) { - /* STUB */ - return NULL; + guac_pool* pool = malloc(sizeof(guac_pool)); + + /* If unable to allocate, just return NULL. */ + if (pool == NULL) + return NULL; + + /* Initialize empty pool */ + pool->min_size = size; + pool->__next_value = 0; + pool->__head = NULL; + pool->__tail = NULL; + + return pool; } void guac_pool_free(guac_pool* pool) { - /* STUB */ + free(pool); } int guac_pool_next_int(guac_pool* pool) { From b9bbf0ae7ba5c548b0baf5469a9259ac963a0538 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 11:29:31 -0700 Subject: [PATCH 267/330] Implemented guac_pool_free_int. --- libguac/src/pool.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/libguac/src/pool.c b/libguac/src/pool.c index d8469ed5..f6873697 100644 --- a/libguac/src/pool.c +++ b/libguac/src/pool.c @@ -68,6 +68,21 @@ int guac_pool_next_int(guac_pool* pool) { } void guac_pool_free_int(guac_pool* pool, int value) { - /* STUB */ + + /* Allocate and initialize new returned value */ + guac_pool_int* pool_int = malloc(sizeof(guac_pool_int)); + pool_int->value = value; + pool_int->__next = NULL; + + /* If pool empty, store as sole entry. */ + if (pool->__tail == NULL) + pool->__head = pool->__tail = pool_int; + + /* Otherwise, append to end of pool. */ + else { + pool->__tail->__next = pool_int; + pool->__tail = pool_int; + } + } From e02b3e3a0e40270f90815ff380fd43605689d7a0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 11:53:37 -0700 Subject: [PATCH 268/330] Implement all pool functions. --- libguac/src/pool.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/libguac/src/pool.c b/libguac/src/pool.c index f6873697..153e913a 100644 --- a/libguac/src/pool.c +++ b/libguac/src/pool.c @@ -63,8 +63,32 @@ void guac_pool_free(guac_pool* pool) { } int guac_pool_next_int(guac_pool* pool) { - /* STUB */ - return 0; + + int value; + + /* If more integers are needed, or we are out of integers, return a new one. */ + if (pool->__head == NULL || pool->__next_value < pool->min_size) + return pool->__next_value++; + + /* Otherwise, remove first integer. */ + value = pool->__head->value; + + /* If only one element exists, reset pool to empty. */ + if (pool->__tail == pool->__head) { + free(pool->__head); + pool->__head = NULL; + pool->__tail = NULL; + } + + /* Otherwise, advance head. */ + else { + guac_pool_int* old_head = pool->__head; + pool->__head = old_head->__next; + free(old_head); + } + + /* Return retrieved value. */ + return value; } void guac_pool_free_int(guac_pool* pool, int value) { From 97ac78c1e595f2645dd14b053439319881ed97e6 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 19 Aug 2012 20:46:02 -0700 Subject: [PATCH 269/330] Added hash.c and hash.h, including a basic image hash function. --- libguac/include/hash.h | 57 ++++++++++++++++++++ libguac/src/Makefile.am | 2 + libguac/src/hash.c | 113 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 libguac/include/hash.h create mode 100644 libguac/src/hash.c diff --git a/libguac/include/hash.h b/libguac/include/hash.h new file mode 100644 index 00000000..8f7a8bfb --- /dev/null +++ b/libguac/include/hash.h @@ -0,0 +1,57 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#ifndef _GUAC_HASH_H +#define _GUAC_HASH_H + +#include + +/** + * Produces a 24-bit hash value from all pixels of the given surface. The + * surface provided must be RGB or ARGB with each pixel stored in 32 bits. + * The hashing algorithm used is a variant of the cyclic polynomial rolling + * hash. + * + * @param surface The Cairo surface to hash. + * @return An arbitrary 24-bit unsigned integer value intended to be well + * distributed across different images. + */ +int guac_hash_surface(cairo_surface_t* surface); + +#endif + diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index 8fc5ab8f..fdd595ed 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -42,6 +42,7 @@ libguacincdir = $(includedir)/guacamole libguacinc_HEADERS = \ ../include/client.h \ ../include/error.h \ + ../include/hash.h \ ../include/instruction.h \ ../include/layer.h \ ../include/plugin.h \ @@ -60,6 +61,7 @@ libguac_la_SOURCES = \ client.c \ client-handlers.c \ error.c \ + hash.c \ instruction.c \ palette.c \ plugin.c \ diff --git a/libguac/src/hash.c b/libguac/src/hash.c new file mode 100644 index 00000000..2ecf1961 --- /dev/null +++ b/libguac/src/hash.c @@ -0,0 +1,113 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#include +#include + +/* + * Arbitrary hash function whhich maps ALL 32-bit numbers onto 24-bit numbers + * evenly, while guaranteeing that all 24-bit numbers are mapped onto + * themselves. + */ +int _guac_hash_32to24(int value) { + + /* Grab highest-order byte */ + int upper = value & 0xFF000000; + + /* XOR upper with lower three bytes, truncate to 24-bit */ + return + (value & 0xFFFFFF) + ^ (upper >> 8) + ^ (upper >> 16) + ^ (upper >> 24); + +} + +/** + * Rotates a given 32-bit integer by N bits. + * + * NOTE: We probably should check for available bitops.h macros first. + */ +unsigned int _guac_rotate(unsigned int value, int amount) { + + /* amount = amount % 32 */ + amount &= 0x1F; + + /* Return rotated amount */ + return (value >> amount) | (value << (32 - amount)); + +} + +int guac_hash_surface(cairo_surface_t* surface) { + + /* Init to zero */ + int hash_value = 0; + + int x, y; + + /* Get image data and metrics */ + unsigned char* data = cairo_image_surface_get_data(surface); + int width = cairo_image_surface_get_width(surface); + int height = cairo_image_surface_get_height(surface); + int stride = cairo_image_surface_get_stride(surface); + + for (y=0; y Date: Sun, 19 Aug 2012 21:10:19 -0700 Subject: [PATCH 270/330] Fix signedness, fix hash size. --- libguac/include/hash.h | 2 +- libguac/src/hash.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libguac/include/hash.h b/libguac/include/hash.h index 8f7a8bfb..61115eb2 100644 --- a/libguac/include/hash.h +++ b/libguac/include/hash.h @@ -51,7 +51,7 @@ * @return An arbitrary 24-bit unsigned integer value intended to be well * distributed across different images. */ -int guac_hash_surface(cairo_surface_t* surface); +unsigned int guac_hash_surface(cairo_surface_t* surface); #endif diff --git a/libguac/src/hash.c b/libguac/src/hash.c index 2ecf1961..6b21e1e5 100644 --- a/libguac/src/hash.c +++ b/libguac/src/hash.c @@ -44,10 +44,10 @@ * evenly, while guaranteeing that all 24-bit numbers are mapped onto * themselves. */ -int _guac_hash_32to24(int value) { +unsigned int _guac_hash_32to24(unsigned int value) { /* Grab highest-order byte */ - int upper = value & 0xFF000000; + unsigned int upper = value & 0xFF000000; /* XOR upper with lower three bytes, truncate to 24-bit */ return @@ -73,10 +73,10 @@ unsigned int _guac_rotate(unsigned int value, int amount) { } -int guac_hash_surface(cairo_surface_t* surface) { +unsigned int guac_hash_surface(cairo_surface_t* surface) { /* Init to zero */ - int hash_value = 0; + unsigned int hash_value = 0; int x, y; @@ -95,19 +95,19 @@ int guac_hash_surface(cairo_surface_t* surface) { for (x=0; x Date: Sun, 19 Aug 2012 23:18:52 -0700 Subject: [PATCH 271/330] Add surface compare. --- libguac/include/hash.h | 2 ++ libguac/src/hash.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/libguac/include/hash.h b/libguac/include/hash.h index 61115eb2..4a4dc865 100644 --- a/libguac/include/hash.h +++ b/libguac/include/hash.h @@ -53,5 +53,7 @@ */ unsigned int guac_hash_surface(cairo_surface_t* surface); +int guac_surface_cmp(cairo_surface_t* a, cairo_surface_t* b); + #endif diff --git a/libguac/src/hash.c b/libguac/src/hash.c index 6b21e1e5..0fc8aaff 100644 --- a/libguac/src/hash.c +++ b/libguac/src/hash.c @@ -37,6 +37,7 @@ #include +#include #include /* @@ -111,3 +112,40 @@ unsigned int guac_hash_surface(cairo_surface_t* surface) { } +int guac_surface_cmp(cairo_surface_t* a, cairo_surface_t* b) { + + /* Surface A metrics */ + unsigned char* data_a = cairo_image_surface_get_data(a); + int width_a = cairo_image_surface_get_width(a); + int height_a = cairo_image_surface_get_height(a); + int stride_a = cairo_image_surface_get_stride(a); + + /* Surface B metrics */ + unsigned char* data_b = cairo_image_surface_get_data(b); + int width_b = cairo_image_surface_get_width(b); + int height_b = cairo_image_surface_get_height(b); + int stride_b = cairo_image_surface_get_stride(b); + + int y; + + /* If core dimensions differ, just compare those. Done. */ + if (width_a != width_b) return width_a - width_b; + if (height_a != height_b) return height_a - height_b; + + for (y=0; y Date: Mon, 20 Aug 2012 19:19:26 -0700 Subject: [PATCH 272/330] Add magic number to hash (prevent all pure-black or similarly-black images from hashing to same value universally). --- libguac/src/hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/src/hash.c b/libguac/src/hash.c index 0fc8aaff..225f0def 100644 --- a/libguac/src/hash.c +++ b/libguac/src/hash.c @@ -101,7 +101,7 @@ unsigned int guac_hash_surface(cairo_surface_t* surface) { /* Compute next hash */ hash_value = - _guac_rotate(hash_value, 1) ^ color; + _guac_rotate(hash_value, 1) ^ color ^ 0x1B872E69; } From eb450a6b3f375cd2bce733577bdb38599f7bbcb7 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 20 Aug 2012 19:38:20 -0700 Subject: [PATCH 273/330] Prototyped out part of indexed image support, added docs. --- libguac/include/hash.h | 96 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/libguac/include/hash.h b/libguac/include/hash.h index 4a4dc865..c17cc2b8 100644 --- a/libguac/include/hash.h +++ b/libguac/include/hash.h @@ -41,6 +41,91 @@ #include +/** + * A wrapper for a Cairo surface which allows fast image queries (linear time + * in the size of the query image). Given an arbitrary input image, the first + * occurence of that image within the contained surface can be found quickly. + */ +typedef struct guac_indexed_surface { + + /** + * The Cairo surface which is indexed. + */ + cairo_surface_t* surface; + +} guac_indexed_surface; + +typedef struct guac_indexed_surface_subimage { + + /** + * The indexed surface this subimage is a part of. + */ + guac_indexed_surface* surface; + + /** + * The X coordinate of the upper-left point of the rectangle + * of the subimage. + */ + int x; + + /** + * The Y coordinate of the upper-left point of the rectangle + * of the subimage. + */ + int y; + + /** + * The width of the subimage in pixels. + */ + int width; + + /** + * The height of the subimage in pixels. + */ + int height; + +} guac_indexed_surface_subimage; + +/** + * Creates a new indexed surface, using the given surface as the image data + * source. The given surface will be made searchable such that queries of + * images which are at least the given width and height can be resolved + * quickly. + * + * @param surface The Cairo surface to index. + * @param min_width The minimum image width to allow for queries. + * @param min_height The minimum image height to allow for queries. + * @return A newly allocated guac_indexed_surface. + */ +guac_indexed_surface* guac_indexed_surface_alloc(cairo_surface_t* surface, + int min_width, int min_height); + +/** + * Frees the given indexed surface. + * + * @param surface The guac_indexed_surface to free. + */ +void guac_indexed_surface_free(guac_indexed_surface* surface); + +/** + * Given an indexed surface and a query image, finds the rectangle of the + * subimage of the indexed surface containing exactly the query image (if + * any) and saves the result. + * + * @param surface The guac_indexed_surface to query. + * @param query The image to search for within the indexed surface. + * @param result A pointer to an already-allocated + * guac_indexed_surface_subimage which will be modified + * to contain the result if a result is found. + * @return Non-zero if the given query image was found within the indexed + * surface, in which case the result will be stored in the given + * guac_indexed_surface_subimage, or zero if the query image could + * not be found, in which case the given guac_indexed_surface_subimage + * will not be modified. + */ +int guac_indexed_surface_find(guac_indexed_surface* surface, + cairo_surface_t* query, guac_indexed_surface_subimage* result); + /** * Produces a 24-bit hash value from all pixels of the given surface. The * surface provided must be RGB or ARGB with each pixel stored in 32 bits. @@ -53,6 +138,17 @@ */ unsigned int guac_hash_surface(cairo_surface_t* surface); +/** + * Given two Cairo surfaces, returns zero if the data contained within each + * is identical, and a positive or negative value if the value of the first + * is found to be lexically greater or less than the second respectively. + * + * @param a The first Cairo surface to compare. + * @param b The Cairo surface to compare the first surface against. + * @return Zero if the data contained within each is identical, and a positive + * or negative value if the value of the first is found to be lexically + * greater or less than the second respectively. + */ int guac_surface_cmp(cairo_surface_t* a, cairo_surface_t* b); #endif From 98436072020f41869ee09a39ebc0a98f2468035f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 16:51:56 -0700 Subject: [PATCH 274/330] Add test for guac_pool. --- libguac/tests/Makefile.am | 15 +++-- libguac/tests/test_libguac.c | 2 + libguac/tests/util/guac_pool.c | 105 ++++++++++++++++++++++++++++++++ libguac/tests/util/util_suite.c | 71 +++++++++++++++++++++ libguac/tests/util/util_suite.h | 46 ++++++++++++++ 5 files changed, 233 insertions(+), 6 deletions(-) create mode 100644 libguac/tests/util/guac_pool.c create mode 100644 libguac/tests/util/util_suite.c create mode 100644 libguac/tests/util/util_suite.h diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index 435258d3..8a4d0254 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -41,18 +41,21 @@ AM_CFLAGS = -Werror -Wall -pedantic -I../include TESTS = test_libguac check_PROGRAMS = test_libguac -noinst_HEADERS = \ - protocol/suite.h \ - client/client_suite.h +noinst_HEADERS = \ + client/client_suite.h \ + protocol/suite.h \ + util/util_suite.h test_libguac_SOURCES = \ test_libguac.c \ + client/client_suite.c \ + client/buffer_pool.c \ + client/layer_pool.c \ protocol/suite.c \ protocol/instruction_read.c \ protocol/instruction_write.c \ - client/client_suite.c \ - client/buffer_pool.c \ - client/layer_pool.c + util/util_suite.c \ + util/guac_pool.c test_libguac_LDADD = $(top_builddir)/src/libguac.la @CUNIT_LIBS@ diff --git a/libguac/tests/test_libguac.c b/libguac/tests/test_libguac.c index 6549d73b..8648b9e9 100644 --- a/libguac/tests/test_libguac.c +++ b/libguac/tests/test_libguac.c @@ -39,6 +39,7 @@ #include "protocol/suite.h" #include "client/client_suite.h" +#include "util/util_suite.h" int main() { @@ -49,6 +50,7 @@ int main() { /* Register suites */ register_protocol_suite(); register_client_suite(); + register_util_suite(); /* Run tests */ CU_basic_set_mode(CU_BRM_VERBOSE); diff --git a/libguac/tests/util/guac_pool.c b/libguac/tests/util/guac_pool.c new file mode 100644 index 00000000..77783ac7 --- /dev/null +++ b/libguac/tests/util/guac_pool.c @@ -0,0 +1,105 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include + +#include "pool.h" +#include "util_suite.h" + +#define UNSEEN 0 +#define SEEN_PHASE_1 1 +#define SEEN_PHASE_2 2 + +#define POOL_SIZE 128 + +void test_guac_pool() { + + guac_pool* pool; + + int i; + int seen[POOL_SIZE] = {0}; + int value; + + /* Get pool */ + pool = guac_pool_alloc(POOL_SIZE); + CU_ASSERT_PTR_NOT_NULL_FATAL(pool); + + /* Fill pool */ + for (i=0; i= 0); + CU_ASSERT(value < POOL_SIZE); + + /* This should be an integer we have not seen yet */ + CU_ASSERT_EQUAL(UNSEEN, seen[value]); + seen[value] = SEEN_PHASE_1; + + /* Return value to pool */ + guac_pool_free_int(pool, value); + + } + + /* Now that pool is filled, we should get ONLY previously seen integers */ + for (i=0; i= 0); + CU_ASSERT(value < POOL_SIZE); + + /* This should be an integer we have seen already */ + CU_ASSERT_EQUAL(SEEN_PHASE_1, seen[value]); + seen[value] = SEEN_PHASE_2; + + } + + /* Pool is filled to minimum now. Next value should be size + 1. */ + value = guac_pool_next_int(pool); + + CU_ASSERT_EQUAL(POOL_SIZE+1, value); + + /* Free pool */ + guac_pool_free(pool); + +} + diff --git a/libguac/tests/util/util_suite.c b/libguac/tests/util/util_suite.c new file mode 100644 index 00000000..394f1dd3 --- /dev/null +++ b/libguac/tests/util/util_suite.c @@ -0,0 +1,71 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include + +#include "util_suite.h" + +int util_suite_init() { + return 0; +} + +int util_suite_cleanup() { + return 0; +} + +int register_util_suite() { + + /* Add util test suite */ + CU_pSuite suite = CU_add_suite("util", + util_suite_init, util_suite_cleanup); + if (suite == NULL) { + CU_cleanup_registry(); + return CU_get_error(); + } + + /* Add tests */ + if ( + CU_add_test(suite, "guac-pool", test_guac_pool) == NULL + ) { + CU_cleanup_registry(); + return CU_get_error(); + } + + return 0; + +} + diff --git a/libguac/tests/util/util_suite.h b/libguac/tests/util/util_suite.h new file mode 100644 index 00000000..ae7f3912 --- /dev/null +++ b/libguac/tests/util/util_suite.h @@ -0,0 +1,46 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_TEST_UTIL_SUITE_H +#define _GUAC_TEST_UTIL_SUITE_H + +int register_util_suite(); + +void test_guac_pool(); + +#endif + From 91d73c850fcf8d73aef3f88fcab132436a69cb46 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 16:52:39 -0700 Subject: [PATCH 275/330] Fix test. --- libguac/tests/util/guac_pool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/tests/util/guac_pool.c b/libguac/tests/util/guac_pool.c index 77783ac7..cd08e60a 100644 --- a/libguac/tests/util/guac_pool.c +++ b/libguac/tests/util/guac_pool.c @@ -93,10 +93,10 @@ void test_guac_pool() { } - /* Pool is filled to minimum now. Next value should be size + 1. */ + /* Pool is filled to minimum now. Next value should be equal to size. */ value = guac_pool_next_int(pool); - CU_ASSERT_EQUAL(POOL_SIZE+1, value); + CU_ASSERT_EQUAL(POOL_SIZE, value); /* Free pool */ guac_pool_free(pool); From d0bc7f2d7e84dcc196eaa4a13507c6fc2c8af08f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 17:54:58 -0700 Subject: [PATCH 276/330] Bounds checks in tests should be fatal assertions. --- libguac/tests/client/buffer_pool.c | 8 ++++---- libguac/tests/client/layer_pool.c | 8 ++++---- libguac/tests/util/guac_pool.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libguac/tests/client/buffer_pool.c b/libguac/tests/client/buffer_pool.c index 2cd5f07f..eaf54566 100644 --- a/libguac/tests/client/buffer_pool.c +++ b/libguac/tests/client/buffer_pool.c @@ -63,8 +63,8 @@ void test_buffer_pool() { /* Index should be within pool size */ CU_ASSERT_PTR_NOT_NULL_FATAL(layer); - CU_ASSERT(layer->index < 0); - CU_ASSERT(layer->index >= -GUAC_BUFFER_POOL_INITIAL_SIZE); + CU_ASSERT_FATAL(layer->index < 0); + CU_ASSERT_FATAL(layer->index >= -GUAC_BUFFER_POOL_INITIAL_SIZE); /* This should be a layer we have not seen yet */ CU_ASSERT_FALSE(seen[-layer->index - 1]); @@ -77,8 +77,8 @@ void test_buffer_pool() { /* Now that pool is filled, we should get a previously seen layer */ layer = guac_client_alloc_buffer(client); - CU_ASSERT(layer->index < 0); - CU_ASSERT(layer->index >= -GUAC_BUFFER_POOL_INITIAL_SIZE); + CU_ASSERT_FATAL(layer->index < 0); + CU_ASSERT_FATAL(layer->index >= -GUAC_BUFFER_POOL_INITIAL_SIZE); CU_ASSERT_TRUE(seen[-layer->index - 1]); /* Free client */ diff --git a/libguac/tests/client/layer_pool.c b/libguac/tests/client/layer_pool.c index 7727d85b..0a5b9b76 100644 --- a/libguac/tests/client/layer_pool.c +++ b/libguac/tests/client/layer_pool.c @@ -63,8 +63,8 @@ void test_layer_pool() { /* Index should be within pool size */ CU_ASSERT_PTR_NOT_NULL_FATAL(layer); - CU_ASSERT(layer->index > 0); - CU_ASSERT(layer->index <= GUAC_BUFFER_POOL_INITIAL_SIZE); + CU_ASSERT_FATAL(layer->index > 0); + CU_ASSERT_FATAL(layer->index <= GUAC_BUFFER_POOL_INITIAL_SIZE); /* This should be a layer we have not seen yet */ CU_ASSERT_FALSE(seen[layer->index - 1]); @@ -77,8 +77,8 @@ void test_layer_pool() { /* Now that pool is filled, we should get a previously seen layer */ layer = guac_client_alloc_layer(client); - CU_ASSERT(layer->index > 0); - CU_ASSERT(layer->index <= GUAC_BUFFER_POOL_INITIAL_SIZE); + CU_ASSERT_FATAL(layer->index > 0); + CU_ASSERT_FATAL(layer->index <= GUAC_BUFFER_POOL_INITIAL_SIZE); CU_ASSERT_TRUE(seen[layer->index - 1]); /* Free client */ diff --git a/libguac/tests/util/guac_pool.c b/libguac/tests/util/guac_pool.c index cd08e60a..c4fba37e 100644 --- a/libguac/tests/util/guac_pool.c +++ b/libguac/tests/util/guac_pool.c @@ -65,8 +65,8 @@ void test_guac_pool() { value = guac_pool_next_int(pool); /* Value should be within pool size */ - CU_ASSERT(value >= 0); - CU_ASSERT(value < POOL_SIZE); + CU_ASSERT_FATAL(value >= 0); + CU_ASSERT_FATAL(value < POOL_SIZE); /* This should be an integer we have not seen yet */ CU_ASSERT_EQUAL(UNSEEN, seen[value]); @@ -84,8 +84,8 @@ void test_guac_pool() { value = guac_pool_next_int(pool); /* Value should be within pool size */ - CU_ASSERT(value >= 0); - CU_ASSERT(value < POOL_SIZE); + CU_ASSERT_FATAL(value >= 0); + CU_ASSERT_FATAL(value < POOL_SIZE); /* This should be an integer we have seen already */ CU_ASSERT_EQUAL(SEEN_PHASE_1, seen[value]); From 6adce8bab07c3d740c8bed9ad77b2f53de61b7f7 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 17:55:24 -0700 Subject: [PATCH 277/330] Migrate to guac_pool for layer and buffer pools. --- libguac/include/client.h | 37 ++----------- libguac/include/layer.h | 11 ---- libguac/src/client.c | 116 +++++++-------------------------------- 3 files changed, 26 insertions(+), 138 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 9481ab5a..b1b481ee 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -43,6 +43,7 @@ #include "instruction.h" #include "layer.h" +#include "pool.h" #include "resource.h" #include "socket.h" #include "timestamp.h" @@ -352,42 +353,14 @@ struct guac_client { guac_client_log_handler* log_error_handler; /** - * The index of the next available buffer. + * Pool of buffer indices. */ - int __next_buffer_index; + guac_pool* __buffer_pool; /** - * The head pointer of the list of all available (allocated but not used) - * buffers. + * Pool of layer indices. */ - guac_layer* __available_buffers; - - /** - * Pointer to the last buffer in the list of all available buffers. - */ - guac_layer* __last_available_buffer; - - /** - * The index of the next available layer. - */ - int __next_layer_index; - - /** - * The head pointer of the list of all available (allocated but not used) - * layers. - */ - guac_layer* __available_layers; - - /** - * Pointer to the last layer in the list of all available layers. - */ - guac_layer* __last_available_layer; - - /** - * The head pointer of the list of all allocated layers, regardless of use - * status. - */ - guac_layer* __all_layers; + guac_pool* __layer_pool; }; diff --git a/libguac/include/layer.h b/libguac/include/layer.h index b02ec6e3..6e867b35 100644 --- a/libguac/include/layer.h +++ b/libguac/include/layer.h @@ -63,17 +63,6 @@ struct guac_layer { */ char* uri; - /** - * The next allocated layer in the list of all layers. - */ - guac_layer* __next; - - /** - * The next available (unused) layer in the list of - * allocated but free'd layers. - */ - guac_layer* __next_available; - }; #endif diff --git a/libguac/src/client.c b/libguac/src/client.c index 4466b342..0a771ffb 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -44,6 +44,7 @@ #include "error.h" #include "layer.h" #include "plugin.h" +#include "pool.h" #include "protocol.h" #include "socket.h" #include "time.h" @@ -51,43 +52,17 @@ guac_layer __GUAC_DEFAULT_LAYER = { .index = 0, .uri = "layer://0", - .__next = NULL, - .__next_available = NULL }; const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; guac_layer* guac_client_alloc_layer(guac_client* client) { - guac_layer* allocd_layer; - - /* If available layers, pop off first available layer */ - if (client->__next_layer_index > GUAC_BUFFER_POOL_INITIAL_SIZE && - client->__available_layers != NULL) { - - allocd_layer = client->__available_layers; - client->__available_layers = client->__available_layers->__next_available; - - /* If last layer, reset last available layer pointer */ - if (allocd_layer == client->__last_available_layer) - client->__last_available_layer = NULL; - - } - - /* If no available layer, allocate new layer, add to __all_layers list */ - else { - - /* Init new layer */ - allocd_layer = malloc(sizeof(guac_layer)); - allocd_layer->index = client->__next_layer_index++; - allocd_layer->uri = malloc(64); - snprintf(allocd_layer->uri, 64, "layer://%i", allocd_layer->index); - - /* Add to __all_layers list */ - allocd_layer->__next = client->__all_layers; - client->__all_layers = allocd_layer; - - } + /* Init new layer */ + guac_layer* allocd_layer = malloc(sizeof(guac_layer)); + allocd_layer->index = guac_pool_next_int(client->__layer_pool)+1; + allocd_layer->uri = malloc(64); + snprintf(allocd_layer->uri, 64, "layer://%i", allocd_layer->index); return allocd_layer; @@ -95,35 +70,11 @@ guac_layer* guac_client_alloc_layer(guac_client* client) { guac_layer* guac_client_alloc_buffer(guac_client* client) { - guac_layer* allocd_layer; - - /* If available layers, pop off first available buffer */ - if (client->__next_buffer_index < -GUAC_BUFFER_POOL_INITIAL_SIZE && - client->__available_buffers != NULL) { - - allocd_layer = client->__available_buffers; - client->__available_buffers = client->__available_buffers->__next_available; - - /* If last buffer, reset last available buffer pointer */ - if (allocd_layer == client->__last_available_buffer) - client->__last_available_buffer = NULL; - - } - - /* If no available buffer, allocate new buffer, add to __all_layers list */ - else { - - /* Init new layer */ - allocd_layer = malloc(sizeof(guac_layer)); - allocd_layer->index = client->__next_buffer_index--; - allocd_layer->uri = malloc(64); - snprintf(allocd_layer->uri, 64, "layer://%i", allocd_layer->index); - - /* Add to __all_layers list */ - allocd_layer->__next = client->__all_layers; - client->__all_layers = allocd_layer; - - } + /* Init new layer */ + guac_layer* allocd_layer = malloc(sizeof(guac_layer)); + allocd_layer->index = -guac_pool_next_int(client->__buffer_pool) - 1; + allocd_layer->uri = malloc(64); + snprintf(allocd_layer->uri, 64, "layer://%i", allocd_layer->index); return allocd_layer; @@ -131,29 +82,21 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { void guac_client_free_buffer(guac_client* client, guac_layer* layer) { - /* Add layer to tail of pool of available buffers */ - if (client->__last_available_buffer != NULL) - client->__last_available_buffer->__next_available = layer; + /* Release index to pool */ + guac_pool_free_int(client->__buffer_pool, -layer->index - 1); - if (client->__available_buffers == NULL) - client->__available_buffers = layer; - - client->__last_available_buffer = layer; - layer->__next_available = NULL; + /* Free layer */ + free(layer); } void guac_client_free_layer(guac_client* client, guac_layer* layer) { - /* Add layer to tail of pool of available layers */ - if (client->__last_available_layer != NULL) - client->__last_available_layer->__next_available = layer; + /* Release index to pool */ + guac_pool_free_int(client->__layer_pool, layer->index - 1); - if (client->__available_layers == NULL) - client->__available_layers = layer; - - client->__last_available_layer = layer; - layer->__next_available = NULL; + /* Free layer */ + free(layer); } @@ -175,12 +118,8 @@ guac_client* guac_client_alloc() { client->state = GUAC_CLIENT_RUNNING; - client->__all_layers = NULL; - client->__available_buffers = client->__last_available_buffer = NULL; - client->__available_layers = client->__last_available_layer = NULL; - - client->__next_buffer_index = -1; - client->__next_layer_index = 1; + client->__buffer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); + client->__layer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); return client; @@ -195,19 +134,6 @@ void guac_client_free(guac_client* client) { } - /* Free all layers */ - while (client->__all_layers != NULL) { - - /* Get layer, update layer pool head */ - guac_layer* layer = client->__all_layers; - client->__all_layers = layer->__next; - - /* Free layer */ - free(layer->uri); - free(layer); - - } - free(client); } From ac0d98518b86113b695beb7c04ff623ffcb7b607 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 17:56:50 -0700 Subject: [PATCH 278/330] pool.h must be installed (included by client.h which is installed) --- libguac/src/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index fdd595ed..750dd817 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -42,10 +42,11 @@ libguacincdir = $(includedir)/guacamole libguacinc_HEADERS = \ ../include/client.h \ ../include/error.h \ - ../include/hash.h \ + ../include/hash.h \ ../include/instruction.h \ ../include/layer.h \ ../include/plugin.h \ + ../include/pool.h \ ../include/protocol.h \ ../include/resource.h \ ../include/socket.h \ @@ -54,7 +55,6 @@ libguacinc_HEADERS = \ noinst_HEADERS = \ ../include/client-handlers.h \ ../include/palette.h \ - ../include/pool.h \ ../include/unicode.h libguac_la_SOURCES = \ From 5403bf7c3acab434bb283f4e43302626ef2abc9b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 19:57:19 -0700 Subject: [PATCH 279/330] Add resource pool to client. --- libguac/include/client.h | 30 ++++++++++++++++++++++++++++-- libguac/src/client.c | 7 +++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index b1b481ee..05d14172 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -134,6 +134,14 @@ typedef int guac_client_init_handler(guac_client* client, int argc, char** argv) */ #define GUAC_BUFFER_POOL_INITIAL_SIZE 1024 +/** + * The number of initial slots to allocate for resources within the client resource + * map. The client resource map maps resource indices to actual guac_resource instances. + * This map will need to be reallocated once the number of resources required exceeds + * the available number of slots. + */ +#define GUAC_RESOURCE_MAP_INITIAL_SIZE 1024 + /** * Possible current states of the Guacamole client. Currently, the only * two states are GUAC_CLIENT_RUNNING and GUAC_CLIENT_STOPPING. @@ -353,15 +361,33 @@ struct guac_client { guac_client_log_handler* log_error_handler; /** - * Pool of buffer indices. + * Pool of buffer indices. Buffers are simply layers with negative indices. Note that + * because guac_pool always gives non-negative indices starting at 0, the output of + * this guac_pool will be adjusted. */ guac_pool* __buffer_pool; /** - * Pool of layer indices. + * Pool of layer indices. Note that because guac_pool always gives non-negative indices + * starting at 0, the output of this guac_pool will be adjusted. */ guac_pool* __layer_pool; + /** + * Pool of server-side resource indices. + */ + guac_pool* __resource_pool; + + /** + * Array of all allocated resources. + */ + guac_resource** __resource_map; + + /** + * The number of elements in the __resource_map array. + */ + int __available_resource_slots; + }; /** diff --git a/libguac/src/client.c b/libguac/src/client.c index 0a771ffb..9dfe835e 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -118,9 +118,16 @@ guac_client* guac_client_alloc() { client->state = GUAC_CLIENT_RUNNING; + /* Allocate buffer and layer pools */ client->__buffer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); client->__layer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); + /* Allocate resource pool */ + client->__resource_pool = guac_pool_alloc(0); + client->__available_resource_slots = GUAC_RESOURCE_MAP_INITIAL_SIZE; + client->__resource_map = + malloc(sizeof(guac_resource*) * client->__available_resource_slots); + return client; } From a11469885469e321c9891a40367ac18323def1ad Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 20:08:15 -0700 Subject: [PATCH 280/330] Implement alloc/free for guac_resource. --- libguac/src/client.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/libguac/src/client.c b/libguac/src/client.c index 9dfe835e..db228f12 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -56,6 +56,29 @@ guac_layer __GUAC_DEFAULT_LAYER = { const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; +guac_resource* guac_client_alloc_resource(guac_client* client) { + + /* Init new layer */ + guac_resource* resource = malloc(sizeof(guac_resource)); + resource->index = guac_pool_next_int(client->__resource_pool); + resource->accept_handler = NULL; + resource->reject_handler = NULL; + resource->data = NULL; + + /* Resize resource map if necessary */ + if (resource->index >= client->__available_resource_slots) { + client->__available_resource_slots = resource->index * 2; + client->__resource_map = realloc(client->__resource_map, + sizeof(guac_resource*) * client->__available_resource_slots); + } + + /* Store resource in map */ + client->__resource_map[resource->index] = resource; + + return resource; + +} + guac_layer* guac_client_alloc_layer(guac_client* client) { /* Init new layer */ @@ -80,6 +103,16 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { } +void guac_client_free_resource(guac_client* client, guac_resource* resource) { + + /* Release index to pool */ + guac_pool_free_int(client->__resource_pool, resource->index); + + /* Free resource */ + free(resource); + +} + void guac_client_free_buffer(guac_client* client, guac_layer* layer) { /* Release index to pool */ From 54ef3f48fab710f4fc183c6e94768930eb165f5c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 20:20:34 -0700 Subject: [PATCH 281/330] Add unit test for resource pool. --- libguac/tests/Makefile.am | 1 + libguac/tests/client/client_suite.c | 1 + libguac/tests/client/client_suite.h | 1 + libguac/tests/client/resource_pool.c | 139 +++++++++++++++++++++++++++ 4 files changed, 142 insertions(+) create mode 100644 libguac/tests/client/resource_pool.c diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index 8a4d0254..fc49c680 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -51,6 +51,7 @@ test_libguac_SOURCES = \ client/client_suite.c \ client/buffer_pool.c \ client/layer_pool.c \ + client/resource_pool.c \ protocol/suite.c \ protocol/instruction_read.c \ protocol/instruction_write.c \ diff --git a/libguac/tests/client/client_suite.c b/libguac/tests/client/client_suite.c index b2c83c72..9834dec4 100644 --- a/libguac/tests/client/client_suite.c +++ b/libguac/tests/client/client_suite.c @@ -61,6 +61,7 @@ int register_client_suite() { if ( CU_add_test(suite, "layer-pool", test_layer_pool) == NULL || CU_add_test(suite, "buffer-pool", test_buffer_pool) == NULL + || CU_add_test(suite, "resource-pool", test_resource_pool) == NULL ) { CU_cleanup_registry(); return CU_get_error(); diff --git a/libguac/tests/client/client_suite.h b/libguac/tests/client/client_suite.h index 804c85dd..5415ebed 100644 --- a/libguac/tests/client/client_suite.h +++ b/libguac/tests/client/client_suite.h @@ -42,6 +42,7 @@ int register_client_suite(); void test_layer_pool(); void test_buffer_pool(); +void test_resource_pool(); #endif diff --git a/libguac/tests/client/resource_pool.c b/libguac/tests/client/resource_pool.c new file mode 100644 index 00000000..6f1d0f2b --- /dev/null +++ b/libguac/tests/client/resource_pool.c @@ -0,0 +1,139 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include + +#include "client.h" +#include "client_suite.h" + +void test_resource_pool() { + + guac_client* client; + guac_resource* resource0; + guac_resource* resource1; + guac_resource* resource2; + + /* Get client */ + client = guac_client_alloc(); + CU_ASSERT_PTR_NOT_NULL_FATAL(client); + + /* + * POOL: [ EMPTY ] + * IN USE: [ NONE ] + */ + + /* First resource should be resource 0 */ + resource0 = guac_client_alloc_resource(client); + CU_ASSERT_PTR_NOT_NULL_FATAL(resource0); + CU_ASSERT_EQUAL_FATAL(0, resource0->index); + + /* + * POOL: [ EMPTY ] + * IN USE: [ 0 ] + */ + + /* Put 0 back in pool (1) */ + guac_client_free_resource(client, resource0); + + /* + * POOL: [ 0 ] + * IN USE: [ NONE ] + */ + + /* Since we free'd 0, we should get 0 again here (1) */ + resource0 = guac_client_alloc_resource(client); + CU_ASSERT_PTR_NOT_NULL_FATAL(resource0); + CU_ASSERT_EQUAL_FATAL(0, resource0->index); + + /* + * POOL: [ EMPTY ] + * IN USE: [ 0 ] + */ + + /* We should get a new resource here */ + resource1 = guac_client_alloc_resource(client); + CU_ASSERT_PTR_NOT_NULL_FATAL(resource1); + CU_ASSERT_EQUAL_FATAL(1, resource1->index); + + /* + * POOL: [ EMPTY ] + * IN USE: [ 0 1 ] + */ + + /* Put 0 back in pool (2) */ + guac_client_free_resource(client, resource0); + + /* + * POOL: [ 0 ] + * IN USE: [ 1 ] + */ + + /* Since we free'd 0, we should get 0 again here (2) */ + resource0 = guac_client_alloc_resource(client); + CU_ASSERT_PTR_NOT_NULL_FATAL(resource0); + CU_ASSERT_EQUAL_FATAL(0, resource0->index); + + /* + * POOL: [ EMPTY ] + * IN USE: [ 0 1 ] + */ + + /* We should get a new resource here */ + resource2 = guac_client_alloc_resource(client); + CU_ASSERT_PTR_NOT_NULL_FATAL(resource2); + CU_ASSERT_EQUAL_FATAL(2, resource2->index); + + /* + * POOL: [ EMPTY ] + * IN USE: [ 0 1 2 ] + */ + + /* Free all resources */ + guac_client_free_resource(client, resource2); + guac_client_free_resource(client, resource1); + guac_client_free_resource(client, resource0); + + /* + * POOL: [ 0 1 2 ] + * IN USE: [ EMPTY ] + */ + + /* Free client */ + guac_client_free(client); + +} + From a38d59451d7773e5312d54d54fee84f77cfa2a89 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 20:23:03 -0700 Subject: [PATCH 282/330] Properly free pools in guac_client_free --- libguac/src/client.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libguac/src/client.c b/libguac/src/client.c index db228f12..34ebbbed 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -174,6 +174,14 @@ void guac_client_free(guac_client* client) { } + /* Free layer pools */ + guac_pool_free(client->__buffer_pool); + guac_pool_free(client->__layer_pool); + + /* Free resource pool */ + guac_pool_free(client->__resource_pool); + free(client->__resource_map); + free(client); } From c95931e687456b5b5218b3dd812349d98fd8a283 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 20:30:03 -0700 Subject: [PATCH 283/330] Add accept/reject instruction handler stubs. --- libguac/include/client-handlers.h | 14 ++++++++++++++ libguac/src/client-handlers.c | 12 ++++++++++++ 2 files changed, 26 insertions(+) diff --git a/libguac/include/client-handlers.h b/libguac/include/client-handlers.h index 7db42e6f..c48f12b8 100644 --- a/libguac/include/client-handlers.h +++ b/libguac/include/client-handlers.h @@ -106,6 +106,20 @@ int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction); */ int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction); +/** + * Internal initial handler for the accept instruction. When an accept instruction + * is received, this handler will be called. The accept handler of the corresponding + * resource will be called if the resource is valid and the handler is defined. + */ +int __guac_handle_accept(guac_client* client, guac_instruction* instruction); + +/** + * Internal initial handler for the reject instruction. When a reject instruction + * is received, this handler will be called. The reject handler of the corresponding + * resource will be called if the resource is valid and the handler is defined. + */ +int __guac_handle_reject(guac_client* client, guac_instruction* instruction); + /** * Instruction handler mapping table. This is a NULL-terminated array of * __guac_instruction_handler_mapping structures, each mapping an opcode diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index a6a144f3..f7397041 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -50,6 +50,8 @@ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { {"key", __guac_handle_key}, {"clipboard", __guac_handle_clipboard}, {"disconnect", __guac_handle_disconnect}, + {"accept", __guac_handle_accept}, + {"reject", __guac_handle_reject}, {NULL, NULL} }; @@ -120,3 +122,13 @@ int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction) return -1; } +int __guac_handle_accept(guac_client* client, guac_instruction* instruction) { + /* STUB */ + return -1; +} + +int __guac_handle_reject(guac_client* client, guac_instruction* instruction) { + /* STUB */ + return -1; +} + From f4f4e04e0e921ff653a67dac37c620d945317e82 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 6 Sep 2012 20:37:16 -0700 Subject: [PATCH 284/330] Call accept/reject handler of associated resource if resource is valid. --- libguac/src/client-handlers.c | 37 +++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index f7397041..459b6d47 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -123,12 +123,41 @@ int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction) } int __guac_handle_accept(guac_client* client, guac_instruction* instruction) { - /* STUB */ - return -1; + + /* Get index, check validity */ + int index = __guac_parse_int(instruction->argv[0]); + if (index < client->__available_resource_slots) { + + /* Build parameters */ + char* mimetype = instruction->argv[1]; + guac_resource* resource = client->__resource_map[index]; + + /* If accept handler defined, call it */ + if (resource->accept_handler) + return resource->accept_handler(resource, mimetype); + + } + + /* Ignore invalid indices */ + return 0; + } int __guac_handle_reject(guac_client* client, guac_instruction* instruction) { - /* STUB */ - return -1; + + /* Get index, check validity */ + int index = __guac_parse_int(instruction->argv[0]); + if (index < client->__available_resource_slots) { + + /* Build parameters */ + guac_resource* resource = client->__resource_map[index]; + + /* If reject handler defined, call it */ + if (resource->reject_handler) + return resource->reject_handler(resource); + + } + + return 0; } From ddf705ad26e354ba8dc28b986db8f5125d26266b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 20 Sep 2012 21:08:33 -0700 Subject: [PATCH 285/330] Fix newlines. --- libguac/include/resource.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/libguac/include/resource.h b/libguac/include/resource.h index 3663f29b..ad66551c 100644 --- a/libguac/include/resource.h +++ b/libguac/include/resource.h @@ -59,12 +59,15 @@ typedef struct guac_resource guac_resource; /** - * Handler which begins resource transfer when the client accepts an exposed resource. + * Handler which begins resource transfer when the client accepts an exposed + * resource. */ -typedef int guac_resource_accept_handler(guac_resource* resource, const char* mimetype); +typedef int guac_resource_accept_handler(guac_resource* resource, + const char* mimetype); /** - * Handler which cancels resource transfer when the client rejects an exposed resource. + * Handler which cancels resource transfer when the client rejects an exposed + * resource. */ typedef int guac_resource_reject_handler(guac_resource* resource); @@ -80,12 +83,14 @@ struct guac_resource { int index; /** - * Handler which will be called when this resource is accepted by the client. + * Handler which will be called when this resource is accepted by the + * client. */ guac_resource_accept_handler* accept_handler; /** - * Handler which will be called when this resource is rejected by the client. + * Handler which will be called when this resource is rejected by the + * client. */ guac_resource_reject_handler* reject_handler; From eabd17df648d5cf4a54b55df1d4b05b745749657 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 20 Sep 2012 23:56:25 -0700 Subject: [PATCH 286/330] Add parent client to resource. --- libguac/include/resource.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libguac/include/resource.h b/libguac/include/resource.h index ad66551c..612b5a0f 100644 --- a/libguac/include/resource.h +++ b/libguac/include/resource.h @@ -39,6 +39,8 @@ #ifndef _GUAC_RESOURCE_H #define _GUAC_RESOURCE_H +#include "client.h" + /** * Provides functions and structures required for handling resources. * @@ -94,6 +96,11 @@ struct guac_resource { */ guac_resource_reject_handler* reject_handler; + /** + * The client this resource was allocated for. + */ + guac_client* client; + /** * Arbitrary data associated with this resource. */ From 657b83808cfa787cac54359140cda0bec9eee90c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 18 Oct 2012 01:34:25 -0700 Subject: [PATCH 287/330] Removed resource subprotocol (in favor of protocol nesting). --- libguac/include/client-handlers.h | 14 --- libguac/include/client.h | 43 --------- libguac/include/layer.h | 7 -- libguac/include/protocol.h | 45 --------- libguac/include/resource.h | 111 --------------------- libguac/src/Makefile.am | 1 - libguac/src/client-handlers.c | 41 -------- libguac/src/client.c | 50 +--------- libguac/src/protocol.c | 62 ------------ libguac/tests/Makefile.am | 1 - libguac/tests/client/client_suite.c | 1 - libguac/tests/client/client_suite.h | 1 - libguac/tests/client/resource_pool.c | 139 --------------------------- 13 files changed, 1 insertion(+), 515 deletions(-) delete mode 100644 libguac/include/resource.h delete mode 100644 libguac/tests/client/resource_pool.c diff --git a/libguac/include/client-handlers.h b/libguac/include/client-handlers.h index c48f12b8..7db42e6f 100644 --- a/libguac/include/client-handlers.h +++ b/libguac/include/client-handlers.h @@ -106,20 +106,6 @@ int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction); */ int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction); -/** - * Internal initial handler for the accept instruction. When an accept instruction - * is received, this handler will be called. The accept handler of the corresponding - * resource will be called if the resource is valid and the handler is defined. - */ -int __guac_handle_accept(guac_client* client, guac_instruction* instruction); - -/** - * Internal initial handler for the reject instruction. When a reject instruction - * is received, this handler will be called. The reject handler of the corresponding - * resource will be called if the resource is valid and the handler is defined. - */ -int __guac_handle_reject(guac_client* client, guac_instruction* instruction); - /** * Instruction handler mapping table. This is a NULL-terminated array of * __guac_instruction_handler_mapping structures, each mapping an opcode diff --git a/libguac/include/client.h b/libguac/include/client.h index 05d14172..1c600c12 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -44,7 +44,6 @@ #include "instruction.h" #include "layer.h" #include "pool.h" -#include "resource.h" #include "socket.h" #include "timestamp.h" @@ -134,14 +133,6 @@ typedef int guac_client_init_handler(guac_client* client, int argc, char** argv) */ #define GUAC_BUFFER_POOL_INITIAL_SIZE 1024 -/** - * The number of initial slots to allocate for resources within the client resource - * map. The client resource map maps resource indices to actual guac_resource instances. - * This map will need to be reallocated once the number of resources required exceeds - * the available number of slots. - */ -#define GUAC_RESOURCE_MAP_INITIAL_SIZE 1024 - /** * Possible current states of the Guacamole client. Currently, the only * two states are GUAC_CLIENT_RUNNING and GUAC_CLIENT_STOPPING. @@ -373,21 +364,6 @@ struct guac_client { */ guac_pool* __layer_pool; - /** - * Pool of server-side resource indices. - */ - guac_pool* __resource_pool; - - /** - * Array of all allocated resources. - */ - guac_resource** __resource_map; - - /** - * The number of elements in the __resource_map array. - */ - int __available_resource_slots; - }; /** @@ -512,25 +488,6 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer); */ void guac_client_free_layer(guac_client* client, guac_layer* layer); -/** - * Allocates a new resource. An arbitrary index is automatically assigned - * if no existing resource index is available for use. - * - * @param client The proxy client to allocate the resource for. - * @return The next available resource, or a newly allocated resource. - */ -guac_resource* guac_client_alloc_resource(guac_client* client); - -/** - * Frees an existing resource, re-adding it to the client's resource - * pool, such that it can be reused by a subsequent call to - * guac_client_alloc_resource(). - * - * @param client The proxy client to free the resource for. - * @oaran resource The resource to return to the resource pool. - */ -void guac_client_free_resource(guac_client* client, guac_resource* resource); - /** * The default Guacamole client layer, layer 0. */ diff --git a/libguac/include/layer.h b/libguac/include/layer.h index 6e867b35..956a84e3 100644 --- a/libguac/include/layer.h +++ b/libguac/include/layer.h @@ -56,13 +56,6 @@ struct guac_layer { */ int index; - /** - * The URI which must be passed via a resource instruction to denote - * a resource related to this layer. This value is automatically set - * upon allocation. - */ - char* uri; - }; #endif diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 62ade022..6c4fca8c 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -41,7 +41,6 @@ #include #include "layer.h" -#include "resource.h" #include "socket.h" #include "timestamp.h" @@ -193,22 +192,6 @@ int guac_protocol_send_args(guac_socket* socket, const char** args); */ int guac_protocol_send_connect(guac_socket* socket, const char** args); -/** - * Sends a data instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param resource The resource associated with the data being sent. - * @param data The data to send. - * @param size The number of bytes from the beginning of the given buffer - * of data to send. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_data(guac_socket* socket, guac_resource* resource, - const unsigned char* data, size_t size); - /** * Sends a disconnect instruction over the given guac_socket connection. * @@ -220,18 +203,6 @@ int guac_protocol_send_data(guac_socket* socket, guac_resource* resource, */ int guac_protocol_send_disconnect(guac_socket* socket); -/** - * Sends an end instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param resource The resource being closed. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_end(guac_socket* socket, guac_resource* resource); - /** * Sends an error instruction over the given guac_socket connection. * @@ -244,22 +215,6 @@ int guac_protocol_send_end(guac_socket* socket, guac_resource* resource); */ int guac_protocol_send_error(guac_socket* socket, const char* error); -/** - * Sends a resource instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @param resource The resource being exposed. - * @param uri The URI this resource should be exposed to. - * @param mimetypes A NULL-terminated array of strings, where each string is - * an available mimetype. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_resource(guac_socket* socket, guac_resource* resource, - const char* uri, const char** mimetypes); - /** * Sends a set instruction over the given guac_socket connection. * diff --git a/libguac/include/resource.h b/libguac/include/resource.h deleted file mode 100644 index 612b5a0f..00000000 --- a/libguac/include/resource.h +++ /dev/null @@ -1,111 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -#ifndef _GUAC_RESOURCE_H -#define _GUAC_RESOURCE_H - -#include "client.h" - -/** - * Provides functions and structures required for handling resources. - * - * NOTE: The data and end instructions are currently implemented client-side - * only, and allocation of resources must ALWAYS be server-side. - * - * Each resource is mono-directional. Two resources must be allocated for - * bidirectional communication. - * - * Exposure of client-side resources to the server will be accomplished - * over the same protocol (resource -> accept/reject -> data -> end). The - * mono-directional nature of resources will allow the index spaces of - * client and server resources to be independent. - * - * @file resource.h - */ - -typedef struct guac_resource guac_resource; - -/** - * Handler which begins resource transfer when the client accepts an exposed - * resource. - */ -typedef int guac_resource_accept_handler(guac_resource* resource, - const char* mimetype); - -/** - * Handler which cancels resource transfer when the client rejects an exposed - * resource. - */ -typedef int guac_resource_reject_handler(guac_resource* resource); - -/** - * Represents a single resource which can be requested or exposed via - * the Guacamole protocol. - */ -struct guac_resource { - - /** - * The index of this resource. - */ - int index; - - /** - * Handler which will be called when this resource is accepted by the - * client. - */ - guac_resource_accept_handler* accept_handler; - - /** - * Handler which will be called when this resource is rejected by the - * client. - */ - guac_resource_reject_handler* reject_handler; - - /** - * The client this resource was allocated for. - */ - guac_client* client; - - /** - * Arbitrary data associated with this resource. - */ - void* data; - -}; - -#endif diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index 750dd817..241e98de 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -48,7 +48,6 @@ libguacinc_HEADERS = \ ../include/plugin.h \ ../include/pool.h \ ../include/protocol.h \ - ../include/resource.h \ ../include/socket.h \ ../include/timestamp.h diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index 459b6d47..a6a144f3 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -50,8 +50,6 @@ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { {"key", __guac_handle_key}, {"clipboard", __guac_handle_clipboard}, {"disconnect", __guac_handle_disconnect}, - {"accept", __guac_handle_accept}, - {"reject", __guac_handle_reject}, {NULL, NULL} }; @@ -122,42 +120,3 @@ int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction) return -1; } -int __guac_handle_accept(guac_client* client, guac_instruction* instruction) { - - /* Get index, check validity */ - int index = __guac_parse_int(instruction->argv[0]); - if (index < client->__available_resource_slots) { - - /* Build parameters */ - char* mimetype = instruction->argv[1]; - guac_resource* resource = client->__resource_map[index]; - - /* If accept handler defined, call it */ - if (resource->accept_handler) - return resource->accept_handler(resource, mimetype); - - } - - /* Ignore invalid indices */ - return 0; - -} - -int __guac_handle_reject(guac_client* client, guac_instruction* instruction) { - - /* Get index, check validity */ - int index = __guac_parse_int(instruction->argv[0]); - if (index < client->__available_resource_slots) { - - /* Build parameters */ - guac_resource* resource = client->__resource_map[index]; - - /* If reject handler defined, call it */ - if (resource->reject_handler) - return resource->reject_handler(resource); - - } - - return 0; -} - diff --git a/libguac/src/client.c b/libguac/src/client.c index 34ebbbed..259a959d 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -50,42 +50,16 @@ #include "time.h" guac_layer __GUAC_DEFAULT_LAYER = { - .index = 0, - .uri = "layer://0", + .index = 0 }; const guac_layer* GUAC_DEFAULT_LAYER = &__GUAC_DEFAULT_LAYER; -guac_resource* guac_client_alloc_resource(guac_client* client) { - - /* Init new layer */ - guac_resource* resource = malloc(sizeof(guac_resource)); - resource->index = guac_pool_next_int(client->__resource_pool); - resource->accept_handler = NULL; - resource->reject_handler = NULL; - resource->data = NULL; - - /* Resize resource map if necessary */ - if (resource->index >= client->__available_resource_slots) { - client->__available_resource_slots = resource->index * 2; - client->__resource_map = realloc(client->__resource_map, - sizeof(guac_resource*) * client->__available_resource_slots); - } - - /* Store resource in map */ - client->__resource_map[resource->index] = resource; - - return resource; - -} - guac_layer* guac_client_alloc_layer(guac_client* client) { /* Init new layer */ guac_layer* allocd_layer = malloc(sizeof(guac_layer)); allocd_layer->index = guac_pool_next_int(client->__layer_pool)+1; - allocd_layer->uri = malloc(64); - snprintf(allocd_layer->uri, 64, "layer://%i", allocd_layer->index); return allocd_layer; @@ -96,23 +70,11 @@ guac_layer* guac_client_alloc_buffer(guac_client* client) { /* Init new layer */ guac_layer* allocd_layer = malloc(sizeof(guac_layer)); allocd_layer->index = -guac_pool_next_int(client->__buffer_pool) - 1; - allocd_layer->uri = malloc(64); - snprintf(allocd_layer->uri, 64, "layer://%i", allocd_layer->index); return allocd_layer; } -void guac_client_free_resource(guac_client* client, guac_resource* resource) { - - /* Release index to pool */ - guac_pool_free_int(client->__resource_pool, resource->index); - - /* Free resource */ - free(resource); - -} - void guac_client_free_buffer(guac_client* client, guac_layer* layer) { /* Release index to pool */ @@ -155,12 +117,6 @@ guac_client* guac_client_alloc() { client->__buffer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); client->__layer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); - /* Allocate resource pool */ - client->__resource_pool = guac_pool_alloc(0); - client->__available_resource_slots = GUAC_RESOURCE_MAP_INITIAL_SIZE; - client->__resource_map = - malloc(sizeof(guac_resource*) * client->__available_resource_slots); - return client; } @@ -178,10 +134,6 @@ void guac_client_free(guac_client* client) { guac_pool_free(client->__buffer_pool); guac_pool_free(client->__layer_pool); - /* Free resource pool */ - guac_pool_free(client->__resource_pool); - free(client->__resource_map); - free(client); } diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 42fe5f9c..84344470 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -575,26 +575,6 @@ int guac_protocol_send_curve(guac_socket* socket, const guac_layer* layer, } -int guac_protocol_send_data(guac_socket* socket, guac_resource* resource, - const unsigned char* data, size_t size) { - - /* Calculate base64 length */ - int base64_length = (size + 2) / 3 * 4; - - /* Send base64-encoded data */ - return - guac_socket_write_string(socket, "4.data,") - || __guac_socket_write_length_int(socket, resource->index) - || guac_socket_write_string(socket, ",") - || guac_socket_write_int(socket, base64_length) - || guac_socket_write_string(socket, ".") - || guac_socket_write_base64(socket, data, size) - || guac_socket_flush_base64(socket) - || guac_socket_write_string(socket, ";"); - -} - - int guac_protocol_send_disconnect(guac_socket* socket) { return guac_socket_write_string(socket, "10.disconnect;"); } @@ -634,15 +614,6 @@ int guac_protocol_send_distort(guac_socket* socket, const guac_layer* layer, } -int guac_protocol_send_end(guac_socket* socket, guac_resource* resource) { - - return - guac_socket_write_string(socket, "3.end,") - || __guac_socket_write_length_int(socket, resource->index) - || guac_socket_write_string(socket, ";"); -} - - int guac_protocol_send_error(guac_socket* socket, const char* error) { return @@ -813,39 +784,6 @@ int guac_protocol_send_reset(guac_socket* socket, const guac_layer* layer) { } -int guac_protocol_send_resource(guac_socket* socket, guac_resource* resource, - const char* uri, const char** mimetypes) { - - /* Write resource header */ - if ( - guac_socket_write_string(socket, "8.resource,") - || __guac_socket_write_length_int(socket, resource->index) - || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_string(socket, uri) - ) - return -1; - - /* Write each mimetype */ - while (*mimetypes != NULL) { - - /* Write mimetype */ - if ( - guac_socket_write_string(socket, ",") - || __guac_socket_write_length_string(socket, *mimetypes) - ) - return -1; - - /* Next mimetype */ - mimetypes++; - - } - - /* Finish instruction */ - return guac_socket_write_string(socket, ";"); - -} - - int guac_protocol_send_set(guac_socket* socket, const guac_layer* layer, const char* name, const char* value) { diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index fc49c680..8a4d0254 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -51,7 +51,6 @@ test_libguac_SOURCES = \ client/client_suite.c \ client/buffer_pool.c \ client/layer_pool.c \ - client/resource_pool.c \ protocol/suite.c \ protocol/instruction_read.c \ protocol/instruction_write.c \ diff --git a/libguac/tests/client/client_suite.c b/libguac/tests/client/client_suite.c index 9834dec4..b2c83c72 100644 --- a/libguac/tests/client/client_suite.c +++ b/libguac/tests/client/client_suite.c @@ -61,7 +61,6 @@ int register_client_suite() { if ( CU_add_test(suite, "layer-pool", test_layer_pool) == NULL || CU_add_test(suite, "buffer-pool", test_buffer_pool) == NULL - || CU_add_test(suite, "resource-pool", test_resource_pool) == NULL ) { CU_cleanup_registry(); return CU_get_error(); diff --git a/libguac/tests/client/client_suite.h b/libguac/tests/client/client_suite.h index 5415ebed..804c85dd 100644 --- a/libguac/tests/client/client_suite.h +++ b/libguac/tests/client/client_suite.h @@ -42,7 +42,6 @@ int register_client_suite(); void test_layer_pool(); void test_buffer_pool(); -void test_resource_pool(); #endif diff --git a/libguac/tests/client/resource_pool.c b/libguac/tests/client/resource_pool.c deleted file mode 100644 index 6f1d0f2b..00000000 --- a/libguac/tests/client/resource_pool.c +++ /dev/null @@ -1,139 +0,0 @@ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is libguac. - * - * The Initial Developer of the Original Code is - * Michael Jumper. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include - -#include "client.h" -#include "client_suite.h" - -void test_resource_pool() { - - guac_client* client; - guac_resource* resource0; - guac_resource* resource1; - guac_resource* resource2; - - /* Get client */ - client = guac_client_alloc(); - CU_ASSERT_PTR_NOT_NULL_FATAL(client); - - /* - * POOL: [ EMPTY ] - * IN USE: [ NONE ] - */ - - /* First resource should be resource 0 */ - resource0 = guac_client_alloc_resource(client); - CU_ASSERT_PTR_NOT_NULL_FATAL(resource0); - CU_ASSERT_EQUAL_FATAL(0, resource0->index); - - /* - * POOL: [ EMPTY ] - * IN USE: [ 0 ] - */ - - /* Put 0 back in pool (1) */ - guac_client_free_resource(client, resource0); - - /* - * POOL: [ 0 ] - * IN USE: [ NONE ] - */ - - /* Since we free'd 0, we should get 0 again here (1) */ - resource0 = guac_client_alloc_resource(client); - CU_ASSERT_PTR_NOT_NULL_FATAL(resource0); - CU_ASSERT_EQUAL_FATAL(0, resource0->index); - - /* - * POOL: [ EMPTY ] - * IN USE: [ 0 ] - */ - - /* We should get a new resource here */ - resource1 = guac_client_alloc_resource(client); - CU_ASSERT_PTR_NOT_NULL_FATAL(resource1); - CU_ASSERT_EQUAL_FATAL(1, resource1->index); - - /* - * POOL: [ EMPTY ] - * IN USE: [ 0 1 ] - */ - - /* Put 0 back in pool (2) */ - guac_client_free_resource(client, resource0); - - /* - * POOL: [ 0 ] - * IN USE: [ 1 ] - */ - - /* Since we free'd 0, we should get 0 again here (2) */ - resource0 = guac_client_alloc_resource(client); - CU_ASSERT_PTR_NOT_NULL_FATAL(resource0); - CU_ASSERT_EQUAL_FATAL(0, resource0->index); - - /* - * POOL: [ EMPTY ] - * IN USE: [ 0 1 ] - */ - - /* We should get a new resource here */ - resource2 = guac_client_alloc_resource(client); - CU_ASSERT_PTR_NOT_NULL_FATAL(resource2); - CU_ASSERT_EQUAL_FATAL(2, resource2->index); - - /* - * POOL: [ EMPTY ] - * IN USE: [ 0 1 2 ] - */ - - /* Free all resources */ - guac_client_free_resource(client, resource2); - guac_client_free_resource(client, resource1); - guac_client_free_resource(client, resource0); - - /* - * POOL: [ 0 1 2 ] - * IN USE: [ EMPTY ] - */ - - /* Free client */ - guac_client_free(client); - -} - From cd23eac4ee4286c0c4ac995214ada2c5f533c9a1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 18 Oct 2012 20:46:17 -0700 Subject: [PATCH 288/330] Add stream structure. --- libguac/include/stream.h | 68 ++++++++++++++++++++++++++++++++++++++++ libguac/src/Makefile.am | 1 + 2 files changed, 69 insertions(+) create mode 100644 libguac/include/stream.h diff --git a/libguac/include/stream.h b/libguac/include/stream.h new file mode 100644 index 00000000..06dc7b45 --- /dev/null +++ b/libguac/include/stream.h @@ -0,0 +1,68 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_STREAM_H +#define _GUAC_STREAM_H + +/** + * Provides functions and structures required for allocating and using nested + * streams. + * + * @file layer.h + */ + +typedef struct guac_stream guac_stream; + +/** + * Represents a single nested stream within the Guacamole protocol. + */ +struct guac_stream { + + /** + * The index of this layer. + */ + int index; + + /** + * A guac_socket which writes to this stream. + */ + guac_socket* socket; + +}; + +#endif + diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index 241e98de..411b2780 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -49,6 +49,7 @@ libguacinc_HEADERS = \ ../include/pool.h \ ../include/protocol.h \ ../include/socket.h \ + ../include/stream.h \ ../include/timestamp.h noinst_HEADERS = \ From 31729bf62d0ac635f560a3240e6bd483c7865a0c Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 18 Oct 2012 20:57:11 -0700 Subject: [PATCH 289/330] Add pool and stream alloc/free. --- libguac/include/client.h | 36 +++++++++++++++++++++++++++++++----- libguac/src/client.c | 25 ++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index 1c600c12..d0255c28 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -45,6 +45,7 @@ #include "layer.h" #include "pool.h" #include "socket.h" +#include "stream.h" #include "timestamp.h" /** @@ -352,18 +353,24 @@ struct guac_client { guac_client_log_handler* log_error_handler; /** - * Pool of buffer indices. Buffers are simply layers with negative indices. Note that - * because guac_pool always gives non-negative indices starting at 0, the output of - * this guac_pool will be adjusted. + * Pool of buffer indices. Buffers are simply layers with negative indices. + * Note that because guac_pool always gives non-negative indices starting + * at 0, the output of this guac_pool will be adjusted. */ guac_pool* __buffer_pool; /** - * Pool of layer indices. Note that because guac_pool always gives non-negative indices - * starting at 0, the output of this guac_pool will be adjusted. + * Pool of layer indices. Note that because guac_pool always gives + * non-negative indices starting at 0, the output of this guac_pool will + * be adjusted. */ guac_pool* __layer_pool; + /** + * Pool of stream indices. + */ + guac_pool* __stream_pool; + }; /** @@ -488,6 +495,25 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer); */ void guac_client_free_layer(guac_client* client, guac_layer* layer); +/** + * Allocates a new stream. An arbitrary index is automatically assigned + * if no previously-allocated stream is available for use. + * + * @param client The proxy client to allocate the layer buffer for. + * @return The next available stream, or a newly allocated stream. + */ +guac_stream* guac_client_alloc_stream(guac_client* client); + +/** + * Returns the given stream to the pool of available streams, such that it + * can be reused by any subsequent call to guac_client_alloc_stream(). + * + * @param client The proxy client to return the buffer to. + * @param stream The stream to return to the pool of available stream. + */ +void guac_client_free_stream(guac_client* client, guac_stream* stream); + + /** * The default Guacamole client layer, layer 0. */ diff --git a/libguac/src/client.c b/libguac/src/client.c index 259a959d..814048b0 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -88,13 +88,33 @@ void guac_client_free_buffer(guac_client* client, guac_layer* layer) { void guac_client_free_layer(guac_client* client, guac_layer* layer) { /* Release index to pool */ - guac_pool_free_int(client->__layer_pool, layer->index - 1); + guac_pool_free_int(client->__layer_pool, layer->index); /* Free layer */ free(layer); } +guac_stream* guac_client_alloc_stream(guac_client* client) { + + /* Init new stream */ + guac_stream* allocd_stream = malloc(sizeof(guac_stream)); + allocd_stream->index = guac_pool_next_int(client->__stream_pool); + + return allocd_stream; + +} + +void guac_client_free_stream(guac_client* client, guac_stream* stream) { + + /* Release index to pool */ + guac_pool_free_int(client->__stream_pool, stream->index - 1); + + /* Free stream */ + free(stream); + +} + guac_client* guac_client_alloc() { /* Allocate new client */ @@ -117,6 +137,9 @@ guac_client* guac_client_alloc() { client->__buffer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); client->__layer_pool = guac_pool_alloc(GUAC_BUFFER_POOL_INITIAL_SIZE); + /* Allocate stream pool */ + client->__stream_pool = guac_pool_alloc(0); + return client; } From 2f169b2b69a6ed0f8e3f53a7b6220e39b7d42b43 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 00:19:54 -0700 Subject: [PATCH 290/330] Use handlers rather than hard file descriptor. Allow explicit alloc/free of socket. --- libguac/include/socket.h | 124 ++++++++++++++++++++++++++++++++------ libguac/src/instruction.c | 4 +- libguac/src/socket.c | 6 +- 3 files changed, 113 insertions(+), 21 deletions(-) diff --git a/libguac/include/socket.h b/libguac/include/socket.h index dbf745f1..f558f9a8 100644 --- a/libguac/include/socket.h +++ b/libguac/include/socket.h @@ -47,17 +47,71 @@ * @file socket.h */ +typedef struct guac_socket guac_socket; + +/** + * Generic read handler for socket read operations, modeled after the standard + * POSIX read() function. When set within a guac_socket, a handler of this type + * will be called when data needs to be read into the socket. + * + * @param socket The guac_socket being read from. + * @param buf The arbitrary buffer we must populate with data. + * @param count The maximum number of bytes to read into the buffer. + * @return The number of bytes read, or -1 if an error occurs. + */ +typedef ssize_t guac_socket_read_handler(guac_socket* socket, + void* buf, size_t count); + +/** + * Generic write handler for socket write operations, modeled after the standard + * POSIX write() function. When set within a guac_socket, a handler of this type + * will be called when data needs to be write into the socket. + * + * @param socket The guac_socket being written to. + * @param buf The arbitrary buffer containing data to be written. + * @param count The maximum number of bytes to write from the buffer. + * @return The number of bytes written, or -1 if an error occurs. + */ +typedef ssize_t guac_socket_write_handler(guac_socket* socket, + void* buf, size_t count); + +/** + * Generic handler for the closing of a socket, modeled after the standard + * POSIX close() function. When set within a guac_socket, a handler of this type + * will be called when the socket is closed. + * + * @param socket The guac_socket being closed. + * @return Zero on success, or -1 if an error occurs. + */ +typedef int guac_socket_free_handler(guac_socket* socket); /** * The core I/O object of Guacamole. guac_socket provides buffered input and * output as well as convenience methods for efficiently writing base64 data. */ -typedef struct guac_socket { +struct guac_socket { /** - * The file descriptor to be read from / written to. + * Arbitrary socket-specific data. */ - int fd; + void* data; + + /** + * Handler which will be called when data needs to be read from the socket. + */ + guac_socket_read_handler* read_handler; + + /** + * Handler which will be called whenever data is written to this socket. + * Note that because guac_socket automatically buffers written data, this + * handler might only get called when the socket is flushed. + */ + guac_socket_write_handler* write_handler; + + /** + * Handler which will be called when the socket is free'd (closed). + */ + guac_socket_free_handler* free_handler; /** * The number of bytes present in the base64 "ready" buffer. @@ -114,7 +168,23 @@ typedef struct guac_socket { */ char* __instructionbuf_elementv[64]; -} guac_socket; +}; + +/** + * Allocates a new, completely blank guac_socket. This guac_socket will do + * absolutely nothing when used unless its handlers are defined. + * + * @returns A newly-allocated guac_socket, or NULL if the guac_socket could + * not be allocated. + */ +guac_socket* guac_socket_alloc(); + +/** + * Frees the given guac_socket and all associated resources. + * + * @param socket The guac_socket to free. + */ +void guac_socket_free(guac_socket* socket); /** * Allocates and initializes a new guac_socket object with the given open @@ -161,11 +231,11 @@ ssize_t guac_socket_write_int(guac_socket* socket, int64_t i); ssize_t guac_socket_write_string(guac_socket* socket, const char* str); /** - * Writes the given binary data to the given guac_socket object as base64-encoded - * data. The data written may be buffered until the buffer is flushed + * Writes the given binary data to the given guac_socket object as base64- + * encoded data. The data written may be buffered until the buffer is flushed * automatically or manually. Beware that because base64 data is buffered - * on top of the write buffer already used, a call to guac_socket_flush_base64() must - * be made before non-base64 writes (or writes of an independent block of + * on top of the write buffer already used, a call to guac_socket_flush_base64() + * must be made before non-base64 writes (or writes of an independent block of * base64 data) can be made. * * If an error occurs while writing, a non-zero value is returned, and @@ -178,6 +248,35 @@ ssize_t guac_socket_write_string(guac_socket* socket, const char* str); */ ssize_t guac_socket_write_base64(guac_socket* socket, const void* buf, size_t count); +/** + * Writes the given data to the specified socket. The data written may be + * buffered until the buffer is flushed automatically or manually. + * + * If an error occurs while writing, a non-zero value is returned, and + * guac_error is set appropriately. + * + * @param socket The guac_socket object to write to. + * @param buf A buffer containing the data to write. + * @param count The number of bytes to write. + * @return Zero on success, or non-zero if an error occurs while writing. + */ +ssize_t guac_socket_write(guac_socket* socket, const void* buf, size_t count); + +/** + * Attempts to read data from the socket, filling up to the specified number + * of bytes in the given buffer. + * + * If an error occurs while writing, a non-zero value is returned, and + * guac_error is set appropriately. + * + * @param socket The guac_socket to read from. + * @param buf The buffer to read bytes into. + * @param count The maximum number of bytes to read. + * @return The number of bytes read, or non-zero if an error occurs while + * reading. + */ +ssize_t guac_socket_read(guac_socket* socket, const void* buf, size_t count); + /** * Flushes the base64 buffer, writing padding characters as necessary. * @@ -219,14 +318,5 @@ ssize_t guac_socket_flush(guac_socket* socket); */ int guac_socket_select(guac_socket* socket, int usec_timeout); -/** - * Frees resources allocated to the given guac_socket object. Note that this - * implicitly flush all buffers, but will NOT close the associated file - * descriptor. - * - * @param socket The guac_socket object to close. - */ -void guac_socket_close(guac_socket* socket); - #endif diff --git a/libguac/src/instruction.c b/libguac/src/instruction.c index 6073a69d..78724d64 100644 --- a/libguac/src/instruction.c +++ b/libguac/src/instruction.c @@ -50,8 +50,8 @@ int __guac_fill_instructionbuf(guac_socket* socket) { int retval; /* Attempt to fill buffer */ - retval = read( - socket->fd, + retval = guac_socket_read( + socket, socket->__instructionbuf + socket->__instructionbuf_used_length, socket->__instructionbuf_size - socket->__instructionbuf_used_length ); diff --git a/libguac/src/socket.c b/libguac/src/socket.c index bb35393f..cf1aa3e2 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -148,12 +148,14 @@ ssize_t guac_socket_write_string(guac_socket* socket, const char* str) { /* Flush when necessary, return on error */ if (socket->__written > 8188 /* sizeof(__out_buf) - 4 */) { - retval = __guac_socket_write(socket, __out_buf, socket->__written); + retval = socket->write_handler(socket, + __out_buf, socket->__written); if (retval < 0) return retval; socket->__written = 0; + } } @@ -193,7 +195,7 @@ ssize_t __guac_socket_write_base64_triplet(guac_socket* socket, int a, int b, in /* Flush when necessary, return on error */ if (socket->__written > 8188 /* sizeof(__out_buf) - 4 */) { - retval = __guac_socket_write(socket, __out_buf, socket->__written); + retval = socket->write_handler(socket, __out_buf, socket->__written); if (retval < 0) return retval; From b0921370916880e4b2d9ea80571b28741b2368b2 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 00:34:04 -0700 Subject: [PATCH 291/330] Add select handler, partial refactor. --- libguac/include/socket.h | 25 ++++++++++++++++++++++++ libguac/src/socket.c | 42 +++++++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/libguac/include/socket.h b/libguac/include/socket.h index f558f9a8..42e5c902 100644 --- a/libguac/include/socket.h +++ b/libguac/include/socket.h @@ -47,6 +47,12 @@ * @file socket.h */ +typedef struct guac_socket_fd_data { + + int fd; + +} guac_socket_fd_data; + typedef struct guac_socket guac_socket; /** @@ -75,6 +81,19 @@ typedef ssize_t guac_socket_read_handler(guac_socket* socket, typedef ssize_t guac_socket_write_handler(guac_socket* socket, void* buf, size_t count); +/** + * Generic handler for socket select operations, similar to the POSIX select() + * function. When guac_socket_select() is called on a guac_socket, its + * guac_socket_select_handler will be invoked, if defined. + * + * @param socket The guac_socket being selected. + * @param usec_timeout The maximum number of microseconds to wait for data, or + * -1 to potentially wait forever. + * @return Positive on success, zero if the timeout elapsed and no data is + * available, negative on error. + */ +typedef int guac_socket_select_handler(guac_socket* socket, int usec_timeout); + /** * Generic handler for the closing of a socket, modeled after the standard * POSIX close() function. When set within a guac_socket, a handler of this type @@ -108,6 +127,12 @@ struct guac_socket { */ guac_socket_write_handler* write_handler; + /** + * Handler which will be called whenever guac_socket_select is invoked + * on this socket. + */ + guac_socket_select_handler* select_handler; + /** * Handler which will be called when the socket is free'd (closed). */ diff --git a/libguac/src/socket.c b/libguac/src/socket.c index cf1aa3e2..138ba8b5 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -57,13 +57,14 @@ #include "error.h" char __guac_socket_BASE64_CHARACTERS[64] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' }; -guac_socket* guac_socket_open(int fd) { +guac_socket* guac_socket_alloc() { guac_socket* socket = malloc(sizeof(guac_socket)); @@ -76,7 +77,7 @@ guac_socket* guac_socket_open(int fd) { socket->__ready = 0; socket->__written = 0; - socket->fd = fd; + socket->data = NULL; /* Allocate instruction buffer */ socket->__instructionbuf_size = 1024; @@ -95,11 +96,33 @@ guac_socket* guac_socket_open(int fd) { socket->__instructionbuf_parse_start = 0; socket->__instructionbuf_elementc = 0; + /* No handlers yet */ + socket->read_handler = NULL; + socket->write_handler = NULL; + socket->select_handler = NULL; + socket->free_handler = NULL; + return socket; } -void guac_socket_close(guac_socket* socket) { +guac_socket* guac_socket_open(int fd) { + + /* Allocate socket and associated data */ + guac_socket* socket = guac_socket_alloc(); + guac_socket_fd_data* data = malloc(sizeof(guac_socket_fd_data)); + + /* Store file descriptor as socket data */ + data->fd = fd; + socket->data = data; + + /* FIXME: Set read/write/free handlers */ + + return socket; + +} + +void guac_socket_free(guac_socket* socket) { guac_socket_flush(socket); free(socket->__instructionbuf); free(socket); @@ -108,14 +131,15 @@ void guac_socket_close(guac_socket* socket) { /* Write bytes, limit rate */ ssize_t __guac_socket_write(guac_socket* socket, const char* buf, int count) { + guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; int retval; #ifdef __MINGW32__ /* MINGW32 WINSOCK only works with send() */ - retval = send(socket->fd, buf, count, 0); + retval = send(data->fd, buf, count, 0); #else /* Use write() for all other platforms */ - retval = write(socket->fd, buf, count); + retval = write(data->fd, buf, count); #endif /* Record errors in guac_error */ From 9444fdb234550b8973de67a11a838593cef43de2 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 00:45:29 -0700 Subject: [PATCH 292/330] Call select handler as needed, implement FD-based socket. --- libguac/src/socket.c | 143 ++++++++++++++++++++++++++----------------- 1 file changed, 86 insertions(+), 57 deletions(-) diff --git a/libguac/src/socket.c b/libguac/src/socket.c index 138ba8b5..1855c132 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -64,6 +64,82 @@ char __guac_socket_BASE64_CHARACTERS[64] = { '8', '9', '+', '/' }; +ssize_t __guac_socket_write(guac_socket* socket, + void* buf, size_t count) { + + /* If handler defined, call it. */ + if (socket->write_handler) + return socket->write_handler(socket, buf, count); + + /* Otherwise, pretend everything was written. */ + return count; + +} + +/* Write bytes, limit rate */ +ssize_t __guac_socket_fd_write_handler(guac_socket* socket, + void* buf, size_t count) { + + guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; + int retval; + +#ifdef __MINGW32__ + /* MINGW32 WINSOCK only works with send() */ + retval = send(data->fd, buf, count, 0); +#else + /* Use write() for all other platforms */ + retval = write(data->fd, buf, count); +#endif + + /* Record errors in guac_error */ + if (retval < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Error writing data to socket"; + } + + return retval; +} + + +int __guac_socket_fd_select_handler(guac_socket* socket, int usec_timeout) { + + guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; + + fd_set fds; + struct timeval timeout; + int retval; + + /* No timeout if usec_timeout is negative */ + if (usec_timeout < 0) + retval = select(data->fd + 1, &fds, NULL, NULL, NULL); + + /* Handle timeout if specified */ + else { + timeout.tv_sec = usec_timeout/1000000; + timeout.tv_usec = usec_timeout%1000000; + + FD_ZERO(&fds); + FD_SET(data->fd, &fds); + + retval = select(data->fd + 1, &fds, NULL, NULL, &timeout); + } + + /* Properly set guac_error */ + if (retval < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Error while waiting for data on socket"; + } + + if (retval == 0) { + guac_error = GUAC_STATUS_INPUT_TIMEOUT; + guac_error_message = "Timeout while waiting for data on socket"; + } + + return retval; + +} + + guac_socket* guac_socket_alloc() { guac_socket* socket = malloc(sizeof(guac_socket)); @@ -117,6 +193,7 @@ guac_socket* guac_socket_open(int fd) { socket->data = data; /* FIXME: Set read/write/free handlers */ + socket->write_handler = __guac_socket_fd_write_handler; return socket; @@ -128,29 +205,6 @@ void guac_socket_free(guac_socket* socket) { free(socket); } -/* Write bytes, limit rate */ -ssize_t __guac_socket_write(guac_socket* socket, const char* buf, int count) { - - guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; - int retval; - -#ifdef __MINGW32__ - /* MINGW32 WINSOCK only works with send() */ - retval = send(data->fd, buf, count, 0); -#else - /* Use write() for all other platforms */ - retval = write(data->fd, buf, count); -#endif - - /* Record errors in guac_error */ - if (retval < 0) { - guac_error = GUAC_STATUS_SEE_ERRNO; - guac_error_message = "Error writing data to socket"; - } - - return retval; -} - ssize_t guac_socket_write_int(guac_socket* socket, int64_t i) { char buffer[128]; @@ -172,8 +226,7 @@ ssize_t guac_socket_write_string(guac_socket* socket, const char* str) { /* Flush when necessary, return on error */ if (socket->__written > 8188 /* sizeof(__out_buf) - 4 */) { - retval = socket->write_handler(socket, - __out_buf, socket->__written); + retval = __guac_socket_write(socket, __out_buf, socket->__written); if (retval < 0) return retval; @@ -219,7 +272,7 @@ ssize_t __guac_socket_write_base64_triplet(guac_socket* socket, int a, int b, in /* Flush when necessary, return on error */ if (socket->__written > 8188 /* sizeof(__out_buf) - 4 */) { - retval = socket->write_handler(socket, __out_buf, socket->__written); + retval = __guac_socket_write(socket, __out_buf, socket->__written); if (retval < 0) return retval; @@ -281,7 +334,8 @@ ssize_t guac_socket_flush(guac_socket* socket) { /* Flush remaining bytes in buffer */ if (socket->__written > 0) { - retval = __guac_socket_write(socket, socket->__out_buf, socket->__written); + retval = __guac_socket_write(socket, + socket->__out_buf, socket->__written); if (retval < 0) return retval; @@ -310,37 +364,12 @@ ssize_t guac_socket_flush_base64(guac_socket* socket) { int guac_socket_select(guac_socket* socket, int usec_timeout) { - fd_set fds; - struct timeval timeout; - int retval; + /* Call select handler if defined */ + if (socket->select_handler) + return socket->select_handler(socket, usec_timeout); - /* No timeout if usec_timeout is negative */ - if (usec_timeout < 0) - retval = select(socket->fd + 1, &fds, NULL, NULL, NULL); - - /* Handle timeout if specified */ - else { - timeout.tv_sec = usec_timeout/1000000; - timeout.tv_usec = usec_timeout%1000000; - - FD_ZERO(&fds); - FD_SET(socket->fd, &fds); - - retval = select(socket->fd + 1, &fds, NULL, NULL, &timeout); - } - - /* Properly set guac_error */ - if (retval < 0) { - guac_error = GUAC_STATUS_SEE_ERRNO; - guac_error_message = "Error while waiting for data on socket"; - } - - if (retval == 0) { - guac_error = GUAC_STATUS_INPUT_TIMEOUT; - guac_error_message = "Timeout while waiting for data on socket"; - } - - return retval; + /* Otherwise, assume ready. */ + return 1; } From 208649306a56ceb237e70fd51903b988cf9359b9 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 00:46:08 -0700 Subject: [PATCH 293/330] Add select handler - still need read and free. --- libguac/src/socket.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libguac/src/socket.c b/libguac/src/socket.c index 1855c132..c795a630 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -193,7 +193,8 @@ guac_socket* guac_socket_open(int fd) { socket->data = data; /* FIXME: Set read/write/free handlers */ - socket->write_handler = __guac_socket_fd_write_handler; + socket->write_handler = __guac_socket_fd_write_handler; + socket->select_handler = __guac_socket_fd_select_handler; return socket; From d44ec4b2c17d0ef200dfcc01789c48ae35666d3e Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 12:07:49 -0700 Subject: [PATCH 294/330] Add read handler, call free handler when needed, add guac_socket_read. --- libguac/include/socket.h | 2 +- libguac/src/socket.c | 61 +++++++++++++++++++++++++++++++--------- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/libguac/include/socket.h b/libguac/include/socket.h index 42e5c902..26f25c44 100644 --- a/libguac/include/socket.h +++ b/libguac/include/socket.h @@ -300,7 +300,7 @@ ssize_t guac_socket_write(guac_socket* socket, const void* buf, size_t count); * @return The number of bytes read, or non-zero if an error occurs while * reading. */ -ssize_t guac_socket_read(guac_socket* socket, const void* buf, size_t count); +ssize_t guac_socket_read(guac_socket* socket, void* buf, size_t count); /** * Flushes the base64 buffer, writing padding characters as necessary. diff --git a/libguac/src/socket.c b/libguac/src/socket.c index c795a630..468eef67 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -76,7 +76,48 @@ ssize_t __guac_socket_write(guac_socket* socket, } -/* Write bytes, limit rate */ +/* TODO: Implement guac_socket_write (buffered write) */ + +ssize_t guac_socket_read(guac_socket* socket, void* buf, size_t count) { + + /* If handler defined, call it. */ + if (socket->read_handler) + return socket->read_handler(socket, buf, count); + + /* Otherwise, pretend nothing was read. */ + return 0; + +} + +int guac_socket_select(guac_socket* socket, int usec_timeout) { + + /* Call select handler if defined */ + if (socket->select_handler) + return socket->select_handler(socket, usec_timeout); + + /* Otherwise, assume ready. */ + return 1; + +} + +ssize_t __guac_socket_fd_read_handler(guac_socket* socket, + void* buf, size_t count) { + + guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; + + /* Read from socket */ + int retval = read(data->fd, buf, count); + + /* Record errors in guac_error */ + if (retval < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Error reading data from socket"; + } + + return retval; + +} + ssize_t __guac_socket_fd_write_handler(guac_socket* socket, void* buf, size_t count) { @@ -193,6 +234,7 @@ guac_socket* guac_socket_open(int fd) { socket->data = data; /* FIXME: Set read/write/free handlers */ + socket->read_handler = __guac_socket_fd_read_handler; socket->write_handler = __guac_socket_fd_write_handler; socket->select_handler = __guac_socket_fd_select_handler; @@ -201,6 +243,11 @@ guac_socket* guac_socket_open(int fd) { } void guac_socket_free(guac_socket* socket) { + + /* Call free handler if defined */ + if (socket->free_handler) + socket->free_handler(socket); + guac_socket_flush(socket); free(socket->__instructionbuf); free(socket); @@ -362,15 +409,3 @@ ssize_t guac_socket_flush_base64(guac_socket* socket) { } - -int guac_socket_select(guac_socket* socket, int usec_timeout) { - - /* Call select handler if defined */ - if (socket->select_handler) - return socket->select_handler(socket, usec_timeout); - - /* Otherwise, assume ready. */ - return 1; - -} - From f3384e8eb7be2c0d884c482350c2aa2d3ae0593b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 12:09:01 -0700 Subject: [PATCH 295/330] Update read/write tests to match API changes. --- libguac/tests/protocol/instruction_read.c | 2 +- libguac/tests/protocol/instruction_write.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/tests/protocol/instruction_read.c b/libguac/tests/protocol/instruction_read.c index ef65a0be..a4eb5720 100644 --- a/libguac/tests/protocol/instruction_read.c +++ b/libguac/tests/protocol/instruction_read.c @@ -114,7 +114,7 @@ void test_instruction_read() { CU_ASSERT_STRING_EQUAL(instruction->argv[1], "worldworldworld"); guac_instruction_free(instruction); - guac_socket_close(socket); + guac_socket_free(socket); } diff --git a/libguac/tests/protocol/instruction_write.c b/libguac/tests/protocol/instruction_write.c index 36a6838a..2592bb45 100644 --- a/libguac/tests/protocol/instruction_write.c +++ b/libguac/tests/protocol/instruction_write.c @@ -81,7 +81,7 @@ void test_instruction_write() { guac_protocol_send_sync(socket, 12345); guac_socket_flush(socket); - guac_socket_close(socket); + guac_socket_free(socket); exit(0); } From 563726174ad71433f5ccae8216c8f2ddf893e80a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 12:26:17 -0700 Subject: [PATCH 296/330] Remove fixme. --- libguac/src/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/src/socket.c b/libguac/src/socket.c index 468eef67..a5495ac1 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -233,7 +233,7 @@ guac_socket* guac_socket_open(int fd) { data->fd = fd; socket->data = data; - /* FIXME: Set read/write/free handlers */ + /* Set read/write handlers */ socket->read_handler = __guac_socket_fd_read_handler; socket->write_handler = __guac_socket_fd_write_handler; socket->select_handler = __guac_socket_fd_select_handler; From ffc6b389b8ad433f46b7ff4cd840b1488a969255 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 12:42:46 -0700 Subject: [PATCH 297/330] Move fd-specific code to socket-fd.c --- libguac/src/Makefile.am | 1 + libguac/src/socket-fd.c | 157 ++++++++++++++++++++++++++++++++++++++++ libguac/src/socket.c | 99 ------------------------- 3 files changed, 158 insertions(+), 99 deletions(-) create mode 100644 libguac/src/socket-fd.c diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index 411b2780..ff97dedb 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -68,6 +68,7 @@ libguac_la_SOURCES = \ pool.c \ protocol.c \ socket.c \ + socket-fd.c \ timestamp.c \ unicode.c diff --git a/libguac/src/socket-fd.c b/libguac/src/socket-fd.c new file mode 100644 index 00000000..ace37efc --- /dev/null +++ b/libguac/src/socket-fd.c @@ -0,0 +1,157 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * David PHAM-VAN Ulteo SAS - http://www.ulteo.com + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __MINGW32__ +#include +#else +#include +#endif + +#include +#include + +#include "socket.h" +#include "error.h" + +ssize_t __guac_socket_fd_read_handler(guac_socket* socket, + void* buf, size_t count) { + + guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; + + /* Read from socket */ + int retval = read(data->fd, buf, count); + + /* Record errors in guac_error */ + if (retval < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Error reading data from socket"; + } + + return retval; + +} + +ssize_t __guac_socket_fd_write_handler(guac_socket* socket, + void* buf, size_t count) { + + guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; + int retval; + +#ifdef __MINGW32__ + /* MINGW32 WINSOCK only works with send() */ + retval = send(data->fd, buf, count, 0); +#else + /* Use write() for all other platforms */ + retval = write(data->fd, buf, count); +#endif + + /* Record errors in guac_error */ + if (retval < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Error writing data to socket"; + } + + return retval; +} + + +int __guac_socket_fd_select_handler(guac_socket* socket, int usec_timeout) { + + guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; + + fd_set fds; + struct timeval timeout; + int retval; + + /* No timeout if usec_timeout is negative */ + if (usec_timeout < 0) + retval = select(data->fd + 1, &fds, NULL, NULL, NULL); + + /* Handle timeout if specified */ + else { + timeout.tv_sec = usec_timeout/1000000; + timeout.tv_usec = usec_timeout%1000000; + + FD_ZERO(&fds); + FD_SET(data->fd, &fds); + + retval = select(data->fd + 1, &fds, NULL, NULL, &timeout); + } + + /* Properly set guac_error */ + if (retval < 0) { + guac_error = GUAC_STATUS_SEE_ERRNO; + guac_error_message = "Error while waiting for data on socket"; + } + + if (retval == 0) { + guac_error = GUAC_STATUS_INPUT_TIMEOUT; + guac_error_message = "Timeout while waiting for data on socket"; + } + + return retval; + +} + +guac_socket* guac_socket_open(int fd) { + + /* Allocate socket and associated data */ + guac_socket* socket = guac_socket_alloc(); + guac_socket_fd_data* data = malloc(sizeof(guac_socket_fd_data)); + + /* Store file descriptor as socket data */ + data->fd = fd; + socket->data = data; + + /* Set read/write handlers */ + socket->read_handler = __guac_socket_fd_read_handler; + socket->write_handler = __guac_socket_fd_write_handler; + socket->select_handler = __guac_socket_fd_select_handler; + + return socket; + +} + diff --git a/libguac/src/socket.c b/libguac/src/socket.c index a5495ac1..050386a5 100644 --- a/libguac/src/socket.c +++ b/libguac/src/socket.c @@ -100,86 +100,6 @@ int guac_socket_select(guac_socket* socket, int usec_timeout) { } -ssize_t __guac_socket_fd_read_handler(guac_socket* socket, - void* buf, size_t count) { - - guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; - - /* Read from socket */ - int retval = read(data->fd, buf, count); - - /* Record errors in guac_error */ - if (retval < 0) { - guac_error = GUAC_STATUS_SEE_ERRNO; - guac_error_message = "Error reading data from socket"; - } - - return retval; - -} - -ssize_t __guac_socket_fd_write_handler(guac_socket* socket, - void* buf, size_t count) { - - guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; - int retval; - -#ifdef __MINGW32__ - /* MINGW32 WINSOCK only works with send() */ - retval = send(data->fd, buf, count, 0); -#else - /* Use write() for all other platforms */ - retval = write(data->fd, buf, count); -#endif - - /* Record errors in guac_error */ - if (retval < 0) { - guac_error = GUAC_STATUS_SEE_ERRNO; - guac_error_message = "Error writing data to socket"; - } - - return retval; -} - - -int __guac_socket_fd_select_handler(guac_socket* socket, int usec_timeout) { - - guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; - - fd_set fds; - struct timeval timeout; - int retval; - - /* No timeout if usec_timeout is negative */ - if (usec_timeout < 0) - retval = select(data->fd + 1, &fds, NULL, NULL, NULL); - - /* Handle timeout if specified */ - else { - timeout.tv_sec = usec_timeout/1000000; - timeout.tv_usec = usec_timeout%1000000; - - FD_ZERO(&fds); - FD_SET(data->fd, &fds); - - retval = select(data->fd + 1, &fds, NULL, NULL, &timeout); - } - - /* Properly set guac_error */ - if (retval < 0) { - guac_error = GUAC_STATUS_SEE_ERRNO; - guac_error_message = "Error while waiting for data on socket"; - } - - if (retval == 0) { - guac_error = GUAC_STATUS_INPUT_TIMEOUT; - guac_error_message = "Timeout while waiting for data on socket"; - } - - return retval; - -} - guac_socket* guac_socket_alloc() { @@ -223,25 +143,6 @@ guac_socket* guac_socket_alloc() { } -guac_socket* guac_socket_open(int fd) { - - /* Allocate socket and associated data */ - guac_socket* socket = guac_socket_alloc(); - guac_socket_fd_data* data = malloc(sizeof(guac_socket_fd_data)); - - /* Store file descriptor as socket data */ - data->fd = fd; - socket->data = data; - - /* Set read/write handlers */ - socket->read_handler = __guac_socket_fd_read_handler; - socket->write_handler = __guac_socket_fd_write_handler; - socket->select_handler = __guac_socket_fd_select_handler; - - return socket; - -} - void guac_socket_free(guac_socket* socket) { /* Call free handler if defined */ From 518903483d7a1123add420c5fb61b73ded433f97 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 13:45:06 -0700 Subject: [PATCH 298/330] Add nest instruction. --- libguac/include/protocol.h | 16 ++++++++++++++++ libguac/src/protocol.c | 11 +++++++++++ 2 files changed, 27 insertions(+) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 6c4fca8c..fc73394d 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -215,6 +215,22 @@ int guac_protocol_send_disconnect(guac_socket* socket); */ int guac_protocol_send_error(guac_socket* socket, const char* error); +/** + * Sends a nest instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param index The integer index of the stram to send the protocol + * data over. + * @param data A string containing protocol data, which must be UTF-8 + * encoded and null-terminated. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_nest(guac_socket* socket, int index, + const char* data); + /** * Sends a set instruction over the given guac_socket connection. * diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 84344470..eba527d7 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -715,6 +715,17 @@ int guac_protocol_send_name(guac_socket* socket, const char* name) { } +int guac_protocol_send_nest(guac_socket* socket, int index, + const char* data) { + + return + guac_socket_write_string(socket, "4.nest,") + || __guac_socket_write_length_int(socket, index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_string(socket, data) + || guac_socket_write_string(socket, ";"); + +} int guac_protocol_send_png(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface) { From 112360c4b166b4d3a5d62d9776106f858c32acc4 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 13:46:16 -0700 Subject: [PATCH 299/330] Move fd info struct to socket-fd.c --- libguac/include/socket.h | 6 ------ libguac/src/socket-fd.c | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libguac/include/socket.h b/libguac/include/socket.h index 26f25c44..3d1c6e60 100644 --- a/libguac/include/socket.h +++ b/libguac/include/socket.h @@ -47,12 +47,6 @@ * @file socket.h */ -typedef struct guac_socket_fd_data { - - int fd; - -} guac_socket_fd_data; - typedef struct guac_socket guac_socket; /** diff --git a/libguac/src/socket-fd.c b/libguac/src/socket-fd.c index ace37efc..970dcd2e 100644 --- a/libguac/src/socket-fd.c +++ b/libguac/src/socket-fd.c @@ -56,6 +56,12 @@ #include "socket.h" #include "error.h" +typedef struct guac_socket_fd_data { + + int fd; + +} guac_socket_fd_data; + ssize_t __guac_socket_fd_read_handler(guac_socket* socket, void* buf, size_t count) { From 014fc579ca9a18a64a6124047942baa8398788f1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 14:06:39 -0700 Subject: [PATCH 300/330] Add nested protocol socket. --- libguac/src/Makefile.am | 1 + libguac/src/socket-nest.c | 152 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 libguac/src/socket-nest.c diff --git a/libguac/src/Makefile.am b/libguac/src/Makefile.am index ff97dedb..340ab4c7 100644 --- a/libguac/src/Makefile.am +++ b/libguac/src/Makefile.am @@ -69,6 +69,7 @@ libguac_la_SOURCES = \ protocol.c \ socket.c \ socket-fd.c \ + socket-nest.c \ timestamp.c \ unicode.c diff --git a/libguac/src/socket-nest.c b/libguac/src/socket-nest.c new file mode 100644 index 00000000..2f06200d --- /dev/null +++ b/libguac/src/socket-nest.c @@ -0,0 +1,152 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * David PHAM-VAN Ulteo SAS - http://www.ulteo.com + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __MINGW32__ +#include +#else +#include +#endif + +#include +#include + +#include "socket.h" +#include "protocol.h" +#include "error.h" +#include "unicode.h" + +#define GUAC_SOCKET_NEST_BUFFER_SIZE 8192 + +typedef struct guac_socket_nest_data { + + guac_socket* parent; + char buffer[GUAC_SOCKET_NEST_BUFFER_SIZE]; + int index; + +} guac_socket_nest_data; + +ssize_t __guac_socket_nest_write_handler(guac_socket* socket, + void* buf, size_t count) { + + guac_socket_nest_data* data = (guac_socket_nest_data*) socket->data; + unsigned char* source = (unsigned char*) buf; + + /* Current location in destination buffer during copy */ + char* current = data->buffer; + + /* Number of bytes remaining in source buffer */ + int remaining = count; + + /* If we can't actually store that many bytes, reduce number of bytes + * expected to be written */ + if (remaining > GUAC_SOCKET_NEST_BUFFER_SIZE) + remaining = GUAC_SOCKET_NEST_BUFFER_SIZE; + + /* Current offset within destination buffer */ + int offset; + + /* Number of characters before start of next character */ + int skip = 0; + + /* Copy UTF-8 characters into buffer */ + for (offset = 0; offset < GUAC_SOCKET_NEST_BUFFER_SIZE; offset++) { + + /* Get next byte */ + unsigned char c = *source; + remaining--; + + /* If skipping, then skip */ + if (skip > 0) skip--; + + /* Otherwise, determine next skip value, and increment length */ + else { + + /* Determine skip value (size in bytes of rest of character) */ + skip = guac_utf8_charsize(c) - 1; + + /* If not enough bytes to complete character, break */ + if (skip > remaining) + break; + + } + + /* Store byte */ + *current = c; + + /* Advance to next character */ + source++; + current++; + + } + + /* Append null-terminator */ + *current = 0; + + /* Send nest instruction containing read UTF-8 segment */ + guac_protocol_send_nest(data->parent, data->index, data->buffer); + + /* Return number of bytes actually written */ + return offset; + +} + +guac_socket* guac_socket_nest(guac_socket* parent, int index) { + + /* Allocate socket and associated data */ + guac_socket* socket = guac_socket_alloc(); + guac_socket_nest_data* data = malloc(sizeof(guac_socket_nest_data)); + + /* Store file descriptor as socket data */ + data->parent = parent; + socket->data = data; + + /* Set write handler */ + socket->write_handler = __guac_socket_nest_write_handler; + + return socket; + +} + From e04533c29905780c4a8897e0e3236dfb982d9953 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 14:17:57 -0700 Subject: [PATCH 301/330] Add missing declaration for guac_socket_nest. --- libguac/include/socket.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libguac/include/socket.h b/libguac/include/socket.h index 3d1c6e60..a9085bfd 100644 --- a/libguac/include/socket.h +++ b/libguac/include/socket.h @@ -219,6 +219,22 @@ void guac_socket_free(guac_socket* socket); */ guac_socket* guac_socket_open(int fd); +/** + * Allocates and initializes a new guac_socket which writes all data via + * nest instructions to the given existing, open guac_socket. + * + * If an error occurs while allocating the guac_socket object, NULL is returned, + * and guac_error is set appropriately. + * + * @param parent The guac_socket this new guac_socket should write nest + * instructions to. + * @param index The stream index to use for the written nest instructions. + * @return A newly allocated guac_socket object associated with the given + * guac_socket and stream index, or NULL if an error occurs while + * allocating the guac_socket object. + */ +guac_socket* guac_socket_nest(guac_socket* parent, int index); + /** * Writes the given unsigned int to the given guac_socket object. The data * written may be buffered until the buffer is flushed automatically or From 4ae92fa62dec7c71b08bcec27e5641a3f5eb2c3d Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 14:18:09 -0700 Subject: [PATCH 302/330] Implement test for nested sockets. --- libguac/tests/Makefile.am | 1 + libguac/tests/protocol/nest_write.c | 126 ++++++++++++++++++++++++++++ libguac/tests/protocol/suite.c | 1 + libguac/tests/protocol/suite.h | 1 + 4 files changed, 129 insertions(+) create mode 100644 libguac/tests/protocol/nest_write.c diff --git a/libguac/tests/Makefile.am b/libguac/tests/Makefile.am index 8a4d0254..6712e6cd 100644 --- a/libguac/tests/Makefile.am +++ b/libguac/tests/Makefile.am @@ -54,6 +54,7 @@ test_libguac_SOURCES = \ protocol/suite.c \ protocol/instruction_read.c \ protocol/instruction_write.c \ + protocol/nest_write.c \ util/util_suite.c \ util/guac_pool.c diff --git a/libguac/tests/protocol/nest_write.c b/libguac/tests/protocol/nest_write.c new file mode 100644 index 00000000..bc0d6439 --- /dev/null +++ b/libguac/tests/protocol/nest_write.c @@ -0,0 +1,126 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include + +#include "error.h" +#include "instruction.h" +#include "protocol.h" +#include "socket.h" + +#include "suite.h" + +void test_nest_write() { + + int rfd, wfd; + int fd[2], childpid; + + /* Create pipe */ + CU_ASSERT_EQUAL_FATAL(pipe(fd), 0); + + /* File descriptors */ + rfd = fd[0]; + wfd = fd[1]; + + /* Fork */ + if ((childpid = fork()) == -1) { + /* ERROR */ + perror("fork"); + return; + } + + /* Child (pipe writer) */ + if (childpid != 0) { + + guac_socket* nested_socket; + guac_socket* socket; + + close(rfd); + + /* Open guac socket */ + socket = guac_socket_open(wfd); + + /* Nest socket */ + nested_socket = guac_socket_nest(socket, 0); + + /* Write instruction */ + guac_protocol_send_clipboard(nested_socket, "a" UTF8_4 "b" UTF8_4 "c"); + guac_protocol_send_sync(nested_socket, 12345); + guac_socket_flush(nested_socket); + guac_socket_flush(socket); + + guac_socket_free(nested_socket); + guac_socket_free(socket); + exit(0); + } + + /* Parent (unit test) */ + else { + + char expected[] = + "4.nest,1.0,33." + "9.clipboard,11.a" UTF8_4 "b" UTF8_4 "c;" + "4.sync,5.12345;" + ";"; + + int numread; + char buffer[1024]; + int offset = 0; + + close(wfd); + + /* Read everything available into buffer */ + while ((numread = + read(rfd, + &(buffer[offset]), + sizeof(buffer)-offset)) != 0) { + offset += numread; + } + + /* Add NULL terminator */ + buffer[offset] = '\0'; + + /* Read value should be equal to expected value */ + CU_ASSERT_STRING_EQUAL(buffer, expected); + + } + +} + diff --git a/libguac/tests/protocol/suite.c b/libguac/tests/protocol/suite.c index 6c7cca25..925433c7 100644 --- a/libguac/tests/protocol/suite.c +++ b/libguac/tests/protocol/suite.c @@ -61,6 +61,7 @@ int register_protocol_suite() { if ( CU_add_test(suite, "instruction-read", test_instruction_read) == NULL || CU_add_test(suite, "instruction-write", test_instruction_write) == NULL + || CU_add_test(suite, "nest-write", test_nest_write) == NULL ) { CU_cleanup_registry(); return CU_get_error(); diff --git a/libguac/tests/protocol/suite.h b/libguac/tests/protocol/suite.h index 7e8b5b8c..f05d2c1f 100644 --- a/libguac/tests/protocol/suite.h +++ b/libguac/tests/protocol/suite.h @@ -50,6 +50,7 @@ int register_protocol_suite(); void test_instruction_read(); void test_instruction_write(); +void test_nest_write(); #endif From 9d8d0650f508f672e9b3830f1b471322e81b6142 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 14:21:15 -0700 Subject: [PATCH 303/330] Fix expected string for nest test. --- libguac/tests/protocol/nest_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/tests/protocol/nest_write.c b/libguac/tests/protocol/nest_write.c index bc0d6439..a360560f 100644 --- a/libguac/tests/protocol/nest_write.c +++ b/libguac/tests/protocol/nest_write.c @@ -95,7 +95,7 @@ void test_nest_write() { else { char expected[] = - "4.nest,1.0,33." + "4.nest,1.0,42." "9.clipboard,11.a" UTF8_4 "b" UTF8_4 "c;" "4.sync,5.12345;" ";"; From fe30cd3073bc478b1dfb3073c380c4598be2dc64 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 19 Oct 2012 14:24:03 -0700 Subject: [PATCH 304/330] Handle nested socket within stream alloc/free. --- libguac/src/client.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libguac/src/client.c b/libguac/src/client.c index 814048b0..cf96e428 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -101,6 +101,12 @@ guac_stream* guac_client_alloc_stream(guac_client* client) { guac_stream* allocd_stream = malloc(sizeof(guac_stream)); allocd_stream->index = guac_pool_next_int(client->__stream_pool); + /* Nest socket */ + allocd_stream->socket = guac_socket_nest( + client->socket, + allocd_stream->index + ); + return allocd_stream; } @@ -109,6 +115,9 @@ void guac_client_free_stream(guac_client* client, guac_stream* stream) { /* Release index to pool */ guac_pool_free_int(client->__stream_pool, stream->index - 1); + + /* Release socket */ + guac_socket_free(stream->socket); /* Free stream */ free(stream); From 875c2108e868f604c71caa5f3f8b46edeab1b901 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 21 Oct 2012 14:52:00 -0700 Subject: [PATCH 305/330] Add size/video/audio instruction handlers. --- libguac/include/client-handlers.h | 21 ++++++++++ libguac/include/client.h | 67 +++++++++++++++++++++++++++++++ libguac/src/client-handlers.c | 31 ++++++++++++++ 3 files changed, 119 insertions(+) diff --git a/libguac/include/client-handlers.h b/libguac/include/client-handlers.h index 7db42e6f..cb1ddca4 100644 --- a/libguac/include/client-handlers.h +++ b/libguac/include/client-handlers.h @@ -99,6 +99,27 @@ int __guac_handle_key(guac_client* client, guac_instruction* instruction); */ int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction); +/** + * Internal initial handler for the size instruction. When a size instruction + * is received, this handler will be called. The client's size handler will + * be invoked if defined. + */ +int __guac_handle_size(guac_client* client, guac_instruction* instruction); + +/** + * Internal initial handler for the video instruction. When a video instruction + * is received, this handler will be called. The client's video handler will + * be invoked if defined. + */ +int __guac_handle_video(guac_client* client, guac_instruction* instruction); + +/** + * Internal initial handler for the audio instruction. When a audio instruction + * is received, this handler will be called. The client's audio handler will + * be invoked if defined. + */ +int __guac_handle_audio(guac_client* client, guac_instruction* instruction); + /** * Internal initial handler for the disconnect instruction. When a disconnect instruction * is received, this handler will be called. Disconnect instructions are automatically diff --git a/libguac/include/client.h b/libguac/include/client.h index d0255c28..3b52fa42 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -77,6 +77,22 @@ typedef int guac_client_key_handler(guac_client* client, int keysym, int pressed */ typedef int guac_client_clipboard_handler(guac_client* client, char* copied); +/** + * Handler for Guacamole screen size events. + */ +typedef int guac_client_size_handler(guac_client* client, + int width, int height); + +/** + * Handler for Guacamole audio format events. + */ +typedef int guac_client_audio_handler(guac_client* client, char* mimetype); + +/** + * Handler for Guacamole video format events. + */ +typedef int guac_client_video_handler(guac_client* client, char* mimetype); + /** * Handler for freeing up any extra data allocated by the client * implementation. @@ -280,6 +296,57 @@ struct guac_client { */ guac_client_clipboard_handler* clipboard_handler; + /** + * Handler for size events sent by the Guacamole web-client. + * + * The handler takes an integer width and integer height, representing + * the current visible screen area of the client. + * + * Example: + * @code + * int size_handler(guac_client* client, int width, int height); + * + * int guac_client_init(guac_client* client, int argc, char** argv) { + * client->size_handler = size_handler; + * } + * @endcode + */ + guac_client_size_handler* size_handler; + + /** + * Handler for audio format events sent by the Guacamole web-client. + * + * The handler takes the mimetype of the audio format being advertised + * as supported by the client. + * + * Example: + * @code + * int audio_handler(guac_client* client, char* mimetype); + * + * int guac_client_init(guac_client* client, int argc, char** argv) { + * client->audio_handler = audio_handler; + * } + * @endcode + */ + guac_client_audio_handler* audio_handler; + + /** + * Handler for video format events sent by the Guacamole web-client. + * + * The handler takes the mimetype of the video format being advertised + * as supported by the client. + * + * Example: + * @code + * int video_handler(guac_client* client, char* mimetype); + * + * int guac_client_init(guac_client* client, int argc, char** argv) { + * client->video_handler = video_handler; + * } + * @endcode + */ + guac_client_video_handler* video_handler; + /** * Handler for freeing data when the client is being unloaded. * diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index a6a144f3..494081ad 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -50,6 +50,9 @@ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { {"key", __guac_handle_key}, {"clipboard", __guac_handle_clipboard}, {"disconnect", __guac_handle_disconnect}, + {"size", __guac_handle_size}, + {"audio", __guac_handle_audio}, + {"video", __guac_handle_video}, {NULL, NULL} }; @@ -115,6 +118,34 @@ int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction) return 0; } +int __guac_handle_size(guac_client* client, guac_instruction* instruction) { + if (client->size_handler) + return client->size_handler( + client, + atoi(instruction->argv[0]), /* width */ + atoi(instruction->argv[1]) /* height */ + ); + return 0; +} + +int __guac_handle_video(guac_client* client, guac_instruction* instruction) { + if (client->video_handler) + return client->video_handler( + client, + instruction->argv[0] /* mimetype */ + ); + return 0; +} + +int __guac_handle_audio(guac_client* client, guac_instruction* instruction) { + if (client->audio_handler) + return client->audio_handler( + client, + instruction->argv[0] /* mimetype */ + ); + return 0; +} + int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction) { /* Return error code to force disconnect */ return -1; From fbf61fe81d9e5dc9c0f14fb65e171bf85f972370 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 21 Oct 2012 23:06:54 -0700 Subject: [PATCH 306/330] Add begin instruction, to be sent after connection succeeds. --- libguac/include/protocol.h | 11 +++++++++++ libguac/src/protocol.c | 3 +++ 2 files changed, 14 insertions(+) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index fc73394d..a525ddab 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -180,6 +180,17 @@ typedef enum guac_line_join_style { */ int guac_protocol_send_args(guac_socket* socket, const char** args); +/** + * Sends a begin instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_begin(guac_socket* socket); + /** * Sends a connect instruction over the given guac_socket connection. * diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index eba527d7..bda4b920 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -399,6 +399,9 @@ int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, } +int guac_protocol_send_begin(guac_socket* socket) { + return guac_socket_write_string(socket, "5.begin;"); +} int guac_protocol_send_cfill(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, From f021858d949d19a0eb80787c5693a062e72a1046 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 22 Oct 2012 14:37:41 -0700 Subject: [PATCH 307/330] Add guac_client_info structure. --- libguac/include/client.h | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/libguac/include/client.h b/libguac/include/client.h index 3b52fa42..6275d5fe 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -170,6 +170,42 @@ typedef enum guac_client_state { } guac_client_state; +/** + * Information exposed by the remote client during the connection handshake + * which can be used by a client plugin. + */ +typedef struct guac_client_info { + + /** + * The number of pixels the remote client requests for the display width. + * This need not be honored by a client plugin implementation, but if the + * underlying protocol of the client plugin supports dynamic sizing of the + * screen, honoring the display size request is recommended. + */ + int optimal_width; + + /** + * The number of pixels the remote client requests for the display height. + * This need not be honored by a client plugin implementation, but if the + * underlying protocol of the client plugin supports dynamic sizing of the + * screen, honoring the display size request is recommended. + */ + int optimal_height; + + /** + * NULL-terminated array of client-supported audio mimetypes. If the client + * does not support audio at all, this will be NULL. + */ + char* audio_mimetypes; + + /** + * NULL-terminated array of client-supported video mimetypes. If the client + * does not support video at all, this will be NULL. + */ + char* video_mimetypes; + +} guac_client_info; + /** * Guacamole proxy client. * @@ -207,6 +243,12 @@ struct guac_client { */ guac_timestamp last_sent_timestamp; + /** + * Information structure containing properties exposed by the remote + * client during the initial handshake process. + */ + guac_client_info info; + /** * Arbitrary reference to proxy client-specific data. Implementors of a * Guacamole proxy client can store any data they want here, which can then From f0de5cb6f0c6755d0e176f8af78eab08c12eca44 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 22 Oct 2012 15:45:22 -0700 Subject: [PATCH 308/330] Revert "Add begin instruction, to be sent after connection succeeds." This reverts commit 19c8d7ec283abd8f8dffe2690aa3973009552304. --- libguac/include/protocol.h | 11 ----------- libguac/src/protocol.c | 3 --- 2 files changed, 14 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index a525ddab..fc73394d 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -180,17 +180,6 @@ typedef enum guac_line_join_style { */ int guac_protocol_send_args(guac_socket* socket, const char** args); -/** - * Sends a begin instruction over the given guac_socket connection. - * - * If an error occurs sending the instruction, a non-zero value is - * returned, and guac_error is set appropriately. - * - * @param socket The guac_socket connection to use. - * @return Zero on success, non-zero on error. - */ -int guac_protocol_send_begin(guac_socket* socket); - /** * Sends a connect instruction over the given guac_socket connection. * diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index bda4b920..eba527d7 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -399,9 +399,6 @@ int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, } -int guac_protocol_send_begin(guac_socket* socket) { - return guac_socket_write_string(socket, "5.begin;"); -} int guac_protocol_send_cfill(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, From eca42455662ce1b6cdfde671872062a7782567f5 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 22 Oct 2012 15:49:43 -0700 Subject: [PATCH 309/330] Updated ChangeLog --- libguac/ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libguac/ChangeLog b/libguac/ChangeLog index a79100e5..7ae48c07 100644 --- a/libguac/ChangeLog +++ b/libguac/ChangeLog @@ -1,3 +1,9 @@ +2012-10-22 Michael Jumper + + * Implement protocol nesting (via "nest" instruction) + * Add size/audio/video events + * Add guac_client_info structure to be populated during handshake + 2012-07-23 Michael Jumper * Add unit tests for Unicode in protocol From ebdc70058ebf5e3b741d1c3e1ee6d6c5b689cae1 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 23 Oct 2012 11:17:25 -0700 Subject: [PATCH 310/330] Remove audio/video event (use handshake instead) --- libguac/ChangeLog | 2 +- libguac/include/client-handlers.h | 14 ------------- libguac/include/client.h | 34 ------------------------------- libguac/src/client-handlers.c | 20 ------------------ 4 files changed, 1 insertion(+), 69 deletions(-) diff --git a/libguac/ChangeLog b/libguac/ChangeLog index 7ae48c07..207a5c4c 100644 --- a/libguac/ChangeLog +++ b/libguac/ChangeLog @@ -1,7 +1,7 @@ 2012-10-22 Michael Jumper * Implement protocol nesting (via "nest" instruction) - * Add size/audio/video events + * Add size events * Add guac_client_info structure to be populated during handshake 2012-07-23 Michael Jumper diff --git a/libguac/include/client-handlers.h b/libguac/include/client-handlers.h index cb1ddca4..24f9c631 100644 --- a/libguac/include/client-handlers.h +++ b/libguac/include/client-handlers.h @@ -106,20 +106,6 @@ int __guac_handle_clipboard(guac_client* client, guac_instruction* instruction); */ int __guac_handle_size(guac_client* client, guac_instruction* instruction); -/** - * Internal initial handler for the video instruction. When a video instruction - * is received, this handler will be called. The client's video handler will - * be invoked if defined. - */ -int __guac_handle_video(guac_client* client, guac_instruction* instruction); - -/** - * Internal initial handler for the audio instruction. When a audio instruction - * is received, this handler will be called. The client's audio handler will - * be invoked if defined. - */ -int __guac_handle_audio(guac_client* client, guac_instruction* instruction); - /** * Internal initial handler for the disconnect instruction. When a disconnect instruction * is received, this handler will be called. Disconnect instructions are automatically diff --git a/libguac/include/client.h b/libguac/include/client.h index 6275d5fe..c32f70e2 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -355,40 +355,6 @@ struct guac_client { */ guac_client_size_handler* size_handler; - /** - * Handler for audio format events sent by the Guacamole web-client. - * - * The handler takes the mimetype of the audio format being advertised - * as supported by the client. - * - * Example: - * @code - * int audio_handler(guac_client* client, char* mimetype); - * - * int guac_client_init(guac_client* client, int argc, char** argv) { - * client->audio_handler = audio_handler; - * } - * @endcode - */ - guac_client_audio_handler* audio_handler; - - /** - * Handler for video format events sent by the Guacamole web-client. - * - * The handler takes the mimetype of the video format being advertised - * as supported by the client. - * - * Example: - * @code - * int video_handler(guac_client* client, char* mimetype); - * - * int guac_client_init(guac_client* client, int argc, char** argv) { - * client->video_handler = video_handler; - * } - * @endcode - */ - guac_client_video_handler* video_handler; - /** * Handler for freeing data when the client is being unloaded. * diff --git a/libguac/src/client-handlers.c b/libguac/src/client-handlers.c index 494081ad..bc203772 100644 --- a/libguac/src/client-handlers.c +++ b/libguac/src/client-handlers.c @@ -51,8 +51,6 @@ __guac_instruction_handler_mapping __guac_instruction_handler_map[] = { {"clipboard", __guac_handle_clipboard}, {"disconnect", __guac_handle_disconnect}, {"size", __guac_handle_size}, - {"audio", __guac_handle_audio}, - {"video", __guac_handle_video}, {NULL, NULL} }; @@ -128,24 +126,6 @@ int __guac_handle_size(guac_client* client, guac_instruction* instruction) { return 0; } -int __guac_handle_video(guac_client* client, guac_instruction* instruction) { - if (client->video_handler) - return client->video_handler( - client, - instruction->argv[0] /* mimetype */ - ); - return 0; -} - -int __guac_handle_audio(guac_client* client, guac_instruction* instruction) { - if (client->audio_handler) - return client->audio_handler( - client, - instruction->argv[0] /* mimetype */ - ); - return 0; -} - int __guac_handle_disconnect(guac_client* client, guac_instruction* instruction) { /* Return error code to force disconnect */ return -1; From 601e75b4f4a90bf20e2f31f0166d0400aeb789a8 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 24 Oct 2012 09:57:06 -0700 Subject: [PATCH 311/330] Add audio instruction. --- libguac/include/protocol.h | 19 +++++++++++++++++++ libguac/src/protocol.c | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index fc73394d..fd5cffd9 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -271,6 +271,25 @@ int guac_protocol_send_select(guac_socket* socket, const char* protocol); */ int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp); +/* MEDIA INSTRUCTIONS */ + +/** + * Sends an audio instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param channel The index of the audio channel the sound should play on. + * @param mimetype The mimetype of the data being sent. + * @param duration The duration of the sound being sent, in milliseconds. + * @param data The audio data to be sent. + * @param size The number of bytes of audio data to send. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_audio(guac_socket* socket, int channel, + const char* mimetype, int duration, void* data, int size); + /* DRAWING INSTRUCTIONS */ /** diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index eba527d7..44ff4233 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -399,6 +399,26 @@ int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, } +int guac_protocol_send_audio(guac_socket* socket, int channel, + const char* mimetype, int duration, void* data, int size) { + + int base64_length = (size + 2) / 3 * 4; + + return + guac_socket_write_string(socket, "5.audio,") + || __guac_socket_write_length_int(socket, channel) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_string(socket, mimetype) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, duration) + || guac_socket_write_string(socket, ",") + || guac_socket_write_int(socket, base64_length) + || guac_socket_write_string(socket, ".") + || guac_socket_write_base64(socket, data, size) + || guac_socket_flush_base64(socket) + || guac_socket_write_string(socket, ";"); + +} int guac_protocol_send_cfill(guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, From 872bb16872a1138fe92f273c818724740dcb9497 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 24 Oct 2012 12:01:21 -0700 Subject: [PATCH 312/330] Updated ChangeLog --- libguac/ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libguac/ChangeLog b/libguac/ChangeLog index 207a5c4c..ad6c72a1 100644 --- a/libguac/ChangeLog +++ b/libguac/ChangeLog @@ -1,3 +1,7 @@ +2012-10-24 Michael Jumper + + * Implement audio instruction + 2012-10-22 Michael Jumper * Implement protocol nesting (via "nest" instruction) From ef9914cfdf45971b73a37ccc190a47cb4cfd5282 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 25 Oct 2012 10:54:30 -0700 Subject: [PATCH 313/330] Add video instruction. --- libguac/include/protocol.h | 17 +++++++++++++++++ libguac/src/protocol.c | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index fd5cffd9..7269e5a0 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -290,6 +290,23 @@ int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp); int guac_protocol_send_audio(guac_socket* socket, int channel, const char* mimetype, int duration, void* data, int size); +/** + * Sends an video instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @param mimetype The mimetype of the data being sent. + * @param duration The duration of the video being sent, in milliseconds. + * @param data The video data to be sent. + * @param size The number of bytes of video data to send. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_video(guac_socket* socket, const guac_layer* layer, + const char* mimetype, int duration, void* data, int size); + /* DRAWING INSTRUCTIONS */ /** diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 44ff4233..4b7245b4 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -944,4 +944,23 @@ int guac_protocol_send_transform(guac_socket* socket, const guac_layer* layer, } +int guac_protocol_send_video(guac_socket* socket, const guac_layer* layer, + const char* mimetype, int duration, void* data, int size) { + int base64_length = (size + 2) / 3 * 4; + + return + guac_socket_write_string(socket, "5.video,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_string(socket, mimetype) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, duration) + || guac_socket_write_string(socket, ",") + || guac_socket_write_int(socket, base64_length) + || guac_socket_write_string(socket, ".") + || guac_socket_write_base64(socket, data, size) + || guac_socket_flush_base64(socket) + || guac_socket_write_string(socket, ";"); + +} From 264a7f232b780a96cc3451b3b56b52292fafa927 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 25 Oct 2012 11:37:21 -0700 Subject: [PATCH 314/330] Prototypes for functions for chunked writes of audio/video instructions over a guac_socket. --- libguac/include/protocol.h | 120 ++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 7269e5a0..087971a6 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -291,7 +291,66 @@ int guac_protocol_send_audio(guac_socket* socket, int channel, const char* mimetype, int duration, void* data, int size); /** - * Sends an video instruction over the given guac_socket connection. + * Begins a audio instruction over the given guac_socket connection. Only the + * initial non-data part of the instruction and the length of the data part + * of the instruction are sent. The actual contents of the data must be + * sent with guac_protocol_send_audio_data(), and the instruction must be + * completed with guac_protocol_send_audio_end(). + * + * Note that the size of the audio to be sent MUST be known ahead of time, + * even though the data of the audio may be sent in chunks. + * + * No further instruction data may be sent along the givven guac_socket + * except via guac_protocol_send_audio_data() until the audio instruction + * is completed with guac_protocol_send_audio_end(). + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param channel The index of the audio channel the sound should play on. + * @param mimetype The mimetype of the data being sent. + * @param duration The duration of the audio being sent, in milliseconds. + * @param size The number of bytes of audio data to send. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_audio_header(guac_socket* socket, + int channel, const char* mimetype, int duration, int size); + +/** + * Writes a block of audio data to the currently in-progress audio instruction + * which was started with guac_protocol_send_audio_header(). Exactly the + * number of requested bytes are written unless an error occurs. This function + * may be called multiple times per audio instruction for each chunk of audio + * data being written, allowing the potentially huge audio instruction to be + * split across multiple writes. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param data The audio data to write. + * @param count The number of bytes within the given buffer of audio data + * that must be written. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_audio_data(guac_socket* socket, void* data, int count); + +/** + * Completes the audio instruction which was started with + * guac_protocol_send_audio_header(), and whose data has been written with + * guac_protocol_send_audio_data(). + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_audio_end(guac_socket* socket); + +/** + * Sends a video instruction over the given guac_socket connection. * * If an error occurs sending the instruction, a non-zero value is * returned, and guac_error is set appropriately. @@ -307,6 +366,65 @@ int guac_protocol_send_audio(guac_socket* socket, int channel, int guac_protocol_send_video(guac_socket* socket, const guac_layer* layer, const char* mimetype, int duration, void* data, int size); +/** + * Begins a video instruction over the given guac_socket connection. Only the + * initial non-data part of the instruction and the length of the data part + * of the instruction are sent. The actual contents of the data must be + * sent with guac_protocol_send_video_data(), and the instruction must be + * completed with guac_protocol_send_video_end(). + * + * Note that the size of the video to be sent MUST be known ahead of time, + * even though the data of the video may be sent in chunks. + * + * No further instruction data may be sent along the givven guac_socket + * except via guac_protocol_send_video_data() until the video instruction + * is completed with guac_protocol_send_video_end(). + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param layer The destination layer. + * @param mimetype The mimetype of the data being sent. + * @param duration The duration of the video being sent, in milliseconds. + * @param size The number of bytes of video data to send. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_video_header(guac_socket* socket, + const guac_layer* layer, const char* mimetype, int duration, int size); + +/** + * Writes a block of video data to the currently in-progress video instruction + * which was started with guac_protocol_send_video_header(). Exactly the + * number of requested bytes are written unless an error occurs. This function + * may be called multiple times per video instruction for each chunk of video + * data being written, allowing the potentially huge video instruction to be + * split across multiple writes. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param data The video data to write. + * @param count The number of bytes within the given buffer of video data + * that must be written. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_video_data(guac_socket* socket, void* data, int count); + +/** + * Completes the video instruction which was started with + * guac_protocol_send_video_header(), and whose data has been written with + * guac_protocol_send_video_data(). + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_video_end(guac_socket* socket); + /* DRAWING INSTRUCTIONS */ /** From 6d47cbc7952e33653ecf4a29fd1790158bebb28f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 25 Oct 2012 11:56:11 -0700 Subject: [PATCH 315/330] Implement chunked write instructions. --- libguac/src/protocol.c | 57 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 4b7245b4..ab28f3b5 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -402,6 +402,17 @@ int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, int guac_protocol_send_audio(guac_socket* socket, int channel, const char* mimetype, int duration, void* data, int size) { + return + guac_protocol_send_audio_header(socket, channel, + mimetype, duration, size) + || guac_protocol_send_audio_data(socket, data, size) + || guac_protocol_send_audio_end(socket); + +} + +int guac_protocol_send_audio_header(guac_socket* socket, + int channel, const char* mimetype, int duration, int size) { + int base64_length = (size + 2) / 3 * 4; return @@ -413,9 +424,20 @@ int guac_protocol_send_audio(guac_socket* socket, int channel, || __guac_socket_write_length_int(socket, duration) || guac_socket_write_string(socket, ",") || guac_socket_write_int(socket, base64_length) - || guac_socket_write_string(socket, ".") - || guac_socket_write_base64(socket, data, size) - || guac_socket_flush_base64(socket) + || guac_socket_write_string(socket, "."); + +} + +int guac_protocol_send_audio_data(guac_socket* socket, void* data, int count) { + + return guac_socket_write_base64(socket, data, count); + +} + +int guac_protocol_send_audio_end(guac_socket* socket) { + + return + guac_socket_flush_base64(socket) || guac_socket_write_string(socket, ";"); } @@ -947,6 +969,17 @@ int guac_protocol_send_transform(guac_socket* socket, const guac_layer* layer, int guac_protocol_send_video(guac_socket* socket, const guac_layer* layer, const char* mimetype, int duration, void* data, int size) { + return + guac_protocol_send_video_header(socket, layer, + mimetype, duration, size) + || guac_protocol_send_video_data(socket, data, size) + || guac_protocol_send_video_end(socket); + +} + +int guac_protocol_send_video_header(guac_socket* socket, + const guac_layer* layer, const char* mimetype, int duration, int size) { + int base64_length = (size + 2) / 3 * 4; return @@ -958,9 +991,21 @@ int guac_protocol_send_video(guac_socket* socket, const guac_layer* layer, || __guac_socket_write_length_int(socket, duration) || guac_socket_write_string(socket, ",") || guac_socket_write_int(socket, base64_length) - || guac_socket_write_string(socket, ".") - || guac_socket_write_base64(socket, data, size) - || guac_socket_flush_base64(socket) + || guac_socket_write_string(socket, "."); + +} + +int guac_protocol_send_video_data(guac_socket* socket, void* data, int count) { + + return guac_socket_write_base64(socket, data, count); + +} + +int guac_protocol_send_video_end(guac_socket* socket) { + + return + guac_socket_flush_base64(socket) || guac_socket_write_string(socket, ";"); } + From 36f04a87d2bafbecba26796b46bd69b61eca6701 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 25 Oct 2012 11:57:06 -0700 Subject: [PATCH 316/330] Update ChangeLog --- libguac/ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libguac/ChangeLog b/libguac/ChangeLog index ad6c72a1..ca912d39 100644 --- a/libguac/ChangeLog +++ b/libguac/ChangeLog @@ -1,3 +1,8 @@ +2012-10-25 Michael Jumper + + * Implement video instruction + * Implement chunked write versions of audio/video functions + 2012-10-24 Michael Jumper * Implement audio instruction From 882d50790ba756d36ca1c9ee1c36268114d52f89 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 25 Oct 2012 18:00:33 -0700 Subject: [PATCH 317/330] Implemented file instruction and chunked file writing functions. --- libguac/include/protocol.h | 74 ++++++++++++++++++++++++++++++++++++++ libguac/src/protocol.c | 42 ++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index 087971a6..ba3a04ec 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -349,6 +349,80 @@ int guac_protocol_send_audio_data(guac_socket* socket, void* data, int count); */ int guac_protocol_send_audio_end(guac_socket* socket); +/** + * Sends a file instruction over the given guac_socket connection. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param name A name describing the file being sent. + * @param mimetype The mimetype of the data being sent. + * @param data The file data to be sent. + * @param size The number of bytes of file data to send. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_file(guac_socket* socket, const char* name, + const char* mimetype, void* data, int size); + +/** + * Begins a file instruction over the given guac_socket connection. Only the + * initial non-data part of the instruction and the length of the data part + * of the instruction are sent. The actual contents of the data must be + * sent with guac_protocol_send_file_data(), and the instruction must be + * completed with guac_protocol_send_file_end(). + * + * Note that the size of the file to be sent MUST be known ahead of time, + * even though the data of the file may be sent in chunks. + * + * No further instruction data may be sent along the givven guac_socket + * except via guac_protocol_send_file_data() until the file instruction + * is completed with guac_protocol_send_file_end(). + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param name A name describing the file being sent. + * @param mimetype The mimetype of the data being sent. + * @param size The number of bytes of file data to send. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_file_header(guac_socket* socket, const char* name, + const char* mimetype, int size); + +/** + * Writes a block of file data to the currently in-progress file instruction + * which was started with guac_protocol_send_file_header(). Exactly the + * number of requested bytes are written unless an error occurs. This function + * may be called multiple times per file instruction for each chunk of file + * data being written, allowing the potentially huge file instruction to be + * split across multiple writes. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @param data The file data to write. + * @param count The number of bytes within the given buffer of file data + * that must be written. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_file_data(guac_socket* socket, void* data, int count); + +/** + * Completes the file instruction which was started with + * guac_protocol_send_file_header(), and whose data has been written with + * guac_protocol_send_file_data(). + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket The guac_socket connection to use. + * @return Zero on success, non-zero on error. + */ +int guac_protocol_send_file_end(guac_socket* socket); + /** * Sends a video instruction over the given guac_socket connection. * diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index ab28f3b5..4d4fd19a 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -665,6 +665,48 @@ int guac_protocol_send_error(guac_socket* socket, const char* error) { } +int guac_protocol_send_file(guac_socket* socket, const char* name, + const char* mimetype, void* data, int size) { + + return + guac_protocol_send_file_header(socket, name, + mimetype, size) + || guac_protocol_send_file_data(socket, data, size) + || guac_protocol_send_file_end(socket); + +} + +int guac_protocol_send_file_header(guac_socket* socket, const char* name, + const char* mimetype, int size) { + + int base64_length = (size + 2) / 3 * 4; + + return + guac_socket_write_string(socket, "4.file,") + || __guac_socket_write_length_string(socket, name) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_string(socket, mimetype) + || guac_socket_write_string(socket, ",") + || guac_socket_write_int(socket, base64_length) + || guac_socket_write_string(socket, "."); + +} + +int guac_protocol_send_file_data(guac_socket* socket, void* data, int count) { + + return guac_socket_write_base64(socket, data, count); + +} + +int guac_protocol_send_file_end(guac_socket* socket) { + + return + guac_socket_flush_base64(socket) + || guac_socket_write_string(socket, ";"); + +} + + int guac_protocol_send_identity(guac_socket* socket, const guac_layer* layer) { return From 237e7c98dd125bb0677e34664f208b7687337739 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 25 Oct 2012 19:50:43 -0700 Subject: [PATCH 318/330] Fix mimetype types. --- libguac/include/client.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libguac/include/client.h b/libguac/include/client.h index c32f70e2..0e2e78ea 100644 --- a/libguac/include/client.h +++ b/libguac/include/client.h @@ -196,13 +196,13 @@ typedef struct guac_client_info { * NULL-terminated array of client-supported audio mimetypes. If the client * does not support audio at all, this will be NULL. */ - char* audio_mimetypes; + const char** audio_mimetypes; /** * NULL-terminated array of client-supported video mimetypes. If the client * does not support video at all, this will be NULL. */ - char* video_mimetypes; + const char** video_mimetypes; } guac_client_info; From 60fbdf148bf2b467d57b2ada30d75a1b4d914517 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 1 Nov 2012 20:52:50 -0700 Subject: [PATCH 319/330] Use double durations for audio and video. --- libguac/include/protocol.h | 8 ++++---- libguac/src/protocol.c | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libguac/include/protocol.h b/libguac/include/protocol.h index ba3a04ec..a9c21ce0 100644 --- a/libguac/include/protocol.h +++ b/libguac/include/protocol.h @@ -288,7 +288,7 @@ int guac_protocol_send_sync(guac_socket* socket, guac_timestamp timestamp); * @return Zero on success, non-zero on error. */ int guac_protocol_send_audio(guac_socket* socket, int channel, - const char* mimetype, int duration, void* data, int size); + const char* mimetype, double duration, void* data, int size); /** * Begins a audio instruction over the given guac_socket connection. Only the @@ -315,7 +315,7 @@ int guac_protocol_send_audio(guac_socket* socket, int channel, * @return Zero on success, non-zero on error. */ int guac_protocol_send_audio_header(guac_socket* socket, - int channel, const char* mimetype, int duration, int size); + int channel, const char* mimetype, double duration, int size); /** * Writes a block of audio data to the currently in-progress audio instruction @@ -438,7 +438,7 @@ int guac_protocol_send_file_end(guac_socket* socket); * @return Zero on success, non-zero on error. */ int guac_protocol_send_video(guac_socket* socket, const guac_layer* layer, - const char* mimetype, int duration, void* data, int size); + const char* mimetype, double duration, void* data, int size); /** * Begins a video instruction over the given guac_socket connection. Only the @@ -465,7 +465,7 @@ int guac_protocol_send_video(guac_socket* socket, const guac_layer* layer, * @return Zero on success, non-zero on error. */ int guac_protocol_send_video_header(guac_socket* socket, - const guac_layer* layer, const char* mimetype, int duration, int size); + const guac_layer* layer, const char* mimetype, double duration, int size); /** * Writes a block of video data to the currently in-progress video instruction diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 4d4fd19a..90021115 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -400,7 +400,7 @@ int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer, } int guac_protocol_send_audio(guac_socket* socket, int channel, - const char* mimetype, int duration, void* data, int size) { + const char* mimetype, double duration, void* data, int size) { return guac_protocol_send_audio_header(socket, channel, @@ -411,7 +411,7 @@ int guac_protocol_send_audio(guac_socket* socket, int channel, } int guac_protocol_send_audio_header(guac_socket* socket, - int channel, const char* mimetype, int duration, int size) { + int channel, const char* mimetype, double duration, int size) { int base64_length = (size + 2) / 3 * 4; @@ -421,7 +421,7 @@ int guac_protocol_send_audio_header(guac_socket* socket, || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, duration) + || __guac_socket_write_length_double(socket, duration) || guac_socket_write_string(socket, ",") || guac_socket_write_int(socket, base64_length) || guac_socket_write_string(socket, "."); @@ -1009,7 +1009,7 @@ int guac_protocol_send_transform(guac_socket* socket, const guac_layer* layer, } int guac_protocol_send_video(guac_socket* socket, const guac_layer* layer, - const char* mimetype, int duration, void* data, int size) { + const char* mimetype, double duration, void* data, int size) { return guac_protocol_send_video_header(socket, layer, @@ -1020,7 +1020,7 @@ int guac_protocol_send_video(guac_socket* socket, const guac_layer* layer, } int guac_protocol_send_video_header(guac_socket* socket, - const guac_layer* layer, const char* mimetype, int duration, int size) { + const guac_layer* layer, const char* mimetype, double duration, int size) { int base64_length = (size + 2) / 3 * 4; @@ -1030,7 +1030,7 @@ int guac_protocol_send_video_header(guac_socket* socket, || guac_socket_write_string(socket, ",") || __guac_socket_write_length_string(socket, mimetype) || guac_socket_write_string(socket, ",") - || __guac_socket_write_length_int(socket, duration) + || __guac_socket_write_length_double(socket, duration) || guac_socket_write_string(socket, ",") || guac_socket_write_int(socket, base64_length) || guac_socket_write_string(socket, "."); From c25683783e61563ac1caecc91d678c5430f4a024 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 13 Nov 2012 11:46:34 -0800 Subject: [PATCH 320/330] Output 16 digits after decimal for doubles in protocol. --- libguac/src/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/src/protocol.c b/libguac/src/protocol.c index 90021115..8ed1e091 100644 --- a/libguac/src/protocol.c +++ b/libguac/src/protocol.c @@ -83,7 +83,7 @@ ssize_t __guac_socket_write_length_int(guac_socket* socket, int64_t i) { ssize_t __guac_socket_write_length_double(guac_socket* socket, double d) { char buffer[128]; - snprintf(buffer, sizeof(buffer), "%g", d); + snprintf(buffer, sizeof(buffer), "%.16g", d); return __guac_socket_write_length_string(socket, buffer); } From 2f75ff701841f8585b3905ac9b058c7ef3be10f9 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 29 Nov 2012 19:35:17 -0800 Subject: [PATCH 321/330] Fix leak in stream pool. --- libguac/src/client.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libguac/src/client.c b/libguac/src/client.c index cf96e428..62b60885 100644 --- a/libguac/src/client.c +++ b/libguac/src/client.c @@ -166,6 +166,9 @@ void guac_client_free(guac_client* client) { guac_pool_free(client->__buffer_pool); guac_pool_free(client->__layer_pool); + /* Free stream pool */ + guac_pool_free(client->__stream_pool); + free(client); } From 3e209e19834eca1ad8a8afcac18da8fcf0ab272f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 29 Nov 2012 19:36:13 -0800 Subject: [PATCH 322/330] Update stylesheet. --- libguac/doc/docbook.xslt | 83 ++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/libguac/doc/docbook.xslt b/libguac/doc/docbook.xslt index f8ffd0e3..7df2e642 100644 --- a/libguac/doc/docbook.xslt +++ b/libguac/doc/docbook.xslt @@ -2,17 +2,17 @@ - + - + + libguac @@ -21,7 +21,8 @@ - + + @@ -31,6 +32,13 @@ + + + + + + + @@ -45,54 +53,61 @@ + + + + - - - - - - - Description - - - + + + - - Parameters + + + Parameters - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + + + Return Value + + + + + From 825e3da0a29d95fd8381231a4596aeaf6b8f594b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 29 Nov 2012 20:02:58 -0800 Subject: [PATCH 323/330] Fix leaky pools. --- libguac/src/pool.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libguac/src/pool.c b/libguac/src/pool.c index 153e913a..85167619 100644 --- a/libguac/src/pool.c +++ b/libguac/src/pool.c @@ -59,7 +59,20 @@ guac_pool* guac_pool_alloc(int size) { } void guac_pool_free(guac_pool* pool) { + + /* Free all ints in pool */ + guac_pool_int* current = pool->__head; + while (current != NULL) { + + guac_pool_int* old = current; + current = current->__next; + + free(old); + } + + /* Free pool */ free(pool); + } int guac_pool_next_int(guac_pool* pool) { From 17c755dde40be7ff9e7db1606359dd84eeea5649 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 1 Dec 2012 19:01:27 -0800 Subject: [PATCH 324/330] Removed experimental structures. --- libguac/include/hash.h | 85 ------------------------------------------ 1 file changed, 85 deletions(-) diff --git a/libguac/include/hash.h b/libguac/include/hash.h index c17cc2b8..312a05f1 100644 --- a/libguac/include/hash.h +++ b/libguac/include/hash.h @@ -41,91 +41,6 @@ #include -/** - * A wrapper for a Cairo surface which allows fast image queries (linear time - * in the size of the query image). Given an arbitrary input image, the first - * occurence of that image within the contained surface can be found quickly. - */ -typedef struct guac_indexed_surface { - - /** - * The Cairo surface which is indexed. - */ - cairo_surface_t* surface; - -} guac_indexed_surface; - -typedef struct guac_indexed_surface_subimage { - - /** - * The indexed surface this subimage is a part of. - */ - guac_indexed_surface* surface; - - /** - * The X coordinate of the upper-left point of the rectangle - * of the subimage. - */ - int x; - - /** - * The Y coordinate of the upper-left point of the rectangle - * of the subimage. - */ - int y; - - /** - * The width of the subimage in pixels. - */ - int width; - - /** - * The height of the subimage in pixels. - */ - int height; - -} guac_indexed_surface_subimage; - -/** - * Creates a new indexed surface, using the given surface as the image data - * source. The given surface will be made searchable such that queries of - * images which are at least the given width and height can be resolved - * quickly. - * - * @param surface The Cairo surface to index. - * @param min_width The minimum image width to allow for queries. - * @param min_height The minimum image height to allow for queries. - * @return A newly allocated guac_indexed_surface. - */ -guac_indexed_surface* guac_indexed_surface_alloc(cairo_surface_t* surface, - int min_width, int min_height); - -/** - * Frees the given indexed surface. - * - * @param surface The guac_indexed_surface to free. - */ -void guac_indexed_surface_free(guac_indexed_surface* surface); - -/** - * Given an indexed surface and a query image, finds the rectangle of the - * subimage of the indexed surface containing exactly the query image (if - * any) and saves the result. - * - * @param surface The guac_indexed_surface to query. - * @param query The image to search for within the indexed surface. - * @param result A pointer to an already-allocated - * guac_indexed_surface_subimage which will be modified - * to contain the result if a result is found. - * @return Non-zero if the given query image was found within the indexed - * surface, in which case the result will be stored in the given - * guac_indexed_surface_subimage, or zero if the query image could - * not be found, in which case the given guac_indexed_surface_subimage - * will not be modified. - */ -int guac_indexed_surface_find(guac_indexed_surface* surface, - cairo_surface_t* query, guac_indexed_surface_subimage* result); - /** * Produces a 24-bit hash value from all pixels of the given surface. The * surface provided must be RGB or ARGB with each pixel stored in 32 bits. From df06d1a354e006fa735995dfc04909a52710421a Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 1 Dec 2012 19:02:02 -0800 Subject: [PATCH 325/330] Fixed guac_pool comments. --- libguac/include/pool.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libguac/include/pool.h b/libguac/include/pool.h index 07b5e933..a88ccdd0 100644 --- a/libguac/include/pool.h +++ b/libguac/include/pool.h @@ -47,16 +47,24 @@ typedef struct guac_pool_int guac_pool_int; +/** + * A pool of integers. Integers can be removed from and later free'd back + * into the pool. New integers are returned when the pool is exhausted, + * or when the pool has not met some minimum size. Old, free'd integers + * are returned otherwise. + */ typedef struct guac_pool { /** - * The minimum number of integers which must have been returned by guac_pool_next_int - * before previously-used and freed integers are allowed to be returned. + * The minimum number of integers which must have been returned by + * guac_pool_next_int before previously-used and freed integers are + * allowed to be returned. */ int min_size; /** - * The next integer to be released (after no more integers remain in the pool. + * The next integer to be released (after no more integers remain in the + * pool. */ int __next_value; @@ -73,7 +81,7 @@ typedef struct guac_pool { } guac_pool; /** - * Represents a single layer within the Guacamole protocol. + * Represents a single integer within a larger pool of integers. */ struct guac_pool_int { From 5232056a1b5981ae430c0bd089894c03ef66978f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 1 Dec 2012 19:39:22 -0800 Subject: [PATCH 326/330] Mark internal structs as private. --- libguac/src/socket-fd.c | 12 ++++++------ libguac/src/socket-nest.c | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libguac/src/socket-fd.c b/libguac/src/socket-fd.c index 970dcd2e..9139a906 100644 --- a/libguac/src/socket-fd.c +++ b/libguac/src/socket-fd.c @@ -56,16 +56,16 @@ #include "socket.h" #include "error.h" -typedef struct guac_socket_fd_data { +typedef struct __guac_socket_fd_data { int fd; -} guac_socket_fd_data; +} __guac_socket_fd_data; ssize_t __guac_socket_fd_read_handler(guac_socket* socket, void* buf, size_t count) { - guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; + __guac_socket_fd_data* data = (__guac_socket_fd_data*) socket->data; /* Read from socket */ int retval = read(data->fd, buf, count); @@ -83,7 +83,7 @@ ssize_t __guac_socket_fd_read_handler(guac_socket* socket, ssize_t __guac_socket_fd_write_handler(guac_socket* socket, void* buf, size_t count) { - guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; + __guac_socket_fd_data* data = (__guac_socket_fd_data*) socket->data; int retval; #ifdef __MINGW32__ @@ -106,7 +106,7 @@ ssize_t __guac_socket_fd_write_handler(guac_socket* socket, int __guac_socket_fd_select_handler(guac_socket* socket, int usec_timeout) { - guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; + __guac_socket_fd_data* data = (__guac_socket_fd_data*) socket->data; fd_set fds; struct timeval timeout; @@ -146,7 +146,7 @@ guac_socket* guac_socket_open(int fd) { /* Allocate socket and associated data */ guac_socket* socket = guac_socket_alloc(); - guac_socket_fd_data* data = malloc(sizeof(guac_socket_fd_data)); + __guac_socket_fd_data* data = malloc(sizeof(__guac_socket_fd_data)); /* Store file descriptor as socket data */ data->fd = fd; diff --git a/libguac/src/socket-nest.c b/libguac/src/socket-nest.c index 2f06200d..92e431f6 100644 --- a/libguac/src/socket-nest.c +++ b/libguac/src/socket-nest.c @@ -60,18 +60,18 @@ #define GUAC_SOCKET_NEST_BUFFER_SIZE 8192 -typedef struct guac_socket_nest_data { +typedef struct __guac_socket_nest_data { guac_socket* parent; char buffer[GUAC_SOCKET_NEST_BUFFER_SIZE]; int index; -} guac_socket_nest_data; +} __guac_socket_nest_data; ssize_t __guac_socket_nest_write_handler(guac_socket* socket, void* buf, size_t count) { - guac_socket_nest_data* data = (guac_socket_nest_data*) socket->data; + __guac_socket_nest_data* data = (__guac_socket_nest_data*) socket->data; unsigned char* source = (unsigned char*) buf; /* Current location in destination buffer during copy */ @@ -137,7 +137,7 @@ guac_socket* guac_socket_nest(guac_socket* parent, int index) { /* Allocate socket and associated data */ guac_socket* socket = guac_socket_alloc(); - guac_socket_nest_data* data = malloc(sizeof(guac_socket_nest_data)); + __guac_socket_nest_data* data = malloc(sizeof(__guac_socket_nest_data)); /* Store file descriptor as socket data */ data->parent = parent; From ce32b03171629e42c7703479dee2c42ced853d27 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 1 Dec 2012 20:04:05 -0800 Subject: [PATCH 327/330] Remove include files from doc. --- libguac/doc/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/doc/Doxyfile b/libguac/doc/Doxyfile index 1a5ba0be..9d936ce6 100644 --- a/libguac/doc/Doxyfile +++ b/libguac/doc/Doxyfile @@ -384,7 +384,7 @@ HIDE_SCOPE_NAMES = NO # will put a list of the files that are included by a file in the documentation # of that file. -SHOW_INCLUDE_FILES = YES +SHOW_INCLUDE_FILES = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation From 4badb9a89b6059f4476528124b7b401b24942340 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 1 Dec 2012 20:11:14 -0800 Subject: [PATCH 328/330] Fix documentation. --- libguac/include/hash.h | 8 +++++++- libguac/include/pool.h | 4 ++-- libguac/include/stream.h | 2 +- libguac/include/unicode.h | 6 ++++++ 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/libguac/include/hash.h b/libguac/include/hash.h index 312a05f1..d181e357 100644 --- a/libguac/include/hash.h +++ b/libguac/include/hash.h @@ -35,12 +35,18 @@ * * ***** END LICENSE BLOCK ***** */ - #ifndef _GUAC_HASH_H #define _GUAC_HASH_H #include +/** + * Provides functions and structures for producing likely-to-be-unique hash + * values for images. + * + * @file hash.h + */ + /** * Produces a 24-bit hash value from all pixels of the given surface. The * surface provided must be RGB or ARGB with each pixel stored in 32 bits. diff --git a/libguac/include/pool.h b/libguac/include/pool.h index a88ccdd0..629d863b 100644 --- a/libguac/include/pool.h +++ b/libguac/include/pool.h @@ -39,8 +39,8 @@ #define _GUAC_POOL_H /** - * Provides functions and structures for maintaining dynamically allocated and freed - * pools of integers. + * Provides functions and structures for maintaining dynamically allocated and + * freed pools of integers. * * @file pool.h */ diff --git a/libguac/include/stream.h b/libguac/include/stream.h index 06dc7b45..fa0bb089 100644 --- a/libguac/include/stream.h +++ b/libguac/include/stream.h @@ -42,7 +42,7 @@ * Provides functions and structures required for allocating and using nested * streams. * - * @file layer.h + * @file stream.h */ typedef struct guac_stream guac_stream; diff --git a/libguac/include/unicode.h b/libguac/include/unicode.h index 3364641e..cace74e2 100644 --- a/libguac/include/unicode.h +++ b/libguac/include/unicode.h @@ -40,6 +40,12 @@ #include +/** + * Provides functions for manipulating Unicode strings. + * + * @file unicode.h + */ + /** * Given the initial byte of a single UTF-8 character, returns the overall * byte size of the entire character. From a9132dac57508c9cbc1bac1844efeeda2d7a1fde Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 1 Dec 2012 20:11:36 -0800 Subject: [PATCH 329/330] Fix version number in Doxyfile. --- libguac/doc/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libguac/doc/Doxyfile b/libguac/doc/Doxyfile index 9d936ce6..9e7129d9 100644 --- a/libguac/doc/Doxyfile +++ b/libguac/doc/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = libguac # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 0.6.1 +PROJECT_NUMBER = 0.7.0 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. From 315a5f9b0a00100fd4bd326ec437994deace197b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 2 Dec 2012 11:32:07 -0800 Subject: [PATCH 330/330] Remove docbook stylesheet. --- libguac/doc/docbook.xslt | 116 --------------------------------------- 1 file changed, 116 deletions(-) delete mode 100644 libguac/doc/docbook.xslt diff --git a/libguac/doc/docbook.xslt b/libguac/doc/docbook.xslt deleted file mode 100644 index 7df2e642..00000000 --- a/libguac/doc/docbook.xslt +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - libguac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Description - - - - - - - - - - - Parameters - - - - - - - - - - - - - - - - - - - - - - - Return Value - - - - - - - - - - -