diff options
Diffstat (limited to 'plugins/!NotAdopted/VypressChat/libvqproto')
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/COPYING | 340 | ||||
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/PROTOCOL | 348 | ||||
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/README | 7 | ||||
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/link.c | 611 | ||||
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/link.h | 106 | ||||
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/makefile | 21 | ||||
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/message.c | 1218 | ||||
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/message.h | 57 | ||||
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/protocol-direct-connections | 97 | ||||
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/uuid.c | 108 | ||||
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/uuid.h | 27 | ||||
-rw-r--r-- | plugins/!NotAdopted/VypressChat/libvqproto/vqproto.h | 595 |
12 files changed, 3535 insertions, 0 deletions
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/COPYING b/plugins/!NotAdopted/VypressChat/libvqproto/COPYING new file mode 100644 index 0000000000..fbdd65f6f8 --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ 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
+this service 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.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+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
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE 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.
+
+ 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
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/PROTOCOL b/plugins/!NotAdopted/VypressChat/libvqproto/PROTOCOL new file mode 100644 index 0000000000..352ccd6057 --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/PROTOCOL @@ -0,0 +1,348 @@ +$Id: PROTOCOL,v 1.1 2005/02/23 16:10:14 bobas Exp $
+
+Vypress Chat protocol description
+revision 1.0, 2005-01-23
+---------------------------------
+
+I've recieved requests for VypressChat protocol specs, so here it is. This is
+based on information I got from Vasily Krysin (echat) and Konstantin Vyatkin
+(Vypress Research). Please note that information concerning 1.9.x is
+incomplete; Vypress Research stopped answering my emails, It look like
+they don't want to support vyqchat anymore. If you know anything more
+than below, please contact me, so I could make this manual as complete
+as possible. Especially RSA usage and bulletin-board support deatils are
+welcome!
+
+I. Vypress Chat 1.5.x protocol
+------------------------------
+
+Warning! Information provided below may contain subtle errors (like
+sender exchanged with reciever). If in doubt, please compare it with
+vcprotocol.cpp from VyQChat (see VCProtocol::vc_* functions). These
+mistakes will be corrected in future revisions of this document.
+
+Each Vypress Chat packet begins with 'X' and 9 random characters from
+'0'..'9' range (unique packet ID). Then comes packet type id (single
+character). For example:
+
+X1234567892#Main\0Nick\0text of string\0
+
+^^ ^^ ^ ^ ^ ^ ^----- 0x00 == string splitter
+|| || | | | |------------------- plain text to display on chat
+|| || | | |--------------------- 0x00 == string splitter
+|| || | |------------------------- nick
+|| || |--------------------------- 0x00 == string splitter
+|| ||-------------------------------- channel
+|| |--------------------------------- 0x32 == type of packet - chat
+||------------------------------------------ packet id
+|------------------------------------------- 0x58 == Vypress Chat
+
+==============================================================================
+Available packets:
+
+**********************************************************************************************
+*** Packet from list updater (Who here)
+
+ '0' + <Name of updater> + #0
+ ^^^ - its a single byte 0x00,
+ showing end of a line
+
+
+**********************************************************************************************
+*** Answer to the previous packet ("Im here")
+
+ '1' + <Name of updater> + #0 + <Name of responder> + #0 + Status + RemoteActive
+ ^^^^^
+ status of responder (byte)
+ '0' - Normal
+ '1' - DND
+ '2' - Away
+ '3' - Offline
+ ^^^^^
+ window state (byte)
+ '0' - active
+ '1' - not active
+
+**********************************************************************************************
+*** Simple chat string on the channel
+
+ '2' + <Name of channel> + #0 + <Name of author> + #0 + <Text> + #0
+
+
+**********************************************************************************************
+*** Nick change
+
+ '3' + <From who> + #0 + <To who> + #0 + Gender
+ ^^^^ - gender of the user
+ '0' - male
+ '1' - female
+
+**********************************************************************************************
+*** Join to channel
+
+ '4' + <Who joined> + #0 + <Name of channel> + #0 + Status + Gender
+
+**********************************************************************************************
+*** Leave from channel
+
+ '5' + <Who leaved> + #0 + <Name of channel> + #0 + Gender
+
+**********************************************************************************************
+*** Message
+
+ '6' + <From who> + #0 + <To who> + #0 + <Text> + #0
+
+**********************************************************************************************
+*** Multiaddress message
+
+ 'E' + <From who> + #0 + <To who> + #0 + <Text> + #0
+
+**********************************************************************************************
+*** Message ack
+
+ '7' + Status + <Who received> + #0 + <To who ack> + #0 + Gender + CurrentAA + #0
+ ^^^^^^^^^
+ current autoanswer (may be empty, for ex in Normal mode)
+
+**********************************************************************************************
+*** Remote execution
+
+ '8' + <Who execute> + #0 + <To who> + #0 + <Command line> + #0 + <Password> + #0
+ ^^^^^^^^
+ may be empty
+
+**********************************************************************************************
+*** Execution ack
+
+ '9' + <To who> + #0 + <From who> + #0 + <Execution text> + #0
+
+**********************************************************************************************
+*** /ME on the channels
+
+ 'A' + <Name of channel> + #0 + <Who said> + #0 + <Text> + #0
+
+**********************************************************************************************
+*** New topic
+
+ 'B' + <Name of channel> + #0 + <Text of topic> + ' (' + <Name of author> + ') ' + #0
+
+**********************************************************************************************
+*** Current topic (sending to each who join channel)
+
+ 'C' + <To who> + #0 + <Name of channel> + #0 + <Text of topic> + #0
+
+**********************************************************************************************
+*** Change of status
+
+ 'D' + <Who changed> + #0 + Status + Gender + CurrentAA + #0
+
+**********************************************************************************************
+*** INFO request
+
+ 'F' + <To who> + #0 + <From who> + #0
+
+**********************************************************************************************
+*** INFO request ack
+
+ 'G' + <To who> + #0 + <From who> + #0 + <Computer name> + #0 + <User name> + #0 + <IP addresses> + #0 + <List of channels - one string without splitting> + '#' + #0 + CurrentAA + #0
+
+**********************************************************************************************
+*** BEEP
+
+ signal
+ 'H' + '0' + <To who> + #0 + <From who> + #0
+
+ ack
+ 'H' + '1' + <To who> + #0 + <From who> + #0 + Gender
+
+**********************************************************************************************
+*** Sound request
+
+ 'I' + <From who> + #0 + <File name> + #0 + <Name of channel> + #0
+
+**********************************************************************************************
+*** Private
+
+ join to chat
+ 'J' + '0' + <From who> + #0 + <To who> + #0 + Gender
+
+ leave chat
+ 'J' + '1' + <From who> + #0 + <To who> + #0 + Gender
+
+ Simple string
+ 'J' + '2' + <From who> + #0 + <To who> + #0 + <Text> + #0
+
+ "/me" string
+ 'J' + '3' + <From who> + #0 + <To who> + #0 + <Text> + #0
+
+**********************************************************************************************
+*** /HERE request
+
+ 'L' + <From who> + #0 + <Name of channel> + #0
+
+**********************************************************************************************
+*** /HERE ack
+
+ 'K' + <To who> + #0 + <Name of channel> + #0 + <From who> + #0 + RemoteActive
+
+**********************************************************************************************
+*** Activity change
+
+ 'M' + <From who> + #0 + RemoteActive
+
+**********************************************************************************************
+*** Request for channel list
+
+ 'N' + <From who> + #0
+
+**********************************************************************************************
+*** Request for channel list ack
+
+ 'O' + <To who> + #0 + <List of channels - one string without splitting> + '#' + #0
+
+**********************************************************************************************
+*** Ping (not implemented - SeaD)
+
+ ping
+ 'P' + '0' + <To who> + #0 + <From who> + #0 + <Time hh:mm:ss - 8 symbols> + #0
+
+ pong
+ 'P' + '1' + <To who> + #0 + <From who> + #0 + <Received time sending back hh:mm:ss - 8 symbols> + #0)
+
+**********************************************************************************************
+
+II. Vypress Chat 1.9.x protocol changes
+---------------------------------------
+
+Vypress Chat 1.9.x uses version advertising, so that newer VC versions
+know what functions are supported by remote side of conversation and can
+preserve compatibility with older software.
+
+Second important change is unique user ID based on the UUID. As far as I
+know UUIDs are supported in Windows only for now. UUID is a 128-bit
+number that should be globally unique and persistent (should not change
+after reset). Vypress Chat 1.9 uses UUID when handling a nickname
+conflict; Vypress Chat 1.9.1 also uses it during file transfer. UUID is
+widely used at 1.9.5 and 2.0 to store RSA public key in association with
+user. (see
+http://msdn.microsoft.com/library/en-us/dnnetcomp/html/PPCGuidGen.asp
+for info on how to create uuids). In vyqchat UUIDs are created using
+OpenSSL random numbers generator, and than saved in config file so it
+doesn't change (until you delete this file); UUID is however not really
+used yet for any purpose, except including in packets.
+
+//**************************************************************************
+//*** Join to the #Main (MAIN_CHANNEL_NAME)
+//
+// '4' + <Who's joined> + #0 + <Channel name> + #0 + Status + Gender
+//
+// Ver 1.9:
+// '4' + <Nickname> + #0 + "#Main" + #0 + (char)Status + (char)Gender + #0 +
+(dword)VERSION + UUID + (char)cCodePage + (DWORD)dwColor + #0
+
+PACKERSION(1,9) indicates the protocol version. Version 1,92 means that
+your client is able to receive files via TCP. Version 1,93 means you
+are able to respond to the TCP pings. Version 1,9 should be used unless
+you implement these featues. Version should be encoded using 4 bytes, so
+for example, version 1.91 looks like this: 5B,00,01,00
+
+cCodePage should be '1' for UTF8 encoding, '0' otherwise.
+
+It is suggested to always set it to '1' (to indicate that you are using
+UTF-8 encodings for all strings) to avoid charset incompatibility. When you
+are joining the network with such flag, Vypress Chat 1.9 or later will send
+you all text string as UTF-8 encoded (including nicknames and channel names
+in all packets).
+
+dwColor is a RGB encoded color value that chat may use to display your
+strings at common chat. This is optional feature in Vypress Chat that allows
+using custom color and if a user has this feature switched on then Chat will
+use this value to display your text. You may use RGB(0,0,0) (black).
+
+Vypress Chat 1.9 relies on the PING-PONG for maintaining users list, so
+you should respond to the following packets:
+
+//**************************************************************************
+//*** PING
+//
+// PING
+// 'P' + '0' + <ToWhom> + #0 + <FromNickname> + #0 + <Time in the format
+hh:mm:ss, 8 charactes> + #0
+
+Response:
+//**************************************************************************
+//*** PONG
+//
+// PONG
+// 'P' + '1' + <ToWhom> + #0 + <MyNicknmane> + #0 + <received time should
+be sent back> + #0)
+
+//**************************************************************************
+//*** I'm here!
+//
+// '1' + <NickFrom> + #0 + <YourNick> + #0 + Status + RemoteActive
+// ^^^^^
+// your current status
+// '0' - Normal
+// '1' - DND
+// '2' - Away
+// '3' - Offline
+// ^^^^^
+// windows state
+// '0' - active
+// '1' - inactive
+//
+// Ver 1.9:
+// '1' + <NickFrom> + #0 + <YourNick> + #0 + (char)Status + RemoteActive +
+#0 + (DWORD)PACKVERSION(1.9) + (char)Gender + UUID + #0 + (DWORD)0
+(reserved) + (char)cCodePage + (DWORD)dwColor#0
+//
+// CodePage: 0 - Current ANSI, 1 - UTF-8
+
+//**************************************************************************
+//*** Who is here?
+//
+// '0' + <FromNickname> + #0 + (char)cCodePage + #0
+//
+
+//**************************************************************************
+//*** Join a channel #Channel
+//
+// '4' + <NicknameFrom> + #0 + <ChannelName> + #0 + Status + Gender
+//
+// Ver 1.9:
+// '4' + <NicknameFrom> + #0 + < ChannelName > + #0 + (char)Status +
+(char)Gender + #0 + (char)cCodePage + #0
+
+
+//**************************************************************************
+//*** Message delivery confirmation / AutoAnswer
+//
+// '7' + Status + <ToNickname> + #0 + <FromNickname> + #0 + Gender
+// + CurrentAA + #0
+//
+^^^^^^^^
+// current auto answer (may be empty)
+// Ver 1.9
+//
+// '7' + Status + <ToNickname> + #0 + <FromNickname> + #0 + Gender +
+CurrentAA + #0 + PacketSignature + #0
+//
+
+PacketSignature - first random bytes from the packet header with message
+
+//**************************************************************************
+//*** INFO request reply
+//
+// 'G' + <ToNickname> + #0 + <FromNickname> + #0 + <Computer name> + #0 +
+<Current user name> + #0 + <IP addresses> + #0 + <Channels list, without
+separators in one line> + '#' + #0 + CurrentAA + #0 + <Platform (OS)
+version> +#0 + <Chat software> + #0
+
+
+//**************************************************************************
+//*** Flood blocking notification (your packets was blocked by other user
+// for flood)
+//
+// 'Z' + <ToNickname> + #0 + <FromNickname> + #0 + <seconds count> + #0
+
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/README b/plugins/!NotAdopted/VypressChat/libvqproto/README new file mode 100644 index 0000000000..49842d7176 --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/README @@ -0,0 +1,7 @@ +$Id: README,v 1.1 2005/02/23 16:10:14 bobas Exp $
+
+I. What it is
+===============================
+This library implements support for QuickChat and Vypress Chat (tm) networks.
+
+To be written
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/link.c b/plugins/!NotAdopted/VypressChat/libvqproto/link.c new file mode 100644 index 0000000000..876af36d03 --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/link.c @@ -0,0 +1,611 @@ +/*
+ * libvqproto: Vypress/QChat protocol interface library
+ * (c) Saulius Menkevicius 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: link.c,v 1.14 2005/03/08 17:21:23 bobas Exp $
+ */
+
+#include <time.h>
+#include <stdlib.h>
+
+#include "vqproto.h"
+#include "link.h"
+#include "message.h"
+
+/* global data
+ */
+#ifndef MEMWATCH
+void * (* vqp_mmi_malloc)(size_t) = NULL;
+void (* vqp_mmi_free)(void *) = NULL;
+#endif
+
+/* static routines
+ */
+static __inline unsigned short
+ushort2bcd(unsigned short ushort)
+{
+ return (ushort % 10) | (((ushort / 10) % 10) << 4)
+ | (((ushort / 100) % 10) << 8) | (((ushort / 1000) % 10) << 12);
+}
+
+static void
+vqp_make_msg_sig(struct vqp_message_struct * msg)
+{
+ static unsigned rand_num = 0;
+ int i;
+
+ /* hash message contents to get some initial random num */
+ if(!rand_num) {
+ for(i=0; i < msg->content_len; i++)
+ rand_num += msg->content[i];
+ rand_num %= 211;
+ }
+
+ /* make sure the rng is seeded correctly */
+ srand((unsigned) time(NULL) + rand_num++);
+
+ /* generate packet signature */
+ for(i=0; i < VQP_LINK_SIG_LEN; i++)
+ msg->sig[i] = (unsigned char)('0' + rand() % ('9' - '0' + 1));
+
+ /* add '\0' at the end (not truly necessary, but it helps to have
+ * asciiz string instead of an unbounded char[]
+ */
+ msg->sig[VQP_LINK_SIG_LEN] = '\0';
+}
+
+static int
+vqp_is_seen_msg_sig(struct vqp_link_struct * link, char * sig)
+{
+ int i;
+ for(i = 0; i < VQP_LINK_SEEN_SIGS_NUM; i++)
+ if(!memcmp(link->seen_sigs[i], sig, VQP_LINK_SIG_LEN))
+ return 1;
+ return 0;
+}
+
+static void
+vqp_add_seen_msg_sig(struct vqp_message_struct * msg)
+{
+ memcpy(msg->link->seen_sigs[msg->link->seen_sig_inc],
+ msg->sig, VQP_LINK_SIG_LEN);
+ msg->link->seen_sig_inc = (msg->link->seen_sig_inc + 1)
+ % VQP_LINK_SEEN_SIGS_NUM;
+}
+
+static int
+vqp_link_open_setup_udp_multicast(struct vqp_link_struct * link)
+{
+ struct ip_mreq mreq;
+ const unsigned char opt_loop = 1;
+ const unsigned char ttl = 32;
+
+ /* set IP_MULTICAST_LOOP to 1, so our host receives
+ * the messages we send
+ */
+ if(setsockopt( link->tx_socket, IPPROTO_IP, IP_MULTICAST_LOOP,
+ (void*)&opt_loop, sizeof(opt_loop)
+ ) != 0)
+ return -1;
+
+ /* set IP_MULTICAST_TTL to 32, that is the packets
+ * will go through 32 routers before getting scrapped
+ */
+ if(setsockopt( link->tx_socket, IPPROTO_IP, IP_MULTICAST_TTL,
+ (void *)&ttl, sizeof(ttl)
+ ) != 0)
+ return -1;
+
+
+ /* set our group membership */
+ mreq.imr_multiaddr.s_addr = htonl(link->conndata.udp.multicast_address);
+ mreq.imr_interface.s_addr = INADDR_ANY;
+ if(setsockopt( link->rx_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (void *)&mreq, sizeof(mreq)
+ ) != 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+vqp_link_open_setup_tx_broadcast(struct vqp_link_struct * link)
+{
+ const int sock_opt = 1;
+ return setsockopt(
+ link->tx_socket, SOL_SOCKET, SO_BROADCAST,
+ (void *)&sock_opt, sizeof(sock_opt));
+}
+
+static int
+vqp_link_open_setup_udp(struct vqp_link_struct * link, int * p_error)
+{
+ int setup_result;
+ const int sockopt_true = 1;
+ struct sockaddr_in sin;
+
+ /* setup tx socket */
+ link->tx_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if(link->tx_socket < 0) {
+ if(p_error)
+ *p_error = errno;
+ return 1;
+ }
+
+ link->rx_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if(link->rx_socket < 0) {
+ if(p_error)
+ *p_error = errno;
+
+ closesocket(link->tx_socket);
+ return 1;
+ }
+
+ /* on win32 we can setup the socket so we can
+ * use multiple clients on the same pc
+ */
+#ifdef _WIN32
+ setsockopt(
+ link->rx_socket, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&sockopt_true, sizeof(sockopt_true));
+#endif
+
+ /* bind rx socket */
+ sin.sin_family = PF_INET;
+ sin.sin_addr.s_addr = htonl(link->conndata.udp.local_address
+ ? link->conndata.udp.local_address
+ : INADDR_ANY);
+ sin.sin_port = htons(link->port);
+ if(bind(link->rx_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ if(p_error)
+ *p_error = errno;
+
+ closesocket(link->rx_socket);
+ closesocket(link->tx_socket);
+ return 1;
+ }
+
+ link->tx_socket = link->rx_socket;
+
+ /* setup sockets for multicast or broadcast service
+ */
+ setup_result = (link->options & VQP_PROTOCOL_OPT_MULTICAST)
+ ? vqp_link_open_setup_udp_multicast(link)
+ : vqp_link_open_setup_tx_broadcast(link);
+
+ if(setup_result < 0) {
+ if(p_error)
+ *p_error = errno;
+
+ closesocket(link->rx_socket);
+ closesocket(link->tx_socket);
+ return 1;
+ }
+
+ /* success */
+ return 0;
+}
+
+static int vqp_link_open_setup_ipx(struct vqp_link_struct * link, int * p_error)
+{
+ struct sockaddr_ipx six;
+
+ /* setup tx socket */
+ link->tx_socket = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
+ if(link->tx_socket < 0) {
+ if(p_error)
+ *p_error = errno;
+ return 1;
+ }
+
+ if(vqp_link_open_setup_tx_broadcast(link)) {
+ if(p_error)
+ *p_error = errno;
+
+ closesocket(link->tx_socket);
+ return 1;
+ }
+
+ /* setup rx socket */
+ link->rx_socket = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
+ if(link->rx_socket < 0) {
+ if(p_error)
+ *p_error = errno;
+ closesocket(link->rx_socket);
+ return 1;
+ }
+
+ /* bind rx socket */
+ memset(&six, 0, sizeof(six));
+ six.sa_family = AF_IPX;
+ six.sa_socket = htons(ushort2bcd(link->port));
+
+ if(bind(link->rx_socket, (struct sockaddr *)&six, sizeof(six))) {
+ if(p_error)
+ *p_error = errno;
+
+ closesocket(link->rx_socket);
+ closesocket(link->tx_socket);
+ return 1;
+ }
+
+ /* save node and network number */
+ memcpy(link->conndata.ipx.netnum, six.sa_netnum, 4);
+ memcpy(link->conndata.ipx.nodenum, six.sa_nodenum, 6);
+
+ /* success */
+ return 0;
+}
+
+/* exported routines
+ */
+void vqp_init(
+ void * (* mmi_malloc_func)(size_t),
+ void (* mmi_free_func)(void *))
+{
+#ifndef MEMWATCH
+ if(mmi_malloc_func)
+ vqp_mmi_malloc = mmi_malloc_func;
+ else vqp_mmi_malloc = malloc;
+
+ if(mmi_free_func)
+ vqp_mmi_free = mmi_free_func;
+ else vqp_mmi_free = free;
+#endif
+}
+
+void vqp_uninit()
+{
+}
+
+vqp_link_t vqp_link_open(
+ enum vqp_protocol_type protocol,
+ enum vqp_protocol_options options,
+ enum vqp_protocol_connection connection,
+ unsigned long local_address,
+ unsigned long * p_broadcast_addresses, /* 0UL terminated list */
+ unsigned long multicast_address,
+ unsigned short port,
+ int * p_error)
+{
+ struct vqp_link_struct * link;
+
+ /* alloc and init link struct */
+ link = vqp_mmi_malloc(sizeof(struct vqp_link_struct));
+ if(!link) {
+ if(p_error) *p_error = ENOMEM;
+ return NULL;
+ }
+
+ link->rx_socket = 0;
+ link->tx_socket = 0;
+ link->protocol = protocol;
+ link->options = options;
+ link->connection = connection;
+ link->port = port ? port: 8167;
+ link->seen_sig_inc = 0;
+ memset(link->seen_sigs, 0, VQP_LINK_SEEN_SIGS_NUM * VQP_LINK_SIG_LEN);
+
+ if(connection == VQP_PROTOCOL_CONN_UDP) {
+ /* UDP
+ */
+ link->conndata.udp.local_address = local_address;
+ link->conndata.udp.multicast_address = multicast_address;
+ link->conndata.udp.p_broadcast_addresses = NULL;
+
+ if(vqp_link_open_setup_udp(link, p_error)) {
+ vqp_mmi_free(link);
+ return NULL;
+ }
+
+ /* setup broadcast masks lists
+ */
+ if(!(link->options & VQP_PROTOCOL_OPT_MULTICAST)) {
+ /* standard broadcast
+ */
+ int i;
+ for(i = 0; p_broadcast_addresses[i]; i++) /* nothing */ ;
+
+ if(!i) {
+ /* no broadcast addresses defined:
+ * use 255.255.255.255 */
+ link->conndata.udp.p_broadcast_addresses
+ = vqp_mmi_malloc(sizeof(unsigned long) * 2);
+
+ if(!link->conndata.udp.p_broadcast_addresses) {
+ vqp_mmi_free(link);
+ if(p_error)
+ *p_error = ENOMEM;
+
+ closesocket(link->rx_socket);
+ closesocket(link->tx_socket);
+ return NULL;
+ }
+
+ link->conndata.udp.p_broadcast_addresses[0] = 0xffffffffUL;
+ link->conndata.udp.p_broadcast_addresses[1] = 0UL;
+ } else {
+ /* copy broadcast addresses */
+ size_t listsz = sizeof(unsigned long) * (i + 1);
+ link->conndata.udp.p_broadcast_addresses = vqp_mmi_malloc(listsz);
+
+ if(link->conndata.udp.p_broadcast_addresses == NULL) {
+ vqp_mmi_free(link);
+ if(p_error)
+ *p_error = ENOMEM;
+
+ closesocket(link->rx_socket);
+ closesocket(link->tx_socket);
+ return NULL;
+ }
+ memcpy(link->conndata.udp.p_broadcast_addresses,
+ p_broadcast_addresses, listsz);
+ }
+ }
+ }
+ else {
+ /* IPX
+ */
+ if(vqp_link_open_setup_ipx(link, p_error)) {
+ vqp_mmi_free(link);
+ return NULL;
+ }
+ }
+
+ return (vqp_link_t)link;
+}
+
+int vqp_link_close(vqp_link_t vqlink)
+{
+ struct vqp_link_struct * link = P_VQP_LINK_STRUCT(vqlink);
+
+ closesocket(link->tx_socket);
+ closesocket(link->rx_socket);
+
+ if(link->connection == VQP_PROTOCOL_CONN_UDP && link->conndata.udp.p_broadcast_addresses)
+ vqp_mmi_free(link->conndata.udp.p_broadcast_addresses);
+
+ vqp_mmi_free(link);
+
+ return 0;
+}
+
+int vqp_link_rx_socket(vqp_link_t link)
+{
+ return P_VQP_LINK_STRUCT(link)->rx_socket;
+}
+
+enum vqp_protocol_type
+vqp_link_protocol(vqp_link_t link)
+{
+ return P_VQP_LINK_STRUCT(link)->protocol;
+}
+
+int vqp_link_send(vqp_msg_t vqmsg)
+{
+ struct vqp_message_struct * msg = P_VQP_MESSAGE_STRUCT(vqmsg);
+ char * packet;
+ size_t packet_len;
+
+ /* check that the message contains something */
+ if(msg->content_len == 0)
+ return EINVAL;
+
+ /* check that we have the correct msg dst addr (if specified)
+ */
+
+ if(msg->link->protocol == VQP_PROTOCOL_VYPRESSCHAT) {
+ /* assign & register unique packet id for the message */
+ vqp_make_msg_sig(msg);
+ vqp_add_seen_msg_sig(msg);
+
+ /* alloc real packet contents with signature */
+ packet_len = 1 + VQP_LINK_SIG_LEN + msg->content_len;
+ packet = vqp_mmi_malloc(packet_len);
+ if(!packet)
+ return ENOMEM;
+
+ /* fill packet contents in */
+ packet[0] = 'X'; /* vypress chat packet */
+ memcpy(packet + 1, msg->sig, VQP_LINK_SIG_LEN);
+ memcpy(packet + 1 + VQP_LINK_SIG_LEN,
+ msg->content, msg->content_len);
+ } else {
+ /* there's no packet sig to add for quickchat packets */
+ packet = msg->content;
+ packet_len = msg->content_len;
+ }
+
+ if(msg->link->connection == VQP_PROTOCOL_CONN_UDP) {
+ /* IP/UDP transport
+ */
+ struct sockaddr_in sin;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = PF_INET;
+ sin.sin_port = htons(msg->link->port);
+
+ /* send message to all the netmasks/multicasts specified */
+ if(!vqp_addr_is_nil(&msg->dst_addr)) {
+ /* send packet directly to specified address
+ */
+ sin.sin_addr.s_addr = htonl(msg->dst_addr.node.ip);
+ sendto(msg->link->tx_socket, packet, packet_len, 0,
+ (struct sockaddr *)&sin, sizeof(sin));
+ }
+ else if(msg->link->protocol == VQP_PROTOCOL_VYPRESSCHAT
+ && (msg->link->options & VQP_PROTOCOL_OPT_MULTICAST))
+ {
+ /* send packet to multicast group
+ */
+ sin.sin_addr.s_addr = htonl(msg->link->conndata.udp.multicast_address);
+ sendto(msg->link->tx_socket, packet, packet_len, 0,
+ (struct sockaddr *)&sin, sizeof(sin));
+ }
+ else {
+ /* send packet to multiple broadcast addresses
+ */
+ int n;
+ for(n = 0; msg->link->conndata.udp.p_broadcast_addresses[n] != 0; n++) {
+ sin.sin_addr.s_addr = htonl(
+ msg->link->conndata.udp.p_broadcast_addresses[n]);
+
+ sendto(msg->link->tx_socket, packet, packet_len, 0,
+ (struct sockaddr *)&sin, sizeof(sin));
+ }
+ }
+ }
+ else if(msg->link->connection == VQP_PROTOCOL_CONN_IPX) {
+ /* IPX transport
+ */
+ struct sockaddr_ipx six;
+
+ memset(&six, 0, sizeof(six));
+ six.sa_family = AF_IPX;
+ six.sa_socket = htons(ushort2bcd(msg->link->port));
+
+ if(!vqp_addr_is_nil(&msg->dst_addr)) {
+ /* send packet to specified address
+ */
+ memcpy(six.sa_netnum, msg->link->conndata.ipx.netnum, 4);
+ memcpy(six.sa_nodenum, msg->dst_addr.node.ipx, 6);
+ }
+ else {
+ /* send packet to broadcast
+ */
+ memset(six.sa_netnum, 0, 4);
+ memset(six.sa_nodenum, 0xff, 6);
+ }
+
+ sendto( msg->link->tx_socket, packet, packet_len, 0,
+ (struct sockaddr *)&six, sizeof(six));
+ }
+
+ /* free packet data */
+ if(packet != msg->content)
+ vqp_mmi_free(packet);
+
+ return 0; /* packet sent ok */
+}
+
+int vqp_link_recv(vqp_link_t vqlink, vqp_msg_t * p_in_msg)
+{
+ struct vqp_link_struct * link = P_VQP_LINK_STRUCT(vqlink);
+ struct vqp_message_struct * msg;
+ struct sockaddr_in sin;
+ struct sockaddr_ipx six;
+ socklen_t sa_len;
+ char * buf;
+ ssize_t buf_data_len;
+
+ /* receive the msg */
+ buf = vqp_mmi_malloc(VQP_MAX_PACKET_SIZE);
+
+ if(link->connection == VQP_PROTOCOL_CONN_UDP) {
+ sa_len = sizeof(sin);
+ buf_data_len = recvfrom(
+ link->rx_socket, (void*)buf, VQP_MAX_PACKET_SIZE, 0,
+ (struct sockaddr *) &sin, &sa_len);
+ } else {
+ sa_len = sizeof(six);
+ buf_data_len = recvfrom(
+ link->rx_socket, (void *)buf, VQP_MAX_PACKET_SIZE, 0,
+ (struct sockaddr *) &six, &sa_len);
+ }
+
+ if(buf_data_len <= 1) {
+ vqp_mmi_free(buf);
+ return errno;
+ }
+
+ if(link->protocol == VQP_PROTOCOL_VYPRESSCHAT) {
+ /* check that the packets begins with 'X' and contains
+ * a signature */
+ if(buf[0] != 'X' || buf_data_len < (1 + VQP_LINK_SIG_LEN + 1)) {
+ vqp_mmi_free(buf);
+ return 1;
+ }
+
+ /* check that the signature is not already seen */
+ if(vqp_is_seen_msg_sig(link, buf + 1)) {
+ vqp_mmi_free(buf);
+ return 1;
+ }
+ }
+
+ /* alloc message */
+ msg = vqp_mmi_malloc(sizeof(struct vqp_message_struct));
+ if(!msg) return 1;
+
+ msg->link = link;
+ msg->src_addr.conn = link->connection;
+ if(link->connection == VQP_PROTOCOL_CONN_UDP) {
+ msg->src_addr.node.ip = ntohl(sin.sin_addr.s_addr);
+ } else {
+ memcpy(msg->src_addr.node.ipx, six.sa_nodenum, 6);
+ }
+
+ /* copy contents */
+ msg->content_len = (link->protocol == VQP_PROTOCOL_VYPRESSCHAT)
+ ? buf_data_len - 1 - VQP_LINK_SIG_LEN
+ : buf_data_len;
+
+ msg->content = vqp_mmi_malloc(msg->content_len);
+ if(!msg->content) {
+ vqp_mmi_free(buf);
+ vqp_mmi_free(msg);
+ return 1;
+ }
+
+ if(link->protocol == VQP_PROTOCOL_VYPRESSCHAT) {
+ /* copy signature */
+ memcpy(msg->sig, buf + 1, VQP_LINK_SIG_LEN);
+ msg->sig[VQP_LINK_SIG_LEN] = '\0';
+
+ /* copy contents */
+ memcpy(msg->content, buf + 1 + VQP_LINK_SIG_LEN, msg->content_len);
+ } else {
+ memcpy(msg->content, buf, msg->content_len);
+ }
+
+ /* free packet buffer */
+ vqp_mmi_free(buf);
+
+ /* return the msg */
+ *p_in_msg = msg;
+ return 0;
+}
+
+void vqp_addr_nil(vqp_link_t link, vqp_addr_t * p_addr)
+{
+ p_addr->conn = P_VQP_LINK_STRUCT(link)->connection;
+ memset(&p_addr->node, 0, sizeof(union vqp_addr_node_union));
+}
+
+int vqp_addr_is_nil(vqp_addr_t * p_addr)
+{
+ int is_nil;
+
+ if(p_addr->conn == VQP_PROTOCOL_CONN_UDP) {
+ is_nil = (p_addr->node.ip == 0);
+ } else {
+ char nil_ipx[6] = { 0, 0, 0, 0, 0, 0 };
+ is_nil = memcmp(nil_ipx, p_addr->node.ipx, 6) == 0;
+ }
+ return is_nil;
+}
+
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/link.h b/plugins/!NotAdopted/VypressChat/libvqproto/link.h new file mode 100644 index 0000000000..d7ee7bcbed --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/link.h @@ -0,0 +1,106 @@ +/*
+ * libvqproto: Vypress/QChat protocol interface library
+ * (c) Saulius Menkevicius 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: link.h,v 1.11 2005/03/08 17:21:36 bobas Exp $
+ */
+
+#ifndef __LINK_H
+#define __LINK_H
+
+/* header stuff */
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef _WIN32
+/* Win32 system */
+# include <windows.h>
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <wsipx.h>
+#else
+/* UNIX system */
+# include <sys/types.h>
+# include <netinet/in.h>
+# include <sys/socket.h>
+# include <sys/time.h>
+# include <unistd.h>
+# include <netdb.h>
+#endif
+
+/* windows compatibility hacks
+ */
+#ifdef WIN32
+#define ENETUNREACH ENOENT
+#define ENOMSG ENOENT
+#else
+/* unix system */
+#define closesocket close
+#endif
+
+/* link structure
+ */
+#define VQP_LINK_SEEN_SIGS_NUM 20
+#define VQP_LINK_SIG_LEN 9
+
+struct vqp_link_struct {
+ /* link info */
+ enum vqp_protocol_type protocol;
+ enum vqp_protocol_options options;
+ enum vqp_protocol_connection connection;
+ unsigned short port;
+
+ /* connection-specific data */
+ union vqp_link_conndata_union {
+ struct vqp_link_conndata_udp_struct {
+ unsigned long local_address;
+ unsigned long * p_broadcast_addresses;
+ unsigned long multicast_address;
+ } udp;
+
+ struct vqp_link_conndata_ipx_struct {
+ unsigned char netnum[4];
+ unsigned char nodenum[6];
+ } ipx;
+ } conndata;
+
+
+ /* link sockets */
+ int rx_socket, tx_socket;
+
+ /* keeps track packet sigs already seen */
+ unsigned int seen_sig_inc;
+ char seen_sigs[VQP_LINK_SEEN_SIGS_NUM][VQP_LINK_SIG_LEN];
+};
+#define P_VQP_LINK_STRUCT(p) ((struct vqp_link_struct *) p)
+
+/* global data */
+
+#ifdef MEMWATCH
+# include "../contrib/memwatch.h"
+# define vqp_mmi_malloc(s) malloc(s)
+# define vqp_mmi_free(p) free(p)
+#else
+extern void * (* vqp_mmi_malloc)(size_t);
+extern void (* vqp_mmi_free)(void *);
+#endif
+
+#endif /* __LINK_H */
+
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/makefile b/plugins/!NotAdopted/VypressChat/libvqproto/makefile new file mode 100644 index 0000000000..dc76a8eb0c --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/makefile @@ -0,0 +1,21 @@ +# $Id: makefile,v 1.5 2005/03/14 22:35:18 bobas Exp $
+
+TARGET_STATIC = libvqproto.a
+
+O_FILES = link.o message.o uuid.o
+HEADERS = vqproto.h link.h message.h uuid.h
+
+$(TARGET_STATIC): $(O_FILES)
+ $(AR) r $(TARGET_STATIC) $(O_FILES)
+
+link.o: link.c $(HEADERS)
+ $(CC) -c link.c -o link.o
+
+message.o: message.c $(HEADERS)
+ $(CC) -c message.c -o message.o
+
+uuid.o: uuid.c $(HEADERS)
+ $(CC) -c uuid.c -o uuid.o
+
+clean:
+ rm -f *.o $(TARGET_STATIC)
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/message.c b/plugins/!NotAdopted/VypressChat/libvqproto/message.c new file mode 100644 index 0000000000..1ea1233c68 --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/message.c @@ -0,0 +1,1218 @@ +/*
+ * libvqproto: Vypress/QChat protocol interface library
+ * (c) Saulius Menkevicius 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: message.c,v 1.18 2005/03/08 16:53:22 bobas Exp $
+ */
+
+#include <stdarg.h>
+#include <sys/types.h>
+
+#include "vqproto.h"
+#include "link.h"
+#include "message.h"
+
+#ifdef _WIN32
+typedef unsigned int uint32_t;
+#endif
+
+/* static data
+ */
+
+/* static routines
+ */
+static char *
+vqp_msg_printf(size_t * p_res_sz, char * fmt, ...)
+{
+ char * buf, * str;
+ size_t buf_sz, buf_alloc, len;
+ va_list vargs;
+ int ival;
+
+#define BUF_ALLOC_CHUNK 256
+#define BUF_ENSURE_FREE_SZ(size) \
+ if(buf_sz + (size) > buf_alloc) { \
+ char * new_buf; \
+ buf_alloc = ((buf_sz + size + BUF_ALLOC_CHUNK - 1) / BUF_ALLOC_CHUNK) \
+ * BUF_ALLOC_CHUNK; \
+ new_buf = vqp_mmi_malloc(buf_alloc); \
+ if(!new_buf) { \
+ vqp_mmi_free(buf); \
+ va_end(vargs); \
+ return NULL; \
+ } \
+ memcpy(new_buf, buf, buf_sz); \
+ vqp_mmi_free(buf); \
+ buf = new_buf; \
+ }
+
+ /* initialize vars */
+ buf_sz = 0;
+ buf_alloc = BUF_ALLOC_CHUNK;
+ buf = vqp_mmi_malloc(buf_alloc);
+ if(!buf) return NULL;
+
+ /* append args */
+ va_start(vargs, fmt);
+
+ for(; *fmt; fmt ++) {
+ if(*fmt == '%') {
+ switch( *(++ fmt)) {
+ case 'c':
+ /* char */
+ BUF_ENSURE_FREE_SZ(1);
+ buf[buf_sz ++] = (char)va_arg(vargs, int);
+ break;
+
+ case 'l':
+ /* long */
+ BUF_ENSURE_FREE_SZ(sizeof(uint32_t));
+ *((uint32_t *)(buf + buf_sz)) = (uint32_t)va_arg(vargs, int);
+ buf_sz += sizeof(uint32_t);
+ break;
+
+ case 's': /* asciiz */
+ len = strlen(str = va_arg(vargs, char *)) + 1;
+ BUF_ENSURE_FREE_SZ(len);
+ memcpy(buf + buf_sz, (str), len);
+ buf_sz += len;
+ break;
+
+ case 'h':
+ /* channel ('#" + asciiz) */
+ len = strlen(str = va_arg(vargs, char *)) + 2;
+ BUF_ENSURE_FREE_SZ(len);
+ buf[buf_sz] = '#';
+ memcpy(buf + buf_sz + 1, str, len - 1);
+ buf_sz += len;
+ break;
+
+ case 'u':
+ /* uuid */
+ BUF_ENSURE_FREE_SZ(sizeof(vqp_uuid_t));
+ memcpy(buf + buf_sz, (char*)va_arg(vargs, vqp_uuid_t *), sizeof(vqp_uuid_t));
+ buf_sz += sizeof(vqp_uuid_t);
+ break;
+
+ case 'S': /* enum vqp_status */
+ BUF_ENSURE_FREE_SZ(1);
+ ival = va_arg(vargs, int);
+ buf[buf_sz++] = ((enum vqp_status)ival == VQP_STATUS_NOTAVAILABLE)
+ ? '3'
+ : ((enum vqp_status)ival == VQP_STATUS_AWAY)
+ ? '2'
+ : ((enum vqp_status)ival == VQP_STATUS_DND)
+ ? '1': '0';
+ break;
+
+ case 'G': /* enum vqp_gender */
+ BUF_ENSURE_FREE_SZ(1);
+ buf[buf_sz ++] = ((enum vqp_gender)va_arg(vargs, int)
+ == VQP_GENDER_MALE) ? '0': '1';
+ break;
+
+ case 'C': /* enum vqp_codepage */
+ BUF_ENSURE_FREE_SZ(1);
+ buf[buf_sz ++] = ((enum vqp_codepage)va_arg(vargs, int)
+ == VQP_CODEPAGE_LOCALE) ? '0': '1';
+ break;
+
+ case 'A': /* enum vqp_active */
+ BUF_ENSURE_FREE_SZ(1);
+ buf[buf_sz ++] = ((enum vqp_active)va_arg(vargs, int)
+ == VQP_ACTIVE_INACTIVE) ? '0': '1';
+ break;
+
+ case '0': /* '\0' */
+ BUF_ENSURE_FREE_SZ(1);
+ buf[buf_sz ++] = '\0';
+ break;
+
+ /* case '%': */
+ default:
+ /* '%' and the rest */
+ BUF_ENSURE_FREE_SZ(1);
+ buf[buf_sz ++] = *fmt;
+ break;
+ }
+ } else {
+ BUF_ENSURE_FREE_SZ(1);
+ buf[buf_sz ++] = *fmt;
+ }
+ }
+
+ va_end(vargs);
+
+ *p_res_sz = buf_sz;
+ return buf;
+}
+
+/* vqp_msg_scanf:
+ * reads message format (same as vqp_msg_printf)
+ * returns:
+ * non-0 on failure,
+ * 0, on success
+ */
+static int
+vqp_msg_scanf(const struct vqp_message_struct * msg, char * fmt, ...)
+{
+ va_list vargs;
+ char ** str_args[8], * str;
+ const char * buf = msg->content, * scan;
+ ssize_t buf_sz = msg->content_len;
+ int n_str_args = 0, i;
+
+ va_start(vargs, fmt);
+
+ for(; *fmt; fmt++) {
+ /* no more data */
+ if(buf_sz <= 0)
+ goto error_cleanup;
+
+ if(*fmt == '%') {
+ switch(* (++fmt)) {
+ case 'c':
+ *(va_arg(vargs, char *)) = *(buf++);
+ buf_sz -= 1;
+ break;
+
+ case 'l':
+ if(buf_sz < sizeof(uint32_t))
+ goto error_cleanup;
+
+ *(va_arg(vargs, uint32_t *)) = *(uint32_t *)buf;
+ buf += sizeof(uint32_t);
+ buf_sz -= sizeof(uint32_t);
+ break;
+
+ case 'u':
+ if(buf_sz < sizeof(vqp_uuid_t))
+ goto error_cleanup;
+
+ memcpy((char*)va_arg(vargs, vqp_uuid_t *), buf, sizeof(vqp_uuid_t));
+ buf += sizeof(vqp_uuid_t);
+ buf_sz -= sizeof(vqp_uuid_t);
+ break;
+
+ case 's':
+ /* get the length of this string */
+ i = 0;
+ for(scan = buf; *scan != '\0'; scan ++)
+ if(++i == buf_sz) break;
+
+ /* alloc & copy the string */
+ str = vqp_mmi_malloc(i + 1);
+ if(!str) goto error_cleanup;
+
+ memcpy(str, buf, i);
+ str[i] = '\0';
+ buf += i + 1;
+ buf_sz -= i + 1;
+
+ /* store arg */
+ str_args[n_str_args] = va_arg(vargs, char **);
+ *str_args[n_str_args++] = str;
+ break;
+
+ case 'h':
+ /* channel must begin with a '#' */
+ if(*buf != '#')
+ goto error_cleanup;
+
+ /* get the length of channel name (minus the '#' char) */
+ i = 0;
+ for(scan = buf + 1; *scan != '\0'; scan ++)
+ if(++i == buf_sz) break;
+
+ /* the channel name must not be an empty string */
+ if(!i) goto error_cleanup;
+
+ /* alloc & copy the string */
+ str = vqp_mmi_malloc(i + 1);
+ if(!str) goto error_cleanup;
+
+ /* copy the channel name and '\0' (minus the '#') */
+ memcpy(str, buf + 1, i);
+ str[i] = '\0';
+ buf += i + 2;
+ buf_sz -= i + 2;
+
+ /* store arg */
+ str_args[n_str_args] = va_arg(vargs, char **);
+ *str_args[n_str_args++] = str;
+ break;
+
+ case 'S':
+ *(va_arg(vargs, enum vqp_status *)) =
+ (*buf == '3')
+ ? VQP_STATUS_NOTAVAILABLE
+ : (*buf == '2')
+ ? VQP_STATUS_AWAY
+ : (*buf == '1')
+ ? VQP_STATUS_DND
+ : VQP_STATUS_AVAILABLE;
+ buf ++;
+ buf_sz --;
+ break;
+
+ case 'G':
+ *(va_arg(vargs, enum vqp_gender *)) =
+ (*buf == '0') ? VQP_GENDER_MALE: VQP_GENDER_FEMALE;
+ buf ++;
+ buf_sz --;
+ break;
+
+ case 'C':
+ *(va_arg(vargs, enum vqp_codepage *)) =
+ (*buf == '0') ? VQP_CODEPAGE_LOCALE: VQP_CODEPAGE_UTF8;
+ buf ++;
+ buf_sz --;
+ break;
+
+ case 'A':
+ *(va_arg(vargs, enum vqp_active *)) =
+ (*buf == '0') ? VQP_ACTIVE_INACTIVE: VQP_ACTIVE_ACTIVE;
+ buf ++;
+ buf_sz --;
+ break;
+
+ case '0':
+ default:
+ if(*buf != (*fmt == '0' ? '\0': *fmt))
+ goto error_cleanup;
+ buf ++;
+ buf_sz --;
+ break;
+ }
+ } else if(*fmt == '\0') {
+ /* ignore the rest of buf string */
+ goto success;
+ } else {
+ if(*fmt != *buf)
+ goto error_cleanup;
+ buf ++;
+ buf_sz --;
+ }
+ }
+
+success:
+ /* everything was parsed ok */
+ return 0;
+
+error_cleanup:
+ /* free the strings we've alloced so far
+ * and nullify their argument pointers
+ */
+ for(i = 0; i < n_str_args; i++) {
+ free(*str_args[i]);
+ *str_args[i] = NULL;
+ }
+
+ va_end(vargs);
+ return 1;
+}
+
+/* exported routines
+ */
+
+const char *
+vqp_msg_signature(const vqp_msg_t msg)
+{
+ return P_VQP_MESSAGE_STRUCT(msg)->sig;
+}
+
+vqp_link_t
+vqp_msg_link(const vqp_msg_t msg)
+{
+ return (vqp_link_t)P_VQP_MESSAGE_STRUCT(msg)->link;
+}
+
+vqp_addr_t
+vqp_msg_src_addr(const vqp_msg_t msg)
+{
+ return P_VQP_MESSAGE_STRUCT(msg)->src_addr;
+}
+
+/* vqp_msg_parse:
+ * parses the specified message and invokes the corresponding
+ * callback for the message type specified in `parse_func' struct
+ * returns:
+ * non-0 on error
+ * 0 on success
+ */
+void vqp_msg_parse(
+ const struct vqp_parse_func_struct * parsers,
+ const vqp_msg_t vqmsg,
+ void * user_data)
+{
+ const struct vqp_message_struct * msg = P_VQP_MESSAGE_STRUCT(vqmsg);
+ char * s_src = NULL, * s_dst = NULL, * s_text = NULL,
+ * s_timestamp = NULL, * s_floodsecs = NULL, * s_password = NULL,
+ * s_cmdline = NULL, * s_channel = NULL, * s_packetsig = NULL,
+ * s_workgroup = NULL;
+ enum vqp_codepage codepage;
+ enum vqp_status status;
+ enum vqp_gender gender;
+ enum vqp_active active;
+ vqp_uuid_t uuid;
+ unsigned int i_swversion, i_pref_color, i_reserved;
+
+ if(msg->content_len < 2)
+ return;
+
+ switch(msg->content[0])
+ {
+ case '0': /* refresh req */
+ if(!parsers->func_refresh_req)
+ break;
+
+ if(!vqp_msg_scanf(msg, "0%s%C", &s_src, &codepage)) {
+ parsers->func_refresh_req(vqmsg, user_data, s_src, codepage);
+ }
+ else if(!vqp_msg_scanf(msg, "0%s", &s_src)) {
+ parsers->func_refresh_req(vqmsg, user_data, s_src, VQP_CODEPAGE_LOCALE);
+ }
+ break;
+
+ case '1': /* refresh ack */
+ if(!parsers->func_refresh_ack)
+ break;
+
+ /* try to parse as a vypresschat 1.9+ version of ack */
+ if(msg->link->protocol == VQP_PROTOCOL_VYPRESSCHAT
+ && !vqp_msg_scanf(
+ msg, "1%s%s%S%A%0" "%l%G%u" "%0%l%C%l",
+ &s_dst, &s_src, &status, &active,
+ &i_swversion, &gender, &uuid,
+ &i_reserved, &codepage, &i_pref_color))
+ {
+ parsers->func_refresh_ack(
+ vqmsg, user_data,
+ s_src, s_dst, status, active, gender, i_swversion, &uuid,
+ codepage, i_pref_color);
+ }
+ else if(!vqp_msg_scanf(msg, "1%s%s%S%A", &s_dst, &s_src, &status, &active))
+ {
+ vqp_uuid_t empty_uuid;
+ vqp_uuid_create_nil(&empty_uuid);
+
+ parsers->func_refresh_ack(
+ vqmsg, user_data,
+ s_src, s_dst, status, active,
+ VQP_COMPAT_GENDER, VQP_COMPAT_SWVERSION, &empty_uuid,
+ VQP_COMPAT_CODEPAGE, VQP_COMPAT_PREF_COLOR);
+ }
+ else if(msg->link->protocol == VQP_PROTOCOL_QUICKCHAT
+ && !vqp_msg_scanf(msg, "1%s%s%S", &s_dst, &s_src, &status))
+ {
+ vqp_uuid_t empty_uuid;
+ vqp_uuid_create_nil(&empty_uuid);
+
+ parsers->func_refresh_ack(
+ vqmsg, user_data,
+ s_src, s_dst, status,
+ VQP_COMPAT_ACTIVE, VQP_COMPAT_GENDER, VQP_COMPAT_SWVERSION,
+ &empty_uuid, VQP_COMPAT_CODEPAGE, VQP_COMPAT_PREF_COLOR);
+ }
+
+ break;
+
+ case 'P': /* ping / pong */
+ if(msg->link->protocol != VQP_PROTOCOL_VYPRESSCHAT)
+ break;
+
+ if(!vqp_msg_scanf(msg, "P0%s%s%s", &s_dst, &s_src, &s_timestamp)) {
+ if(parsers->func_ping)
+ parsers->func_ping(vqmsg, user_data, s_src, s_dst, s_timestamp);
+ }
+ else if(!vqp_msg_scanf(msg, "P1%s%s%s", &s_dst, &s_src, &s_timestamp)) {
+ if(parsers->func_ping)
+ parsers->func_ping(vqmsg, user_data, s_src, s_dst, s_timestamp);
+ }
+
+ break;
+
+ case 'Z': /* flood notification */
+ if(msg->link->protocol != VQP_PROTOCOL_VYPRESSCHAT
+ || !parsers->func_flood_notification)
+ break;
+
+ if(!vqp_msg_scanf(msg, "Z%s%s%s", &s_dst, &s_src, &s_floodsecs)) {
+ parsers->func_flood_notification(
+ vqmsg, user_data, s_src, s_dst, s_floodsecs);
+ }
+
+ break;
+
+ case '8': /* remote execution */
+ if(!parsers->func_remote_exec)
+ break;
+
+ if(!vqp_msg_scanf(msg, "8%s%s%s%s", &s_src, &s_dst, &s_cmdline, s_password)) {
+ parsers->func_remote_exec(
+ vqmsg, user_data,
+ s_src, s_dst, s_cmdline, s_password);
+ }
+
+ break;
+
+ case '9': /* remote exec ack */
+ if(!parsers->func_remote_exec_ack)
+ break;
+
+ if(!vqp_msg_scanf(msg, "9%s%s%s", &s_dst, &s_src, &s_text)) {
+ parsers->func_remote_exec_ack(
+ vqmsg, user_data,
+ s_src, s_dst, s_text);
+ }
+ break;
+
+ case '3': /* nick change */
+ if(!parsers->func_nick_change)
+ break;
+
+ if(!vqp_msg_scanf(msg, "3%s%s%G", &s_src, &s_text, &gender)) {
+ parsers->func_nick_change(vqmsg, user_data, s_src, s_text, gender);
+ }
+ else if(!vqp_msg_scanf(msg, "3%s%s", &s_src, &s_text)) {
+ parsers->func_nick_change(
+ vqmsg, user_data, s_src, s_text, VQP_COMPAT_GENDER);
+ }
+
+ break;
+
+ case 'D': /* status change */
+ if(!parsers->func_status_change)
+ break;
+
+ if(!vqp_msg_scanf(msg, "D%s%S%G%s", &s_src, &status, &gender, &s_text)) {
+ parsers->func_status_change(
+ vqmsg, user_data, s_src, status, gender, s_text);
+ }
+
+ break;
+
+ case 'M': /* active change */
+ if(!parsers->func_active_change)
+ break;
+
+ if(!vqp_msg_scanf(msg, "M%s%A", &s_src, &active)) {
+ parsers->func_active_change(vqmsg, user_data, s_src, active);
+ }
+
+ break;
+
+ case '4': /* channel join */
+ if(!parsers->func_channel_join)
+ break;
+
+ if(msg->link->protocol==VQP_PROTOCOL_VYPRESSCHAT
+ && !vqp_msg_scanf(
+ msg, "4%s#" VQP_MAIN_CHANNEL "%0%S%G%0%l%u" "%0%C%l%0",
+ &s_src, &status, &gender, &i_swversion, &uuid,
+ &codepage, &i_pref_color))
+ {
+ parsers->func_channel_join(
+ vqmsg, user_data,
+ VQP_MAIN_CHANNEL, s_src, status, gender, i_swversion, &uuid,
+ codepage, i_pref_color);
+ }
+ else if(msg->link->protocol == VQP_PROTOCOL_VYPRESSCHAT
+ && !vqp_msg_scanf(
+ msg, "4%s%h%S%G%0%C%0",
+ &s_src, &s_channel, &status, &gender, &codepage))
+ {
+ vqp_uuid_t nil_uuid;
+ vqp_uuid_create_nil(&nil_uuid);
+
+ parsers->func_channel_join(
+ vqmsg, user_data,
+ s_channel, s_src, status, gender, VQP_COMPAT_SWVERSION, &nil_uuid,
+ codepage, VQP_COMPAT_PREF_COLOR);
+ }
+ else if(!vqp_msg_scanf(msg, "4%s%h%S%G", &s_src, &s_channel, &status, &gender)) {
+ vqp_uuid_t nil_uuid;
+ vqp_uuid_create_nil(&nil_uuid);
+
+ parsers->func_channel_join(
+ vqmsg, user_data,
+ s_channel, s_src, status, gender, VQP_COMPAT_SWVERSION,
+ &nil_uuid, VQP_COMPAT_CODEPAGE, VQP_COMPAT_PREF_COLOR);
+ }
+
+ break;
+
+ case '5': /* channel leave */
+ if(!parsers->func_channel_leave)
+ break;
+
+ if(!vqp_msg_scanf(msg, "5%s%h%G", &s_src, &s_channel, &gender)) {
+ parsers->func_channel_leave(vqmsg, user_data, s_channel, s_src, gender);
+ }
+
+ break;
+
+ case '2': /* channel text */
+ if(!parsers->func_channel_text)
+ break;
+
+ if(!vqp_msg_scanf(msg, "2%h%s%s", &s_channel, &s_src, &s_text)) {
+ parsers->func_channel_text(
+ vqmsg, user_data, s_channel, s_src, s_text, 0);
+ }
+
+ break;
+
+ case 'A': /* channel /me text */
+ if(!parsers->func_channel_text)
+ break;
+
+ if(!vqp_msg_scanf(msg, "A%h%s%s", &s_channel, &s_src, &s_text)) {
+ parsers->func_channel_text(
+ vqmsg, user_data, s_channel, s_src, s_text, 1);
+ }
+
+ break;
+
+ case 'I': /* channel sound request */
+ if(!parsers->func_channel_sound)
+ break;
+
+ if(!vqp_msg_scanf(msg, "I%s%s%h", &s_src, &s_text, &s_channel)) {
+ parsers->func_channel_sound(
+ vqmsg, user_data, s_channel, s_src, s_text);
+ }
+
+ break;
+
+ case 'B': /* topic change */
+ if(!parsers->func_channel_topic_change)
+ break;
+
+ if(msg->link->protocol == VQP_PROTOCOL_VYPRESSCHAT
+ && !vqp_msg_scanf(msg, "B%h%s", &s_channel, &s_text))
+ {
+ parsers->func_channel_topic_change(
+ vqmsg, user_data, s_channel, s_text);
+ }
+ else if(msg->link->protocol == VQP_PROTOCOL_QUICKCHAT
+ && !vqp_msg_scanf(msg, "B%s", &s_text))
+ {
+ parsers->func_channel_topic_change(
+ vqmsg, user_data, VQP_MAIN_CHANNEL, s_text);
+ }
+
+ break;
+
+ case 'C': /* current topic */
+ if(!parsers->func_channel_current_topic)
+ break;
+
+ if(msg->link->protocol == VQP_PROTOCOL_VYPRESSCHAT
+ && !vqp_msg_scanf(msg, "C%s%h%s", &s_dst, &s_channel, &s_text))
+ {
+ parsers->func_channel_current_topic(
+ vqmsg, user_data, s_dst, s_channel, s_text);
+ }
+ else if(msg->link->protocol == VQP_PROTOCOL_QUICKCHAT
+ && !vqp_msg_scanf(msg, "C%s%s", &s_dst, &s_text))
+ {
+ parsers->func_channel_current_topic(
+ vqmsg, user_data, s_dst, VQP_MAIN_CHANNEL, s_text);
+ }
+
+ break;
+
+ case 'L': /* whois is on this channel req */
+ if(!parsers->func_channel_whohere_req)
+ break;
+
+ if(!vqp_msg_scanf(msg, "L%s%h", &s_src, &s_channel)) {
+ parsers->func_channel_whohere_req(
+ vqmsg, user_data, s_channel, s_src);
+ }
+
+ break;
+
+ case 'K': /* whois is on this channel ack */
+ if(!parsers->func_channel_whohere_ack)
+ break;
+
+ if(!vqp_msg_scanf(msg, "K%s%h%s%A", &s_dst, &s_channel, &s_src, &active)) {
+ parsers->func_channel_whohere_ack(
+ vqmsg, user_data, s_channel, s_src, s_dst, active);
+ }
+
+ break;
+
+ case 'N': /* channel list req */
+ if(!parsers->func_channel_list_req)
+ break;
+
+ if(!vqp_msg_scanf(msg, "N%s", &s_src)) {
+ parsers->func_channel_list_req(vqmsg, user_data, s_src);
+ }
+
+ break;
+
+ case 'O': /* channel list ack */
+ if(!parsers->func_channel_list_ack)
+ break;
+
+ if(!vqp_msg_scanf(msg, "O%s%s", &s_dst, &s_text)) {
+ parsers->func_channel_list_ack(vqmsg, user_data, s_dst, s_text);
+ }
+
+ break;
+
+ case '6': /* message */
+ if(!parsers->func_message)
+ break;
+
+ if(!vqp_msg_scanf(msg, "6%s%s%s", &s_src, &s_dst, &s_text)) {
+ parsers->func_message(vqmsg, user_data, s_src, s_dst, s_text, 0);
+ }
+
+ break;
+
+ case 'E': /* multiaddress message */
+ if(!parsers->func_message)
+ break;
+
+ if(!vqp_msg_scanf(msg, "E%s%s%s", &s_src, &s_dst, &s_text)) {
+ parsers->func_message(vqmsg, user_data, s_src, s_dst, s_text, 1);
+ }
+
+ break;
+
+ case '7': /* message ack */
+ if(!parsers->func_message_ack)
+ break;
+
+ if(msg->link->protocol==VQP_PROTOCOL_VYPRESSCHAT
+ && !vqp_msg_scanf(
+ msg, "7%S%s%s%G%s%s",
+ &status, &s_dst, &s_src, &gender, &s_text, &s_packetsig))
+ {
+ parsers->func_message_ack(
+ vqmsg, user_data,
+ s_src, s_dst, status, gender, s_text, s_packetsig);
+ }
+ else if(!vqp_msg_scanf(
+ msg, "7%S%s%s%G%s",
+ &status, &s_dst, &s_src, &gender, &s_text))
+ {
+ parsers->func_message_ack(
+ vqmsg, user_data,
+ s_src, s_dst, status, gender, s_text, VQP_COMPAT_PACKET_SIG);
+ }
+
+ break;
+
+ case 'F': /* info req */
+ if(!parsers->func_info_req)
+ break;
+
+ if(!vqp_msg_scanf(msg, "F%s%s", &s_dst, &s_src)) {
+ parsers->func_info_req(vqmsg, user_data, s_src, s_dst);
+ }
+
+ break;
+
+ case 'G': /* info ack */
+ if(!parsers->func_info_ack)
+ break;
+
+ if(msg->link->protocol == VQP_PROTOCOL_VYPRESSCHAT
+ && !vqp_msg_scanf(msg, "G%s%s%s%s" "%s%s%s" "%s%s%s",
+ &s_dst, &s_src, &s_text, &s_packetsig,
+ &s_timestamp, &s_channel, &s_password,
+ &s_workgroup, &s_cmdline, &s_floodsecs))
+ {
+ parsers->func_info_ack(
+ vqmsg, user_data,
+ s_src, s_dst, s_text, s_packetsig,
+ s_timestamp, s_channel, s_password, s_workgroup,
+ s_cmdline, s_floodsecs);
+ }
+ else if(msg->link->protocol == VQP_PROTOCOL_VYPRESSCHAT
+ && !vqp_msg_scanf(msg, "G%s%s%s%s" "%s%s%s",
+ &s_dst, &s_src, &s_text, &s_packetsig,
+ &s_timestamp, &s_channel, &s_cmdline))
+ {
+ parsers->func_info_ack(
+ vqmsg, user_data,
+ s_src, s_dst, s_text, s_packetsig,
+ s_timestamp, s_channel, s_cmdline, VQP_COMPAT_NETGROUP,
+ VQP_COMPAT_PLATFORM, VQP_COMPAT_SWNAME_VC
+ );
+ }
+ else if(msg->link->protocol == VQP_PROTOCOL_QUICKCHAT
+ && !vqp_msg_scanf(msg, "G%s%s%s%s" "%s%s%s%s",
+ &s_dst, &s_src, &s_text, &s_packetsig,
+ &s_timestamp, &s_password, &s_channel, &s_cmdline))
+ {
+ char * address_str = vqp_mmi_malloc(64);
+
+ if(address_str) {
+ if(msg->link->connection == VQP_PROTOCOL_CONN_UDP) {
+ sprintf(address_str, "%u.%u.%u.%u:%u",
+ (unsigned)((msg->src_addr.node.ip >> 24) & 0xff),
+ (unsigned)((msg->src_addr.node.ip >> 16) & 0xff),
+ (unsigned)((msg->src_addr.node.ip >> 8) & 0xff),
+ (unsigned)(msg->src_addr.node.ip & 0xff),
+ (unsigned)msg->link->port
+ );
+ } else {
+ sprintf(address_str, "%x-%x-%x-%x-%x-%x:%u",
+ (unsigned)(msg->src_addr.node.ipx[0]),
+ (unsigned)(msg->src_addr.node.ipx[1]),
+ (unsigned)(msg->src_addr.node.ipx[2]),
+ (unsigned)(msg->src_addr.node.ipx[3]),
+ (unsigned)(msg->src_addr.node.ipx[4]),
+ (unsigned)(msg->src_addr.node.ipx[5]),
+ (unsigned)msg->link->port
+ );
+ }
+
+ parsers->func_info_ack(
+ vqmsg, user_data,
+ s_src, s_dst, s_text, s_packetsig,
+ address_str, s_channel, s_cmdline, VQP_COMPAT_NETGROUP,
+ VQP_COMPAT_PLATFORM, VQP_COMPAT_SWNAME_QC
+ );
+ vqp_mmi_free(address_str);
+ }
+ }
+
+ break;
+
+ case 'H': /* beep / beep-ack */
+ if(msg->content[1] == '0' && parsers->func_beep_signal) {
+ if(!vqp_msg_scanf(msg, "H0%s%s", &s_dst, &s_src)) {
+ parsers->func_beep_signal(vqmsg, user_data, s_src, s_dst);
+ }
+ }
+ else if(msg->content[1] == '1' && parsers->func_beep_ack) {
+ if(!vqp_msg_scanf(msg, "H1%s%s%G", &s_dst, &s_src, &gender)) {
+ parsers->func_beep_ack(vqmsg, user_data, s_src, s_dst, gender);
+ }
+ }
+
+ break;
+
+ case 'J': /* private open/close/text */
+ if(msg->content[1] == '0' && parsers->func_private_open) {
+ if(!vqp_msg_scanf(msg, "J0%s%s%G", &s_src, &s_dst, &gender)) {
+ parsers->func_private_open(vqmsg, user_data, s_src, s_dst, gender);
+ }
+ }
+ else if(msg->content[1] == '1' && parsers->func_private_close) {
+ if(!vqp_msg_scanf(msg, "J1%s%s%G", &s_src, &s_dst, &gender)) {
+ parsers->func_private_close(vqmsg, user_data, s_src, s_dst, gender);
+ }
+ }
+ else if(msg->content[1] == '2' && parsers->func_private_text) {
+ if(!vqp_msg_scanf(msg, "J2%s%s%s", &s_src, &s_dst, &s_text)) {
+ parsers->func_private_text(
+ vqmsg, user_data, s_src, s_dst, s_text, 0);
+ }
+ }
+ else if(msg->content[1] == '3' && parsers->func_private_text) {
+ if(!vqp_msg_scanf(msg, "J3%s%s%s", &s_src, &s_dst, &s_text)) {
+ parsers->func_private_text(
+ vqmsg, user_data, s_src, s_dst, s_text, 1);
+ }
+ }
+
+ break;
+
+ default:
+ /* unknown message */
+ break;
+ }
+
+ /* free strings we've parsed in */
+ if(s_src) vqp_mmi_free(s_src);
+ if(s_dst) vqp_mmi_free(s_dst);
+ if(s_text) vqp_mmi_free(s_text);
+ if(s_timestamp) vqp_mmi_free(s_timestamp);
+ if(s_floodsecs) vqp_mmi_free(s_floodsecs);
+ if(s_password) vqp_mmi_free(s_password);
+ if(s_cmdline) vqp_mmi_free(s_cmdline);
+ if(s_channel) vqp_mmi_free(s_channel);
+ if(s_packetsig) vqp_mmi_free(s_packetsig);
+ if(s_workgroup) vqp_mmi_free(s_workgroup);
+}
+
+void vqp_msg_free(vqp_msg_t msg)
+{
+ if(P_VQP_MESSAGE_STRUCT(msg)->content)
+ vqp_mmi_free(P_VQP_MESSAGE_STRUCT(msg)->content);
+
+ vqp_mmi_free(msg);
+}
+
+void vqp_msg_set_dst_addr(vqp_msg_t msg, vqp_addr_t dst_addr)
+{
+ P_VQP_MESSAGE_STRUCT(msg)->dst_addr = dst_addr;
+}
+
+/* message contructor functions
+ */
+
+#define NEWMSG_INIT(vqlink) \
+ struct vqp_message_struct * msg; \
+ msg = vqp_mmi_malloc(sizeof(struct vqp_message_struct)); \
+ if(!msg) return NULL; \
+ msg->link = (vqlink); \
+ vqp_addr_nil(vqlink, &msg->dst_addr);
+
+#define NEWMSG_PRINTF(fmt, ...) \
+ msg->content = vqp_msg_printf(&msg->content_len, fmt, __VA_ARGS__); \
+ if(!msg->content) { vqp_mmi_free(msg); return NULL; }
+
+#define NEWMSG_RETURN() \
+ return (vqp_msg_t)msg;
+
+/* user detection messages
+ */
+vqp_msg_t vqp_msg_refresh_req(
+ vqp_link_t link,
+ const char * src, enum vqp_codepage src_codepage)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("0%s%C%0", src, src_codepage);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_refresh_ack(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ enum vqp_status src_status, enum vqp_active src_active, enum vqp_gender src_gender,
+ unsigned int src_swversion, const vqp_uuid_t * src_uuid,
+ enum vqp_codepage src_codepage, unsigned int src_pref_color)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF(
+ "1%s%s%S%A%0" "%l%G%u%0%l" "%C%l%0",
+ dst, src, src_status, src_active,
+ (unsigned int)src_swversion, src_gender, src_uuid, (unsigned int)0,
+ src_codepage, (unsigned int)src_pref_color);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_ping(
+ vqp_link_t link,
+ const char * src, const char * dst, const char * time_stamp)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("P0%s%s%s", dst, src, time_stamp);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_pong(
+ vqp_link_t link,
+ const char * src, const char * dst, const char * orig_time_stamp)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("P1%s%s%s", dst, src, orig_time_stamp);
+ NEWMSG_RETURN();
+}
+
+/* flood notification */
+vqp_msg_t vqp_msg_flood_notification(
+ vqp_link_t link,
+ const char * src, const char * dst, const char * secs_blocked)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("Z%s%s%s", dst, src, secs_blocked);
+ NEWMSG_RETURN();
+}
+
+/* remote execution */
+vqp_msg_t vqp_msg_remote_exec(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * cmdline, const char * password)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("8%s%s%s%s", dst, src, cmdline, password);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_remote_exec_ack(
+ vqp_link_t link,
+ const char * src, const char * dst, const char * exec_text)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("9%s%s%s", dst, src, exec_text);
+ NEWMSG_RETURN();
+}
+
+/* user status */
+vqp_msg_t vqp_msg_nick_change(
+ vqp_link_t link,
+ const char * src, const char * src_new_nick, enum vqp_gender src_gender)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("3%s%s%G", src, src_new_nick, src_gender);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_status_change(
+ vqp_link_t link,
+ const char * src, enum vqp_status src_status,
+ enum vqp_gender src_gender, const char * src_autoanswer)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("D%s%S%G%s", src, src_status, src_gender, src_autoanswer);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_active_change(
+ vqp_link_t link,
+ const char * src, enum vqp_active src_is_active)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("M%s%A", src, src_is_active);
+ NEWMSG_RETURN();
+}
+
+/* channels */
+vqp_msg_t vqp_msg_channel_join(
+ vqp_link_t link,
+ const char * channel, const char * src,
+ enum vqp_status src_status, enum vqp_gender src_gender,
+ unsigned int src_swversion, const vqp_uuid_t * src_uuid,
+ enum vqp_codepage src_codepage, unsigned int src_pref_color)
+{
+ NEWMSG_INIT(link);
+
+ if(!strcmp(channel, VQP_MAIN_CHANNEL)) {
+ NEWMSG_PRINTF(
+ "4%s%h%S%G%0" "%l%u%0%C%l%0%0",
+ src, channel, src_status, src_gender,
+ src_swversion, src_uuid, src_codepage, src_pref_color);
+ } else {
+ NEWMSG_PRINTF(
+ "4%s%h%S%G%C%0",
+ src, channel, src_status, src_gender, src_codepage);
+ }
+
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_channel_leave(
+ vqp_link_t link,
+ const char * channel, const char * src,
+ enum vqp_gender src_gender)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("5%s%h%G", src, channel, src_gender);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_channel_text(
+ vqp_link_t link,
+ const char * channel, const char * src,
+ const char * text, int is_action_text)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF(is_action_text ? "A%h%s%s": "2%h%s%s", channel, src, text);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_channel_sound(
+ vqp_link_t link,
+ const char * channel, const char * src,
+ const char * sound_filename)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("I%s%s%h", src, sound_filename, channel);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_channel_topic_change(
+ vqp_link_t link,
+ const char * channel, const char * topic_text)
+{
+ NEWMSG_INIT(link);
+ if(P_VQP_LINK_STRUCT(link)->protocol == VQP_PROTOCOL_VYPRESSCHAT) {
+ NEWMSG_PRINTF("B%h%s", channel, topic_text);
+ } else {
+ NEWMSG_PRINTF("B%s", topic_text);
+ }
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_channel_current_topic(
+ vqp_link_t link,
+ const char * channel, const char * dst, const char * topic_text)
+{
+ NEWMSG_INIT(link);
+ if(P_VQP_LINK_STRUCT(link)->protocol == VQP_PROTOCOL_VYPRESSCHAT) {
+ NEWMSG_PRINTF("C%s%h%s", dst, channel, topic_text);
+ } else {
+ NEWMSG_PRINTF("C%s%s", dst, topic_text);
+ }
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_channel_whohere_req(
+ vqp_link_t link,
+ const char * channel, const char * src)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("L%s%h", src, channel);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_channel_whohere_ack(
+ vqp_link_t link,
+ const char * channel, const char * src, const char * dst,
+ enum vqp_active src_is_active)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("K%s%h%s%A", dst, channel, src, src_is_active);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_channel_list_req(
+ vqp_link_t link,
+ const char * src)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("N%s", src);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_channel_list_ack(
+ vqp_link_t link,
+ const char * dst, const char * channel_list)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("O%s%s", dst, channel_list);
+ NEWMSG_RETURN();
+}
+
+/* message delivery/ack */
+vqp_msg_t vqp_msg_message(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * text, int is_multiaddress_msg)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF(is_multiaddress_msg ? "E%s%s%s": "6%s%s%s", src, dst, text);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_message_ack(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ enum vqp_status src_status, enum vqp_gender src_gender,
+ const char * src_autoanswer, const char * orig_packetsig)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("7%S%s%s%G%s%s",
+ src_status, dst, src, src_gender, src_autoanswer, orig_packetsig);
+ NEWMSG_RETURN();
+}
+
+/* info req-ack */
+vqp_msg_t vqp_msg_info_req(
+ vqp_link_t link,
+ const char * src, const char * dst)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("F%s%s", dst, src);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_info_ack(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * src_computer_name, const char * src_user_name,
+ const char * src_ip_address, const char * src_channel_list,
+ const char * src_autoanswer, const char * src_workgroup,
+ const char * src_platform, const char * src_software)
+{
+ NEWMSG_INIT(link);
+
+ if(P_VQP_LINK_STRUCT(link)->protocol == VQP_PROTOCOL_VYPRESSCHAT) {
+ NEWMSG_PRINTF("G%s%s%s%s" "%s%s%s" "%s%s%s%0",
+ dst, src, src_computer_name, src_user_name,
+ src_ip_address, src_channel_list, src_autoanswer,
+ src_workgroup, src_platform, src_software);
+ } else {
+ NEWMSG_PRINTF("G%s%s%s%s0 %%%00 Kb%0%s%s",
+ dst, src, src_computer_name, src_user_name,
+ src_channel_list, src_autoanswer);
+ }
+ NEWMSG_RETURN();
+}
+
+/* beep's */
+vqp_msg_t vqp_msg_beep_signal(
+ vqp_link_t link,
+ const char * src, const char * dst)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("H0%s%s", dst, src);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_beep_ack(
+ vqp_link_t link,
+ const char * src, const char * dst, enum vqp_gender src_gender)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("H1%s%s%G", dst, src, src_gender);
+ NEWMSG_RETURN();
+}
+
+/* privates */
+vqp_msg_t vqp_msg_private_open(
+ vqp_link_t link,
+ const char * src, const char * dst, enum vqp_gender src_gender)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("J0%s%s%G", src, dst, src_gender);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_private_close(
+ vqp_link_t link,
+ const char * src, const char * dst, enum vqp_gender src_gender)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF("J1%s%s%G", src, dst, src_gender);
+ NEWMSG_RETURN();
+}
+
+vqp_msg_t vqp_msg_private_text(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * text, int is_action_text)
+{
+ NEWMSG_INIT(link);
+ NEWMSG_PRINTF(
+ is_action_text ? "J3%s%s%s": "J2%s%s%s",
+ src, dst, text);
+ NEWMSG_RETURN();
+}
+
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/message.h b/plugins/!NotAdopted/VypressChat/libvqproto/message.h new file mode 100644 index 0000000000..7f39081f27 --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/message.h @@ -0,0 +1,57 @@ +/*
+ * libvqproto: Vypress/QChat protocol interface library
+ * (c) Saulius Menkevicius 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: message.h,v 1.12 2005/03/08 16:53:22 bobas Exp $
+ */
+
+#ifndef __MESSAGE_H
+#define __MESSAGE_H
+
+#include "link.h"
+
+/* message defaults */
+#define VQP_COMPAT_ACTIVE VQP_ACTIVE_ACTIVE
+#define VQP_COMPAT_GENDER VQP_GENDER_MALE
+#define VQP_COMPAT_CODEPAGE VQP_CODEPAGE_LOCALE
+#define VQP_COMPAT_SWVERSION 0
+#define VQP_COMPAT_PREF_COLOR 0
+#define VQP_COMPAT_PACKET_SIG ""
+#define VQP_COMPAT_SWNAME_QC "QuickChat 1.5 (or compatible)"
+#define VQP_COMPAT_SWNAME_VC "VypressChat 1.5 (or compatible)"
+#define VQP_COMPAT_NETGROUP ""
+#ifdef _WIN32
+# define VQP_COMPAT_PLATFORM "Windows"
+#else
+# define VQP_COMPAT_PLATFORM "Unix"
+#endif
+
+/* message structs */
+
+struct vqp_message_struct {
+ struct vqp_link_struct * link;
+
+ char sig[VQP_LINK_SIG_LEN + 1]; /* packet signature */
+ size_t content_len; /* message length */
+ char * content; /* message contents */
+ vqp_addr_t src_addr; /* packet source address */
+ vqp_addr_t dst_addr; /* packet destination address (can be not specified) */
+};
+#define P_VQP_MESSAGE_STRUCT(p) ((struct vqp_message_struct *)p)
+
+#endif /* __MESSAGE_H */
+
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/protocol-direct-connections b/plugins/!NotAdopted/VypressChat/libvqproto/protocol-direct-connections new file mode 100644 index 0000000000..9de272f17f --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/protocol-direct-connections @@ -0,0 +1,97 @@ +$Id: protocol-direct-connections,v 1.1 2005/03/17 11:02:44 bobas Exp $
+
+Vypress Chat 1.9x+ direct connection descriptions
+(used for file transfer and private messages)
+2005-03-14
+---------------------------------
+
+You should have TCP listening socket at the same port as you have
+UDP message socket. After accepting and getting the socket you
+should recv an packet header, with 2 newlines at the end. newlines
+are (char)0x0a.
+
+[File transfer request]
+ protocol: vychat<0x0a>
+ version: 1<0x0a>
+ message-type: file-transfer<0x0a>
+ content-type: binary<0x0a>
+ content-length: 213<0x0a>
+ file-name: abc.txt<0x0a>
+ file-desc: my text file description<0x0a>
+ files-left: 0<0x0a>
+ desc-files-name:<0x20>
+ desc-files-size: 0<0x0a>
+ user-uuid: my-uuid(MS UUID string representation)<0x0a>
+ <0x0a>
+ <0x0a>
+ <0x00>
+
+ [<file-content> if we get <file-transfer-ack>]
+
+[File transfer ack]
+ protocol: vychat<0x0a>
+ version: 1<0x0a>
+ message-type: file-transfer-ready<0x0a>
+ <0x0a>
+
+[File transfer deny]
+ protocol: vychat<0x0a>
+ version: 1<0x0a>
+ message-type: file-transfer-deny<0x0a>
+ start-from: 0<0x0a>
+ <0x0a>
+
+[File transfer done]
+ protocol: vychat<0x0a>
+ version: 1<0x0a>
+ message-type: file-transfer-done<0x0a>
+ ?????????????????????????????????
+
+[Chat request]
+ protocol: vychat<0x0a>
+ version: 1<0x0a>
+ message-type: chat-request<0x0a>
+ user-uuid: <my-uuid(MS UUID string representation)><0x0a>
+ user-name: <my-nickname><0x0a>
+ ckey: <public key for this communication><0x0a>
+ content-length: 0<0x0a>
+ <0x0a>
+
+[Chat request OK]
+ protocol: vychat<0x0a>
+ version: 1<0x0a>
+ message-type: chat-request-ok<0x0a>
+ user-uuid: <my-uuid(MS UUID string representation)><0x0a>
+ user-name: HIGHLAND<0x0a>
+ ckey: <0x0a>
+ content-length: 0<0x0a>
+ <0x0a>
+
+[Chat msg: typing]
+ protocol: vychat<0x0a>
+ version: 1<0x0a>
+ message-type: chat-msg-typing<0x0a>
+ user-uuid: <my-uuid(MS UUID string representation)><0x0a>
+ user-name: HIGHLAND<0x0a>
+ typing-mode: <'0' or '1'><0x0a>
+ content-length: 0<0x0a>
+ <0x0a>
+
+[Chat msg]
+ protocol: vychat<0x0a>
+ version: 1<0x0a>
+ message-type: chat-msg<0x0a>
+ user-uuid: <my-uuid(MS UUID string representation)><0x0a>
+ user-name: HIGHLAND<0x0a>
+ content-length: <content-length><0x0a>
+ <0x0a>
+ <content>
+
+[Chat request FIN]
+ protocol: vychat<0x0a>
+ version: 1<0x0a>
+ message-type: chat-request-fin
+ user-uuid: <my-uuid><0x0a>
+ user-name: <my-nickname><0x0a>
+ content-length: 0<0x0a>
+ <0x0a>
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/uuid.c b/plugins/!NotAdopted/VypressChat/libvqproto/uuid.c new file mode 100644 index 0000000000..9d4073af07 --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/uuid.c @@ -0,0 +1,108 @@ +/*
+ * libvqproto: Vypress/QChat protocol interface library
+ * (c) Saulius Menkevicius 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: uuid.c,v 1.2 2005/03/02 18:29:09 bobas Exp $
+ */
+
+#include "vqproto.h"
+#include "link.h"
+#include "uuid.h"
+
+#ifdef _WIN32
+# include <rpc.h>
+#endif
+
+/* static data
+ */
+
+/* static routines
+ */
+
+/* exported routines
+ */
+
+void vqp_uuid_create(vqp_uuid_t * p_uuid)
+{
+#ifdef _WIN32
+ UuidCreate((UUID *) p_uuid);
+#else
+ /* XXX */
+#endif
+}
+
+void vqp_uuid_create_nil(vqp_uuid_t * p_uuid)
+{
+#ifdef _WIN32
+ UuidCreateNil((UUID *) p_uuid);
+#else
+ /* XXX */
+#endif
+}
+
+int vqp_uuid_is_nil(const vqp_uuid_t * p_uuid)
+{
+#ifdef _WIN32
+ RPC_STATUS rpc_status;
+ return UuidIsNil((UUID *) p_uuid, &rpc_status);
+#else
+ /* XXX */
+ return 0;
+#endif
+}
+
+int vqp_uuid_is_equal(const vqp_uuid_t * p_uuid_a, const vqp_uuid_t * p_uuid_b)
+{
+#ifdef _WIN32
+ RPC_STATUS rpc_status;
+ return UuidCompare((UUID *) p_uuid_a, (UUID *) p_uuid_b, &rpc_status) == 0;
+#else
+ /* XXX */
+ return 0;
+#endif
+}
+
+char * vqp_uuid_to_string(const vqp_uuid_t * p_uuid)
+{
+#ifdef _WIN32
+ unsigned char * rpc_str;
+ char * str;
+ int len;
+
+ UuidToString((UUID *) p_uuid, &rpc_str);
+ len = strlen(rpc_str) + 1;
+ str = vqp_mmi_malloc(len);
+ memcpy(str, rpc_str, len);
+ RpcStringFree(&rpc_str);
+
+ return str;
+#else
+ /* XXX */
+ return NULL;
+#endif
+}
+
+int vqp_uuid_from_string(vqp_uuid_t * p_uuid, const char * str)
+{
+#ifdef _WIN32
+ return UuidFromString((unsigned char *)str, (UUID *) p_uuid) != RPC_S_OK;
+#else
+ /* XXX */
+ return 1;
+#endif
+}
+
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/uuid.h b/plugins/!NotAdopted/VypressChat/libvqproto/uuid.h new file mode 100644 index 0000000000..485ef5ce48 --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/uuid.h @@ -0,0 +1,27 @@ +/*
+ * libvqproto: Vypress/QChat protocol interface library
+ * (c) Saulius Menkevicius 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: uuid.h,v 1.1 2005/02/28 19:55:23 bobas Exp $
+ */
+
+#ifndef __UUID_H
+#define __UUID_H
+
+
+#endif /* __UUID_H */
+
diff --git a/plugins/!NotAdopted/VypressChat/libvqproto/vqproto.h b/plugins/!NotAdopted/VypressChat/libvqproto/vqproto.h new file mode 100644 index 0000000000..a631936c26 --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/libvqproto/vqproto.h @@ -0,0 +1,595 @@ +/*
+ * libvqproto: Vypress/QChat protocol interface library
+ * (c) Saulius Menkevicius 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: vqproto.h,v 1.14 2005/03/17 11:02:44 bobas Exp $
+ */
+
+#ifndef __VQPROTO_H
+#define __VQPROTO_H
+
+/* required headers */
+#include <sys/types.h>
+
+/* notes
+ *-----------------------------------
+
+I. All the functions (except some of them) return 0 on success, and non-0
+ as unix-style error constant (ENOMEM, EACCESS, etc).
+
+*/
+
+/* API constants & macros
+ *-----------------------------------*/
+#define VQP_MAX_PACKET_SIZE 0x2000
+#define VQP_MAIN_CHANNEL "Main"
+#define VQP_MAKE_SWVERSION(hi, lo) \
+ ((((hi) & 0xffff) << 16) | ((lo) & 0xffff))
+
+/* type definitions
+ *-----------------------------------*/
+typedef void * vqp_link_t;
+typedef void * vqp_msg_t;
+typedef void * vqp_dconn_t;
+
+typedef struct vqp_uuid_struct {
+ unsigned long data1;
+ unsigned short data2, data3;
+ unsigned char data4[8];
+} vqp_uuid_t;
+
+enum vqp_protocol_type {
+ VQP_PROTOCOL_QUICKCHAT,
+ VQP_PROTOCOL_VYPRESSCHAT
+}
+;
+enum vqp_protocol_options {
+ VQP_PROTOCOL_OPT_MULTICAST = 1,
+ VQP_PROTOCOL_OPT_FILETRANSFER = 2
+};
+
+enum vqp_protocol_connection {
+ VQP_PROTOCOL_CONN_UDP,
+ VQP_PROTOCOL_CONN_IPX
+};
+
+enum vqp_status {
+ VQP_STATUS_AVAILABLE,
+ VQP_STATUS_AWAY,
+ VQP_STATUS_DND,
+ VQP_STATUS_NOTAVAILABLE
+};
+
+enum vqp_active {
+ VQP_ACTIVE_ACTIVE,
+ VQP_ACTIVE_INACTIVE
+};
+
+enum vqp_gender {
+ VQP_GENDER_MALE,
+ VQP_GENDER_FEMALE
+};
+
+enum vqp_codepage {
+ VQP_CODEPAGE_LOCALE,
+ VQP_CODEPAGE_UTF8
+};
+
+typedef struct vqp_addr_struct {
+ enum vqp_protocol_connection conn;
+
+ union vqp_addr_node_union {
+ unsigned long ip;
+ unsigned char ipx[6];
+ } node;
+} vqp_addr_t;
+
+struct vqp_parse_func_struct {
+ unsigned int struct_size;
+
+ /* user detection */
+ void (* func_refresh_req)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, enum vqp_codepage src_codepage);
+
+ void (* func_refresh_ack)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst,
+ enum vqp_status src_mode, enum vqp_active src_active, enum vqp_gender src_gender,
+ unsigned int src_swversion, const vqp_uuid_t * src_uuid,
+ enum vqp_codepage src_codepage, unsigned int src_pref_color);
+
+ void (* func_ping)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst, const char * time_stamp);
+
+ void (* func_pong)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst, const char * orig_time_stamp);
+
+ /* flood notification */
+ void (* func_flood_notification)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst, const char * secs_blocked);
+
+ /* remote execution */
+ void (* func_remote_exec)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst,
+ const char * cmdline, const char * password);
+
+ void (* func_remote_exec_ack)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst, const char * exec_text);
+
+ /* user status */
+ void (* func_nick_change)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * src_new_nick, enum vqp_gender src_gender);
+
+ void (* func_status_change)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, enum vqp_status src_status,
+ enum vqp_gender src_gender, const char * src_autoanswer);
+
+ void (* func_active_change)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, enum vqp_active src_is_active);
+
+ /* channels */
+ void (* func_channel_join)(
+ const vqp_msg_t msg, void * user_data,
+ const char * channel, const char * src,
+ enum vqp_status src_status, enum vqp_gender src_gender,
+ unsigned int src_swversion, const vqp_uuid_t * src_uuid,
+ enum vqp_codepage src_codepage, unsigned int src_pref_color);
+
+ void (* func_channel_leave)(
+ const vqp_msg_t msg, void * user_data,
+ const char * channel, const char * src,
+ enum vqp_gender src_gender);
+
+ void (* func_channel_text)(
+ const vqp_msg_t msg, void * user_data,
+ const char * channel, const char * src,
+ const char * text, int is_action_text);
+
+ void (* func_channel_sound)(
+ const vqp_msg_t msg, void * user_data,
+ const char * channel, const char * src,
+ const char * sound_filename);
+
+ void (* func_channel_topic_change)(
+ const vqp_msg_t msg, void * user_data,
+ const char * channel, const char * topic_text);
+
+ void (* func_channel_current_topic)(
+ const vqp_msg_t msg, void * user_data,
+ const char * channel, const char * dst,
+ const char * topic_text);
+
+ void (* func_channel_whohere_req)(
+ const vqp_msg_t msg, void * user_data,
+ const char * channel, const char * src);
+
+ void (* func_channel_whohere_ack)(
+ const vqp_msg_t msg, void * user_data,
+ const char * channel, const char * src, const char * dst,
+ enum vqp_active src_is_active);
+
+ void (* func_channel_list_req)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src);
+
+ void (* func_channel_list_ack)(
+ const vqp_msg_t msg, void * user_data,
+ const char * dst, const char * channel_list);
+
+ /* message delivery/ack */
+ void (* func_message)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst,
+ const char * text, int is_multiaddress_msg);
+
+ void (* func_message_ack)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst,
+ enum vqp_status src_status, enum vqp_gender src_gender,
+ const char * src_autoanswer, const char * orig_packetsig);
+
+ /* info req-ack */
+ void (* func_info_req)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst);
+
+ void (* func_info_ack)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst,
+ const char * src_computer_name, const char * src_user_name,
+ const char * src_ip_addresses, const char * src_channel_list,
+ const char * src_autoanswer, const char * src_workgroup,
+ const char * src_platform, const char * src_software);
+
+ /* beep's */
+ void (* func_beep_signal)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst);
+
+ void (* func_beep_ack)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst, enum vqp_gender src_gender);
+
+ /* privates */
+ void (* func_private_open)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst, enum vqp_gender src_gender);
+
+ void (* func_private_close)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst, enum vqp_gender src_gender);
+
+ void (* func_private_text)(
+ const vqp_msg_t msg, void * user_data,
+ const char * src, const char * dst,
+ const char * text, int is_action_text);
+};
+
+struct vqp_dconn_parse_funcs {
+ unsigned int struct_size;
+
+ /* user detection */
+ void (* func_file_transfer) (
+ const vqp_dconn_t dconn, void * user_data,
+ size_t content_len, const char * file_name,
+ const char * file_desc, int files_left, vqp_uuid_t * p_uuid);
+
+ void (* func_file_transfer_ready) (
+ const vqp_dconn_t dconn, void * user_data);
+
+ void (* func_data)(
+ const vqp_dconn_t dconn, void * user_data,
+ void * data, size_t data_sz);
+};
+
+/* link functions
+ *-----------------------------------*/
+
+/* vqp_init:
+ * initializes the library.
+ *
+ * you can override the default memory interface (malloc/free) with user-supplied
+ * routines by specifying mmi_malloc and mmi_free parameters
+ */
+void vqp_init(
+ void * (* mmi_malloc)(size_t),
+ void (* mmi_free)(void *));
+
+/* vqp_uninit:
+ * deinitializes the library.
+ *
+ * currently does nothing, but you should call it anyway
+ */
+void vqp_uninit();
+
+/* vqp_link_open:
+ * allocates new link to the network
+ *
+ * returns:
+ * link identifier (vqp_link_t), or NULL on error
+ * unix error num in *p_error
+ */
+vqp_link_t vqp_link_open(
+ enum vqp_protocol_type protocol,
+ enum vqp_protocol_options options,
+ enum vqp_protocol_connection connection,
+ unsigned long local_address, /* address to bind to (can be 0) (with IP only) */
+ unsigned long * p_broadcast_addresses, /* 0UL terminated list, (with IP only) */
+ unsigned long multicast_address, /* (with IP only) */
+ unsigned short port,
+ int * p_error);
+
+/* vqp_link_close:
+ * closes the link
+ */
+int vqp_link_close(vqp_link_t link);
+
+/* vqp_link_rx_socket:
+ * returns RX (receiving) socket of the link
+ * which can be used to select() the link message socket
+ */
+int vqp_link_rx_socket(vqp_link_t link);
+
+/* vqp_link_file_rx:
+ * returns server socket of the link that you can select() on and accept()
+ * (this works with VQP_PROTOCOL_CONN_UDP only)
+ */
+int vqp_link_file_rx(vqp_link_t link);
+
+/* vqp_link_protocol:
+ * returns links's protocol
+ */
+enum vqp_protocol_type vqp_link_protocol(vqp_link_t);
+
+/* vqp_link_send:
+ * sends specified message
+ */
+int vqp_link_send(vqp_msg_t msg);
+
+/* vqp_link_recv:
+ * receives message from the link
+ *
+ * returns:
+ * 0, on success, *p_in_msg is set to new message
+ * unix-style errno (Exxx), on error
+ */
+int vqp_link_recv(vqp_link_t link, vqp_msg_t * p_in_msg);
+
+/* address funcs
+ *-----------------------------------*/
+/* vqp_addr_nil:
+ * returns a 'nil' address for specified link
+ */
+void vqp_addr_nil(vqp_link_t link, vqp_addr_t * p_addr);
+
+/* vqp_addr_is_nil:
+ * returns if address is a nil address
+ */
+int vqp_addr_is_nil(vqp_addr_t * p_addr);
+
+/* uuid (unique user identifier) funcs
+ *-----------------------------------*/
+
+/* vqp_uuid_create:
+ * creates unique uuid,
+ */
+void vqp_uuid_create(vqp_uuid_t * uuid);
+
+/* vqp_uuid_create_nil:
+ * creates a nil uuid,
+ */
+void vqp_uuid_create_nil(vqp_uuid_t * uuid);
+
+/* vqp_uuid_is_nil:
+ * returns non-0, if the uuid is nil
+ */
+int vqp_uuid_is_nil(const vqp_uuid_t * uuid);
+
+/* vqp_uuid_is_equal:
+ * returns non-0 if the uuids are equal
+ */
+int vqp_uuid_is_equal(const vqp_uuid_t * uuid_a, const vqp_uuid_t * uuid_b);
+
+/* vqp_uuid_to_string:
+ * returns a malloc'ed string representation of the uuid
+ */
+char * vqp_uuid_to_string(const vqp_uuid_t * uuid);
+
+/* vqp_uuid_from_string:
+ * tries to parse the uuid string and copy its contents
+ * to @uuid;
+ * returns:
+ * 0 on success,
+ * non-o on failure
+ */
+int vqp_uuid_from_string(vqp_uuid_t * uuid, const char * str);
+
+/* message handling
+ *-----------------------------------*/
+const char * vqp_msg_signature(const vqp_msg_t msg);
+vqp_link_t vqp_msg_link(const vqp_msg_t msg);
+vqp_addr_t vqp_msg_src_addr(const vqp_msg_t msg);
+
+void vqp_msg_parse(
+ const struct vqp_parse_func_struct * parse_func,
+ const vqp_msg_t msg,
+ void * user_data);
+
+void vqp_msg_free(vqp_msg_t msg);
+
+void vqp_msg_set_dst_addr(vqp_msg_t msg, vqp_addr_t dst_addr);
+
+/* user detection */
+vqp_msg_t vqp_msg_refresh_req(
+ vqp_link_t link,
+ const char * src, enum vqp_codepage src_codepage);
+
+vqp_msg_t vqp_msg_refresh_ack(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ enum vqp_status src_mode, enum vqp_active src_active, enum vqp_gender src_gender,
+ unsigned int src_swversion, const vqp_uuid_t * src_uuid,
+ enum vqp_codepage src_codepage, unsigned int src_pref_color);
+
+vqp_msg_t vqp_msg_ping(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * time_stamp);
+
+vqp_msg_t vqp_msg_pong(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * orig_time_stamp);
+
+/* flood notification */
+vqp_msg_t vqp_msg_flood_notification(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * secs_blocked);
+
+/* remote execution */
+vqp_msg_t vqp_msg_remote_exec(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * cmdline, const char * password);
+
+vqp_msg_t vqp_msg_remote_exec_ack(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * exec_text);
+
+/* user status */
+vqp_msg_t vqp_msg_nick_change(
+ vqp_link_t link,
+ const char * src, const char * src_new_nick, enum vqp_gender src_gender);
+
+vqp_msg_t vqp_msg_status_change(
+ vqp_link_t link,
+ const char * src, enum vqp_status src_status,
+ enum vqp_gender src_gender, const char * src_autoanswer);
+
+vqp_msg_t vqp_msg_active_change(
+ vqp_link_t link,
+ const char * src, enum vqp_active src_is_active);
+
+/* channels */
+vqp_msg_t vqp_msg_channel_join(
+ vqp_link_t link,
+ const char * src, const char * channel,
+ enum vqp_status src_status, enum vqp_gender src_gender,
+ unsigned int src_swversion, const vqp_uuid_t * src_uuid,
+ enum vqp_codepage src_codepage, unsigned int src_pref_color);
+
+vqp_msg_t vqp_msg_channel_leave(
+ vqp_link_t link,
+ const char * channel, const char * src,
+ enum vqp_gender src_gender);
+
+vqp_msg_t vqp_msg_channel_text(
+ vqp_link_t link,
+ const char * channel, const char * src,
+ const char * text, int is_action_text);
+
+vqp_msg_t vqp_msg_channel_sound(
+ vqp_link_t link,
+ const char * channel, const char * src,
+ const char * sound_filename);
+
+vqp_msg_t vqp_msg_channel_topic_change(
+ vqp_link_t link,
+ const char * channel, const char * topic_text);
+
+vqp_msg_t vqp_msg_channel_current_topic(
+ vqp_link_t link,
+ const char * channel, const char * dst,
+ const char * topic_text);
+
+vqp_msg_t vqp_msg_channel_whohere_req(
+ vqp_link_t link,
+ const char * channel, const char * src);
+
+vqp_msg_t vqp_msg_channel_whohere_ack(
+ vqp_link_t link,
+ const char * channel, const char * src, const char * dst,
+ enum vqp_active src_is_active);
+
+vqp_msg_t vqp_msg_channel_list_req(
+ vqp_link_t link,
+ const char * src);
+
+vqp_msg_t vqp_msg_channel_list_ack(
+ vqp_link_t link,
+ const char * dst, const char * channel_list);
+
+/* message delivery/ack */
+vqp_msg_t vqp_msg_message(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * text, int is_multiaddress_msg);
+
+vqp_msg_t vqp_msg_message_ack(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ enum vqp_status src_status, enum vqp_gender src_gender,
+ const char * src_autoanswer, const char * orig_packetsig);
+
+/* info req-ack */
+vqp_msg_t vqp_msg_info_req(
+ vqp_link_t link,
+ const char * src, const char * dst);
+
+vqp_msg_t vqp_msg_info_ack(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * src_computer_name, const char * src_user_name,
+ const char * src_ip_addresses, const char * src_channel_list,
+ const char * src_autoanswer, const char * src_workgroup,
+ const char * src_platform, const char * src_software);
+
+/* beep's */
+vqp_msg_t vqp_msg_beep_signal(
+ vqp_link_t link,
+ const char * src, const char * dst);
+
+vqp_msg_t vqp_msg_beep_ack(
+ vqp_link_t link,
+ const char * src, const char * dst, enum vqp_gender src_gender);
+
+/* privates */
+vqp_msg_t vqp_msg_private_open(
+ vqp_link_t link,
+ const char * src, const char * dst, enum vqp_gender src_gender);
+
+vqp_msg_t vqp_msg_private_close(
+ vqp_link_t link,
+ const char * src, const char * dst, enum vqp_gender src_gender);
+
+vqp_msg_t vqp_msg_private_text(
+ vqp_link_t link,
+ const char * src, const char * dst,
+ const char * text, int is_action_text);
+
+/* direct connection message funcs
+ * (used for file transfers and private messages on vypress chat 2.0)
+ *--------------------------------------------------------------------*/
+
+vqp_dconn_t vqp_dconn_accept(vqp_link_t link);
+
+vqp_dconn_t vqp_dconn_open(vqp_link_t link, vqp_addr_t remote_addr);
+void vqp_dconn_close(vqp_dconn_t dconn);
+
+int vqp_dconn_socket(vqp_dconn_t dconn);
+
+int vqp_dconn_read(
+ vqp_dconn_t dconn, const struct vqp_dconn_parse_funcs * parse_funcs,
+ void * user_data);
+
+int vqp_dconn_send_file_transfer_request(
+ vqp_dconn_t dconn, size_t content_len, const char * file_name,
+ const char * file_desc, int files_left, const vqp_uuid_t * p_uuid);
+
+int vqp_dconn_send_file_transfer_ready(vqp_dconn_t dconn);
+int vqp_dconn_send_file_transfer_deny(vqp_dconn_t dconn);
+int vqp_dconn_send_file_transfer_done(vqp_dconn_t dconn);
+
+int vqp_dconn_send_chat_request(
+ vqp_dconn_t dconn, const vqp_uuid_t * p_uuid, const char * nickname,
+ const char * public_key);
+int vqp_dconn_send_chat_request_ok(
+ vqp_dconn_t dconn, const vqp_uuid_t * p_uuid, const char * nickname);
+int vqp_dconn_send_chat_typing(
+ vqp_dconn_t dconn, const vqp_uuid_t * p_uuid, const char * nickname,
+ int is_typing);
+int vqp_dconn_send_chat_msg(
+ vqp_dconn_t dconn, const vqp_uuid_t * p_uuid, const char * nickname,
+ size_t content_length);
+int vqp_dconn_send_chat_fin(
+ vqp_dconn_t dconn, const vqp_uuid_t * p_uuid, const char * nickname);
+
+int vqp_dconn_send(vqp_dconn_t dconn, const void * data, size_t data_sz);
+
+#endif /* #ifdef __VQPROTO_H */
+
|