├── .gitmodules
├── LICENSE
├── README.md
├── circle.yml
├── tox_tcp_relay
├── avatar.png
├── loop_services.sh
├── tox-bootstrapd.conf
├── tox_tcp_relay.c
└── update_from_ci.sh
└── toxstatus.png
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "c-toxcore"]
2 | path = c-toxcore
3 | url = https://github.com/TokTok/c-toxcore
4 | [submodule "libsodium"]
5 | path = libsodium
6 | url = https://github.com/jedisct1/libsodium
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tox TCP-Relay Node
2 |
3 | run a TCP-Relay/Bootstrap Node for Tox
4 |
5 | ### Build Status
6 |
7 | **CircleCI:** [](https://circleci.com/gh/zoff99/ToxTCP-RelayNode)
8 |
9 | ### Installation (Linux)
10 | ```
11 | git clone https://github.com/zoff99/ToxTCP-RelayNode
12 | cd ToxTCP-RelayNode
13 | cd tox_tcp_relay
14 | chmod a+rwx *.sh tox-bootstrapd*
15 | ./update_from_ci.sh
16 | chmod a+rwx *.sh tox-bootstrapd*
17 | ```
18 |
19 | ### Operation (Linux)
20 | ```
21 | cd ToxTCP-RelayNode
22 | cd tox_tcp_relay
23 | ./loop_services.sh &
24 | sleep 3
25 | cat tox-bootstrapd.log | grep 'Public Key:' # !to see the publickey!
26 | ```
27 |
28 |
29 |
30 | test if your node is working on this webpage:
31 | https://nodes.tox.chat/test
32 |
33 | ```
34 | Public key --> the Public key from the logfile (see above)
35 | IP:Port --> the public external IP address of your Server, the Port=33447 (for TCP) and Port=33446 (for UDP)
36 | UDP / TCP --> select the Protocol you want to Test (both should work)
37 | ```
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | machine:
2 | timezone:
3 | Europe/Berlin
4 | environment:
5 | MAKEFLAGS: ""
6 | ## ----------- RASPI cross compile ----------------
7 | RASPI_PATH: "/home/ubuntu/cc/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin:$PATH"
8 | RASPI_SYSROOT_: "/home/ubuntu/cc/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot"
9 | RASPI_TOOL_PREFIX: arm-linux-gnueabihf
10 | RASPI_INSTALL_DEST: "/home/ubuntu/installdest/"
11 | RASPI_TARGET_: arm-linux-gnueabi
12 | RASPI_HOST_: arm-linux-gnueabi
13 | RASPI_CXX: $RASPI_TOOL_PREFIX-g++
14 | RASPI_AR: $RASPI_TOOL_PREFIX-ar
15 | RASPI_RANLIB: $RASPI_TOOL_PREFIX-ranlib
16 | RASPI_CC: $RASPI_TOOL_PREFIX-gcc
17 | RASPI_LD: $RASPI_TOOL_PREFIX-ld
18 | RASPI_PKG_CONFIG_PATH: "/home/ubuntu/cc/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot/usr/lib/pkgconfig"
19 | RASPI_s_: "/home/ubuntu/src/"
20 | RASPI_PKGSDIR: "/home/ubuntu/pkgs/"
21 | ## ----------- RASPI cross compile ----------------
22 | # ---------------------------------------------------
23 | # v0.1.10 mtweaks2 d4c11ecbc45faf0e66fbe8c4df59b8087d22f409
24 | # v0.1.10 mobtweaks f73b345c21fae0e0e56fae86dc82f63188a00aca
25 | # c-toxcore v0.1.9 a429ef4a28a5e5e0ad010efffb76d2abc3ada0af
26 | # c-toxcore v0.1.8 f6db9333e2d1262e7ba3846563c30f63c98ffa38
27 | # c-toxcore v0.1.7 48c86e942d487a8856cbd25797b320bfb1879ddc
28 | # c-toxcore v0.1.6 895de7ef26e7617769f2271345e414545c2581f8
29 | # c-toxcore v0.1.5 995578f1038842288c1ff552fd796ab2377db6e1
30 | # c-toxcore v0.1.4 27a97a8280813ec05a5209811c40ab23203bb292
31 | # c-toxcore v0.1.3 fdb46f6cf216a866d29402ae991be9c43282dde6
32 | # c-toxcore v0.1.2 a096c71db867ac83fc3e01e0fbe98573d20f9286
33 | # ---------------------------------------------------
34 | # c-toxcore v0.1.9
35 | CTOXCORE_VERSION_HASH: "zoff99/_0.1.10_2017_video_fix_07a"
36 | # c-toxcore repo url
37 | # CTOXCORE_URL: "https://github.com/TokTok/c-toxcore"
38 | CTOXCORE_URL: "https://github.com/zoff99/c-toxcore"
39 | LIBSODIUM_VERSION: "tags/1.0.13"
40 | LIBSODIUM_BRANCH: "1.0.13"
41 | RASPBERRRY_TOOLS_HASH: d820ab9c21969013b4e56c7e9cba25518afcdd44
42 |
43 | dependencies:
44 | pre:
45 | # -----------------------------------
46 | - sudo /etc/init.d/mysql stop ; exit 0
47 | - sudo /etc/init.d/postgresql stop ; exit 0
48 | # -----------------------------------
49 | - sudo apt-get update
50 | - sudo apt-get install cmake
51 | - aptitude search 4l|grep -i convert ; exit 0
52 | - aptitude search 4l|grep -i v4l ; exit 0
53 | - sudo apt-get install build-essential libtool autotools-dev automake checkinstall check git yasm libv4lconvert0 libv4l-dev
54 | - sudo apt-get install libopus-dev libvpx-dev pkg-config
55 | - sudo apt-get install libasound2-dev
56 | - sudo apt-get install linux-generic
57 | - sudo apt-get install libjpeg-dev
58 | - sudo apt-get install libpulse-dev
59 | - sudo apt-get install libconfig-dev
60 |
61 | - sudo bash -c "echo '::1 localhost ipv6-localhost ipv6-loopback' >> /etc/hosts" # ipv6 localhost entry
62 |
63 | - gcc --version ; exit 0
64 | - clang --version ; exit 0
65 |
66 | ### submodules ----------------
67 | - git submodule add --force https://github.com/TokTok/c-toxcore c-toxcore ; echo ok
68 | - git submodule add --force https://github.com/jedisct1/libsodium libsodium ; echo ok
69 | - git submodule init ; git submodule update ; echo ok
70 | # -- sometimes submodule can't find commit hash, whatever ------
71 | - rm -Rf c-toxcore ; git clone "$CTOXCORE_URL"
72 | # -- sometimes submodule can't find commit hash, whatever ------
73 | - cd c-toxcore/ ; git checkout $CTOXCORE_VERSION_HASH
74 | - cd libsodium/ ; git checkout $LIBSODIUM_VERSION
75 | ### submodules ----------------
76 |
77 | ### ------- compile and install libsodium -------
78 | - cd libsodium/ ; ./autogen.sh
79 | - cd libsodium/ ; ./configure && make check
80 | - cd libsodium/ ; sudo bash -c "printf 'y\naa\n\n' | checkinstall --install --pkgname libsodium --pkgversion 1.0.0 --nodoc --deldesc=no --pkglicense='GPL2'"
81 | - cd libsodium/ ; sudo ldconfig
82 | - cd libsodium ; sudo ldconfig -v 2>/dev/null | grep sodium
83 | ## --- now again to save the artefact ---
84 | - cd libsodium ; export INSTALL_DEST=/home/ubuntu/installdest_linux/ ; rm -Rf "$INSTALL_DEST"
85 | - cd libsodium ; export INSTALL_DEST=/home/ubuntu/installdest_linux/ ; mkdir -p "$INSTALL_DEST"/usr ; ./configure --prefix="$INSTALL_DEST"/usr
86 | - cd libsodium ; export INSTALL_DEST=/home/ubuntu/installdest_linux/ ; make install ; ls -alR "$INSTALL_DEST"/usr
87 | - mkdir -p $CIRCLE_ARTIFACTS/ubuntu_14_04_binaries
88 | - export INSTALL_DEST=/home/ubuntu/installdest_linux/ ; cd "$INSTALL_DEST" ; tar -czvf $CIRCLE_ARTIFACTS/ubuntu_14_04_binaries/pkg_libsodium.tar.gz *
89 | ## --- now again to save the artefact ---
90 | ### ------- compile and install libsodium -------
91 |
92 | ### ------------ compile and install c-toxcore ------------
93 | - cd c-toxcore ; cmake -DWARNINGS=OFF .
94 | - cd c-toxcore ; make
95 | - cd c-toxcore ; sudo make install
96 | - cd c-toxcore ; sudo ldconfig -v 2>/dev/null | grep toxcore
97 | ## --- now again to save the artefact ---
98 | - cd c-toxcore ; export INSTALL_DEST=/home/ubuntu/installdest_linux/ ; rm -Rf "$INSTALL_DEST"
99 | - cd c-toxcore ; export INSTALL_DEST=/home/ubuntu/installdest_linux/ ; mkdir -p "$INSTALL_DEST"/usr ; autoreconf -fi ; ./configure --enable-logging --disable-soname-versions --prefix="$INSTALL_DEST"/usr
100 | - cd c-toxcore ; export INSTALL_DEST=/home/ubuntu/installdest_linux/ ; make install ; ls -alR "$INSTALL_DEST"/usr
101 | - mkdir -p $CIRCLE_ARTIFACTS/ubuntu_14_04_binaries
102 | - cp -av c-toxcore/other/bootstrap_daemon/tox-bootstrapd.conf $CIRCLE_ARTIFACTS/ubuntu_14_04_binaries/
103 | - cp -av c-toxcore/tox-bootstrapd $CIRCLE_ARTIFACTS/ubuntu_14_04_binaries/
104 | - cd c-toxcore/ ; /usr/bin/cc -std=c99 -pedantic -isystem /usr/local/include -isystem /usr/include/opus -pthread
105 | CMakeFiles/tox-bootstrapd.dir/other/bootstrap_daemon/src/command_line_arguments.c.o
106 | CMakeFiles/tox-bootstrapd.dir/other/bootstrap_daemon/src/config.c.o
107 | CMakeFiles/tox-bootstrapd.dir/other/bootstrap_daemon/src/log.c.o
108 | CMakeFiles/tox-bootstrapd.dir/other/bootstrap_daemon/src/log_backend_stdout.c.o
109 | CMakeFiles/tox-bootstrapd.dir/other/bootstrap_daemon/src/log_backend_syslog.c.o
110 | CMakeFiles/tox-bootstrapd.dir/other/bootstrap_daemon/src/tox-bootstrapd.c.o
111 | CMakeFiles/tox-bootstrapd.dir/other/bootstrap_node_packets.c.o
112 | -o tox-bootstrapd_static
113 | -L/usr/local/lib -rdynamic -static --static libtoxnetcrypto.a
114 | -lconfig libtoxdht.a libtoxnetwork.a
115 | libtoxcrypto.a -lsodium -lpthread -lrt
116 | -Wl,-rpath,/home/ubuntu/ToxTCP-RelayNode/c-toxcore:/usr/local/lib
117 | - cd c-toxcore/ ; cp -av tox-bootstrapd_static $CIRCLE_ARTIFACTS/ubuntu_14_04_binaries/
118 | - cd c-toxcore/ ; ldd tox-bootstrapd_static ; exit 0
119 | - export INSTALL_DEST=/home/ubuntu/installdest_linux/ ; cd "$INSTALL_DEST" ; tar -czvf $CIRCLE_ARTIFACTS/ubuntu_14_04_binaries/pkg_c-toxcore.tar.gz *
120 | ## --- now again to save the artefact ---
121 | ### ------------ run tests
122 | # - cd c-toxcore ; make test ARGS="-V" ; ex1=$? ; if [ $ex1 -ne 0 ]; then sleep 60; make test ARGS="-V" ; exit $? ; fi
123 | ### ------------ compile and install c-toxcore ------------
124 |
125 |
126 |
127 | ## ----------- RASPI cross compile ----------------
128 | ## ----------- set architecture -------------------
129 | ## ----------- set architecture -------------------
130 | - ARCH="RASPI";printf '#! /bin/bash\nexport CUR_ARCH_="'"$ARCH"'"\n' > ~/glo
131 | - chmod a+rx ~/glo
132 | - cat ~/glo
133 | ## ----------- set architecture -------------------
134 | ## ----------- set architecture -------------------
135 |
136 | - mkdir ~/cc/
137 | - cd ~/cc ; git clone https://github.com/raspberrypi/tools
138 | - cd ~/cc/tools/ ; git checkout $RASPBERRRY_TOOLS_HASH
139 |
140 | - . ~/glo;a=${CUR_ARCH_}_PKG_CONFIG_PATH;mkdir -p "${!a}"
141 | - . ~/glo;a=${CUR_ARCH_}_PKGSDIR;mkdir -p "${!a}"
142 | - . ~/glo;a=${CUR_ARCH_}_SYSROOT_;ls -al "${!a}"
143 | - . ~/glo;a=${CUR_ARCH_}_s_;mkdir -p "${!a}"
144 | - . ~/glo;a=${CUR_ARCH_}_PKGSDIR;mkdir -p "${!a}"
145 |
146 | - . ~/glo;echo 'export PKGSDIR="$'"${CUR_ARCH_}"'_PKGSDIR";export INSTALL_DEST="$'"${CUR_ARCH_}"'_INSTALL_DEST";export PKG_CONFIG_PATH="$'"${CUR_ARCH_}"'_PKG_CONFIG_PATH";export PATH="$'"${CUR_ARCH_}"'_PATH";export CC="$'"${CUR_ARCH_}"'_CC";export CXX="$'"${CUR_ARCH_}"'_CXX";export AR="$'"${CUR_ARCH_}"'_AR";export RANLIB="$'"${CUR_ARCH_}"'_RANLIB";export _s_="$'"${CUR_ARCH_}"'_s_";export _SYSROOT_="$'"${CUR_ARCH_}"'_SYSROOT_";export _HOST_="$'"${CUR_ARCH_}"'_HOST_";export _TARGET_="$'"${CUR_ARCH_}"'_TARGET_";export _TOOL_PREFIX="$'"${CUR_ARCH_}"'_TOOL_PREFIX";export CUR_ARCH_="'"${CUR_ARCH_}"'";export LD="$'"${CUR_ARCH_}"'_LD"' > ~/pp
147 | - chmod u+x ~/pp
148 | - cat ~/pp
149 |
150 | - . ~/glo;printf '#! /bin/bash\n. ~/pp;rm -Rf ~/build/\nmkdir -p ~/build/\narg1_="$1";shift;cd ~/build/;$'"${CUR_ARCH_}"'_s_/"$arg1_"/configure $* && make && make install\n' > ~/do_compile.sh
151 | - chmod a+rx ~/do_compile.sh
152 | - cat ~/do_compile.sh
153 |
154 | - . ~/glo;printf '#! /bin/bash\n. ~/pp;rm -Rf ~/build/\nmkdir -p ~/build/\nrm -Rf "$INSTALL_DEST"\narg1_="$1";shift;cd ~/build/;$_s_/"$arg1_"/configure $* && make && make install && cd "$INSTALL_DEST" && tar -czvf "$PKGSDIR""/"pkg_"$arg1_".tar.gz * && rm -Rf "$INSTALL_DEST" \n' > ~/do_package.sh
155 | - chmod a+rx ~/do_package.sh
156 | - cat ~/do_package.sh
157 |
158 |
159 | - . ~/pp;cd $_s_;git clone --depth=1 --branch=v1.3.0 https://github.com/yasm/yasm.git
160 | - . ~/pp;cd $_s_/yasm/;autoreconf -fi
161 | - . ~/pp;~/do_compile.sh "yasm" --prefix="$_SYSROOT_"/usr --disable-shared --disable-soname-versions --with-sysroot="$_SYSROOT_" --host="$_HOST_" --target="$_TARGET_"
162 |
163 | - . ~/pp;cd $_s_;git clone --depth=1 --branch=v1.6.1 https://github.com/webmproject/libvpx.git
164 | - . ~/pp;export CROSS="arm-linux-gnueabihf-" ; ~/do_compile.sh "libvpx" --prefix="$_SYSROOT_"/usr --disable-examples --disable-unit-tests --target=generic-gnu --extra-cflags="--sysroot=$_SYSROOT_"
165 | - . ~/pp;export CROSS="arm-linux-gnueabihf-" ; ~/do_package.sh "libvpx" --prefix="$INSTALL_DEST"/usr --disable-examples --disable-unit-tests --target=generic-gnu --extra-cflags="--sysroot=$_SYSROOT_"
166 |
167 | - . ~/pp;cd $_s_;git clone --depth=1 --branch=v1.2.1 https://github.com/xiph/opus.git
168 | - . ~/pp;cd $_s_/opus/;autoreconf -fi
169 | - . ~/pp;~/do_compile.sh "opus" --prefix="$_SYSROOT_"/usr --disable-shared --disable-soname-versions --target="$_TOOL_PREFIX" --with-sysroot="$_SYSROOT_" --host="$_TOOL_PREFIX"
170 | - . ~/pp;~/do_package.sh "opus" --prefix="$INSTALL_DEST"/usr --disable-shared --disable-soname-versions --target="$_TOOL_PREFIX" --with-sysroot="$_SYSROOT_" --host="$_TOOL_PREFIX"
171 |
172 | - . ~/pp;cd $_s_;git clone --depth=1 --branch=$LIBSODIUM_BRANCH https://github.com/jedisct1/libsodium.git
173 | - . ~/pp;cd $_s_/libsodium/;autoreconf -fi
174 | - . ~/pp;~/do_compile.sh "libsodium" --prefix="$_SYSROOT_"/usr --disable-shared --disable-soname-versions --target="$_TOOL_PREFIX" --with-sysroot="$_SYSROOT_" --host="$_TOOL_PREFIX" --enable-minimal --disable-pie
175 | - . ~/pp;~/do_package.sh "libsodium" --prefix="$INSTALL_DEST"/usr --disable-shared --disable-soname-versions --target="$_TOOL_PREFIX" --with-sysroot="$_SYSROOT_" --host="$_TOOL_PREFIX" --enable-minimal --disable-pie
176 |
177 | # install raspi binary pkgs -------------------------
178 | - wget 'https://github.com/zoff99/raspi_cross_compile/raw/master/bin_packages/libv4l-dev.tgz' -O ~/pkg2.tgz
179 | - . ~/pp;cd "$_SYSROOT_" ; tar -xzvf ~/pkg2.tgz
180 | - wget 'https://github.com/zoff99/raspi_cross_compile/raw/master/bin_packages/libv4lconvert0.tgz' -O ~/pkg3.tgz
181 | - . ~/pp;cd "$_SYSROOT_" ; tar -xzvf ~/pkg3.tgz
182 | - wget 'https://github.com/zoff99/raspi_cross_compile/raw/master/bin_packages/libjpeg62-turbo.tgz' -O ~/pkg4.tgz
183 | - . ~/pp;cd "$_SYSROOT_" ; tar -xzvf ~/pkg4.tgz
184 | - wget 'https://github.com/zoff99/raspi_cross_compile/raw/master/bin_packages/libjpeg62-turbo-dev.tgz' -O ~/pkg1.tgz
185 | - . ~/pp;cd "$_SYSROOT_" ; tar -xzvf ~/pkg1.tgz
186 | - wget 'https://github.com/zoff99/raspi_cross_compile/raw/master/bin_packages/libconfig-dev.tgz' -O ~/pkg1.tgz
187 | - . ~/pp;cd "$_SYSROOT_" ; tar -xzvf ~/pkg1.tgz
188 | # install raspi binary pkgs -------------------------
189 |
190 | - . ~/pp;cd $_s_;git clone "$CTOXCORE_URL"
191 | - . ~/pp;cd $_s_/c-toxcore/;git checkout $CTOXCORE_VERSION_HASH
192 | - . ~/pp;cd $_s_/c-toxcore/;autoreconf -fi
193 | - . ~/pp;~/do_compile.sh "c-toxcore" --prefix="$_SYSROOT_"/usr --enable-logging --disable-soname-versions --host="$_TOOL_PREFIX" --with-sysroot="$_SYSROOT_" --disable-testing --disable-rt
194 | - . ~/pp;~/do_package.sh "c-toxcore" --prefix="$INSTALL_DEST"/usr --enable-logging --disable-soname-versions --host="$_TOOL_PREFIX" --with-sysroot="$_SYSROOT_" --disable-testing --disable-rt
195 |
196 | # --- toxbootstrapd for RASPI ----
197 | - . ~/pp;~/do_compile.sh "c-toxcore" --prefix="$_SYSROOT_"/usr --enable-logging --enable-daemon --disable-soname-versions --host="$_TOOL_PREFIX" --with-sysroot="$_SYSROOT_" --disable-testing --disable-rt ; exit 0 # this will fail
198 | - . ~/pp; cd /home/ubuntu/build/build ; export V=3 ; /bin/bash ../libtool --tag=CC --mode=link $CC -std=gnu99 -I/home/ubuntu/src//c-toxcore/other/bootstrap_daemon -I"$_SYSROOT_"/usr/include -g -O2 -o tox-bootstrapd ../other/bootstrap_daemon/src/tox_bootstrapd-command_line_arguments.o ../other/bootstrap_daemon/src/tox_bootstrapd-config.o ../other/bootstrap_daemon/src/tox_bootstrapd-log.o ../other/bootstrap_daemon/src/tox_bootstrapd-tox-bootstrapd.o ../other/tox_bootstrapd-bootstrap_node_packets.o libtoxcore.la -L"$_SYSROOT_"/usr/lib -L"$_SYSROOT_"/usr/lib/arm-linux-gnueabihf -lconfig -lsodium ; exit 0
199 | - ls -al /home/ubuntu/build/build/.libs/tox-bootstrapd ; exit 0
200 |
201 | # -- move some lib files for ldd to correctly show output --
202 | - cd ../ ; cd /home/ubuntu/build/build ; . ~/pp ; sed -i -e 's#ld_library_path="/lib:/usr/lib"#ld_library_path="/lib:/usr/lib:/lib/arm-linux-gnueabihf"#' /home/ubuntu/cc/tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-ldd ; exit 0
203 | - cd ../ ; cd /home/ubuntu/build/build ; . ~/pp ; export CT_XLDD_VERBOSE=""; arm-linux-gnueabihf-ldd -s --root $_SYSROOT_ /home/ubuntu/build/build/.libs/tox-bootstrapd ; exit 0
204 | # -- move some lib files for ldd to correctly show output --
205 |
206 |
207 |
208 | - file /home/ubuntu/build/build/.libs/tox-bootstrapd ; exit 0
209 | # --- toxbootstrapd for RASPI ----
210 |
211 | - . ~/pp;mkdir -p $CIRCLE_ARTIFACTS/"${CUR_ARCH_}"/
212 | - . ~/pp;cp -av "$PKGSDIR"/* $CIRCLE_ARTIFACTS/"${CUR_ARCH_}"/
213 |
214 | # --- toxbootstrapd for RASPI ----
215 | - . ~/pp;cp -av /home/ubuntu/build/build/.libs/tox-bootstrapd $CIRCLE_ARTIFACTS/"${CUR_ARCH_}"/ ; exit 0
216 | # --- toxbootstrapd for RASPI ----
217 |
218 | - cd tox_tcp_relay ; rm -fv tox_tcp_relay tox_tcp_relay_static
219 | - cd tox_tcp_relay ; . ~/pp ; $CC -O2 -fPIC -o tox_tcp_relay tox_tcp_relay.c -std=gnu99 -I"$_SYSROOT_"/usr/local/include/ -L"$_SYSROOT_"/usr/lib/arm-linux-gnueabihf/ -lsodium -ltoxcore -ltoxav -lpthread -lvpx -ljpeg -lv4lconvert
220 | - cd tox_tcp_relay ; ldd tox_tcp_relay ; exit 0
221 | - cd tox_tcp_relay ; find . -name '*tox_tcp_relay*' -exec ls -al {} \; 2> /dev/null ; exit 0
222 | - cd tox_tcp_relay ; . ~/pp ; $CC -O2 -Wall -Wextra -Wpedantic -o tox_tcp_relay_static tox_tcp_relay.c -static -std=gnu99 -L"$_SYSROOT_"/usr/lib/arm-linux-gnueabihf/ -I"$_SYSROOT_"/usr/lib/arm-linux-gnueabihf/ -lsodium -ltoxcore -ltoxav -lsodium -lpthread -static-libgcc -static-libstdc++ -lopus -lvpx -lm -lpthread -lv4lconvert -ljpeg -lm -lrt
223 | - cd tox_tcp_relay ; ls -al tox_tcp_relay tox_tcp_relay_static
224 | - cd tox_tcp_relay ;. ~/pp ; cp -av ./tox_tcp_relay $CIRCLE_ARTIFACTS/"${CUR_ARCH_}"/
225 | - cd tox_tcp_relay ;. ~/pp ; cp -av ./tox_tcp_relay_static $CIRCLE_ARTIFACTS/"${CUR_ARCH_}"/
226 |
227 | ## ----------- RASPI cross compile ----------------
228 |
229 |
230 | test:
231 | override:
232 | - cd tox_tcp_relay ; rm -fv tox_tcp_relay tox_tcp_relay_static
233 | - cd tox_tcp_relay ; gcc -O2 -fPIC -o tox_tcp_relay tox_tcp_relay.c -std=gnu99 -lsodium -I/usr/local/include/ -ltoxcore -ltoxav -lpthread -lvpx -lv4lconvert
234 | - cd tox_tcp_relay ; ldd tox_tcp_relay ; exit 0
235 | - find / -name '*libjpeg*' 2> /dev/null ; exit 0
236 | - cd tox_tcp_relay ; gcc -O2 -Wall -Wextra -Wpedantic -o tox_tcp_relay_static tox_tcp_relay.c -static -std=gnu99 -L/usr/local/lib -I/usr/local/include/ -lsodium -ltoxcore -ltoxav -ltoxgroup -ltoxmessenger -ltoxfriends -ltoxnetcrypto -ltoxdht -ltoxnetwork -ltoxcrypto -lsodium -lpthread -static-libgcc -static-libstdc++ -lopus -lvpx -lm -lpthread -lv4lconvert -ljpeg -lm -lrt
237 | - cd tox_tcp_relay ; ls -al tox_tcp_relay tox_tcp_relay_static
238 | - mkdir -p $CIRCLE_ARTIFACTS/ubuntu_14_04_binaries/
239 | - cp -av tox_tcp_relay/tox_tcp_relay $CIRCLE_ARTIFACTS/ubuntu_14_04_binaries/
240 | - cp -av tox_tcp_relay/tox_tcp_relay_static $CIRCLE_ARTIFACTS/ubuntu_14_04_binaries/
241 | - cd tox_tcp_relay ; ./tox_tcp_relay_static :
242 | background: true
243 | - sleep 10
244 | - cd tox_tcp_relay ; cat ./tox_tcp_relay.log
245 | - cd tox_tcp_relay ; cat ./tox_tcp_relay.log | grep '\-\-MyToxID\-\-:' | cut -d':' -f 3
246 | - sleep 10
247 | #- sleep 240
248 | - cd tox_tcp_relay ; cat ./tox_tcp_relay.log
249 |
--------------------------------------------------------------------------------
/tox_tcp_relay/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zoff99/ToxTCP-RelayNode/7fc1ef4ef96d5d2b96cd021e97be4f820b70300c/tox_tcp_relay/avatar.png
--------------------------------------------------------------------------------
/tox_tcp_relay/loop_services.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | cd $(dirname "$0")
4 |
5 | while [ 1 == 1 ]; do
6 | ./tox-bootstrapd_static --foreground --log-backend=stdout --config=tox-bootstrapd.conf >> ./tox-bootstrapd.log 2>&1
7 | sleep 10
8 | done
9 |
--------------------------------------------------------------------------------
/tox_tcp_relay/tox-bootstrapd.conf:
--------------------------------------------------------------------------------
1 | // Tox DHT bootstrap daemon configuration file.
2 |
3 | // Listening port (UDP).
4 | port = 33446
5 |
6 | // A key file is like a password, so keep it where no one can read it.
7 | // If there is no key file, a new one will be generated.
8 | // The daemon should have permission to read/write it.
9 | keys_file_path = "./keys"
10 |
11 | // The PID file written to by the daemon.
12 | // Make sure that the user that daemon runs as has permissions to write to the
13 | // PID file.
14 | pid_file_path = "./tox-bootstrapd.pid"
15 |
16 | // Enable IPv6.
17 | enable_ipv6 = false
18 |
19 | // Fallback to IPv4 in case IPv6 fails.
20 | enable_ipv4_fallback = true
21 |
22 | // Automatically bootstrap with nodes on local area network.
23 | enable_lan_discovery = true
24 |
25 | enable_tcp_relay = true
26 |
27 | // While Tox uses 33445 port by default, 443 (https) and 3389 (rdp) ports are very
28 | // common among nodes, so it's encouraged to keep them in place.
29 | tcp_relay_ports = [33447]
30 |
31 | // Reply to MOTD (Message Of The Day) requests.
32 | enable_motd = true
33 |
34 | // Just a message that is sent when someone requests MOTD.
35 | // Put anything you want, but note that it will be trimmed to fit into 255 bytes.
36 | motd = "tox-bootstrapd"
37 |
38 | // Any number of nodes the daemon will bootstrap itself off.
39 | //
40 | // Remember to replace the provided example with your own node list.
41 | // There is a maintained list of bootstrap nodes on Tox's wiki, if you need it
42 | // (https://wiki.tox.chat/doku.php?id=users:nodes).
43 | //
44 | // You may leave the list empty or remove "bootstrap_nodes" completely,
45 | // in both cases this will be interpreted as if you don't want to bootstrap
46 | // from anyone.
47 | //
48 | // address = any IPv4 or IPv6 address and also any US-ASCII domain name.
49 | bootstrap_nodes = (
50 | ### tox.0x10k.com/bootstrapd-conf/
51 |
52 | {
53 | #1 [DE] - sonOfRa
54 | address = "144.76.60.215"
55 | port = 33445
56 | public_key = "04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F"
57 | },
58 | {
59 | #2 [US] - stal
60 | address = "23.226.230.47"
61 | port = 33445
62 | public_key = "A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074"
63 | },
64 | {
65 | #3 [FR] - Munrek
66 | address = "195.154.119.113"
67 | port = 33445
68 | public_key = "E398A69646B8CEACA9F0B84F553726C1C49270558C57DF5F3C368F05A7D71354"
69 | },
70 | {
71 | #4 [US] - nurupo (nurupo.contributions@gmail.com)
72 | address = "198.46.138.44"
73 | port = 33445
74 | public_key = "F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67"
75 | },
76 | {
77 | #5 [DE] - Martin Schröder
78 | address = "46.38.239.179"
79 | port = 33445
80 | public_key = "F5A1A38EFB6BD3C2C8AF8B10D85F0F89E931704D349F1D0720C3C4059AF2440A"
81 | },
82 | {
83 | #6 [NL] - Impyy
84 | address = "178.62.250.138"
85 | port = 33445
86 | public_key = "788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B"
87 | },
88 | {
89 | #7 [DE] - Manolis
90 | address = "130.133.110.14"
91 | port = 33445
92 | public_key = "461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F"
93 | },
94 | {
95 | #8 [CA] - noisykeyboard
96 | address = "104.167.101.29"
97 | port = 33445
98 | public_key = "5918AC3C06955962A75AD7DF4F80A5D7C34F7DB9E1498D2E0495DE35B3FE8A57"
99 | },
100 | {
101 | #9 [US] - Busindre
102 | address = "205.185.116.116"
103 | port = 33445
104 | public_key = "A179B09749AC826FF01F37A9613F6B57118AE014D4196A0E1105A98F93A54702"
105 | },
106 | {
107 | #10 [US] - Busindre
108 | address = "198.98.51.198"
109 | port = 33445
110 | public_key = "1D5A5F2F5D6233058BF0259B09622FB40B482E4FA0931EB8FD3AB8E7BF7DAF6F"
111 | },
112 | {
113 | #11 [LV] - fUNKIAM
114 | address = "80.232.246.79"
115 | port = 33445
116 | public_key = "CF6CECA0A14A31717CC8501DA51BE27742B70746956E6676FF423A529F91ED5D"
117 | },
118 | {
119 | #12 [NL] - ray65536
120 | address = "108.61.165.198"
121 | port = 33445
122 | public_key = "8E7D0B859922EF569298B4D261A8CCB5FEA14FB91ED412A7603A585A25698832"
123 | },
124 | {
125 | #13 [GB] - Kr9r0x
126 | address = "212.71.252.109"
127 | port = 33445
128 | public_key = "C4CEB8C7AC607C6B374E2E782B3C00EA3A63B80D4910B8649CCACDD19F260819"
129 | },
130 | {
131 | #14 [SI] - fluke571
132 | address = "194.249.212.109"
133 | port = 33445
134 | public_key = "3CEE1F054081E7A011234883BC4FC39F661A55B73637A5AC293DDF1251D9432B"
135 | },
136 | {
137 | #15 [UA] - MAH69K
138 | address = "185.25.116.107"
139 | port = 33445
140 | public_key = "DA4E4ED4B697F2E9B000EEFE3A34B554ACD3F45F5C96EAEA2516DD7FF9AF7B43"
141 | },
142 | {
143 | #16 [CA] - WIeschie
144 | address = "192.99.168.140"
145 | port = 33445
146 | public_key = "6A4D0607A296838434A6A7DDF99F50EF9D60A2C510BBF31FE538A25CB6B4652F"
147 | },
148 | {
149 | #17 [DE] - clearmartin
150 | address = "46.101.197.175"
151 | port = 443
152 | public_key = "CD133B521159541FB1D326DE9850F5E56A6C724B5B8E5EB5CD8D950408E95707"
153 | },
154 | {
155 | #18 [SE] - Rotkaermota
156 | address = "95.215.46.114"
157 | port = 33445
158 | public_key = "5823FB947FF24CF83DDFAC3F3BAA18F96EA2018B16CC08429CB97FA502F40C23"
159 | },
160 | {
161 | #19 [DE] - tastytea
162 | address = "5.189.176.217"
163 | port = 5190
164 | public_key = "2B2137E094F743AC8BD44652C55F41DFACC502F125E99E4FE24D40537489E32F"
165 | },
166 | {
167 | #20 [FR] - pucetox (1D1C0B992DEB6D7F18561176F7F5E572BCC7F2BA5CFA7E9E437B9134122CE96D906A6119F9D2)
168 | address = "217.182.143.254"
169 | port = 2306
170 | public_key = "7AED21F94D82B05774F697B209628CD5A9AD17E0C073D9329076A4C28ED28147"
171 | },
172 | {
173 | #21 [US] - ru_maniac (EBD2A7B649ABB10ED9F47E5113F04000F39D46F087CEB62FCCE1069471FD6915256D197F2A97)
174 | address = "104.223.122.15"
175 | port = 33445
176 | public_key = "0FB96EEBFB1650DDB52E70CF773DDFCABE25A95CC3BB50FC251082E4B63EF82A"
177 | },
178 | {
179 | #22 [DE] - Deliran
180 | address = "78.47.114.252"
181 | port = 33445
182 | public_key = "1C5293AEF2114717547B39DA8EA6F1E331E5E358B35F9B6B5F19317911C5F976"
183 | },
184 | {
185 | #23 [RU] - D4rk4 (35EDC07AEB18B163E07EE33F6CDDA63969F394FF6A617CEAB22A7EBBEAAAF854C0EDFBD46898)
186 | address = "83.137.53.211"
187 | port = 1813
188 | public_key = "53737F6D47FA6BD2808F378E339AF45BF86F39B64E79D6D491C53A1D522E7039"
189 | },
190 | {
191 | #24 [NL] - tibietigni (D36CC0B702621F48FDBC540A57124A744E5133C932E65ACCEBCABF2586A02455171717175989)
192 | address = "81.4.110.149"
193 | port = 33445
194 | public_key = "9E7BD4793FFECA7F32238FA2361040C09025ED3333744483CA6F3039BFF0211E"
195 | },
196 | {
197 | #25 [RU] - Igor Novgorodov
198 | address = "95.31.20.151"
199 | port = 33445
200 | public_key = "9CA69BB74DE7C056D1CC6B16AB8A0A38725C0349D187D8996766958584D39340"
201 | },
202 | {
203 | #26 [CA] - wildermesser
204 | address = "104.233.104.126"
205 | port = 33445
206 | public_key = "EDEE8F2E839A57820DE3DA4156D88350E53D4161447068A3457EE8F59F362414"
207 | },
208 | {
209 | #27 [FR] - a68366
210 | address = "51.254.84.212"
211 | port = 33445
212 | public_key = "AEC204B9A4501412D5F0BB67D9C81B5DB3EE6ADA64122D32A3E9B093D544327D"
213 | },
214 | {
215 | #28 [BR] - umgeher
216 | address = "179.35.206.22"
217 | port = 33445
218 | public_key = "188E072676404ED833A4E947DC1D223DF8EFEBE5F5258573A236573688FB9761"
219 | },
220 | {
221 | #29 [FR] - Skey
222 | address = "5.135.59.163"
223 | port = 33445
224 | public_key = "2D320F971EF2CA18004416C2AAE7BA52BF7949DB34EA8E2E21AF67BD367BE211"
225 | },
226 | {
227 | #30 [RU] - ru_maniac (EBD2A7B649ABB10ED9F47E5113F04000F39D46F087CEB62FCCE1069471FD6915256D197F2A97)
228 | address = "185.58.206.164"
229 | port = 33445
230 | public_key = "24156472041E5F220D1FA11D9DF32F7AD697D59845701CDD7BE7D1785EB9DB39"
231 | },
232 | {
233 | #31 [RU] - gem
234 | address = "188.244.38.183"
235 | port = 33445
236 | public_key = "15A0F9684E2423F9F46CFA5A50B562AE42525580D840CC50E518192BF333EE38"
237 | },
238 | {
239 | #32 [GB] - mrflibble
240 | address = "185.64.89.42"
241 | port = 33445
242 | public_key = "FAAB17014F42F7F20949F61E55F66A73C230876812A9737F5F6D2DCE4D9E4207"
243 | },
244 | {
245 | #33 [RU] - Net.Verified
246 | address = "82.211.31.116"
247 | port = 33445
248 | public_key = "AF97B76392A6474AF2FD269220FDCF4127D86A42EF3A242DF53A40A268A2CD7C"
249 | },
250 | {
251 | #34 [SG] - wiiaam
252 | address = "128.199.199.197"
253 | port = 33445
254 | public_key = "B05C8869DBB4EDDD308F43C1A974A20A725A36EACCA123862FDE9945BF9D3E09"
255 | },
256 | {
257 | #35 [AU] - AssPirate
258 | address = "103.230.156.174"
259 | port = 33445
260 | public_key = "5C4C7A60183D668E5BD8B3780D1288203E2F1BAE4EEF03278019E21F86174C1D"
261 | },
262 | {
263 | #36 [FR] - h4nt3r (3BC3C6875508A2EC86BE3E35E4FA9155E444CFA96671AE7D7D0D2585A0A5FA38E071A5E463E5)
264 | address = "91.121.66.124"
265 | port = 33445
266 | public_key = "4E3F7D37295664BBD0741B6DBCB6431D6CD77FC4105338C2FC31567BF5C8224A"
267 | },
268 | {
269 | #37 [RU] - t3mp
270 | address = "92.54.84.70"
271 | port = 33445
272 | public_key = "5625A62618CB4FCA70E147A71B29695F38CC65FF0CBD68AD46254585BE564802"
273 | },
274 | {
275 | #38 [US] - PrivacyDragon
276 | address = "45.58.44.190"
277 | port = 33445
278 | public_key = "31910C0497D347FF160D6F3A6C0E317BAFA71E8E03BC4CBB2A185C9D4FB8B31E"
279 | },
280 | {
281 | #39 [UA] - strngr
282 | address = "195.93.190.6"
283 | port = 33445
284 | public_key = "FB4CE0DDEFEED45F26917053E5D24BDDA0FA0A3D83A672A9DA2375928B37023D"
285 | },
286 | {
287 | #40 [US] - AbacusAvenger
288 | address = "104.152.107.143"
289 | port = 33445
290 | public_key = "1A56EA3EDF5DF4C0AEABBF3C2E4E603890F87E983CAC8A0D532A335F2C6E3E1F"
291 | },
292 | {
293 | #41 [NL] - ZaWertun
294 | address = "185.52.0.229"
295 | port = 33445
296 | public_key = "5521952892FBD5C185DF7180DB4DEF69D7844DEEE79B1F75A634ED9DF656756E"
297 | },
298 | {
299 | #42 [ES] - _kinka_
300 | address = "87.98.168.93"
301 | port = 33445
302 | public_key = "C3F6C06A624FAE086DA94604A7838DB495769807EC055FADA36EBF2D4484FB33"
303 | },
304 | {
305 | #43 [RU] - MAXL-SPB (06B8B5F3DAED44EDE619E44CCA532D9463EDD2779ADC397E239EDCE9E3474413055FF791700C)
306 | address = "185.61.253.189"
307 | port = 33445
308 | public_key = "73EEBCB4CBBE56BF0E0F01881DDD88C6B250BAE92CF487BE3FBE02FD830CE200"
309 | },
310 | {
311 | #44 [AR] - nek
312 | address = "109.75.40.105"
313 | port = 33445
314 | public_key = "2B9CD794424FD579044EC2FC5252B23DF8B4AAF239C25074F70B1090C3F8C83A"
315 | },
316 | {
317 | #45 [UA] - Phsm
318 | address = "89.184.82.218"
319 | port = 33445
320 | public_key = "20965721D32CE50C3E837DD75B33908B33037E6225110BFF209277AEAF3F9639"
321 | },
322 | {
323 | #46 [SW] - HooinKyoma
324 | address = "95.215.44.78"
325 | port = 33445
326 | public_key = "672DBE27B4ADB9D5FB105A6BB648B2F8FDB89B3323486A7A21968316E012023C"
327 | },
328 | {
329 | #47 [FR] - Ricin.im
330 | address = "81.64.83.32"
331 | port = 1337
332 | public_key = "3651DAB570D7F60381F87B19D6935EE7F5FE01308DCE71C4B69993150C6A903C"
333 | },
334 | {
335 | #48 [GB] - Kostik
336 | address = "185.120.34.64"
337 | port = 33445
338 | public_key = "728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854"
339 | },
340 | {
341 | #49 [RU] - abbat
342 | address = "193.124.186.120"
343 | port = 33445
344 | public_key = "80EF8660D9C5ACE1577BAB031375A0F08284CBFD9F810A857955DCC87377FC4D"
345 | },
346 | {
347 | #50 [NL] - LittleVulpix
348 | address = "146.185.136.123"
349 | port = 33445
350 | public_key = "09993FAF174DFFDC515B398A2EFC5639C4E6D7B736FC864F89786B50EAF88C1A"
351 | },
352 | {
353 | #51 [FR] - LittleVulpix
354 | address = "163.172.136.118"
355 | port = 33445
356 | public_key = "2C289F9F37C20D09DA83565588BF496FAB3764853FA38141817A72E3F18ACA0B"
357 | },
358 | {
359 | #52 [DE] - Sorunome
360 | address = "144.76.31.180"
361 | port = 33445
362 | public_key = "02807CF4F8BB8FB390CC3794BDF1E8449E9A8392C5D3F2200019DA9F1E812E46"
363 | },
364 | {
365 | #53 [NL] - Yani
366 | address = "37.97.185.116"
367 | port = 33445
368 | public_key = "E59A0E71ADA20D35BD1B0957059D7EF7E7792B3D680AE25C6F4DBBA09114D165"
369 | },
370 | {
371 | #54 [RU] - Cactus
372 | address = "193.124.186.205"
373 | port = 5228
374 | public_key = "9906D65F2A4751068A59D30505C5FC8AE1A95E0843AE9372EAFA3BAB6AC16C2C"
375 | },
376 | {
377 | #55 [RU] - linxon
378 | address = "80.87.193.193"
379 | port = 33445
380 | public_key = "B38255EE4B054924F6D79A5E6E5889EC94B6ADF6FE9906F97A3D01E3D083223A"
381 | },
382 | {
383 | #56 [TW] - initramfs
384 | address = "61.230.104.51"
385 | port = 33445
386 | public_key = "3F0A45A268367C1BEA652F258C85F4A66DA76BCAA667A49E770BCC4917AB6A25"
387 | },
388 | {
389 | #57 [US] - brandon
390 | address = "138.68.2.139"
391 | port = 33445
392 | public_key = "49183DBF0E865713154069D1C7C7A2732ED78CF32C4D76AF5304FE31C5FEB81A"
393 | },
394 | {
395 | #58 [US] - EveNeko (tox-bootstrapd@hibiki.eve.moe)
396 | address = "107.150.46.124"
397 | port = 33445
398 | public_key = "D3EB45181B343C2C222A5BCF72B760638E15ED87904625AAD351C594EEFAE03E"
399 | },
400 | {
401 | #59 [GB] - EveNeko (tox-bootstrapd@hibiki.eve.moe)
402 | address = "185.133.194.202"
403 | port = 33445
404 | public_key = "1A480A53FAF2CBBFCC382D786C43E69EEE23F22C7C23A7CFEB6180A373E23E54"
405 | },
406 | {
407 | #60 [DE] - DeadTeam
408 | address = "144.76.163.109"
409 | port = 33445
410 | public_key = "C7D284129E83877D63591F14B3F658D77FF9BA9BA7293AEB2BDFBFE1A803AF47"
411 | },
412 | {
413 | #61 [RU] - Prototik
414 | address = "164.132.51.92"
415 | port = 33445
416 | public_key = "69C3FEBB977687B64FA0213BDEB89A43463BB48DED288150CFFB6429EFF82436"
417 | },
418 | {
419 | #62 [UA] - Stranger
420 | address = "46.229.52.198 "
421 | port = 33445
422 | public_key = "813C8F4187833EF0655B10F7752141A352248462A567529A38B6BBF73E979307"
423 | },
424 | {
425 | #63 [DE] - Prototik
426 | address = "95.188.83.80"
427 | port = 33445
428 | public_key = "B75583B6D967DB8AD7C6D3B6F9318194BCC79B2FEF18F69E2DF275B779E7AA30"
429 | },
430 | {
431 | #64 [DE] - sys0p
432 | address = "138.201.172.228"
433 | port = 33445
434 | public_key = "1B08FC930EE60429B63273CE39068D46316E79A3F7DDAFAD9C8CA65E50047B7A"
435 | },
436 | {
437 | #65 [DE] - Nolz
438 | address = "78.46.81.229"
439 | port = 33445
440 | public_key = "A856243058D1DE633379508ADCAFCF944E40E1672FF402750EF712E30C42012A"
441 | },
442 | {
443 | #66 [CA] - velusip
444 | address = "144.217.86.39"
445 | port = 33445
446 | public_key = "7E5668E0EE09E19F320AD47902419331FFEE147BB3606769CFBE921A2A2FD34C"
447 | },
448 | {
449 | #67 [RU] - Madji
450 | address = "77.37.160.178"
451 | port = 33440
452 | public_key = "CE678DEAFA29182EFD1B0C5B9BC6999E5A20B50A1A6EC18B91C8EBB591712416"
453 | },
454 | {
455 | #68 [RU] - ps
456 | address = "77.37.142.179"
457 | port = 33445
458 | public_key = "98F5830A426C6BF165F895F04B897AFC4F57331B4BE0561F583C9F323194227B"
459 | },
460 | {
461 | #69 [RU] - himura (EB8E9FFB08DC3C31F8450521A884B478A1B4452BBB4C86BDC7E2AD3CC681C146FF77CBEA21EA)
462 | address = "85.21.144.224"
463 | port = 33445
464 | public_key = "8F738BBC8FA9394670BCAB146C67A507B9907C8E564E28C2B59BEBB2FF68711B"
465 | },
466 | {
467 | #70 [DE] - post-factum (tox.natalenko.name, 8218DB335926393789859EDF2D79AC4CC805ADF73472D08165FEA51555502A58AE84FCE7C3D4)
468 | address = "104.207.131.136"
469 | port = 33445
470 | public_key = "1CB6EBFD9D85448FA70D3CAE1220B76BF6FCE911B46ACDCF88054C190589650B"
471 | },
472 | {
473 | #71 [FR] - dolohow
474 | address = "37.187.122.30"
475 | port = 33445
476 | public_key = "BEB71F97ED9C99C04B8489BB75579EB4DC6AB6F441B603D63533122F1858B51D"
477 | },
478 | {
479 | #72 [NZ] - ws
480 | address = "202.36.75.162"
481 | port = 33445
482 | public_key = "F202E0936ABEE09067F55B0955C3FF6A84ABEED3C750A9EB930D926D03248F4C"
483 | },
484 | {
485 | #73 [RU] - bax
486 | address = "94.19.12.244"
487 | port = 33445
488 | public_key = "92E139CCD0006AF84241A38629E77E73BCF2F98602DCC136E8D5F089E5196D46"
489 | },
490 | {
491 | #74 [SI] - nnnn20430 (plfgr.eu.org)
492 | address = "213.161.5.12"
493 | port = 33445
494 | public_key = "F5A2E533EC720927FA970F508D949D5958F37889F039F50C905010244842656E"
495 | },
496 | {
497 | #75 [FR] - SillyPeruvian (completelyunoriginal.moe)
498 | address = "46.105.30.235"
499 | port = 33445
500 | public_key = "FBC7DED0B0B662D81094D91CC312D6CDF12A7B16C7FFB93817143116B510C13E"
501 | },
502 | {
503 | #76 [DE] - CeBe (tox@cebe.cc , 7F50119368DC8FD3B1ECAF5D18E3F8854F0484CEC5BBF625D420B8E38638733C02486E387AF8)
504 | address = "136.243.141.187"
505 | port = 443
506 | public_key = "6EE1FADE9F55CC7938234CC07C864081FC606D8FE7B751EDA217F268F1078A39"
507 | }
508 | )
509 |
--------------------------------------------------------------------------------
/tox_tcp_relay/tox_tcp_relay.c:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Zoff
4 | * in 2017
5 | *
6 | * dirty hack (echobot and toxic were used as blueprint)
7 | *
8 | *
9 | * compile on linux (dynamic):
10 | * gcc -O2 -fPIC -Wall -Wextra -Wpedantic -o toxdoorspy toxdoorspy.c -std=gnu99 -lsodium -I/usr/local/include/ -ltoxcore -ltoxav -lpthread -lvpx -lv4lconvert
11 | * compile for debugging (dynamic):
12 | * gcc -O0 -g -fPIC -Wall -Wextra -Wpedantic -o toxdoorspy toxdoorspy.c -std=gnu99 -lsodium -I/usr/local/include/ -ltoxcore -ltoxav -lpthread -lvpx -lv4lconvert
13 | *
14 | * compile on linux (static):
15 | * gcc -O2 -Wall -Wextra -Wpedantic -o toxdoorspy_static toxdoorspy.c -static -std=gnu99 -L/usr/local/lib -I/usr/local/include/ \
16 | -lsodium -ltoxcore -ltoxav -ltoxgroup -ltoxmessenger -ltoxfriends -ltoxnetcrypto \
17 | -ltoxdht -ltoxnetwork -ltoxcrypto -lsodium -lpthread -static-libgcc -static-libstdc++ \
18 | -lopus -lvpx -lm -lpthread -lv4lconvert
19 | *
20 |
21 | *
22 | *
23 | */
24 |
25 |
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 |
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include
45 |
46 | #include
47 | #include
48 | #include
49 |
50 | #include
51 | #include
52 | #include
53 |
54 | #define V4LCONVERT 1
55 | // #define HAVE_SOUND 1
56 |
57 | #ifdef HAVE_SOUND
58 | #include
59 | #endif
60 |
61 |
62 |
63 | #ifdef V4LCONVERT
64 | #include
65 | #endif
66 |
67 | #ifdef V4LCONVERT
68 | static struct v4lconvert_data *v4lconvert_data;
69 | #endif
70 |
71 |
72 | // ----------- version -----------
73 | // ----------- version -----------
74 | #define VERSION_MAJOR 0
75 | #define VERSION_MINOR 99
76 | #define VERSION_PATCH 1
77 | static const char global_version_string[] = "0.99.1";
78 | // ----------- version -----------
79 | // ----------- version -----------
80 |
81 | typedef struct DHT_node {
82 | const char *ip;
83 | uint16_t port;
84 | const char key_hex[TOX_PUBLIC_KEY_SIZE*2 + 1];
85 | unsigned char key_bin[TOX_PUBLIC_KEY_SIZE];
86 | } DHT_node;
87 |
88 |
89 |
90 | #define MAX_AVATAR_FILE_SIZE 65536
91 | #define TOXIC_MAX_NAME_LENGTH 32 /* Must be <= TOX_MAX_NAME_LENGTH */
92 | #define TIME_STR_SIZE 32
93 | #define MAX_STR_SIZE 200
94 |
95 | #define CURRENT_LOG_LEVEL 9 // 0 -> error, 1 -> warn, 2 -> info, 9 -> debug
96 |
97 | #define KiB 1024
98 | #define MiB 1048576 /* 1024^2 */
99 | #define GiB 1073741824 /* 1024^3 */
100 |
101 | #define seconds_since_last_mod 1 // how long to wait before we process image files in seconds
102 | #define MAX_FILES 6 // how many filetransfers to/from 1 friend at the same time?
103 | #define MAX_RESEND_FILE_BEFORE_ASK 6
104 | #define AUTO_RESEND_SECONDS 60*5 // resend for this much seconds before asking again [5 min]
105 | #define VIDEO_BUFFER_COUNT 3
106 | uint32_t DEFAULT_GLOBAL_VID_BITRATE = 5000; // kbit/sec
107 | #define DEFAULT_GLOBAL_AUD_BITRATE 6 // kbit/sec
108 | #define DEFAULT_GLOBAL_MIN_VID_BITRATE 1000 // kbit/sec
109 | #define DEFAULT_GLOBAL_MIN_AUD_BITRATE 6 // kbit/sec
110 | #define DEFAULT_FPS_SLEEP_MS 250 // 250=4fps, 500=2fps, 160=6fps // default video fps (sleep in msecs.)
111 |
112 | #define CLEAR(x) memset(&(x), 0, sizeof(x))
113 | #define c_sleep(x) usleep(1000*x)
114 |
115 | typedef enum FILE_TRANSFER_STATE {
116 | FILE_TRANSFER_INACTIVE, // == 0 , this is important
117 | FILE_TRANSFER_PAUSED,
118 | FILE_TRANSFER_PENDING,
119 | FILE_TRANSFER_STARTED,
120 | } FILE_TRANSFER_STATE;
121 |
122 | typedef enum FILE_TRANSFER_DIRECTION {
123 | FILE_TRANSFER_SEND,
124 | FILE_TRANSFER_RECV
125 | } FILE_TRANSFER_DIRECTION;
126 |
127 | struct FileTransfer {
128 | FILE *file;
129 | FILE_TRANSFER_STATE state;
130 | FILE_TRANSFER_DIRECTION direction;
131 | uint8_t file_type;
132 | char file_name[TOX_MAX_FILENAME_LENGTH + 1];
133 | char file_path[PATH_MAX + 1]; /* Not used by senders */
134 | double bps;
135 | uint32_t filenum;
136 | uint32_t friendnum;
137 | size_t index;
138 | uint64_t file_size;
139 | uint64_t position;
140 | time_t last_keep_alive; /* The last time we sent or received data */
141 | uint32_t line_id;
142 | uint8_t file_id[TOX_FILE_ID_LENGTH];
143 | };
144 |
145 |
146 | struct LastOnline {
147 | uint64_t last_on;
148 | struct tm tm;
149 | char hour_min_str[TIME_STR_SIZE]; /* holds 24-hour time string e.g. "15:43:24" */
150 | };
151 |
152 | struct GroupChatInvite {
153 | char *key;
154 | uint16_t length;
155 | uint8_t type;
156 | bool pending;
157 | };
158 |
159 | typedef struct {
160 | char name[TOXIC_MAX_NAME_LENGTH + 1];
161 | int namelength;
162 | char statusmsg[TOX_MAX_STATUS_MESSAGE_LENGTH + 1];
163 | size_t statusmsg_len;
164 | char pub_key[TOX_PUBLIC_KEY_SIZE];
165 | char pubkey_string[(TOX_ADDRESS_SIZE * 2 + 1)];
166 | char worksubdir[MAX_STR_SIZE];
167 | uint32_t num;
168 | bool active;
169 | TOX_CONNECTION connection_status;
170 | bool is_typing;
171 | uint8_t status;
172 | struct LastOnline last_online;
173 | int have_resumed_fts; // wait with new FTs until all old FTs have been started (to resume) including avatars!
174 | struct FileTransfer file_receiver[MAX_FILES];
175 | struct FileTransfer file_sender[MAX_FILES];
176 | char last_answer[100];
177 | int waiting_for_answer; // 0 -> no, 1 -> waiting for answer, 2 -> got answer
178 | time_t auto_resend_start_time;
179 | // mz_zip_archive zip_archive;
180 | } ToxicFriend;
181 |
182 | typedef struct {
183 | char name[TOXIC_MAX_NAME_LENGTH + 1];
184 | int namelength;
185 | char pub_key[TOX_PUBLIC_KEY_SIZE];
186 | uint32_t num;
187 | bool active;
188 | uint64_t last_on;
189 | } BlockedFriend;
190 |
191 | typedef struct {
192 | int num_selected;
193 | size_t num_friends;
194 | size_t num_online;
195 | size_t max_idx; /* 1 + the index of the last friend in list */
196 | uint32_t *index;
197 | ToxicFriend *list;
198 | } FriendsList;
199 |
200 |
201 | static struct Avatar {
202 | char name[TOX_MAX_FILENAME_LENGTH + 1];
203 | size_t name_len;
204 | char path[PATH_MAX + 1];
205 | size_t path_len;
206 | off_t size;
207 | } Avatar;
208 |
209 | typedef struct {
210 | bool incoming;
211 | uint32_t state;
212 | uint32_t audio_bit_rate;
213 | uint32_t video_bit_rate;
214 | pthread_mutex_t arb_mutex[1];
215 | } CallControl;
216 |
217 |
218 | struct buffer {
219 | void * start;
220 | size_t length;
221 | };
222 |
223 | typedef struct TOXCAM_AV_VIDEO_FRAME {
224 | uint16_t w, h;
225 | uint8_t *y, *u, *v;
226 | // uint8_t bit_depth;
227 | } toxcam_av_video_frame;
228 |
229 |
230 |
231 | void on_avatar_chunk_request(Tox *m, struct FileTransfer *ft, uint64_t position, size_t length);
232 | int avatar_send(Tox *m, uint32_t friendnum);
233 | struct FileTransfer *new_file_transfer(uint32_t friendnum, uint32_t filenum, FILE_TRANSFER_DIRECTION direction, uint8_t type);
234 | void kill_all_file_transfers_friend(Tox *m, uint32_t friendnum);
235 | int has_reached_max_file_transfer_for_friend(uint32_t num);
236 | static int find_friend_in_friendlist(uint32_t friendnum);
237 | int is_friend_online(Tox *tox, uint32_t num);
238 | void av_local_disconnect(ToxAV *av, uint32_t num);
239 | void run_cmd_return_output(const char *command, char* output, int lastline);
240 | void save_resumable_fts(Tox *m, uint32_t friendnum);
241 | void resume_resumable_fts(Tox *m, uint32_t friendnum);
242 | void left_top_bar_into_yuv_frame(int bar_start_x_pix, int bar_start_y_pix, int bar_w_pix, int bar_h_pix, uint8_t r, uint8_t g, uint8_t b);
243 | void print_font_char(int start_x_pix, int start_y_pix, int font_char_num, uint8_t col_value);
244 | void text_on_yuf_frame_xy(int start_x_pix, int start_y_pix, const char* text);
245 | void blinking_dot_on_frame_xy(int start_x_pix, int start_y_pix, int* state);
246 | void black_yuf_frame_xy();
247 | void rbg_to_yuv(uint8_t r, uint8_t g, uint8_t b, uint8_t *y, uint8_t *u, uint8_t *v);
248 | void set_color_in_yuv_frame_xy(uint8_t *yuv_frame, int px_x, int px_y, int frame_w, int frame_h, uint8_t r, uint8_t g, uint8_t b);
249 |
250 |
251 | const char *savedata_filename = "savedata.tox";
252 | const char *savedata_tmp_filename = "savedata.tox.tmp";
253 | const char *log_filename = "tox_tcp_relay.log";
254 | const char *my_avatar_filename = "avatar.png";
255 |
256 | char *v4l2_device; // video device filename
257 |
258 | const char *shell_cmd__single_shot = "./scripts/single_shot.sh 2> /dev/null";
259 | const char *shell_cmd__get_cpu_temp = "./scripts/get_cpu_temp.sh 2> /dev/null";
260 | const char *shell_cmd__get_gpu_temp = "./scripts/get_gpu_temp.sh 2> /dev/null";
261 | const char *shell_cmd__get_my_number_of_open_files = "cat /proc/sys/fs/file-nr 2> /dev/null";
262 | int global_want_restart = 0;
263 | const char *global_timestamp_format = "%H:%M:%S";
264 | const char *global_long_timestamp_format = "%Y-%m-%d %H:%M:%S";
265 | const char *global_overlay_timestamp_format = "%Y-%m-%d %H:%M:%S";
266 | uint64_t global_start_time;
267 | int global_cam_device_fd = 0;
268 | uint32_t n_buffers;
269 | struct buffer *buffers = NULL;
270 | uint16_t video_width = 0;
271 | uint16_t video_height = 0;
272 | struct v4l2_format format;
273 | struct v4l2_format dest_format;
274 | toxcam_av_video_frame av_video_frame;
275 | vpx_image_t input;
276 | int global_video_active = 0;
277 | int global_send_first_frame = 0;
278 | int switch_nodelist_2 = 0;
279 | int video_high = 0;
280 | int switch_tcponly = 0;
281 |
282 |
283 | uint32_t global_audio_bit_rate;
284 | uint32_t global_video_bit_rate;
285 | ToxAV *mytox_av = NULL;
286 | int tox_loop_running = 1;
287 | int global_blink_state = 0;
288 |
289 | int toxav_video_thread_stop = 0;
290 | int toxav_iterate_thread_stop = 0;
291 |
292 | // -- hardcoded --
293 | // -- hardcoded --
294 | // -- hardcoded --
295 | uint32_t friend_to_send_video_to = -1;
296 | // -- hardcoded --
297 | // -- hardcoded --
298 | // -- hardcoded --
299 |
300 | int video_call_enabled = 0;
301 |
302 | TOX_CONNECTION my_connection_status = TOX_CONNECTION_NONE;
303 | FILE *logfile = NULL;
304 | FriendsList Friends;
305 |
306 | void dbg(int level, const char *fmt, ...)
307 | {
308 | char *level_and_format = NULL;
309 | char *fmt_copy = NULL;
310 |
311 | if (fmt == NULL)
312 | {
313 | return;
314 | }
315 |
316 | if (strlen(fmt) < 1)
317 | {
318 | return;
319 | }
320 |
321 | if (!logfile)
322 | {
323 | return;
324 | }
325 |
326 | if ((level < 0) || (level > 9))
327 | {
328 | level = 0;
329 | }
330 |
331 | level_and_format = malloc(strlen(fmt) + 3);
332 |
333 | if (!level_and_format)
334 | {
335 | // fprintf(stderr, "free:000a\n");
336 | return;
337 | }
338 |
339 | fmt_copy = level_and_format + 2;
340 | strcpy(fmt_copy, fmt);
341 | level_and_format[1] = ':';
342 | if (level == 0)
343 | {
344 | level_and_format[0] = 'E';
345 | }
346 | else if (level == 1)
347 | {
348 | level_and_format[0] = 'W';
349 | }
350 | else if (level == 2)
351 | {
352 | level_and_format[0] = 'I';
353 | }
354 | else
355 | {
356 | level_and_format[0] = 'D';
357 | }
358 |
359 | if (level <= CURRENT_LOG_LEVEL)
360 | {
361 | va_list ap;
362 | va_start(ap, fmt);
363 | vfprintf(logfile, level_and_format, ap);
364 | va_end(ap);
365 | }
366 |
367 | // fprintf(stderr, "free:001\n");
368 | if (level_and_format)
369 | {
370 | // fprintf(stderr, "free:001.a\n");
371 | free(level_and_format);
372 | }
373 | // fprintf(stderr, "free:002\n");
374 | }
375 |
376 |
377 |
378 |
379 |
380 |
381 | // linked list ----------
382 | typedef struct ll_node {
383 | void* val;
384 | struct ll_node* next;
385 | } ll_node_t;
386 |
387 |
388 | void ll_fill_val(void **val, size_t data_size, void* data)
389 | {
390 | if (*val != NULL)
391 | {
392 | free(*val);
393 | *val = NULL;
394 | }
395 |
396 | *val = malloc(data_size);
397 | memcpy(*val, data, data_size);
398 | }
399 |
400 |
401 | // add to the beginning of the list
402 | void ll_push(ll_node_t** head, size_t data_size, void* data)
403 | {
404 | ll_node_t* new_node;
405 | new_node = calloc(1, sizeof(ll_node_t));
406 | ll_fill_val(&(new_node->val), data_size, data);
407 | new_node->next = *head;
408 | *head = new_node;
409 | }
410 |
411 | void* ll_pop(ll_node_t** head)
412 | {
413 | void* retval = NULL;
414 | ll_node_t* next_node = NULL;
415 |
416 | if (*head == NULL)
417 | {
418 | return NULL;
419 | }
420 |
421 | next_node = (*head)->next;
422 | retval = (*head)->val;
423 | free(*head);
424 | *head = next_node;
425 |
426 | return retval;
427 | }
428 |
429 | void ll_free_val(void* val)
430 | {
431 | if (val != NULL)
432 | {
433 | free(val);
434 | val = NULL;
435 | }
436 | }
437 |
438 | void* ll_remove_by_index(ll_node_t** head, int n)
439 | {
440 | int i = 0;
441 | void* retval = NULL;
442 | ll_node_t* current = *head;
443 | ll_node_t* temp_node = NULL;
444 |
445 | if (n == 0)
446 | {
447 | return ll_pop(head);
448 | }
449 |
450 | for (i = 0; i < n-1; i++)
451 | {
452 | if (current->next == NULL)
453 | {
454 | return NULL;
455 | }
456 | current = current->next;
457 | }
458 |
459 | temp_node = current->next;
460 | if (temp_node != NULL)
461 | {
462 | retval = temp_node->val;
463 | current->next = temp_node->next;
464 | free(temp_node);
465 | }
466 |
467 | return retval;
468 | }
469 |
470 | #if 0
471 | void ll_print_list(ll_node_t* head)
472 | {
473 | ll_node_t* current = head;
474 | int i = 0;
475 |
476 | while (current != NULL)
477 | {
478 | dbg(9, "element #%d=%p\n", i, current->val);
479 | i++;
480 | current = current->next;
481 | }
482 | }
483 | #endif
484 |
485 | ll_node_t* resumable_filetransfers = NULL;
486 |
487 | // linked list ----------
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 | time_t get_unix_time(void)
498 | {
499 | return time(NULL);
500 | }
501 |
502 | void yieldcpu(uint32_t ms)
503 | {
504 | usleep(1000 * ms);
505 | }
506 |
507 |
508 | void tox_log_cb__custom(Tox *tox, TOX_LOG_LEVEL level, const char *file, uint32_t line, const char *func, const char *message, void *user_data)
509 | {
510 | dbg(9, "%d:%s:%d:%s:%s\n", (int)level, file, (int)line, func, message);
511 | }
512 |
513 |
514 | Tox *create_tox()
515 | {
516 | Tox *tox;
517 | struct Tox_Options options;
518 |
519 | /*
520 | TOX_ERR_OPTIONS_NEW err_options;
521 | struct Tox_Options options = tox_options_new(&err_options);
522 | if (err_options != TOX_ERR_OPTIONS_NEW_OK)
523 | {
524 | dbg(0, "tox_options_new error\n");
525 | }
526 | */
527 |
528 | tox_options_default(&options);
529 |
530 | // ----------------------------------------------
531 | uint16_t tcp_port = 33447; // act as TCP relay
532 | dbg(0, "TCP relay port: 33447\n");
533 | // uint16_t tcp_port = 0; // DON'T act as TCP relay
534 | // ----------------------------------------------
535 |
536 | // ----------------------------------------------
537 | if (switch_tcponly == 0)
538 | {
539 | options.udp_enabled = true; // UDP mode
540 | dbg(0, "setting UDP mode\n");
541 | }
542 | else
543 | {
544 | options.udp_enabled = false; // TCP mode
545 | dbg(0, "setting TCP mode\n");
546 | }
547 | // ----------------------------------------------
548 |
549 | options.ipv6_enabled = false;
550 | options.local_discovery_enabled = true;
551 | options.hole_punching_enabled = true;
552 | options.tcp_port = tcp_port;
553 |
554 | // ------------------------------------------------------------
555 | // set our own handler for c-toxcore logging messages!!
556 | options.log_callback = tox_log_cb__custom;
557 | // ------------------------------------------------------------
558 |
559 |
560 | FILE *f = fopen(savedata_filename, "rb");
561 | if (f)
562 | {
563 | fseek(f, 0, SEEK_END);
564 | long fsize = ftell(f);
565 | fseek(f, 0, SEEK_SET);
566 |
567 | uint8_t *savedata = malloc(fsize);
568 |
569 | size_t dummy = fread(savedata, fsize, 1, f);
570 | if (dummy < 1)
571 | {
572 | dbg(0, "reading savedata failed\n");
573 | }
574 | fclose(f);
575 |
576 | options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE;
577 | options.savedata_data = savedata;
578 | options.savedata_length = fsize;
579 |
580 | TOX_ERR_NEW error;
581 | tox = tox_new(&options, &error);
582 | dbg(9, "tox_new1:TOX_ERR_NEW = %d\n", (int)error);
583 |
584 | free((void *)savedata);
585 | }
586 | else
587 | {
588 | TOX_ERR_NEW error;
589 | tox = tox_new(&options, &error);
590 | dbg(9, "tox_new2:TOX_ERR_NEW = %d\n", (int)error);
591 | }
592 |
593 | bool local_discovery_enabled = tox_options_get_local_discovery_enabled(&options);
594 | dbg(9, "local discovery enabled = %d\n", (int)local_discovery_enabled);
595 |
596 | dbg(9, "tox = %p\n", tox);
597 | return tox;
598 | }
599 |
600 | void replace_bad_char_from_string(char *str, const char replace_with)
601 | {
602 | // win32: '\ / : * ? " < > |'
603 | char bad_chars[] = "/:*?<>|\"";
604 | int i;
605 | int j;
606 |
607 | if ((str) && (strlen(str) > 0))
608 | {
609 | for(i = 0; (int)i < (int)strlen(str) ;i++)
610 | {
611 | for(j = 0; (int)j < (int)strlen(bad_chars); j++)
612 | if (str[i] == bad_chars[j])
613 | {
614 | str[i] = replace_with;
615 | }
616 | }
617 | }
618 | }
619 |
620 |
621 | void update_savedata_file(const Tox *tox)
622 | {
623 | size_t size = tox_get_savedata_size(tox);
624 | char *savedata = malloc(size);
625 | tox_get_savedata(tox, (uint8_t *)savedata);
626 |
627 | FILE *f = fopen(savedata_tmp_filename, "wb");
628 | fwrite(savedata, size, 1, f);
629 | fclose(f);
630 |
631 | rename(savedata_tmp_filename, savedata_filename);
632 |
633 | free(savedata);
634 | }
635 |
636 | off_t file_size(const char *path)
637 | {
638 | struct stat st;
639 |
640 | if (stat(path, &st) == -1)
641 | {
642 | return 0;
643 | }
644 |
645 | return st.st_size;
646 | }
647 |
648 | int bin_id_to_string(const char *bin_id, size_t bin_id_size, char *output, size_t output_size)
649 | {
650 | if (bin_id_size != TOX_ADDRESS_SIZE || output_size < (TOX_ADDRESS_SIZE * 2 + 1))
651 | {
652 | return -1;
653 | }
654 |
655 | size_t i;
656 | for (i = 0; i < TOX_ADDRESS_SIZE; ++i)
657 | {
658 | snprintf(&output[i * 2], output_size - (i * 2), "%02X", bin_id[i] & 0xff);
659 | }
660 |
661 | return 0;
662 | }
663 |
664 | void random_char(char *output, int len)
665 | {
666 | int i;
667 | srandom(time(NULL));
668 |
669 | for (i = 0; i < len - 1; i++)
670 | {
671 | output[i] = (unsigned char) (rand() % 255 + 1);
672 | }
673 | output[len - 1] = '\0';
674 | }
675 |
676 | void bin_id_to_string_all(const char *bin_id, size_t bin_id_size, char *output, size_t output_size)
677 | {
678 | if (bin_id)
679 | {
680 | size_t i;
681 | for (i = 0; i < bin_id_size; ++i)
682 | {
683 | snprintf(&output[i * 2], output_size - (i * 2), "%02X", bin_id[i] & 0xff);
684 | }
685 | }
686 | }
687 |
688 |
689 | size_t get_file_name(char *namebuf, size_t bufsize, const char *pathname)
690 | {
691 | int len = strlen(pathname) - 1;
692 | char *path = strdup(pathname);
693 |
694 | if (path == NULL)
695 | {
696 | // TODO
697 | }
698 |
699 | while (len >= 0 && pathname[len] == '/')
700 | {
701 | path[len--] = '\0';
702 | }
703 |
704 | char *finalname = strdup(path);
705 |
706 | if (finalname == NULL)
707 | {
708 | // TODO
709 | }
710 |
711 | const char *basenm = strrchr(path, '/');
712 | if (basenm != NULL)
713 | {
714 | if (basenm[1])
715 | {
716 | strcpy(finalname, &basenm[1]);
717 | }
718 | }
719 |
720 | snprintf(namebuf, bufsize, "%s", finalname);
721 | free(finalname);
722 | free(path);
723 |
724 | return strlen(namebuf);
725 | }
726 |
727 | void bootstap_nodes(Tox *tox, DHT_node nodes[], int number_of_nodes, int add_as_tcp_relay)
728 | {
729 |
730 | bool res = 0;
731 | for (size_t i = 0; (int)i < (int)number_of_nodes; i ++)
732 | {
733 | res = sodium_hex2bin(nodes[i].key_bin, sizeof(nodes[i].key_bin),
734 | nodes[i].key_hex, sizeof(nodes[i].key_hex)-1, NULL, NULL, NULL);
735 | // dbg(9, "sodium_hex2bin:res=%d\n", res);
736 |
737 | TOX_ERR_BOOTSTRAP error;
738 | res = tox_bootstrap(tox, nodes[i].ip, nodes[i].port, nodes[i].key_bin, &error);
739 | if (res != true)
740 | {
741 | if (error == TOX_ERR_BOOTSTRAP_OK)
742 | {
743 | // dbg(9, "bootstrap:%s %d [FALSE]res=TOX_ERR_BOOTSTRAP_OK\n", nodes[i].ip, nodes[i].port);
744 | }
745 | else if (error == TOX_ERR_BOOTSTRAP_NULL)
746 | {
747 | // dbg(9, "bootstrap:%s %d [FALSE]res=TOX_ERR_BOOTSTRAP_NULL\n", nodes[i].ip, nodes[i].port);
748 | }
749 | else if (error == TOX_ERR_BOOTSTRAP_BAD_HOST)
750 | {
751 | // dbg(9, "bootstrap:%s %d [FALSE]res=TOX_ERR_BOOTSTRAP_BAD_HOST\n", nodes[i].ip, nodes[i].port);
752 | }
753 | else if (error == TOX_ERR_BOOTSTRAP_BAD_PORT)
754 | {
755 | // dbg(9, "bootstrap:%s %d [FALSE]res=TOX_ERR_BOOTSTRAP_BAD_PORT\n", nodes[i].ip, nodes[i].port);
756 | }
757 | }
758 | else
759 | {
760 | // dbg(9, "bootstrap:%s %d [TRUE]res=%d\n", nodes[i].ip, nodes[i].port, res);
761 | }
762 |
763 | if (add_as_tcp_relay == 1)
764 | {
765 | res = tox_add_tcp_relay(tox, nodes[i].ip, nodes[i].port, nodes[i].key_bin, &error); // use also as TCP relay
766 | if (res != true)
767 | {
768 | if (error == TOX_ERR_BOOTSTRAP_OK)
769 | {
770 | // dbg(9, "add_tcp_relay:%s %d [FALSE]res=TOX_ERR_BOOTSTRAP_OK\n", nodes[i].ip, nodes[i].port);
771 | }
772 | else if (error == TOX_ERR_BOOTSTRAP_NULL)
773 | {
774 | // dbg(9, "add_tcp_relay:%s %d [FALSE]res=TOX_ERR_BOOTSTRAP_NULL\n", nodes[i].ip, nodes[i].port);
775 | }
776 | else if (error == TOX_ERR_BOOTSTRAP_BAD_HOST)
777 | {
778 | // dbg(9, "add_tcp_relay:%s %d [FALSE]res=TOX_ERR_BOOTSTRAP_BAD_HOST\n", nodes[i].ip, nodes[i].port);
779 | }
780 | else if (error == TOX_ERR_BOOTSTRAP_BAD_PORT)
781 | {
782 | // dbg(9, "add_tcp_relay:%s %d [FALSE]res=TOX_ERR_BOOTSTRAP_BAD_PORT\n", nodes[i].ip, nodes[i].port);
783 | }
784 | }
785 | else
786 | {
787 | // dbg(9, "add_tcp_relay:%s %d [TRUE]res=%d\n", nodes[i].ip, nodes[i].port, res);
788 | }
789 | }
790 | else
791 | {
792 | dbg(2, "Not adding any TCP relays\n");
793 | }
794 | }
795 | }
796 |
797 |
798 | void bootstrap(Tox *tox)
799 | {
800 |
801 | // these nodes seem to be faster!!
802 | DHT_node nodes1[] =
803 | {
804 | {"178.62.250.138", 33445, "788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B", {0}},
805 | {"51.15.37.145", 33445, "6FC41E2BD381D37E9748FC0E0328CE086AF9598BECC8FEB7DDF2E440475F300E", {0}},
806 | {"130.133.110.14", 33445, "461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F", {0}},
807 | {"23.226.230.47", 33445, "A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074", {0}},
808 | {"163.172.136.118", 33445, "2C289F9F37C20D09DA83565588BF496FAB3764853FA38141817A72E3F18ACA0B", {0}},
809 | {"217.182.143.254", 443, "7AED21F94D82B05774F697B209628CD5A9AD17E0C073D9329076A4C28ED28147", {0}},
810 | {"185.14.30.213", 443, "2555763C8C460495B14157D234DD56B86300A2395554BCAE4621AC345B8C1B1B", {0}},
811 | {"136.243.141.187", 443, "6EE1FADE9F55CC7938234CC07C864081FC606D8FE7B751EDA217F268F1078A39", {0}},
812 | {"128.199.199.197", 33445, "B05C8869DBB4EDDD308F43C1A974A20A725A36EACCA123862FDE9945BF9D3E09", {0}},
813 | {"198.46.138.44", 33445, "F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67", {0}}
814 | };
815 |
816 |
817 | // more nodes here, but maybe some issues
818 | DHT_node nodes2[] =
819 | {
820 | {"178.62.250.138", 33445, "788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B", {0}},
821 | {"136.243.141.187", 443, "6EE1FADE9F55CC7938234CC07C864081FC606D8FE7B751EDA217F268F1078A39", {0}},
822 | {"185.14.30.213", 443, "2555763C8C460495B14157D234DD56B86300A2395554BCAE4621AC345B8C1B1B", {0}},
823 | {"198.46.138.44",33445,"F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67", {0}},
824 | {"51.15.37.145",33445,"6FC41E2BD381D37E9748FC0E0328CE086AF9598BECC8FEB7DDF2E440475F300E", {0}},
825 | {"130.133.110.14",33445,"461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F", {0}},
826 | {"205.185.116.116",33445,"A179B09749AC826FF01F37A9613F6B57118AE014D4196A0E1105A98F93A54702", {0}},
827 | {"198.98.51.198",33445,"1D5A5F2F5D6233058BF0259B09622FB40B482E4FA0931EB8FD3AB8E7BF7DAF6F", {0}},
828 | {"108.61.165.198",33445,"8E7D0B859922EF569298B4D261A8CCB5FEA14FB91ED412A7603A585A25698832", {0}},
829 | {"194.249.212.109",33445,"3CEE1F054081E7A011234883BC4FC39F661A55B73637A5AC293DDF1251D9432B", {0}},
830 | {"185.25.116.107",33445,"DA4E4ED4B697F2E9B000EEFE3A34B554ACD3F45F5C96EAEA2516DD7FF9AF7B43", {0}},
831 | {"5.189.176.217",5190,"2B2137E094F743AC8BD44652C55F41DFACC502F125E99E4FE24D40537489E32F", {0}},
832 | {"217.182.143.254",2306,"7AED21F94D82B05774F697B209628CD5A9AD17E0C073D9329076A4C28ED28147", {0}},
833 | {"104.223.122.15",33445,"0FB96EEBFB1650DDB52E70CF773DDFCABE25A95CC3BB50FC251082E4B63EF82A", {0}},
834 | {"tox.verdict.gg",33445,"1C5293AEF2114717547B39DA8EA6F1E331E5E358B35F9B6B5F19317911C5F976", {0}},
835 | {"d4rk4.ru",1813,"53737F6D47FA6BD2808F378E339AF45BF86F39B64E79D6D491C53A1D522E7039", {0}},
836 | {"104.233.104.126",33445,"EDEE8F2E839A57820DE3DA4156D88350E53D4161447068A3457EE8F59F362414", {0}},
837 | {"51.254.84.212",33445,"AEC204B9A4501412D5F0BB67D9C81B5DB3EE6ADA64122D32A3E9B093D544327D", {0}},
838 | {"88.99.133.52",33445,"2D320F971EF2CA18004416C2AAE7BA52BF7949DB34EA8E2E21AF67BD367BE211", {0}},
839 | {"185.58.206.164",33445,"24156472041E5F220D1FA11D9DF32F7AD697D59845701CDD7BE7D1785EB9DB39", {0}},
840 | {"92.54.84.70",33445,"5625A62618CB4FCA70E147A71B29695F38CC65FF0CBD68AD46254585BE564802", {0}},
841 | {"195.93.190.6",33445,"FB4CE0DDEFEED45F26917053E5D24BDDA0FA0A3D83A672A9DA2375928B37023D", {0}},
842 | {"tox.uplinklabs.net",33445,"1A56EA3EDF5DF4C0AEABBF3C2E4E603890F87E983CAC8A0D532A335F2C6E3E1F", {0}},
843 | {"toxnode.nek0.net",33445,"20965721D32CE50C3E837DD75B33908B33037E6225110BFF209277AEAF3F9639", {0}},
844 | {"95.215.44.78",33445,"672DBE27B4ADB9D5FB105A6BB648B2F8FDB89B3323486A7A21968316E012023C", {0}},
845 | {"163.172.136.118",33445,"2C289F9F37C20D09DA83565588BF496FAB3764853FA38141817A72E3F18ACA0B", {0}},
846 | {"sorunome.de",33445,"02807CF4F8BB8FB390CC3794BDF1E8449E9A8392C5D3F2200019DA9F1E812E46", {0}},
847 | {"37.97.185.116",33445,"E59A0E71ADA20D35BD1B0957059D7EF7E7792B3D680AE25C6F4DBBA09114D165", {0}},
848 | {"193.124.186.205",5228,"9906D65F2A4751068A59D30505C5FC8AE1A95E0843AE9372EAFA3BAB6AC16C2C", {0}},
849 | {"80.87.193.193",33445,"B38255EE4B054924F6D79A5E6E5889EC94B6ADF6FE9906F97A3D01E3D083223A", {0}},
850 | {"initramfs.io",33445,"3F0A45A268367C1BEA652F258C85F4A66DA76BCAA667A49E770BCC4917AB6A25", {0}},
851 | {"hibiki.eve.moe",33445,"D3EB45181B343C2C222A5BCF72B760638E15ED87904625AAD351C594EEFAE03E", {0}},
852 | {"tox.deadteam.org",33445,"C7D284129E83877D63591F14B3F658D77FF9BA9BA7293AEB2BDFBFE1A803AF47", {0}},
853 | {"46.229.52.198",33445,"813C8F4187833EF0655B10F7752141A352248462A567529A38B6BBF73E979307", {0}},
854 | {"node.tox.ngc.network",33445,"A856243058D1DE633379508ADCAFCF944E40E1672FF402750EF712E30C42012A", {0}},
855 | {"144.217.86.39",33445,"7E5668E0EE09E19F320AD47902419331FFEE147BB3606769CFBE921A2A2FD34C", {0}},
856 | {"185.14.30.213",443,"2555763C8C460495B14157D234DD56B86300A2395554BCAE4621AC345B8C1B1B", {0}},
857 | {"77.37.160.178",33440,"CE678DEAFA29182EFD1B0C5B9BC6999E5A20B50A1A6EC18B91C8EBB591712416", {0}},
858 | {"85.21.144.224",33445,"8F738BBC8FA9394670BCAB146C67A507B9907C8E564E28C2B59BEBB2FF68711B", {0}},
859 | {"tox.natalenko.name",33445,"1CB6EBFD9D85448FA70D3CAE1220B76BF6FCE911B46ACDCF88054C190589650B", {0}},
860 | {"37.187.122.30",33445,"BEB71F97ED9C99C04B8489BB75579EB4DC6AB6F441B603D63533122F1858B51D", {0}},
861 | {"completelyunoriginal.moe",33445,"FBC7DED0B0B662D81094D91CC312D6CDF12A7B16C7FFB93817143116B510C13E", {0}},
862 | {"136.243.141.187",443,"6EE1FADE9F55CC7938234CC07C864081FC606D8FE7B751EDA217F268F1078A39", {0}},
863 | {"tox.abilinski.com",33445,"0E9D7FEE2AA4B42A4C18FE81C038E32FFD8D907AAA7896F05AA76C8D31A20065", {0}},
864 | {"95.215.46.114",33445,"5823FB947FF24CF83DDFAC3F3BAA18F96EA2018B16CC08429CB97FA502F40C23", {0}},
865 | {"51.15.54.207",33445,"1E64DBA45EC810C0BF3A96327DC8A9D441AB262C14E57FCE11ECBCE355305239", {0}}
866 | };
867 |
868 | // only nodes.tox.chat
869 | DHT_node nodes3[] =
870 | {
871 | {"51.15.37.145", 33445, "6FC41E2BD381D37E9748FC0E0328CE086AF9598BECC8FEB7DDF2E440475F300E", {0}}
872 | };
873 |
874 |
875 | if (switch_nodelist_2 == 0)
876 | {
877 | dbg(9, "nodeslist:1\n");
878 | bootstap_nodes(tox, &nodes1, (int)(sizeof(nodes1)/sizeof(DHT_node)), 1);
879 | }
880 | else if (switch_nodelist_2 == 2)
881 | {
882 | dbg(9, "nodeslist:3\n");
883 | bootstap_nodes(tox, &nodes3, (int)(sizeof(nodes3)/sizeof(DHT_node)), 0);
884 | }
885 | else // (switch_nodelist_2 == 1)
886 | {
887 | dbg(9, "nodeslist:2\n");
888 | bootstap_nodes(tox, &nodes2, (int)(sizeof(nodes2)/sizeof(DHT_node)), 1);
889 | }
890 | }
891 |
892 |
893 | // fill string with toxid in upper case hex.
894 | // size of toxid_str needs to be: [TOX_ADDRESS_SIZE*2 + 1] !!
895 | void get_my_toxid(Tox *tox, char *toxid_str)
896 | {
897 | uint8_t tox_id_bin[TOX_ADDRESS_SIZE];
898 | tox_self_get_address(tox, tox_id_bin);
899 |
900 | char tox_id_hex_local[TOX_ADDRESS_SIZE*2 + 1];
901 | sodium_bin2hex(tox_id_hex_local, sizeof(tox_id_hex_local), tox_id_bin, sizeof(tox_id_bin));
902 |
903 | for (size_t i = 0; i < sizeof(tox_id_hex_local)-1; i ++)
904 | {
905 | tox_id_hex_local[i] = toupper(tox_id_hex_local[i]);
906 | }
907 |
908 | snprintf(toxid_str, (size_t)(TOX_ADDRESS_SIZE*2 + 1), "%s", (const char*)tox_id_hex_local);
909 | }
910 |
911 | void print_tox_id(Tox *tox)
912 | {
913 | char tox_id_hex[TOX_ADDRESS_SIZE*2 + 1];
914 | get_my_toxid(tox, tox_id_hex);
915 |
916 | if (logfile)
917 | {
918 | dbg(2, "--MyToxID--:%s\n", tox_id_hex);
919 | int fd = fileno(logfile);
920 | fsync(fd);
921 | }
922 | }
923 |
924 | int is_friend_online(Tox *tox, uint32_t num)
925 | {
926 | int j = find_friend_in_friendlist(num);
927 | switch (Friends.list[j].connection_status)
928 | {
929 | case TOX_CONNECTION_NONE:
930 | return 0;
931 | break;
932 | case TOX_CONNECTION_TCP:
933 | return 1;
934 | break;
935 | case TOX_CONNECTION_UDP:
936 | return 1;
937 | break;
938 | default:
939 | return 0;
940 | break;
941 | }
942 | }
943 |
944 | static int find_friend_in_friendlist(uint32_t friendnum)
945 | {
946 | int i;
947 |
948 | for (i = 0; i <= Friends.max_idx; ++i)
949 | {
950 | if (Friends.list[i].num == friendnum)
951 | {
952 | return i;
953 | }
954 | }
955 |
956 | return -1;
957 | }
958 |
959 | static void update_friend_last_online(uint32_t num, time_t timestamp)
960 | {
961 | int friendlistnum = find_friend_in_friendlist(num);
962 |
963 | Friends.list[friendlistnum].last_online.last_on = timestamp;
964 | Friends.list[friendlistnum].last_online.tm = *localtime((const time_t *)×tamp);
965 |
966 | /* if the format changes make sure TIME_STR_SIZE is the correct size !! */
967 | strftime(Friends.list[friendlistnum].last_online.hour_min_str, TIME_STR_SIZE, global_timestamp_format, &Friends.list[friendlistnum].last_online.tm);
968 | }
969 |
970 | void send_file_to_friend_real(Tox *m, uint32_t num, const char* filename, int resume, uint8_t* fileid_resume)
971 | {
972 | // ------- hack to send file --------
973 | // ------- hack to send file --------
974 | const char *errmsg = NULL;
975 | char path[MAX_STR_SIZE];
976 |
977 | snprintf(path, sizeof(path), "%s", filename);
978 | dbg(2, "send_file_to_friend_real:path=%s\n", path);
979 |
980 | FILE *file_to_send = fopen(path, "r");
981 |
982 | if (file_to_send == NULL)
983 | {
984 | dbg(0, "send_file_to_friend_real:error opening file\n");
985 | return;
986 | }
987 |
988 | off_t filesize = file_size(path);
989 |
990 | if (filesize == 0)
991 | {
992 | dbg(0, "send_file_to_friend_real:filesize 0\n");
993 | fclose(file_to_send);
994 | return;
995 | }
996 |
997 | char file_name[TOX_MAX_FILENAME_LENGTH];
998 | size_t namelen = get_file_name(file_name, sizeof(file_name), path);
999 |
1000 | TOX_ERR_FILE_SEND err;
1001 |
1002 | char *o = calloc(1, (size_t)TOX_FILE_ID_LENGTH);
1003 | uint32_t filenum = -1;
1004 | if (resume == 0)
1005 | {
1006 | dbg(9, "resume == 0\n");
1007 | random_char(o, (int)TOX_FILE_ID_LENGTH);
1008 |
1009 | filenum = tox_file_send(m, num, TOX_FILE_KIND_DATA, (uint64_t)filesize, (uint8_t*)o,
1010 | (uint8_t *)file_name, namelen, &err);
1011 | }
1012 | else
1013 | {
1014 | dbg(9, "resume == 1\n");
1015 |
1016 | filenum = tox_file_send(m, num, TOX_FILE_KIND_DATA, (uint64_t)filesize, fileid_resume,
1017 | (uint8_t *)file_name, namelen, &err);
1018 | }
1019 | dbg(2, "send_file_to_friend:tox_file_send=%s filenum=%d\n", file_name, (int)filenum);
1020 |
1021 | if (err != TOX_ERR_FILE_SEND_OK)
1022 | {
1023 | dbg(0, "send_file_to_friend_real: ! TOX_ERR_FILE_SEND_OK\n");
1024 | goto on_send_error;
1025 | }
1026 |
1027 | dbg(2, "send_file_to_friend_real(1):tox_file_send=%s filenum=%d\n", file_name, (int)filenum);
1028 | struct FileTransfer *ft = new_file_transfer(num, filenum, FILE_TRANSFER_SEND, TOX_FILE_KIND_DATA);
1029 | dbg(2, "send_file_to_friend_real(2):tox_file_send=%s filenum=%d\n", file_name, (int)filenum);
1030 |
1031 | if (!ft)
1032 | {
1033 | dbg(0, "send_file_to_friend_real:ft=NULL\n");
1034 | err = TOX_ERR_FILE_SEND_TOO_MANY;
1035 | goto on_send_error;
1036 | }
1037 |
1038 | memcpy(ft->file_name, file_name, namelen + 1);
1039 | ft->file = file_to_send;
1040 | ft->file_size = filesize;
1041 |
1042 | if (resume == 0)
1043 | {
1044 | dbg(9, "resume == 0\n");
1045 | memcpy(ft->file_id, o, (size_t)TOX_FILE_ID_LENGTH);
1046 | }
1047 | else
1048 | {
1049 | dbg(9, "resume == 1\n");
1050 | memcpy(ft->file_id, fileid_resume, (size_t)TOX_FILE_ID_LENGTH);
1051 | }
1052 |
1053 | dbg(0, "send_file_to_friend_real:tox_file_get_file_id num=%d filenum=%d\n", (int)num, (int)filenum);
1054 | dbg(0, "send_file_to_friend_real:file_id_resume=%d ft->file_id=%d\n", (int)fileid_resume, (int)ft->file_id);
1055 | dbg(0, "send_file_to_friend_real:o=%d ft->file_id=%d\n", (int)o, (int)ft->file_id);
1056 |
1057 | char file_id_str[TOX_FILE_ID_LENGTH * 2 + 1];
1058 | bin_id_to_string_all((char*)ft->file_id, (size_t)TOX_FILE_ID_LENGTH, file_id_str, (size_t)(TOX_FILE_ID_LENGTH * 2 + 1));
1059 | dbg(2, "send_file_to_friend_real:file_id=%s\n", file_id_str);
1060 | bin_id_to_string_all((char*)fileid_resume, (size_t)TOX_FILE_ID_LENGTH, file_id_str, (size_t)(TOX_FILE_ID_LENGTH * 2 + 1));
1061 | dbg(2, "send_file_to_friend_real:fileid_resume=%s\n", file_id_str);
1062 | bin_id_to_string_all((char*)o, (size_t)TOX_FILE_ID_LENGTH, file_id_str, (size_t)(TOX_FILE_ID_LENGTH * 2 + 1));
1063 | dbg(2, "send_file_to_friend_real:o=%s\n", file_id_str);
1064 |
1065 | free(o);
1066 | o = NULL;
1067 |
1068 | return;
1069 |
1070 | on_send_error:
1071 |
1072 | free(o);
1073 | o = NULL;
1074 |
1075 | switch (err)
1076 | {
1077 | case TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND:
1078 | errmsg = "File transfer failed: Invalid friend.";
1079 | break;
1080 |
1081 | case TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED:
1082 | errmsg = "File transfer failed: Friend is offline.";
1083 |
1084 | break;
1085 |
1086 | case TOX_ERR_FILE_SEND_NAME_TOO_LONG:
1087 | errmsg = "File transfer failed: Filename is too long.";
1088 | break;
1089 |
1090 | case TOX_ERR_FILE_SEND_TOO_MANY:
1091 | errmsg = "File transfer failed: Too many concurrent file transfers.";
1092 |
1093 | break;
1094 |
1095 | default:
1096 | errmsg = "File transfer failed.";
1097 | break;
1098 | }
1099 |
1100 | dbg(0, "send_file_to_friend_real:ft error=%s\n", errmsg);
1101 | tox_file_control(m, num, filenum, TOX_FILE_CONTROL_CANCEL, NULL);
1102 | fclose(file_to_send);
1103 |
1104 | // ------- hack to send file --------
1105 | // ------- hack to send file --------
1106 | }
1107 |
1108 | void resume_file_to_friend(Tox *m, uint32_t num, struct FileTransfer* ft)
1109 | {
1110 | char *file_name_incl_full_path = NULL;
1111 | int j = find_friend_in_friendlist(ft->friendnum);
1112 |
1113 | if (j > -1)
1114 | {
1115 | file_name_incl_full_path = malloc(300);
1116 | snprintf(file_name_incl_full_path, 299, "%s/%s", (const char*)Friends.list[j].worksubdir, ft->file_name);
1117 | dbg(2, "resume_file_to_friend:full path=%s\n", file_name_incl_full_path);
1118 | char file_id_str[TOX_FILE_ID_LENGTH * 2 + 1];
1119 | bin_id_to_string_all((char*)ft->file_id, (size_t)TOX_FILE_ID_LENGTH, file_id_str, (size_t)(TOX_FILE_ID_LENGTH * 2 + 1));
1120 | dbg(2, "resume_file_to_friend:file_id=%d file_id_bin=%d\n", (int)file_id_str, (int)ft->file_id);
1121 | dbg(2, "resume_file_to_friend:file_id=%s\n", file_id_str);
1122 |
1123 | dbg(2, "resume_file_to_friend:path=%s friendnum=%d filenum=%d\n", file_name_incl_full_path, (int)ft->friendnum, (int)ft->filenum);
1124 | send_file_to_friend_real(m, ft->friendnum, file_name_incl_full_path, 1, ft->file_id);
1125 | }
1126 | else
1127 | {
1128 | dbg(0, "resume_file_to_friend:friend %d not found in friendlist\n", (int)ft->friendnum);
1129 | }
1130 | }
1131 |
1132 | void send_file_to_friend(Tox *m, uint32_t num, const char* filename)
1133 | {
1134 | send_file_to_friend_real(m, num, filename, 0, NULL);
1135 | }
1136 |
1137 |
1138 | int copy_file(const char *from, const char *to)
1139 | {
1140 | int fd_to, fd_from;
1141 | char buf[4096];
1142 | ssize_t nread;
1143 | int saved_errno;
1144 |
1145 | fd_from = open(from, O_RDONLY);
1146 |
1147 | if (fd_from < 0)
1148 | {
1149 | dbg(0, "copy_file:002\n");
1150 | return -1;
1151 | }
1152 |
1153 | fd_to = open(to, O_WRONLY | O_CREAT | O_EXCL, 0666);
1154 | if (fd_to < 0)
1155 | {
1156 | dbg(0, "copy_file:003\n");
1157 | goto out_error;
1158 | }
1159 |
1160 | while (nread = read(fd_from, buf, sizeof buf), nread > 0)
1161 | {
1162 | char *out_ptr = buf;
1163 | ssize_t nwritten;
1164 |
1165 | do
1166 | {
1167 | nwritten = write(fd_to, out_ptr, nread);
1168 |
1169 | if (nwritten >= 0)
1170 | {
1171 | nread -= nwritten;
1172 | out_ptr += nwritten;
1173 | }
1174 | else if (errno != EINTR)
1175 | {
1176 | dbg(0, "copy_file:004\n");
1177 | goto out_error;
1178 | }
1179 |
1180 | } while (nread > 0);
1181 | }
1182 |
1183 | if (nread == 0)
1184 | {
1185 | if (close(fd_to) < 0)
1186 | {
1187 | fd_to = -1;
1188 | dbg(0, "copy_file:005\n");
1189 | goto out_error;
1190 | }
1191 |
1192 | close(fd_from);
1193 |
1194 | /* Success! */
1195 | return 0;
1196 | }
1197 |
1198 |
1199 | out_error:
1200 | saved_errno = errno;
1201 |
1202 | close(fd_from);
1203 | if (fd_to >= 0)
1204 | {
1205 | close(fd_to);
1206 | }
1207 |
1208 | dbg(0, "copy_file:009\n");
1209 |
1210 | errno = saved_errno;
1211 | return -1;
1212 | }
1213 |
1214 |
1215 |
1216 | char* copy_file_to_friend_subdir(int friendlistnum, const char* file_with_path, const char* filename)
1217 | {
1218 | }
1219 |
1220 | int have_resumed_fts_friend(uint32_t friendnum)
1221 | {
1222 | int j = find_friend_in_friendlist(friendnum);
1223 |
1224 | if (Friends.list[j].have_resumed_fts == 1)
1225 | {
1226 | return 1;
1227 | }
1228 | else
1229 | {
1230 | return 0;
1231 | }
1232 | }
1233 |
1234 | void send_file_to_all_friends(Tox *m, const char* file_with_path, const char* filename)
1235 | {
1236 | }
1237 |
1238 | void on_tox_friend_status(Tox *tox, uint32_t friend_number, TOX_USER_STATUS status, void *user_data)
1239 | {
1240 | dbg(2, "on_tox_friend_status:friendnum=%d status=%d\n", (int)friend_number, (int)status);
1241 | }
1242 |
1243 | void friendlist_onConnectionChange(Tox *m, uint32_t num, TOX_CONNECTION connection_status, void *user_data)
1244 | {
1245 | int friendlistnum = find_friend_in_friendlist(num);
1246 | dbg(2, "friendlist_onConnectionChange:*ENTER*:friendnum=%d %d\n", (int)num, (int)connection_status);
1247 |
1248 | Friends.list[friendlistnum].connection_status = connection_status;
1249 | update_friend_last_online(num, get_unix_time());
1250 |
1251 | if (is_friend_online(m, num) == 1)
1252 | {
1253 | dbg(0, "friend %d just got online\n", num);
1254 |
1255 | resume_resumable_fts(m, num);
1256 |
1257 | if (avatar_send(m, num) == -1)
1258 | {
1259 | dbg(0, "avatar_send failed for friend %d\n", num);
1260 | }
1261 | }
1262 | else
1263 | {
1264 | dbg(0, "friend %d went *OFFLINE*\n", num);
1265 |
1266 | // save all resumeable FTs
1267 | save_resumable_fts(m, num);
1268 | // friend went offline -> cancel all filetransfers
1269 | kill_all_file_transfers_friend(m, num);
1270 | // friend went offline -> hang up on all calls
1271 | av_local_disconnect(mytox_av, num);
1272 | }
1273 |
1274 | dbg(2, "friendlist_onConnectionChange:*READY*:friendnum=%d %d\n", (int)num, (int)connection_status);
1275 |
1276 | }
1277 |
1278 | void friendlist_onFriendAdded(Tox *m, uint32_t num, bool sort)
1279 | {
1280 | // dbg(9, "friendlist_onFriendAdded:001\n");
1281 |
1282 | if (Friends.max_idx == 0)
1283 | {
1284 | // dbg(9, "friendlist_onFriendAdded:001.a malloc 1 friend struct, max_id=%d, num=%d\n", (int)Friends.max_idx, (int)num);
1285 | Friends.list = malloc(sizeof(ToxicFriend));
1286 | }
1287 | else
1288 | {
1289 | // dbg(9, "friendlist_onFriendAdded:001.b realloc %d friend struct, max_id=%d, num=%d\n", (int)(Friends.max_idx + 1), (int)Friends.max_idx, (int)num);
1290 | Friends.list = realloc(Friends.list, ((Friends.max_idx + 1) * sizeof(ToxicFriend)));
1291 | }
1292 |
1293 | // dbg(9, "friendlist_onFriendAdded:001.c set friend to all 0 values\n");
1294 | memset(&Friends.list[Friends.max_idx], 0, sizeof(ToxicFriend)); // fill friend with "0" bytes
1295 |
1296 |
1297 | // dbg(2, "friendlist_onFriendAdded:003:%d\n", (int)Friends.max_idx);
1298 | Friends.list[Friends.max_idx].num = num;
1299 | Friends.list[Friends.max_idx].active = true;
1300 | Friends.list[Friends.max_idx].connection_status = TOX_CONNECTION_NONE;
1301 | Friends.list[Friends.max_idx].status = TOX_USER_STATUS_NONE;
1302 | Friends.list[Friends.max_idx].waiting_for_answer = 0;
1303 | Friends.list[Friends.max_idx].auto_resend_start_time = 0;
1304 | Friends.list[Friends.max_idx].have_resumed_fts = 0;
1305 |
1306 | TOX_ERR_FRIEND_GET_PUBLIC_KEY pkerr;
1307 | tox_friend_get_public_key(m, num, (uint8_t *) Friends.list[Friends.max_idx].pub_key, &pkerr);
1308 |
1309 | if (pkerr != TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK)
1310 | {
1311 | dbg(0, "tox_friend_get_public_key failed (error %d)\n", pkerr);
1312 | }
1313 |
1314 | bin_id_to_string(Friends.list[Friends.max_idx].pub_key, (size_t) TOX_ADDRESS_SIZE, Friends.list[Friends.max_idx].pubkey_string, (size_t) (TOX_ADDRESS_SIZE * 2 + 1));
1315 | // dbg(2, "friend pubkey=%s\n", Friends.list[Friends.max_idx].pubkey_string);
1316 |
1317 | TOX_ERR_FRIEND_GET_LAST_ONLINE loerr;
1318 | time_t t = tox_friend_get_last_online(m, num, &loerr);
1319 |
1320 | if (loerr != TOX_ERR_FRIEND_GET_LAST_ONLINE_OK)
1321 | {
1322 | t = 0;
1323 | }
1324 |
1325 | update_friend_last_online(num, t);
1326 |
1327 | Friends.max_idx++;
1328 |
1329 | }
1330 |
1331 | // after you are finished call free_friendlist_nums !
1332 | uint32_t* load_friendlist_nums(Tox *m)
1333 | {
1334 | size_t numfriends = tox_self_get_friend_list_size(m);
1335 | uint32_t *friend_list = malloc(numfriends * sizeof(uint32_t));
1336 | tox_self_get_friend_list(m, friend_list);
1337 |
1338 | return friend_list;
1339 | }
1340 |
1341 | void free_friendlist_nums(void* friend_list)
1342 | {
1343 | if (friend_list)
1344 | {
1345 | free(friend_list);
1346 | friend_list = NULL;
1347 | }
1348 | }
1349 |
1350 | static void load_friendlist(Tox *m)
1351 | {
1352 | size_t i;
1353 | // TODO
1354 | size_t numfriends = tox_self_get_friend_list_size(m);
1355 | uint32_t* friend_lookup_list = load_friendlist_nums(m);
1356 |
1357 | for (i = 0; i < numfriends; ++i)
1358 | {
1359 | friendlist_onFriendAdded(m, friend_lookup_list[i], false);
1360 | dbg(2, "loading friend num:%d pubkey=%s\n", (int)friend_lookup_list[i], Friends.list[Friends.max_idx - 1].pubkey_string);
1361 | }
1362 |
1363 | free_friendlist_nums((void*) friend_lookup_list);
1364 | }
1365 |
1366 |
1367 |
1368 |
1369 | void close_file_transfer(Tox *m, struct FileTransfer *ft, int CTRL)
1370 | {
1371 | dbg(9, "close_file_transfer:001\n");
1372 |
1373 | if (!ft)
1374 | {
1375 | return;
1376 | }
1377 |
1378 | if (ft->state == FILE_TRANSFER_INACTIVE)
1379 | {
1380 | return;
1381 | }
1382 |
1383 | if (ft->file)
1384 | {
1385 | fclose(ft->file);
1386 | }
1387 |
1388 | if (CTRL >= 0)
1389 | {
1390 | tox_file_control(m, ft->friendnum, ft->filenum, (TOX_FILE_CONTROL) CTRL, NULL);
1391 | }
1392 |
1393 | memset(ft, 0, sizeof(struct FileTransfer));
1394 | ft->state = FILE_TRANSFER_INACTIVE; // == 0
1395 |
1396 | }
1397 |
1398 | int has_reached_max_file_transfer_for_friend(uint32_t num)
1399 | {
1400 | int active_ft = 0;
1401 | int friendlistnum = find_friend_in_friendlist(num);
1402 | int i;
1403 |
1404 | for (i = 0; i < MAX_FILES; ++i)
1405 | {
1406 | struct FileTransfer *ft_send = &Friends.list[friendlistnum].file_sender[i];
1407 |
1408 | if (ft_send->state != FILE_TRANSFER_INACTIVE)
1409 | {
1410 | if (ft_send->file_name != NULL)
1411 | {
1412 | active_ft++;
1413 | }
1414 | }
1415 | }
1416 |
1417 | if (active_ft < MAX_FILES)
1418 | {
1419 | return 0;
1420 | }
1421 | else
1422 | {
1423 | // have reached max filetransfers already
1424 | return 1;
1425 | }
1426 | }
1427 |
1428 | struct FileTransfer *get_file_transfer_from_filename_struct(int friendlistnum, const char* filename)
1429 | {
1430 | size_t i;
1431 |
1432 | for (i = 0; i < MAX_FILES; ++i)
1433 | {
1434 | struct FileTransfer *ft_send = &Friends.list[friendlistnum].file_sender[i];
1435 |
1436 | if (ft_send->state != FILE_TRANSFER_INACTIVE)
1437 | {
1438 | if (ft_send->file_name != NULL)
1439 | {
1440 | if ((strlen(ft_send->file_name) > 0) && (filename != NULL) && (strlen(filename) > 0))
1441 | {
1442 | if (strncmp((char*)ft_send->file_name, filename, strlen(ft_send->file_name)) == 0)
1443 | {
1444 | // dbg(9, "found ft by filename:%s\n", ft_send->file_name);
1445 | return ft_send;
1446 | }
1447 | }
1448 | }
1449 | }
1450 | }
1451 |
1452 | return NULL;
1453 | }
1454 |
1455 |
1456 | struct FileTransfer *get_file_transfer_struct(uint32_t friendnum, uint32_t filenum)
1457 | {
1458 | size_t i;
1459 |
1460 | int friendlistnum = find_friend_in_friendlist(friendnum);
1461 |
1462 | for (i = 0; i < MAX_FILES; ++i)
1463 | {
1464 | struct FileTransfer *ft_send = &Friends.list[friendlistnum].file_sender[i];
1465 |
1466 | if (ft_send->state != FILE_TRANSFER_INACTIVE && ft_send->filenum == filenum)
1467 | {
1468 | return ft_send;
1469 | }
1470 |
1471 | struct FileTransfer *ft_recv = &Friends.list[friendlistnum].file_receiver[i];
1472 |
1473 | if (ft_recv->state != FILE_TRANSFER_INACTIVE && ft_recv->filenum == filenum)
1474 | {
1475 | return ft_recv;
1476 | }
1477 | }
1478 |
1479 | return NULL;
1480 | }
1481 |
1482 | //
1483 | // cut message at 999 chars length !!
1484 | //
1485 | void send_text_message_to_friend(Tox *tox, uint32_t friend_number, const char *fmt, ...)
1486 | {
1487 | char msg2[1000];
1488 | size_t length = 0;
1489 |
1490 | if (fmt == NULL)
1491 | {
1492 | dbg(9, "send_text_message_to_friend:no message to send\n");
1493 | return;
1494 | }
1495 |
1496 | va_list ap;
1497 | va_start(ap, fmt);
1498 | vsnprintf(msg2, 999, fmt, ap);
1499 | va_end(ap);
1500 |
1501 | length = (size_t)strlen(msg2);
1502 | tox_friend_send_message(tox, friend_number, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *)msg2, length, NULL);
1503 | }
1504 |
1505 |
1506 | void friend_request_cb(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length,
1507 | void *user_data)
1508 | {
1509 | uint32_t friendnum = tox_friend_add_norequest(tox, public_key, NULL);
1510 | dbg(2, "add friend:002:friendnum=%d max_id=%d\n", friendnum, (int)Friends.max_idx);
1511 | friendlist_onFriendAdded(tox, friendnum, 0);
1512 |
1513 | update_savedata_file(tox);
1514 | }
1515 |
1516 | /* ssssshhh I stole this from ToxBot, don't tell anyone.. */
1517 | /* ssssshhh and I stole this from EchoBot, don't tell anyone.. */
1518 | static void get_elapsed_time_str(char *buf, int bufsize, uint64_t secs)
1519 | {
1520 | long unsigned int minutes = (secs % 3600) / 60;
1521 | long unsigned int hours = (secs / 3600) % 24;
1522 | long unsigned int days = (secs / 3600) / 24;
1523 |
1524 | snprintf(buf, bufsize, "%lud %luh %lum", days, hours, minutes);
1525 | }
1526 |
1527 | //
1528 | // lastline param ignored for now!!
1529 | //
1530 | void run_cmd_return_output(const char *command, char* output, int lastline)
1531 | {
1532 | FILE *fp = NULL;
1533 | char path[1035];
1534 | char *pos = NULL;
1535 |
1536 | if (!output)
1537 | {
1538 | return;
1539 | }
1540 |
1541 | /* Open the command for reading. */
1542 | fp = popen(command, "r");
1543 | if (fp == NULL)
1544 | {
1545 | dbg(0, "Failed to run command: %s errno=%d error=%s\n", command, errno, strerror(errno));
1546 | output[0] = '\0';
1547 | return;
1548 | }
1549 |
1550 | /* Read the output a line at a time - output it. */
1551 | while (fgets(path, sizeof(path)-1, fp) != NULL)
1552 | {
1553 | snprintf(output, 299, "%s", (const char*)path);
1554 | }
1555 |
1556 | if (strlen(output) > 1)
1557 | {
1558 | if ((pos = strchr(output, '\n')) != NULL)
1559 | {
1560 | *pos = '\0';
1561 | }
1562 | }
1563 |
1564 | /* close */
1565 | pclose(fp);
1566 | }
1567 |
1568 | void remove_friend(Tox *tox, uint32_t friend_number)
1569 | {
1570 | TOX_ERR_FRIEND_DELETE error;
1571 | tox_friend_delete(tox, friend_number, &error);
1572 | }
1573 |
1574 | void cmd_delfriend(Tox *tox, uint32_t friend_number, const char* message)
1575 | {
1576 | uint32_t del_friend_number = -1;
1577 | if (friend_number != del_friend_number)
1578 | {
1579 | // remove_friend(tox, del_friend_number);
1580 | }
1581 | }
1582 |
1583 | void cmd_stats(Tox *tox, uint32_t friend_number)
1584 | {
1585 | switch (my_connection_status)
1586 | {
1587 | case TOX_CONNECTION_NONE:
1588 | send_text_message_to_friend(tox, friend_number, "tox_tcp_relay status:offline");
1589 | break;
1590 | case TOX_CONNECTION_TCP:
1591 | send_text_message_to_friend(tox, friend_number, "tox_tcp_relay status:Online, using TCP");
1592 | break;
1593 | case TOX_CONNECTION_UDP:
1594 | send_text_message_to_friend(tox, friend_number, "tox_tcp_relay status:Online, using UDP");
1595 | break;
1596 | default:
1597 | send_text_message_to_friend(tox, friend_number, "tox_tcp_relay status:*unknown*");
1598 | break;
1599 | }
1600 |
1601 | // ----- uptime -----
1602 | char time_str[200];
1603 | uint64_t cur_time = time(NULL);
1604 | get_elapsed_time_str(time_str, sizeof(time_str), cur_time - global_start_time);
1605 | send_text_message_to_friend(tox, friend_number, "Uptime: %s", time_str);
1606 | // ----- uptime -----
1607 |
1608 | char output_str[1000];
1609 | run_cmd_return_output(shell_cmd__get_my_number_of_open_files, output_str, 1);
1610 | if (strlen(output_str) > 0)
1611 | {
1612 | send_text_message_to_friend(tox, friend_number, "toxcam open files:%s", output_str);
1613 | }
1614 | else
1615 | {
1616 | send_text_message_to_friend(tox, friend_number, "ERROR getting open files");
1617 | }
1618 |
1619 | // --- temp ---
1620 | run_cmd_return_output(shell_cmd__get_cpu_temp, output_str, 1);
1621 | if (strlen(output_str) > 0)
1622 | {
1623 | send_text_message_to_friend(tox, friend_number, "toxcam Cpu temp:%s\xC2\xB0%s", output_str, "C");
1624 | }
1625 | else
1626 | {
1627 | send_text_message_to_friend(tox, friend_number, "ERROR getting Cpu temp");
1628 | }
1629 |
1630 | run_cmd_return_output(shell_cmd__get_gpu_temp, output_str, 1);
1631 | if (strlen(output_str) > 0)
1632 | {
1633 | send_text_message_to_friend(tox, friend_number, "toxcam GPU temp:%s\xC2\xB0%s", output_str, "C");
1634 | }
1635 | else
1636 | {
1637 | send_text_message_to_friend(tox, friend_number, "ERROR getting GPU temp");
1638 | }
1639 | // --- temp ---
1640 |
1641 | char tox_id_hex[TOX_ADDRESS_SIZE*2 + 1];
1642 | get_my_toxid(tox, tox_id_hex);
1643 |
1644 | send_text_message_to_friend(tox, friend_number, "tox:%s", tox_id_hex);
1645 | }
1646 |
1647 | void cmd_kamft(Tox *tox, uint32_t friend_number)
1648 | {
1649 | send_text_message_to_friend(tox, friend_number, "killing all filetransfers to you ...");
1650 | kill_all_file_transfers_friend(tox, friend_number);
1651 | }
1652 |
1653 | void cmd_snap(Tox *tox, uint32_t friend_number)
1654 | {
1655 | send_text_message_to_friend(tox, friend_number, "*Feature DISABLED*");
1656 |
1657 | if (1 == 1 + 1)
1658 | {
1659 | send_text_message_to_friend(tox, friend_number, "capture single shot, and send to all friends ...");
1660 |
1661 | char output_str[1000];
1662 | run_cmd_return_output(shell_cmd__single_shot, output_str, 1);
1663 |
1664 | #if 0
1665 | if (strlen(output_str) > 0)
1666 | {
1667 | // send_text_message_to_friend(tox, friend_number, "toxcam:%s", output_str);
1668 | }
1669 | else
1670 | {
1671 | send_text_message_to_friend(tox, friend_number, "ERROR running snap command");
1672 | }
1673 | #endif
1674 |
1675 | send_text_message_to_friend(tox, friend_number, "... capture single shot, ready!");
1676 |
1677 | }
1678 | }
1679 |
1680 | void cmd_friends(Tox *tox, uint32_t friend_number)
1681 | {
1682 | size_t i;
1683 | // TODO
1684 | size_t numfriends = tox_self_get_friend_list_size(tox);
1685 | int j = -1;
1686 |
1687 | for (i = 0; i < numfriends; ++i)
1688 | {
1689 | j = find_friend_in_friendlist((uint32_t) i);
1690 | if (j > -1)
1691 | {
1692 | send_text_message_to_friend(tox, friend_number, "%d:friend", j);
1693 | send_text_message_to_friend(tox, friend_number, "%d tox:%s", j, (const char*)Friends.list[j].pubkey_string);
1694 | send_text_message_to_friend(tox, friend_number, "%d:last online (in client local time):%s", j, (const char*)Friends.list[j].last_online.hour_min_str);
1695 |
1696 | switch (Friends.list[j].connection_status)
1697 | {
1698 | case TOX_CONNECTION_NONE:
1699 | send_text_message_to_friend(tox, friend_number, "%d:%s", j, "status:offline");
1700 | break;
1701 | case TOX_CONNECTION_TCP:
1702 | send_text_message_to_friend(tox, friend_number, "%d:%s", j, "status:Online, using TCP");
1703 | break;
1704 | case TOX_CONNECTION_UDP:
1705 | send_text_message_to_friend(tox, friend_number, "%d:%s", j, "status:Online, using UDP");
1706 | break;
1707 | default:
1708 | send_text_message_to_friend(tox, friend_number, "%d:%s", j, "status:*unknown*");
1709 | break;
1710 | }
1711 | }
1712 | }
1713 | }
1714 |
1715 | void cmd_restart(Tox *tox, uint32_t friend_number)
1716 | {
1717 | send_text_message_to_friend(tox, friend_number, "toxcam services will restart ...");
1718 |
1719 | global_want_restart = 1;
1720 | }
1721 |
1722 |
1723 | void cmd_vcm(Tox *tox, uint32_t friend_number)
1724 | {
1725 | // send_text_message_to_friend(tox, friend_number, "video-call-me not yet implemented!");
1726 |
1727 | dbg(9, "cmd_vcm:001\n");
1728 |
1729 | if (global_video_active == 1)
1730 | {
1731 | send_text_message_to_friend(tox, friend_number, "there is already a video session active");
1732 | }
1733 | else
1734 | {
1735 | send_text_message_to_friend(tox, friend_number, "i am trying to send my video ...");
1736 |
1737 | if (mytox_av != NULL)
1738 | {
1739 | dbg(9, "cmd_vcm:003\n");
1740 | global_video_bit_rate = DEFAULT_GLOBAL_VID_BITRATE;
1741 | friend_to_send_video_to = friend_number;
1742 | dbg(9, "cmd_vcm:004\n");
1743 |
1744 | TOXAV_ERR_CALL error = 0;
1745 | toxav_call(mytox_av, friend_number, global_audio_bit_rate, global_video_bit_rate, &error);
1746 | // toxav_call(mytox_av, friend_number, 0, 40, &error);
1747 | dbg(9, "cmd_vcm:005\n");
1748 |
1749 | if (error != TOXAV_ERR_CALL_OK)
1750 | {
1751 | switch (error)
1752 | {
1753 | case TOXAV_ERR_CALL_MALLOC:
1754 | dbg(0, "toxav_call (1):TOXAV_ERR_CALL_MALLOC\n");
1755 | break;
1756 |
1757 | case TOXAV_ERR_CALL_SYNC:
1758 | dbg(0, "toxav_call (1):TOXAV_ERR_CALL_SYNC\n");
1759 | break;
1760 |
1761 | case TOXAV_ERR_CALL_FRIEND_NOT_FOUND:
1762 | dbg(0, "toxav_call (1):TOXAV_ERR_CALL_FRIEND_NOT_FOUND\n");
1763 | break;
1764 |
1765 | case TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED:
1766 | dbg(0, "toxav_call (1):TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED\n");
1767 | break;
1768 |
1769 | case TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL:
1770 | dbg(0, "toxav_call (1):TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL\n");
1771 | break;
1772 |
1773 | case TOXAV_ERR_CALL_INVALID_BIT_RATE:
1774 | dbg(0, "toxav_call (1):TOXAV_ERR_CALL_INVALID_BIT_RATE\n");
1775 | break;
1776 |
1777 | default:
1778 | dbg(0, "toxav_call (1):*unknown error*\n");
1779 | break;
1780 | }
1781 | }
1782 | }
1783 | else
1784 | {
1785 | dbg(9, "cmd_vcm:006\n");
1786 | send_text_message_to_friend(tox, friend_number, "sending video failed:toxav==NULL");
1787 | }
1788 | }
1789 |
1790 | dbg(9, "cmd_vcm:099\n");
1791 | }
1792 |
1793 | void send_help_to_friend(Tox *tox, uint32_t friend_number)
1794 | {
1795 | send_text_message_to_friend(tox, friend_number, "=========================\nToxCam version:%s\n=========================", global_version_string);
1796 | // send_text_message_to_friend(tox, friend_number, " commands are:");
1797 | send_text_message_to_friend(tox, friend_number, " .stats --> show ToxCam status");
1798 | send_text_message_to_friend(tox, friend_number, " .friends --> show ToxCam Friends");
1799 | send_text_message_to_friend(tox, friend_number, " .snap --> snap a single still image");
1800 | send_text_message_to_friend(tox, friend_number, " .restart --> restart ToxCam system");
1801 | send_text_message_to_friend(tox, friend_number, " .vcm --> videocall me");
1802 | }
1803 |
1804 | //void start_zipfile(mz_zip_archive *pZip, size_t size_pZip, const char* zip_file_full_path)
1805 | //{
1806 | //}
1807 | //void add_file_to_zipfile(mz_zip_archive *pZip, const char* file_to_add_full_path, const char* filename_in_zipfile)
1808 | //{
1809 | //}
1810 | //void finish_zipfile(mz_zip_archive *pZip)
1811 | //{
1812 | //}
1813 |
1814 | void friend_message_cb(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message,
1815 | size_t length, void *user_data)
1816 | {
1817 | int j;
1818 | int send_back = 0;
1819 |
1820 | if (type == TOX_MESSAGE_TYPE_NORMAL)
1821 | {
1822 | if (message != NULL)
1823 | {
1824 | j = find_friend_in_friendlist(friend_number);
1825 | dbg(2, "message from friend:%d msg:%s\n", (int)friend_number, (char*)message);
1826 |
1827 | if (strncmp((char*)message, ".help", strlen((char*)".help")) == 0)
1828 | {
1829 | send_help_to_friend(tox, friend_number);
1830 | }
1831 | else if (strncmp((char*)message, ".stats", strlen((char*)".stats")) == 0)
1832 | {
1833 | cmd_stats(tox, friend_number);
1834 | }
1835 | else if (strncmp((char*)message, ".friends", strlen((char*)".friends")) == 0)
1836 | {
1837 | cmd_friends(tox, friend_number);
1838 | }
1839 | else if (strncmp((char*)message, ".snap", strlen((char*)".snap")) == 0)
1840 | {
1841 | cmd_snap(tox, friend_number);
1842 | }
1843 | else if (strncmp((char*)message, ".restart", strlen((char*)".restart")) == 0) // restart toxcam processes (no reboot)
1844 | {
1845 | cmd_restart(tox, friend_number);
1846 | }
1847 | else if (strncmp((char*)message, ".vcm", strlen((char*)".vcm")) == 0) // video call me!
1848 | {
1849 | cmd_vcm(tox, friend_number);
1850 | }
1851 | else
1852 | {
1853 | if (Friends.list[j].waiting_for_answer == 1)
1854 | {
1855 | // we want to get user feedback
1856 | snprintf(Friends.list[j].last_answer, 99, (char*)message);
1857 | Friends.list[j].waiting_for_answer = 2;
1858 |
1859 | if (Friends.list[j].last_answer)
1860 | {
1861 | dbg(2, "got answer from friend:%d answer:%s\n", (int)friend_number, Friends.list[j].last_answer);
1862 | }
1863 | else
1864 | {
1865 | dbg(2, "got answer from friend:%d answer:NULL\n", (int)friend_number);
1866 | }
1867 | }
1868 | else
1869 | {
1870 | // send_back = 1;
1871 | // unknown command, just send "help / usage"
1872 | send_help_to_friend(tox, friend_number);
1873 | }
1874 | }
1875 | }
1876 | else
1877 | {
1878 | dbg(2, "message from friend:%d msg:NULL\n", (int)friend_number);
1879 | }
1880 | }
1881 | else
1882 | {
1883 | dbg(2, "message from friend:%d\n", (int)friend_number);
1884 | }
1885 |
1886 | if (send_back == 1)
1887 | {
1888 | tox_friend_send_message(tox, friend_number, type, message, length, NULL);
1889 | }
1890 | }
1891 |
1892 |
1893 |
1894 | void on_file_recv_chunk(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position,
1895 | const uint8_t *data, size_t length, void *user_data)
1896 | {
1897 | struct FileTransfer *ft = get_file_transfer_struct(friendnumber, filenumber);
1898 |
1899 | if (!ft)
1900 | {
1901 | return;
1902 | }
1903 | }
1904 |
1905 |
1906 | void on_file_recv(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint32_t kind, uint64_t file_size,
1907 | const uint8_t *filename, size_t filename_length, void *userdata)
1908 | {
1909 | /* We don't care about receiving avatars */
1910 | if (kind != TOX_FILE_KIND_DATA)
1911 | {
1912 | tox_file_control(m, friendnumber, filenumber, TOX_FILE_CONTROL_CANCEL, NULL);
1913 | dbg(9, "on_file_recv:002:cancel incoming avatar\n");
1914 | return;
1915 | }
1916 | else
1917 | {
1918 | // cancel all filetransfers. we don't want to receive files
1919 | tox_file_control(m, friendnumber, filenumber, TOX_FILE_CONTROL_CANCEL, NULL);
1920 | dbg(9, "on_file_recv:003:cancel incoming file\n");
1921 | return;
1922 | }
1923 | }
1924 |
1925 | void save_resumable_fts(Tox *m, uint32_t friendnum)
1926 | {
1927 | size_t i;
1928 | int friendlistnum = find_friend_in_friendlist(friendnum);
1929 | for (i = 0; i < MAX_FILES; ++i)
1930 | {
1931 | // for now save only sending FTs
1932 | struct FileTransfer *ft = &Friends.list[friendlistnum].file_sender[i];
1933 | if (ft->state != FILE_TRANSFER_INACTIVE)
1934 | {
1935 | dbg(9, "save_resumable_fts:saving sender FT i=%d ftnum=%d for friendnum:#%d pos=%d filesize=%d\n", i, (int)ft->filenum, (int)friendnum, (int)ft->position, (int)ft->file_size);
1936 | ll_push(&resumable_filetransfers, sizeof(struct FileTransfer), ft);
1937 | dbg(9, "save_resumable_fts:pushed struct=%p\n", resumable_filetransfers->val);
1938 | }
1939 | }
1940 |
1941 | Friends.list[friendlistnum].have_resumed_fts = 0;
1942 | }
1943 |
1944 |
1945 |
1946 | void resume_resumable_fts(Tox *m, uint32_t friendnum)
1947 | {
1948 | dbg(9, "resume_resumable_fts:001\n");
1949 |
1950 | ll_node_t* saved_ft_list = resumable_filetransfers;
1951 | int i = 0;
1952 | while (saved_ft_list != NULL)
1953 | {
1954 | dbg(9, "resume_resumable_fts:element #%d=%p\n", i, saved_ft_list->val);
1955 | if (saved_ft_list->val != NULL)
1956 | {
1957 | struct FileTransfer *ft = (struct FileTransfer*)saved_ft_list->val;
1958 | if (ft->friendnum == friendnum)
1959 | {
1960 | dbg(9, "resume_resumable_fts:**found element #%d=%p\n", i, saved_ft_list->val);
1961 | resume_file_to_friend(m, ft->filenum, ft);
1962 | // now remove element, and start loop again
1963 | ll_remove_by_index(&resumable_filetransfers, i);
1964 | saved_ft_list = resumable_filetransfers;
1965 | i = 0;
1966 | continue;
1967 | }
1968 | }
1969 |
1970 | i++;
1971 | saved_ft_list = saved_ft_list->next;
1972 | }
1973 |
1974 | int j = find_friend_in_friendlist(friendnum);
1975 | if (j > -1)
1976 | {
1977 | Friends.list[j].have_resumed_fts = 1;
1978 | }
1979 | }
1980 |
1981 |
1982 |
1983 | void on_file_chunk_request(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position,
1984 | size_t length, void *userdata)
1985 | {
1986 | // dbg(9, "on_file_chunk_request:001:friendnum=%d filenum=%d position=%ld len=%d\n", (int)friendnumber, (int)filenumber, (long)position, (int)length);
1987 | struct FileTransfer *ft = get_file_transfer_struct(friendnumber, filenumber);
1988 |
1989 | if (!ft)
1990 | {
1991 | dbg(0, "on_file_chunk_request:003 ft=NULL\n");
1992 | return;
1993 | }
1994 |
1995 | if (ft->file_type == TOX_FILE_KIND_AVATAR)
1996 | {
1997 | on_avatar_chunk_request(tox, ft, position, length);
1998 | return;
1999 | }
2000 |
2001 |
2002 | if (ft->state != FILE_TRANSFER_STARTED)
2003 | {
2004 | dbg(0, "on_file_chunk_request:005 !FILE_TRANSFER_STARTED\n");
2005 | return;
2006 | }
2007 |
2008 | if (length == 0)
2009 | {
2010 | dbg(2, "File '%s' successfully sent, ft->state=%d\n", ft->file_name, (int)ft->state);
2011 |
2012 | char origname[300];
2013 | snprintf(origname, 299, "%s", (const char*)ft->file_name);
2014 |
2015 | close_file_transfer(tox, ft, -1);
2016 | // also remove the file from disk
2017 |
2018 | int friendlist_num = find_friend_in_friendlist(friendnumber);
2019 | char longname[300];
2020 | snprintf(longname, 299, "%s/%s", (const char*)Friends.list[friendlist_num].worksubdir, origname);
2021 | dbg(2, "delete file %s\n", longname);
2022 | unlink(longname);
2023 |
2024 | return;
2025 | }
2026 |
2027 | if (ft->file == NULL)
2028 | {
2029 | dbg(0, "File transfer for '%s' failed: Null file pointer\n", ft->file_name);
2030 | close_file_transfer(tox, ft, TOX_FILE_CONTROL_CANCEL);
2031 | return;
2032 | }
2033 |
2034 | if (ft->position != position)
2035 | {
2036 | if (fseek(ft->file, position, SEEK_SET) == -1)
2037 | {
2038 | dbg(0, "File transfer for '%s' failed: Seek fail\n", ft->file_name);
2039 | close_file_transfer(tox, ft, TOX_FILE_CONTROL_CANCEL);
2040 | return;
2041 | }
2042 |
2043 | ft->position = position;
2044 | }
2045 |
2046 | uint8_t send_data[length];
2047 | size_t send_length = fread(send_data, 1, sizeof(send_data), ft->file);
2048 |
2049 | if (send_length != length)
2050 | {
2051 | dbg(0, "File transfer for '%s' failed: Read fail\n", ft->file_name);
2052 | close_file_transfer(tox, ft, TOX_FILE_CONTROL_CANCEL);
2053 | return;
2054 | }
2055 |
2056 | TOX_ERR_FILE_SEND_CHUNK err;
2057 | tox_file_send_chunk(tox, friendnumber, filenumber, position, send_data, send_length, &err);
2058 |
2059 | if (err != TOX_ERR_FILE_SEND_CHUNK_OK)
2060 | {
2061 | dbg(0, "tox_file_send_chunk failed in chat callback (error %d)\n", err);
2062 | }
2063 |
2064 | ft->position += send_length;
2065 | ft->bps += send_length;
2066 | ft->last_keep_alive = get_unix_time();
2067 |
2068 | }
2069 |
2070 |
2071 | void on_avatar_file_control(Tox *m, struct FileTransfer *ft, TOX_FILE_CONTROL control)
2072 | {
2073 | switch (control)
2074 | {
2075 | case TOX_FILE_CONTROL_RESUME:
2076 | if (ft->state == FILE_TRANSFER_PENDING)
2077 | {
2078 | ft->state = FILE_TRANSFER_STARTED;
2079 | }
2080 | else if (ft->state == FILE_TRANSFER_PAUSED)
2081 | {
2082 | ft->state = FILE_TRANSFER_STARTED;
2083 | }
2084 |
2085 | break;
2086 |
2087 | case TOX_FILE_CONTROL_PAUSE:
2088 | ft->state = FILE_TRANSFER_PAUSED;
2089 | break;
2090 |
2091 | case TOX_FILE_CONTROL_CANCEL:
2092 | close_file_transfer(m, ft, -1);
2093 | break;
2094 | }
2095 | }
2096 |
2097 |
2098 | void on_file_control(Tox *m, uint32_t friendnumber, uint32_t filenumber, TOX_FILE_CONTROL control,
2099 | void *userdata)
2100 | {
2101 | struct FileTransfer *ft = get_file_transfer_struct(friendnumber, filenumber);
2102 |
2103 | if (!ft)
2104 | {
2105 | return;
2106 | }
2107 |
2108 | if (ft->file_type == TOX_FILE_KIND_AVATAR)
2109 | {
2110 | on_avatar_file_control(m, ft, control);
2111 | return;
2112 | }
2113 |
2114 | dbg(9, "on_file_control:002:file in/out\n");
2115 |
2116 |
2117 |
2118 | switch (control)
2119 | {
2120 | case TOX_FILE_CONTROL_RESUME:
2121 | {
2122 | dbg(9, "on_file_control:003:TOX_FILE_CONTROL_RESUME\n");
2123 |
2124 | ft->last_keep_alive = get_unix_time();
2125 |
2126 | /* transfer is accepted */
2127 | if (ft->state == FILE_TRANSFER_PENDING)
2128 | {
2129 | ft->state = FILE_TRANSFER_STARTED;
2130 | dbg(9, "on_file_control:004:pending -> started\n");
2131 | }
2132 | else if (ft->state == FILE_TRANSFER_PAUSED)
2133 | { /* transfer is resumed */
2134 | ft->state = FILE_TRANSFER_STARTED;
2135 | dbg(9, "on_file_control:005:paused -> started\n");
2136 | }
2137 |
2138 | break;
2139 | }
2140 |
2141 | case TOX_FILE_CONTROL_PAUSE:
2142 | {
2143 | dbg(9, "on_file_control:006:TOX_FILE_CONTROL_PAUSE\n");
2144 | ft->state = FILE_TRANSFER_PAUSED;
2145 | break;
2146 | }
2147 |
2148 | case TOX_FILE_CONTROL_CANCEL:
2149 | {
2150 | dbg(1, "File transfer for '%s' was aborted\n", ft->file_name);
2151 | close_file_transfer(m, ft, -1);
2152 | break;
2153 | }
2154 | }
2155 |
2156 | }
2157 |
2158 |
2159 |
2160 | void on_avatar_chunk_request(Tox *m, struct FileTransfer *ft, uint64_t position, size_t length)
2161 | {
2162 | dbg(9, "on_avatar_chunk_request:001\n");
2163 |
2164 | if (ft->state != FILE_TRANSFER_STARTED)
2165 | {
2166 | dbg(0, "on_avatar_chunk_request:001a:!FILE_TRANSFER_STARTED\n");
2167 | return;
2168 | }
2169 |
2170 | if (length == 0)
2171 | {
2172 | close_file_transfer(m, ft, -1);
2173 | return;
2174 | }
2175 |
2176 | if (ft->file == NULL)
2177 | {
2178 | close_file_transfer(m, ft, TOX_FILE_CONTROL_CANCEL);
2179 | return;
2180 | }
2181 |
2182 | if (ft->position != position)
2183 | {
2184 | if (fseek(ft->file, position, SEEK_SET) == -1)
2185 | {
2186 | close_file_transfer(m, ft, TOX_FILE_CONTROL_CANCEL);
2187 | return;
2188 | }
2189 |
2190 | ft->position = position;
2191 | }
2192 |
2193 | uint8_t send_data[length];
2194 | size_t send_length = fread(send_data, 1, sizeof(send_data), ft->file);
2195 |
2196 | if (send_length != length)
2197 | {
2198 | close_file_transfer(m, ft, TOX_FILE_CONTROL_CANCEL);
2199 | return;
2200 | }
2201 |
2202 | TOX_ERR_FILE_SEND_CHUNK err;
2203 | tox_file_send_chunk(m, ft->friendnum, ft->filenum, position, send_data, send_length, &err);
2204 |
2205 | if (err != TOX_ERR_FILE_SEND_CHUNK_OK)
2206 | {
2207 | dbg(0, "tox_file_send_chunk failed in avatar callback (error %d)\n", err);
2208 | }
2209 |
2210 | ft->position += send_length;
2211 | ft->last_keep_alive = get_unix_time();
2212 | }
2213 |
2214 |
2215 | void self_connection_status_cb(Tox *tox, TOX_CONNECTION connection_status, void *user_data)
2216 | {
2217 | switch (connection_status)
2218 | {
2219 | case TOX_CONNECTION_NONE:
2220 | dbg(2, "Offline\n");
2221 | my_connection_status = TOX_CONNECTION_NONE;
2222 | break;
2223 | case TOX_CONNECTION_TCP:
2224 | dbg(2, "Online, using TCP\n");
2225 | my_connection_status = TOX_CONNECTION_TCP;
2226 | break;
2227 | case TOX_CONNECTION_UDP:
2228 | dbg(2, "Online, using UDP\n");
2229 | my_connection_status = TOX_CONNECTION_UDP;
2230 | break;
2231 | }
2232 | }
2233 |
2234 |
2235 | static struct FileTransfer *new_file_sender(uint32_t friendnum, uint32_t filenum, uint8_t type)
2236 | {
2237 | size_t i;
2238 |
2239 | dbg(9, "new_file_sender:001 friendnum=%d filenum=%d type=%d\n", (int)friendnum, (int) filenum, (int) type);
2240 | int friendlistnum = find_friend_in_friendlist(friendnum);
2241 |
2242 | for (i = 0; i < MAX_FILES; ++i)
2243 | {
2244 | struct FileTransfer *ft = &Friends.list[friendlistnum].file_sender[i];
2245 | dbg(9, "new_file_sender:002 i=%d\n", (int)i);
2246 |
2247 | if (ft->state == FILE_TRANSFER_INACTIVE)
2248 | {
2249 | dbg(9, "new_file_sender:003:reusing sender i=%d\n", (int)i);
2250 |
2251 | memset(ft, 0, sizeof(struct FileTransfer));
2252 | // ft->state = FILE_TRANSFER_INACTIVE; // == 0
2253 |
2254 | ft->index = i;
2255 | ft->friendnum = friendnum;
2256 | ft->filenum = filenum;
2257 | ft->file_type = type;
2258 | ft->last_keep_alive = get_unix_time();
2259 | ft->state = FILE_TRANSFER_PENDING;
2260 | ft->direction = FILE_TRANSFER_SEND;
2261 |
2262 | dbg(9, "new_file_sender:003 i=%d\n", (int)i);
2263 |
2264 | return ft;
2265 | }
2266 | }
2267 |
2268 | return NULL;
2269 | }
2270 |
2271 |
2272 |
2273 | static struct FileTransfer *new_file_receiver(uint32_t friendnum, uint32_t filenum, uint8_t type)
2274 | {
2275 | size_t i;
2276 | int friendlistnum = find_friend_in_friendlist(friendnum);
2277 |
2278 | for (i = 0; i < MAX_FILES; ++i)
2279 | {
2280 | struct FileTransfer *ft = &Friends.list[friendlistnum].file_receiver[i];
2281 |
2282 | if (ft->state == FILE_TRANSFER_INACTIVE) {
2283 | memset(ft, 0, sizeof(struct FileTransfer));
2284 | // ft->state = FILE_TRANSFER_INACTIVE; // == 0
2285 |
2286 | ft->index = i;
2287 | ft->friendnum = friendnum;
2288 | ft->filenum = filenum;
2289 | ft->file_type = type;
2290 | ft->last_keep_alive = get_unix_time();
2291 | ft->state = FILE_TRANSFER_PENDING;
2292 | ft->direction = FILE_TRANSFER_RECV;
2293 | return ft;
2294 | }
2295 | }
2296 |
2297 | return NULL;
2298 | }
2299 |
2300 |
2301 | struct FileTransfer *new_file_transfer(uint32_t friendnum, uint32_t filenum,
2302 | FILE_TRANSFER_DIRECTION direction, uint8_t type)
2303 | {
2304 | if (direction == FILE_TRANSFER_RECV)
2305 | {
2306 | return new_file_receiver(friendnum, filenum, type);
2307 | }
2308 |
2309 | if (direction == FILE_TRANSFER_SEND)
2310 | {
2311 | return new_file_sender(friendnum, filenum, type);
2312 | }
2313 |
2314 | return NULL;
2315 | }
2316 |
2317 |
2318 | int avatar_send(Tox *m, uint32_t friendnum)
2319 | {
2320 | dbg(2, "avatar_send:001 friendnum=%d\n", (int)friendnum);
2321 | dbg(2, "avatar_send:002 %d %s %d\n", (int)Avatar.size, Avatar.name, (int)Avatar.name_len);
2322 |
2323 | TOX_ERR_FILE_SEND err;
2324 | uint32_t filenum = tox_file_send(m, friendnum, TOX_FILE_KIND_AVATAR, (size_t) Avatar.size,
2325 | NULL, (uint8_t *) Avatar.name, Avatar.name_len, &err);
2326 | dbg(2, "avatar_send:tox_file_send=%s filenum=%d\n", (const char*)Avatar.name, (int)filenum);
2327 |
2328 | if (Avatar.size == 0)
2329 | {
2330 | return 0;
2331 | }
2332 |
2333 | if (err != TOX_ERR_FILE_SEND_OK)
2334 | {
2335 | dbg(0, "avatar_send:tox_file_send failed for _friendnumber %d (error %d)\n", friendnum, err);
2336 | return -1;
2337 | }
2338 |
2339 | dbg(2, "avatar_send(1):tox_file_send=%s filenum=%d\n", (const char*)Avatar.name, (int)filenum);
2340 | struct FileTransfer *ft = new_file_transfer(friendnum, filenum, FILE_TRANSFER_SEND, TOX_FILE_KIND_AVATAR);
2341 | dbg(2, "avatar_send(2):tox_file_send=%s filenum=%d\n", (const char*)Avatar.name, (int)filenum);
2342 |
2343 | if (!ft)
2344 | {
2345 | dbg(0, "avatar_send:003:ft=NULL\n");
2346 | return -1;
2347 | }
2348 |
2349 | ft->file = fopen(Avatar.path, "r");
2350 |
2351 | if (ft->file == NULL)
2352 | {
2353 | dbg(0, "avatar_send:004:ft->file=NULL\n");
2354 | return -1;
2355 | }
2356 |
2357 | snprintf(ft->file_name, sizeof(ft->file_name), "%s", Avatar.name);
2358 | ft->file_size = Avatar.size;
2359 |
2360 | return 0;
2361 | }
2362 |
2363 |
2364 | int check_file_signature(const char *signature, size_t size, FILE *fp)
2365 | {
2366 | char buf[size];
2367 | if (fread(buf, size, 1, fp) != 1)
2368 | {
2369 | return -1;
2370 | }
2371 | int ret = memcmp(signature, buf, size);
2372 | if (fseek(fp, 0L, SEEK_SET) == -1)
2373 | {
2374 | return -1;
2375 | }
2376 | return ret == 0 ? 0 : 1;
2377 | }
2378 |
2379 |
2380 | void kill_all_file_transfers_friend(Tox *m, uint32_t friendnum)
2381 | {
2382 | }
2383 | void kill_all_file_transfers(Tox *m)
2384 | {
2385 | }
2386 |
2387 |
2388 | int avatar_set(Tox *m, const char *path, size_t path_len)
2389 | {
2390 | dbg(2, "avatar_set:001\n");
2391 |
2392 | if (path_len == 0 || path_len >= sizeof(Avatar.path))
2393 | {
2394 | return -1;
2395 | }
2396 |
2397 | dbg(9, "avatar_set:002\n");
2398 | FILE *fp = fopen(path, "rb");
2399 |
2400 | if (fp == NULL)
2401 | {
2402 | return -1;
2403 | }
2404 |
2405 | char PNG_signature[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
2406 |
2407 | if (check_file_signature(PNG_signature, sizeof(PNG_signature), fp) != 0)
2408 | {
2409 | fclose(fp);
2410 | return -1;
2411 | }
2412 | fclose(fp);
2413 |
2414 | dbg(9, "avatar_set:003\n");
2415 |
2416 | off_t size = file_size(path);
2417 |
2418 | if (size == 0 || size > MAX_AVATAR_FILE_SIZE)
2419 | {
2420 | return -1;
2421 | }
2422 |
2423 | dbg(9, "avatar_set:004\n");
2424 |
2425 | get_file_name(Avatar.name, sizeof(Avatar.name), path);
2426 | Avatar.name_len = strlen(Avatar.name);
2427 | snprintf(Avatar.path, sizeof(Avatar.path), "%s", path);
2428 | Avatar.path_len = path_len;
2429 | Avatar.size = size;
2430 |
2431 | dbg(9, "avatar_set:099\n");
2432 |
2433 | return 0;
2434 | }
2435 |
2436 | static void avatar_clear(void)
2437 | {
2438 | memset(&Avatar, 0, sizeof(struct Avatar));
2439 | }
2440 |
2441 | void avatar_unset(Tox *m)
2442 | {
2443 | avatar_clear();
2444 | }
2445 |
2446 | int check_number_of_files_to_resend_to_friend(Tox *m, uint32_t friendnum, int friendlistnum)
2447 | {
2448 | }
2449 | void resend_zip_files_and_send(Tox *m, uint32_t friendnum, int friendlistnum)
2450 | {
2451 | }
2452 | void process_friends_dir(Tox *m, uint32_t friendnum, int friendlistnum)
2453 | {
2454 | }
2455 | void check_friends_dir(Tox *m)
2456 | {
2457 | }
2458 | void check_dir(Tox *m)
2459 | {
2460 | }
2461 |
2462 |
2463 | char* get_current_time_date_formatted()
2464 | {
2465 | time_t t;
2466 | struct tm *tm = NULL;
2467 | const int max_size_datetime_str = 100;
2468 | char *str_date_time = malloc(max_size_datetime_str);
2469 |
2470 | memset(str_date_time, 0, 100);
2471 | t = time(NULL);
2472 | tm = localtime(&t);
2473 |
2474 | strftime(str_date_time, max_size_datetime_str, global_overlay_timestamp_format, tm);
2475 |
2476 | // dbg(9, "str_date_time=%s\n", str_date_time);
2477 |
2478 | return str_date_time;
2479 | }
2480 |
2481 |
2482 | // ------------------- V4L2 stuff ---------------------
2483 | // ------------------- V4L2 stuff ---------------------
2484 | // ------------------- V4L2 stuff ---------------------
2485 |
2486 |
2487 | static int xioctl(int fh, unsigned long request, void *arg)
2488 | {
2489 | int r;
2490 |
2491 | do
2492 | {
2493 | r = ioctl(fh, request, arg);
2494 | } while (-1 == r && EINTR == errno);
2495 |
2496 | return r;
2497 | }
2498 |
2499 |
2500 |
2501 | int init_cam()
2502 | {
2503 | int video_dev_open_error = 0;
2504 | int fd;
2505 |
2506 | if ((fd = open(v4l2_device, O_RDWR)) < 0)
2507 | {
2508 | dbg(0, "error opening video device[1]\n");
2509 | video_dev_open_error = 1;
2510 | }
2511 |
2512 | if (video_dev_open_error == 1)
2513 | {
2514 | sleep(20); // sleep 20 seconds
2515 |
2516 | if ((fd = open(v4l2_device, O_RDWR)) < 0)
2517 | {
2518 | dbg(0, "error opening video device[2]\n");
2519 | video_dev_open_error = 1;
2520 | }
2521 | else
2522 | {
2523 | video_dev_open_error = 0;
2524 | }
2525 | }
2526 |
2527 | struct v4l2_capability cap;
2528 | struct v4l2_cropcap cropcap;
2529 | // struct v4l2_crop crop;
2530 |
2531 | if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0)
2532 | {
2533 | dbg(0, "VIDIOC_QUERYCAP\n");
2534 | }
2535 |
2536 | if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
2537 | {
2538 | dbg(0, "The device does not handle single-planar video capture.\n");
2539 | }
2540 |
2541 | if (!(cap.capabilities & V4L2_CAP_STREAMING))
2542 | {
2543 | dbg(0, "The device does not support streaming i/o.\n");
2544 | }
2545 |
2546 |
2547 | /* Select video input, video standard and tune here. */
2548 | CLEAR(cropcap);
2549 |
2550 | cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2551 |
2552 | if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap))
2553 | {
2554 | #if 0
2555 | crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2556 | crop.c = cropcap.defrect; /* reset to full area */
2557 | /* Scale the width and height to 50 % of their original size and center the output. */
2558 | crop.c.width = crop.c.width / 2;
2559 | crop.c.height = crop.c.height / 2;
2560 | crop.c.left = crop.c.left + crop.c.width / 2;
2561 | crop.c.top = crop.c.top + crop.c.height / 2;
2562 |
2563 | if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop))
2564 | {
2565 | switch (errno)
2566 | {
2567 | case EINVAL:
2568 | dbg(0, "Cropping not supported (1)\n");
2569 | break;
2570 | default:
2571 | dbg(0, "some error on croping setup\n");
2572 | break;
2573 | }
2574 | }
2575 | #endif
2576 | }
2577 | else
2578 | {
2579 | dbg(0, "Cropping not supported (2)\n");
2580 | }
2581 |
2582 |
2583 | #ifdef V4LCONVERT
2584 | v4lconvert_data = v4lconvert_create(fd);
2585 | #endif
2586 |
2587 | CLEAR(format);
2588 | CLEAR(dest_format);
2589 |
2590 | format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2591 | format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
2592 |
2593 | format.fmt.pix.width = 1920;
2594 | format.fmt.pix.height = 1080;
2595 |
2596 | dest_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2597 | dest_format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
2598 |
2599 | dest_format.fmt.pix.width = format.fmt.pix.width;
2600 | dest_format.fmt.pix.height = format.fmt.pix.height;
2601 |
2602 | if (format.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
2603 | {
2604 | dbg(2, "Video format(wanted): V4L2_PIX_FMT_YUV420\n");
2605 | }
2606 | else if (format.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
2607 | {
2608 | dbg(2, "Video format(wanted): V4L2_PIX_FMT_MJPEG\n");
2609 | }
2610 | else
2611 | {
2612 | dbg(2, "Video format(wanted): %u\n", format.fmt.pix.pixelformat);
2613 | }
2614 |
2615 | // Get <-> Set ??
2616 | if (-1 == xioctl(fd, VIDIOC_G_FMT, &format))
2617 | {
2618 | dbg(0, "VIDIOC_G_FMT\n");
2619 | }
2620 |
2621 | if (format.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
2622 | {
2623 | dbg(2, "Video format(got): V4L2_PIX_FMT_YUV420\n");
2624 | }
2625 | else if (format.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
2626 | {
2627 | dbg(2, "Video format(got): V4L2_PIX_FMT_MJPEG\n");
2628 | }
2629 | else
2630 | {
2631 | dbg(2, "Video format(got): %u\n", format.fmt.pix.pixelformat);
2632 | }
2633 |
2634 | if (video_high == 1)
2635 | {
2636 | format.fmt.pix.width = 1280;
2637 | format.fmt.pix.height = 720;
2638 | }
2639 | else
2640 | {
2641 | format.fmt.pix.width = 640;
2642 | format.fmt.pix.height = 480;
2643 | }
2644 |
2645 | video_width = format.fmt.pix.width;
2646 | video_height = format.fmt.pix.height;
2647 | dbg(2, "Video size(wanted): %u %u\n", video_width, video_height);
2648 |
2649 | if (-1 == xioctl(fd, VIDIOC_S_FMT, &format))
2650 | {
2651 | dbg(0, "VIDIOC_S_FMT\n");
2652 | }
2653 |
2654 | if (-1 == xioctl(fd, VIDIOC_G_FMT, &format))
2655 | {
2656 | dbg(0, "VIDIOC_G_FMT\n");
2657 | }
2658 |
2659 | video_width = format.fmt.pix.width;
2660 | video_height = format.fmt.pix.height;
2661 | dbg(2, "Video size(got): %u %u\n", video_width, video_height);
2662 |
2663 | dest_format.fmt.pix.width = format.fmt.pix.width;
2664 | dest_format.fmt.pix.height = format.fmt.pix.height;
2665 |
2666 |
2667 | /* Buggy driver paranoia. */
2668 | /*
2669 | min = fmt.fmt.pix.width * 2;
2670 | if (fmt.fmt.pix.bytesperline < min)
2671 | fmt.fmt.pix.bytesperline = min;
2672 | min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
2673 | if (fmt.fmt.pix.sizeimage < min)
2674 | fmt.fmt.pix.sizeimage = min;
2675 | */
2676 |
2677 |
2678 | struct v4l2_requestbuffers bufrequest;
2679 |
2680 | CLEAR(bufrequest);
2681 |
2682 | bufrequest.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2683 | bufrequest.memory = V4L2_MEMORY_MMAP;
2684 | bufrequest.count = VIDEO_BUFFER_COUNT;
2685 |
2686 | dbg(0, "VIDIOC_REQBUFS want type=%d\n", (int)bufrequest.type);
2687 |
2688 | if (-1 == xioctl(fd, VIDIOC_REQBUFS, &bufrequest))
2689 | {
2690 | if (EINVAL == errno)
2691 | {
2692 | dbg(0, "%s does not support x i/o\n", v4l2_device);
2693 | }
2694 | else
2695 | {
2696 | // dbg(0, "VIDIOC_REQBUFS error %d, %s\n", errno, strerror(errno));
2697 | // try again ...
2698 | if (-1 == xioctl(fd, VIDIOC_REQBUFS, &bufrequest))
2699 | {
2700 | if (EINVAL == errno)
2701 | {
2702 | dbg(0, "[2nd] %s does not support x i/o\n", v4l2_device);
2703 | }
2704 | else
2705 | {
2706 | dbg(0, "[2nd] VIDIOC_REQBUFS error %d, %s\n", errno, strerror(errno));
2707 | }
2708 | }
2709 | }
2710 | }
2711 |
2712 | dbg(0, "VIDIOC_REQBUFS got type=%d\n", (int)bufrequest.type);
2713 |
2714 | if (bufrequest.count < 2)
2715 | {
2716 | dbg(0, "Insufficient buffer memory on %s\n", v4l2_device);
2717 | }
2718 |
2719 |
2720 | buffers = calloc(bufrequest.count, sizeof(*buffers));
2721 |
2722 | for (n_buffers = 0; n_buffers < bufrequest.count; ++n_buffers)
2723 | {
2724 | struct v4l2_buffer bufferinfo;
2725 |
2726 | CLEAR(bufferinfo);
2727 |
2728 | bufferinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2729 | bufferinfo.memory = V4L2_MEMORY_MMAP;
2730 | bufferinfo.index = n_buffers;
2731 |
2732 | if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &bufferinfo))
2733 | {
2734 | dbg(9, "VIDIOC_QUERYBUF (2) error %d, %s\n", errno, strerror(errno));
2735 | }
2736 |
2737 | /*
2738 | if (ioctl(fd, VIDIOC_QUERYBUF, &bufferinfo) < 0)
2739 | {
2740 | dbg(0, "VIDIOC_QUERYBUF %d %s\n", errno, strerror(errno));
2741 | }
2742 | */
2743 |
2744 | buffers[n_buffers].length = bufferinfo.length;
2745 | buffers[n_buffers].start = mmap(NULL /* start anywhere */, bufferinfo.length, PROT_READ | PROT_WRITE /* required */,
2746 | MAP_SHARED /* recommended */, fd, bufferinfo.m.offset);
2747 |
2748 | if (MAP_FAILED == buffers[n_buffers].start)
2749 | {
2750 | dbg(0, "mmap error %d, %s\n", errno, strerror(errno));
2751 | }
2752 |
2753 | }
2754 |
2755 | return fd;
2756 | }
2757 |
2758 |
2759 | int v4l_startread()
2760 | {
2761 | dbg(9, "start cam\n");
2762 | size_t i;
2763 | enum v4l2_buf_type type;
2764 |
2765 | for (i = 0; i < n_buffers; ++i)
2766 | {
2767 | struct v4l2_buffer buf;
2768 |
2769 | dbg(9, "buffer (1) %d of %d\n", i, n_buffers);
2770 |
2771 | CLEAR(buf);
2772 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2773 | buf.memory = V4L2_MEMORY_MMAP;
2774 | buf.index = i;
2775 |
2776 | if (-1 == xioctl(global_cam_device_fd, VIDIOC_QBUF, &buf))
2777 | {
2778 | dbg(9, "VIDIOC_QBUF (3) error %d, %s\n", errno, strerror(errno));
2779 | return 0;
2780 | }
2781 | }
2782 |
2783 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2784 | if (-1 == xioctl(global_cam_device_fd, VIDIOC_STREAMON, &type))
2785 | {
2786 | dbg(9, "VIDIOC_STREAMON error %d, %s\n", errno, strerror(errno));
2787 | return 0;
2788 | }
2789 |
2790 | return 1;
2791 | }
2792 |
2793 |
2794 | int v4l_endread()
2795 | {
2796 | dbg(9, "stop webcam\n");
2797 | enum v4l2_buf_type type;
2798 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2799 | if (-1 == xioctl(global_cam_device_fd, VIDIOC_STREAMOFF, &type))
2800 | {
2801 | dbg(9, "VIDIOC_STREAMOFF error %d, %s\n", errno, strerror(errno));
2802 | return 0;
2803 | }
2804 |
2805 | return 1;
2806 | }
2807 |
2808 |
2809 | void yuv422to420(uint8_t *plane_y, uint8_t *plane_u, uint8_t *plane_v, uint8_t *input, uint16_t width, uint16_t height)
2810 | {
2811 | uint8_t *end = input + width * height * 2;
2812 | while (input != end)
2813 | {
2814 | uint8_t *line_end = input + width * 2;
2815 | while (input != line_end)
2816 | {
2817 | *plane_y++ = *input++;
2818 | *plane_v++ = *input++;
2819 | *plane_y++ = *input++;
2820 | *plane_u++ = *input++;
2821 | }
2822 |
2823 | line_end = input + width * 2;
2824 | while (input != line_end)
2825 | {
2826 | *plane_y++ = *input++;
2827 | input++; // u
2828 | *plane_y++ = *input++;
2829 | input++; // v
2830 | }
2831 | }
2832 | }
2833 |
2834 |
2835 | int v4l_getframe(uint8_t *y, uint8_t *u, uint8_t *v, uint16_t width, uint16_t height)
2836 | {
2837 | if (width != video_width || height != video_height)
2838 | {
2839 | dbg(9, "V4L:\twidth/height mismatch %u %u != %u %u\n", width, height, video_width, video_height);
2840 | return 0;
2841 | }
2842 |
2843 | struct v4l2_buffer buf;
2844 |
2845 | CLEAR(buf);
2846 |
2847 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2848 | buf.memory = V4L2_MEMORY_MMAP; // V4L2_MEMORY_USERPTR;
2849 |
2850 | if (-1 == ioctl(global_cam_device_fd, VIDIOC_DQBUF, &buf))
2851 | {
2852 | switch (errno)
2853 | {
2854 | case EINTR:
2855 | case EAGAIN: return 0;
2856 |
2857 | case EIO:
2858 | /* Could ignore EIO, see spec. */
2859 |
2860 | /* fall through */
2861 |
2862 | default: dbg(9, "VIDIOC_DQBUF error %d, %s\n", errno, strerror(errno)); return -1;
2863 |
2864 | }
2865 | }
2866 |
2867 | /*for (i = 0; i < n_buffers; ++i)
2868 | if (buf.m.userptr == (unsigned long)buffers[i].start
2869 | && buf.length == buffers[i].length)
2870 | break;
2871 |
2872 | if(i >= n_buffers) {
2873 | dbg(9, "fatal error\n");
2874 | return 0;
2875 | }*/
2876 |
2877 | // dbg(9, "buf.index=%d\n", (int)buf.index);
2878 |
2879 | void *data = (void *)buffers[buf.index].start; // length = buf.bytesused //(void*)buf.m.userptr
2880 |
2881 | /* assumes planes are continuous memory */
2882 | #ifdef V4LCONVERT
2883 | // dbg(9, "V4LCONVERT\n");
2884 | int result = v4lconvert_convert(v4lconvert_data, &format, &dest_format, data, buf.bytesused, y,
2885 | (video_width * video_height * 3) / 2);
2886 |
2887 | if (result == -1)
2888 | {
2889 | dbg(0, "v4lconvert_convert error %s\n", v4lconvert_get_error_message(v4lconvert_data));
2890 | }
2891 | #else
2892 | dbg(9, "convert2\n");
2893 | if (format.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
2894 | {
2895 | dbg(9, "yuv422to420\n");
2896 | yuv422to420(y, u, v, data, video_width, video_height);
2897 | }
2898 | else
2899 | {
2900 | }
2901 | #endif
2902 |
2903 | if (-1 == xioctl(global_cam_device_fd, VIDIOC_QBUF, &buf))
2904 | {
2905 | dbg(9, "VIDIOC_QBUF (1) error %d, %s\n", errno, strerror(errno));
2906 | }
2907 |
2908 | #ifdef V4LCONVERT
2909 | return (result == -1 ? 0 : 1);
2910 | #else
2911 | return 1;
2912 | #endif
2913 | }
2914 |
2915 |
2916 | void close_cam()
2917 | {
2918 | #ifdef V4LCONVERT
2919 | v4lconvert_destroy(v4lconvert_data);
2920 | #endif
2921 |
2922 | size_t i;
2923 | for (i = 0; i < n_buffers; ++i)
2924 | {
2925 | if (-1 == munmap(buffers[i].start, buffers[i].length))
2926 | {
2927 | dbg(9, "munmap error\n");
2928 | }
2929 | }
2930 |
2931 | close(global_cam_device_fd);
2932 | }
2933 |
2934 | // ------------------- V4L2 stuff ---------------------
2935 | // ------------------- V4L2 stuff ---------------------
2936 | // ------------------- V4L2 stuff ---------------------
2937 |
2938 |
2939 |
2940 | // ------------------ Tox AV stuff --------------------
2941 | // ------------------ Tox AV stuff --------------------
2942 | // ------------------ Tox AV stuff --------------------
2943 |
2944 | static void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data)
2945 | {
2946 | if (global_video_active == 1)
2947 | {
2948 | dbg(9, "Call already active\n");
2949 | }
2950 | else
2951 | {
2952 | dbg(9, "Handling CALL callback friendnum=%d audio_enabled=%d video_enabled=%d\n", (int)friend_number, (int)audio_enabled, (int)video_enabled);
2953 | ((CallControl *)user_data)->incoming = true;
2954 |
2955 | TOXAV_ERR_ANSWER err;
2956 | global_video_bit_rate = DEFAULT_GLOBAL_VID_BITRATE;
2957 | int audio_bitrate = DEFAULT_GLOBAL_AUD_BITRATE;
2958 | int video_bitrate = global_video_bit_rate;
2959 | friend_to_send_video_to = friend_number;
2960 | global_video_active = 1;
2961 | global_send_first_frame = 2;
2962 |
2963 | dbg(9, "Handling CALL callback friendnum=%d audio_bitrate=%d video_bitrate=%d\n", (int)friend_number, (int)audio_bitrate, (int)video_bitrate);
2964 |
2965 | toxav_answer(av, friend_number, audio_bitrate, video_bitrate, &err);
2966 | }
2967 | }
2968 |
2969 | static void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data)
2970 | {
2971 | dbg(9, "Handling CALL STATE callback: %d friend_number=%d\n", state, (int)friend_number);
2972 |
2973 | ((CallControl *)user_data)->state = state;
2974 |
2975 | if (state & TOXAV_FRIEND_CALL_STATE_FINISHED)
2976 | {
2977 | dbg(9, "Call with friend %d finished\n", friend_number);
2978 | global_video_active = 0;
2979 | return;
2980 | }
2981 | else if (state & TOXAV_FRIEND_CALL_STATE_ERROR)
2982 | {
2983 | dbg(9, "Call with friend %d errored\n", friend_number);
2984 | global_video_active = 0;
2985 | return;
2986 | }
2987 | else if (state & TOXAV_FRIEND_CALL_STATE_SENDING_A)
2988 | {
2989 | dbg(9, "Call with friend state:TOXAV_FRIEND_CALL_STATE_SENDING_A\n");
2990 | }
2991 | else if (state & TOXAV_FRIEND_CALL_STATE_SENDING_V)
2992 | {
2993 | dbg(9, "Call with friend state:TOXAV_FRIEND_CALL_STATE_SENDING_V\n");
2994 | }
2995 | else if (state & TOXAV_FRIEND_CALL_STATE_ACCEPTING_A)
2996 | {
2997 | dbg(9, "Call with friend state:TOXAV_FRIEND_CALL_STATE_ACCEPTING_A\n");
2998 | }
2999 | else if (state & TOXAV_FRIEND_CALL_STATE_ACCEPTING_V)
3000 | {
3001 | dbg(9, "Call with friend state:TOXAV_FRIEND_CALL_STATE_ACCEPTING_V\n");
3002 | }
3003 |
3004 | dbg(9, "t_toxav_call_state_cb:002\n");
3005 | int send_audio = (state & TOXAV_FRIEND_CALL_STATE_SENDING_A) && (state & TOXAV_FRIEND_CALL_STATE_ACCEPTING_A);
3006 | int send_video = state & TOXAV_FRIEND_CALL_STATE_SENDING_V && (state & TOXAV_FRIEND_CALL_STATE_ACCEPTING_V);
3007 | dbg(9, "t_toxav_call_state_cb:002a send_audio=%d send_video=%d global_video_bit_rate=%d\n", send_audio, send_video, (int)global_video_bit_rate);
3008 | TOXAV_ERR_BIT_RATE_SET bitrate_err = 0;
3009 | // ** // toxav_bit_rate_set(av, friend_number, 0, send_video ? global_video_bit_rate : 0, &bitrate_err);
3010 | dbg(9, "t_toxav_call_state_cb:004\n");
3011 |
3012 | if (bitrate_err)
3013 | {
3014 | dbg(9, "ToxAV:Error setting/changing video bitrate\n");
3015 | }
3016 |
3017 | if (send_video == 1)
3018 | {
3019 | dbg(9, "t_toxav_call_state_cb:004\n");
3020 | global_video_active = 1;
3021 | global_send_first_frame = 2;
3022 | }
3023 | else
3024 | {
3025 | dbg(9, "t_toxav_call_state_cb:005\n");
3026 | global_video_active = 0;
3027 | global_send_first_frame = 0;
3028 | }
3029 |
3030 | dbg(9, "Call state for friend %d changed to %d, audio=%d, video=%d\n", friend_number, state, send_audio, send_video);
3031 | }
3032 |
3033 | static void t_toxav_bit_rate_status_cb(ToxAV *av, uint32_t friend_number,
3034 | uint32_t audio_bit_rate, uint32_t video_bit_rate,
3035 | void *user_data)
3036 | {
3037 | dbg(0, "t_toxav_bit_rate_status_cb:001 video_bit_rate=%d\n", (int)video_bit_rate);
3038 | dbg(0, "t_toxav_bit_rate_status_cb:001 audio_bit_rate=%d\n", (int)audio_bit_rate);
3039 |
3040 | TOXAV_ERR_BIT_RATE_SET error = 0;
3041 |
3042 |
3043 | uint32_t video_bit_rate_ = video_bit_rate;
3044 |
3045 | if (video_bit_rate < DEFAULT_GLOBAL_MIN_VID_BITRATE)
3046 | {
3047 | video_bit_rate_ = DEFAULT_GLOBAL_MIN_VID_BITRATE;
3048 | }
3049 |
3050 | toxav_bit_rate_set(av, friend_number, audio_bit_rate, video_bit_rate_, &error);
3051 |
3052 | if (error != 0)
3053 | {
3054 | dbg(0, "ToxAV:Setting new Video bitrate has failed with error #%u\n", error);
3055 | }
3056 | else
3057 | {
3058 | global_video_bit_rate = video_bit_rate_;
3059 | }
3060 |
3061 | dbg(2, "suggested bit rates: audio: %d video: %d\n", audio_bit_rate, video_bit_rate);
3062 | dbg(2, "actual bit rates: audio: %d video: %d\n", global_audio_bit_rate, global_video_bit_rate);
3063 | }
3064 |
3065 |
3066 | static void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
3067 | int16_t const *pcm,
3068 | size_t sample_count,
3069 | uint8_t channels,
3070 | uint32_t sampling_rate,
3071 | void *user_data)
3072 | {
3073 | if (global_video_active == 1)
3074 | {
3075 | if (friend_to_send_video_to == friend_number)
3076 | {
3077 | }
3078 | else
3079 | {
3080 | // wrong friend
3081 | }
3082 | }
3083 | else
3084 | {
3085 | }
3086 |
3087 | // CallControl *cc = (CallControl *)user_data;
3088 | // frame *f = (frame *)malloc(sizeof(uint16_t) + sample_count * sizeof(int16_t) * channels);
3089 | // memcpy(f->data, pcm, sample_count * sizeof(int16_t) * channels);
3090 | // f->size = sample_count;
3091 |
3092 | // pthread_mutex_lock(cc->arb_mutex);
3093 | // free(rb_write(cc->arb, f));
3094 | // pthread_mutex_unlock(cc->arb_mutex);
3095 | }
3096 |
3097 |
3098 | static void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
3099 | uint16_t width, uint16_t height,
3100 | uint8_t const *y, uint8_t const *u, uint8_t const *v,
3101 | int32_t ystride, int32_t ustride, int32_t vstride,
3102 | void *user_data)
3103 | {
3104 |
3105 | if (global_video_active == 1)
3106 | {
3107 | if (friend_to_send_video_to == friend_number)
3108 | {
3109 | }
3110 | else
3111 | {
3112 | // wrong friend
3113 | }
3114 | }
3115 | else
3116 | {
3117 | }
3118 |
3119 |
3120 | // ystride = abs(ystride);
3121 | // ustride = abs(ustride);
3122 | // vstride = abs(vstride);
3123 |
3124 | // uint16_t *img_data = (uint16_t *)malloc(height * width * 6);
3125 |
3126 | // unsigned long int i, j;
3127 |
3128 | // for (i = 0; i < height; ++i)
3129 | // {
3130 | // for (j = 0; j < width; ++j)
3131 | // {
3132 | // uint8_t *point = (uint8_t *) img_data + 3 * ((i * width) + j);
3133 | // int yx = y[(i * ystride) + j];
3134 | // int ux = u[((i / 2) * ustride) + (j / 2)];
3135 | // int vx = v[((i / 2) * vstride) + (j / 2)];
3136 |
3137 | // point[0] = YUV2R(yx, ux, vx);
3138 | // point[1] = YUV2G(yx, ux, vx);
3139 | // point[2] = YUV2B(yx, ux, vx);
3140 | // }
3141 | // }
3142 |
3143 |
3144 | // CvMat mat = cvMat(height, width, CV_8UC3, img_data);
3145 |
3146 | // CvSize sz;
3147 | // sz.height = height;
3148 | // sz.width = width;
3149 |
3150 | // IplImage *header = cvCreateImageHeader(sz, 1, 3);
3151 | // IplImage *img = cvGetImage(&mat, header);
3152 | // cvShowImage(vdout, img);
3153 | // free(img_data);
3154 | }
3155 |
3156 | void set_av_video_frame()
3157 | {
3158 | vpx_img_alloc(&input, VPX_IMG_FMT_I420, video_width, video_height, 1);
3159 | av_video_frame.y = input.planes[0]; /**< Y (Luminance) plane and VPX_PLANE_PACKED */
3160 | av_video_frame.u = input.planes[1]; /**< U (Chroma) plane */
3161 | av_video_frame.v = input.planes[2]; /**< V (Chroma) plane */
3162 | av_video_frame.w = input.d_w;
3163 | av_video_frame.h = input.d_h;
3164 | //av_video_frame.bit_depth = input.bit_depth;
3165 |
3166 | dbg(2,"ToxVideo:av_video_frame set\n");
3167 | }
3168 |
3169 | void *thread_av(void *data)
3170 | {
3171 | ToxAV *av = (ToxAV *) data;
3172 |
3173 | pthread_t id = pthread_self();
3174 | pthread_mutex_t av_thread_lock;
3175 |
3176 | if (pthread_mutex_init(&av_thread_lock, NULL) != 0)
3177 | {
3178 | dbg(0, "Error creating av_thread_lock\n");
3179 | }
3180 | else
3181 | {
3182 | dbg(2, "av_thread_lock created successfully\n");
3183 | }
3184 |
3185 | dbg(2, "AV Thread #%d: starting\n", (int) id);
3186 |
3187 | if (video_call_enabled == 1)
3188 | {
3189 | global_cam_device_fd = init_cam();
3190 | dbg(2, "AV Thread #%d: init cam\n", (int) id);
3191 | set_av_video_frame();
3192 | // start streaming
3193 | v4l_startread();
3194 | }
3195 |
3196 | while (toxav_iterate_thread_stop != 1)
3197 | {
3198 | yieldcpu(1000);
3199 | }
3200 |
3201 |
3202 | if (video_call_enabled == 1)
3203 | {
3204 | // end streaming
3205 | v4l_endread();
3206 | }
3207 |
3208 | dbg(2, "ToxVideo:Clean thread exit!\n");
3209 | }
3210 |
3211 |
3212 | void *thread_video_av(void *data)
3213 | {
3214 | ToxAV *av = (ToxAV *) data;
3215 |
3216 | pthread_t id = pthread_self();
3217 | pthread_mutex_t av_thread_lock;
3218 |
3219 | if (pthread_mutex_init(&av_thread_lock, NULL) != 0)
3220 | {
3221 | dbg(0, "Error creating video av_thread_lock\n");
3222 | }
3223 | else
3224 | {
3225 | dbg(2, "av_thread_lock video created successfully\n");
3226 | }
3227 |
3228 | dbg(2, "AV video Thread #%d: starting\n", (int) id);
3229 |
3230 | while (toxav_video_thread_stop != 1)
3231 | {
3232 | pthread_mutex_lock(&av_thread_lock);
3233 | toxav_iterate(av);
3234 | // dbg(9, "AV video Thread #%d running ...", (int) id);
3235 | pthread_mutex_unlock(&av_thread_lock);
3236 | usleep(toxav_iteration_interval(av) * 1000);
3237 | }
3238 |
3239 | dbg(2, "ToxVideo:Clean video thread exit!\n");
3240 | }
3241 |
3242 |
3243 | void av_local_disconnect(ToxAV *av, uint32_t num)
3244 | {
3245 | dbg(9, "av_local_disconnect\n");
3246 | TOXAV_ERR_CALL_CONTROL error = 0;
3247 | toxav_call_control(av, num, TOXAV_CALL_CONTROL_CANCEL, &error);
3248 | global_video_active = 0;
3249 | global_send_first_frame = 0;
3250 | friend_to_send_video_to = -1;
3251 | }
3252 |
3253 |
3254 | // ------------------ Tox AV stuff --------------------
3255 | // ------------------ Tox AV stuff --------------------
3256 | // ------------------ Tox AV stuff --------------------
3257 |
3258 |
3259 |
3260 | // ------------------ YUV420 overlay hack -------------
3261 | // ------------------ YUV420 overlay hack -------------
3262 | // ------------------ YUV420 overlay hack -------------
3263 |
3264 |
3265 |
3266 |
3267 | /**
3268 | * 8x8 monochrome bitmap fonts for rendering
3269 | * Author: Daniel Hepper
3270 | *
3271 | * License: Public Domain
3272 | *
3273 | * Based on:
3274 | * // Summary: font8x8.h
3275 | * // 8x8 monochrome bitmap fonts for rendering
3276 | * //
3277 | * // Author:
3278 | * // Marcel Sondaar
3279 | * // International Business Machines (public domain VGA fonts)
3280 | * //
3281 | * // License:
3282 | * // Public Domain
3283 | *
3284 | * Fetched from: http://dimensionalrift.homelinux.net/combuster/mos3/?p=viewsource&file=/modules/gfx/font8_8.asm
3285 | **/
3286 |
3287 | // Constant: font8x8_basic
3288 | // Contains an 8x8 font map for unicode points U+0000 - U+007F (basic latin)
3289 | char font8x8_basic[128][8] = {
3290 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0000 (nul)
3291 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0001
3292 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0002
3293 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0003
3294 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0004
3295 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0005
3296 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0006
3297 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0007
3298 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0008
3299 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0009
3300 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000A
3301 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000B
3302 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000C
3303 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000D
3304 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000E
3305 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+000F
3306 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0010
3307 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0011
3308 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0012
3309 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0013
3310 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0014
3311 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0015
3312 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0016
3313 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0017
3314 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0018
3315 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0019
3316 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001A
3317 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001B
3318 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001C
3319 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001D
3320 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001E
3321 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+001F
3322 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space)
3323 | { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // U+0021 (!)
3324 | { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0022 (")
3325 | { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // U+0023 (#)
3326 | { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // U+0024 ($)
3327 | { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // U+0025 (%)
3328 | { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // U+0026 (&)
3329 | { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0027 (')
3330 | { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // U+0028 (()
3331 | { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // U+0029 ())
3332 | { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // U+002A (*)
3333 | { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // U+002B (+)
3334 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+002C (,)
3335 | { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // U+002D (-)
3336 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+002E (.)
3337 | { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // U+002F (/)
3338 | { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // U+0030 (0)
3339 | { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // U+0031 (1)
3340 | { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // U+0032 (2)
3341 | { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // U+0033 (3)
3342 | { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // U+0034 (4)
3343 | { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // U+0035 (5)
3344 | { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // U+0036 (6)
3345 | { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // U+0037 (7)
3346 | { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // U+0038 (8)
3347 | { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // U+0039 (9)
3348 | { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // U+003A (:)
3349 | { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06}, // U+003B (//)
3350 | { 0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00}, // U+003C (<)
3351 | { 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00}, // U+003D (=)
3352 | { 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00}, // U+003E (>)
3353 | { 0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00}, // U+003F (?)
3354 | { 0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00}, // U+0040 (@)
3355 | { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // U+0041 (A)
3356 | { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // U+0042 (B)
3357 | { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // U+0043 (C)
3358 | { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // U+0044 (D)
3359 | { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // U+0045 (E)
3360 | { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // U+0046 (F)
3361 | { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // U+0047 (G)
3362 | { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // U+0048 (H)
3363 | { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0049 (I)
3364 | { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // U+004A (J)
3365 | { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // U+004B (K)
3366 | { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // U+004C (L)
3367 | { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // U+004D (M)
3368 | { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // U+004E (N)
3369 | { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // U+004F (O)
3370 | { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // U+0050 (P)
3371 | { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // U+0051 (Q)
3372 | { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // U+0052 (R)
3373 | { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // U+0053 (S)
3374 | { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0054 (T)
3375 | { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U+0055 (U)
3376 | { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0056 (V)
3377 | { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // U+0057 (W)
3378 | { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // U+0058 (X)
3379 | { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // U+0059 (Y)
3380 | { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // U+005A (Z)
3381 | { 0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00}, // U+005B ([)
3382 | { 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00}, // U+005C (\)
3383 | { 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00}, // U+005D (])
3384 | { 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00}, // U+005E (^)
3385 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // U+005F (_)
3386 | { 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0060 (`)
3387 | { 0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00}, // U+0061 (a)
3388 | { 0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00}, // U+0062 (b)
3389 | { 0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00}, // U+0063 (c)
3390 | { 0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00}, // U+0064 (d)
3391 | { 0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00}, // U+0065 (e)
3392 | { 0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00}, // U+0066 (f)
3393 | { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0067 (g)
3394 | { 0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00}, // U+0068 (h)
3395 | { 0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+0069 (i)
3396 | { 0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E}, // U+006A (j)
3397 | { 0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00}, // U+006B (k)
3398 | { 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // U+006C (l)
3399 | { 0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00}, // U+006D (m)
3400 | { 0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00}, // U+006E (n)
3401 | { 0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00}, // U+006F (o)
3402 | { 0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F}, // U+0070 (p)
3403 | { 0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78}, // U+0071 (q)
3404 | { 0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00}, // U+0072 (r)
3405 | { 0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00}, // U+0073 (s)
3406 | { 0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00}, // U+0074 (t)
3407 | { 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00}, // U+0075 (u)
3408 | { 0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // U+0076 (v)
3409 | { 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00}, // U+0077 (w)
3410 | { 0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00}, // U+0078 (x)
3411 | { 0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F}, // U+0079 (y)
3412 | { 0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00}, // U+007A (z)
3413 | { 0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00}, // U+007B ({)
3414 | { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00}, // U+007C (|)
3415 | { 0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00}, // U+007D (})
3416 | { 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
3417 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F
3418 | };
3419 |
3420 |
3421 |
3422 | // "0" -> [48]
3423 | // "9" -> [57]
3424 | // ":" -> [58]
3425 |
3426 |
3427 | void print_font_char(int start_x_pix, int start_y_pix, int font_char_num, uint8_t col_value)
3428 | {
3429 | int font_w = 8;
3430 | int font_h = 8;
3431 |
3432 | uint8_t *y_plane = av_video_frame.y;
3433 | // uint8_t col_value = 0; // black
3434 | char *bitmap = font8x8_basic[font_char_num];
3435 |
3436 | int k;
3437 | int j;
3438 | int offset = 0;
3439 | int set = 0;
3440 |
3441 | for (k=0;k 255 ? 255 : (X) < 0 ? 0 : X)
3517 |
3518 | // RGB -> YUV
3519 | #define RGB2Y(R, G, B) CLIP(( ( 66 * (R) + 129 * (G) + 25 * (B) + 128) >> 8) + 16)
3520 | #define RGB2U(R, G, B) CLIP(( ( -38 * (R) - 74 * (G) + 112 * (B) + 128) >> 8) + 128)
3521 | #define RGB2V(R, G, B) CLIP(( ( 112 * (R) - 94 * (G) - 18 * (B) + 128) >> 8) + 128)
3522 |
3523 | // YUV -> RGB
3524 | #define C(Y) ( (Y) - 16 )
3525 | #define D(U) ( (U) - 128 )
3526 | #define E(V) ( (V) - 128 )
3527 |
3528 | #define YUV2R(Y, U, V) CLIP(( 298 * C(Y) + 409 * E(V) + 128) >> 8)
3529 | #define YUV2G(Y, U, V) CLIP(( 298 * C(Y) - 100 * D(U) - 208 * E(V) + 128) >> 8)
3530 | #define YUV2B(Y, U, V) CLIP(( 298 * C(Y) + 516 * D(U) + 128) >> 8)
3531 |
3532 | void rbg_to_yuv(uint8_t r, uint8_t g, uint8_t b, uint8_t *y, uint8_t *u, uint8_t *v)
3533 | {
3534 | *y = RGB2Y(r, g, b);
3535 | *u = RGB2U(r, g, b);
3536 | *v = RGB2V(r, g, b);
3537 | }
3538 |
3539 | void text_on_yuf_frame_xy(int start_x_pix, int start_y_pix, const char* text)
3540 | {
3541 | int carriage = 0;
3542 | const int letter_width = 8;
3543 | const int letter_spacing = 1;
3544 |
3545 | int block_needed_width = 2 + 2 + (strlen(text) * (letter_width + letter_spacing));
3546 | left_top_bar_into_yuv_frame(start_x_pix, start_y_pix, block_needed_width, 12, 255, 255, 255);
3547 |
3548 | int looper;
3549 |
3550 | for(looper=0;(int)looper < (int)strlen(text);looper++)
3551 | {
3552 | uint8_t c = text[looper];
3553 | if ((c > 0) && (c < 127))
3554 | {
3555 | print_font_char((12 + ((letter_width + letter_spacing) * carriage)), 12, c, 0);
3556 | }
3557 | else
3558 | {
3559 | // leave a blank
3560 | }
3561 | carriage++;
3562 | }
3563 | }
3564 |
3565 | void left_top_bar_into_yuv_frame(int bar_start_x_pix, int bar_start_y_pix, int bar_w_pix, int bar_h_pix, uint8_t r, uint8_t g, uint8_t b)
3566 | {
3567 | // int bar_width = bar_w_pix; // 150; // should be mulitple of 2 !!
3568 | // int bar_height = bar_h_pix; // 20; // should be mulitple of 2 !!
3569 | // int bar_start_x = bar_start_x_pix; // 10; // should be mulitple of 2 !! (zero is also ok)
3570 | // int bar_start_y = bar_start_y_pix; // 10; // should be mulitple of 2 !! (zero is also ok)
3571 |
3572 | // uint8_t *y_plane = av_video_frame.y;
3573 |
3574 | int k;
3575 | int j;
3576 | // int offset = 0;
3577 |
3578 | for (k=0;k mono, 2 -> stereo
3679 | if ((err = snd_pcm_hw_params_set_channels (audio_capture_handle, hw_params, 1)) < 0) {
3680 | dbg(9, "cannot set channel count (%s)\n",
3681 | snd_strerror (err));
3682 | //exit (1);
3683 | }
3684 |
3685 | if ((err = snd_pcm_hw_params (audio_capture_handle, hw_params)) < 0) {
3686 | dbg(9, "cannot set parameters (%s)\n",
3687 | snd_strerror (err));
3688 | //exit (1);
3689 | }
3690 |
3691 | snd_pcm_hw_params_free (hw_params);
3692 |
3693 | if ((err = snd_pcm_prepare (audio_capture_handle)) < 0) {
3694 | dbg(9, "cannot prepare audio interface for use (%s)\n",
3695 | snd_strerror (err));
3696 | //exit (1);
3697 | }
3698 | }
3699 |
3700 | #endif
3701 |
3702 | // ------------------ alsa recording ------------------
3703 | // ------------------ alsa recording ------------------
3704 | // ------------------ alsa recording ------------------
3705 |
3706 |
3707 | void sigint_handler(int signo)
3708 | {
3709 | if (signo == SIGINT)
3710 | {
3711 | printf("received SIGINT, pid=%d\n", getpid());
3712 | tox_loop_running = 0;
3713 | }
3714 | }
3715 |
3716 | int main(int argc, char *argv[])
3717 | {
3718 | global_want_restart = 0;
3719 | global_video_active = 0;
3720 | global_send_first_frame = 0;
3721 |
3722 | // valid audio bitrates: [ bit_rate < 6 || bit_rate > 510 ]
3723 | global_audio_bit_rate = DEFAULT_GLOBAL_AUD_BITRATE;
3724 | global_video_bit_rate = DEFAULT_GLOBAL_VID_BITRATE;
3725 |
3726 | video_high = 0;
3727 |
3728 | logfile = fopen(log_filename, "wb");
3729 | setvbuf(logfile, NULL, _IONBF, 0);
3730 |
3731 | v4l2_device = malloc(400);
3732 | memset(v4l2_device, 0, 400);
3733 | snprintf(v4l2_device, 399, "%s", "/dev/video0");
3734 |
3735 | int aflag = 0;
3736 | char *cvalue = NULL;
3737 | int index;
3738 | int opt;
3739 |
3740 | const char *short_opt = "hvd:t23b:f";
3741 | struct option long_opt[] =
3742 | {
3743 | {"help", no_argument, NULL, 'h'},
3744 | {"version", no_argument, NULL, 'v'},
3745 | {"videodevice", required_argument, NULL, 'd'},
3746 | {NULL, 0, NULL, 0 }
3747 | };
3748 |
3749 | while((opt = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1)
3750 | {
3751 | switch (opt)
3752 | {
3753 | case -1: /* no more arguments */
3754 | case 0: /* long options toggles */
3755 | break;
3756 | case 'a':
3757 | aflag = 1;
3758 | break;
3759 | case '2':
3760 | switch_nodelist_2 = 1;
3761 | break;
3762 | case '3':
3763 | switch_nodelist_2 = 2;
3764 | break;
3765 | case 't':
3766 | switch_tcponly = 1;
3767 | break;
3768 | case 'f':
3769 | video_high = 1;
3770 | break;
3771 | case 'd':
3772 | snprintf(v4l2_device, 399, "%s", optarg);
3773 | // printf("Using Videodevice: %s\n", v4l2_device);
3774 | dbg(3, "Using Videodevice: %s\n", v4l2_device);
3775 | break;
3776 | case 'b':
3777 | DEFAULT_GLOBAL_VID_BITRATE = (uint32_t)atoi(optarg);
3778 | dbg(3, "Using Videobitrate: %d\n", (int)DEFAULT_GLOBAL_VID_BITRATE);
3779 | global_video_bit_rate = DEFAULT_GLOBAL_VID_BITRATE;
3780 | break;
3781 | case 'v':
3782 | printf("Tox TCP-Relay version: %s\n", global_version_string);
3783 | if (logfile)
3784 | {
3785 | fclose(logfile);
3786 | logfile = NULL;
3787 | }
3788 | return(0);
3789 | break;
3790 |
3791 | case 'h':
3792 | printf("Usage: %s [OPTIONS]\n", argv[0]);
3793 | printf(" -d, --videodevice devicefile file\n");
3794 | printf(" -b bitrate video bitrate in kbit/s\n");
3795 | printf(" -f use 720p video mode\n");
3796 | printf(" -t, tcp only mode\n");
3797 | printf(" -2, use alternate bootnode list\n");
3798 | printf(" -3, use only nodes.tox.chat as bootnode\n");
3799 | printf(" -v, --version show version\n");
3800 | printf(" -h, --help print this help and exit\n");
3801 | printf("\n");
3802 | if (logfile)
3803 | {
3804 | fclose(logfile);
3805 | logfile = NULL;
3806 | }
3807 | return(0);
3808 |
3809 | case ':':
3810 | case '?':
3811 | fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
3812 | if (logfile)
3813 | {
3814 | fclose(logfile);
3815 | logfile = NULL;
3816 | }
3817 | return(-2);
3818 |
3819 | default:
3820 | fprintf(stderr, "%s: invalid option -- %c\n", argv[0], opt);
3821 | fprintf(stderr, "Try `%s --help' for more information.\n", argv[0]);
3822 | if (logfile)
3823 | {
3824 | fclose(logfile);
3825 | logfile = NULL;
3826 | }
3827 | return(-2);
3828 | }
3829 | }
3830 |
3831 |
3832 | Tox *tox = create_tox();
3833 | global_start_time = time(NULL);
3834 |
3835 | const char *name = "ToxTCP-Relay";
3836 | tox_self_set_name(tox, (uint8_t *)name, strlen(name), NULL);
3837 |
3838 | const char *status_message = "Tox TCP Relay Node";
3839 | tox_self_set_status_message(tox, (uint8_t *)status_message, strlen(status_message), NULL);
3840 |
3841 | Friends.max_idx = 0;
3842 |
3843 |
3844 | bootstrap(tox);
3845 |
3846 |
3847 | print_tox_id(tox);
3848 |
3849 | // init callbacks ----------------------------------
3850 | // tox_callback_friend_request(tox, friend_request_cb);
3851 | // tox_callback_friend_message(tox, friend_message_cb);
3852 | // tox_callback_friend_connection_status(tox, friendlist_onConnectionChange);
3853 | // tox_callback_friend_status(tox, on_tox_friend_status);
3854 |
3855 | // tox_callback_self_connection_status(tox, self_connection_status_cb);
3856 |
3857 | // tox_callback_file_chunk_request(tox, on_file_chunk_request);
3858 | // tox_callback_file_recv_control(tox, on_file_control);
3859 | // tox_callback_file_recv(tox, on_file_recv);
3860 | // tox_callback_file_recv_chunk(tox, on_file_recv_chunk);
3861 | // init callbacks ----------------------------------
3862 |
3863 |
3864 | update_savedata_file(tox);
3865 | load_friendlist(tox);
3866 |
3867 | char path[300];
3868 | snprintf(path, sizeof(path), "%s", my_avatar_filename);
3869 | int len = strlen(path) - 1;
3870 | avatar_set(tox, path, len);
3871 |
3872 | long long unsigned int cur_time = time(NULL);
3873 | uint8_t off = 1;
3874 | long long loop_counter = 0;
3875 | while (1)
3876 | {
3877 | tox_iterate(tox, NULL);
3878 | usleep(tox_iteration_interval(tox) * 1000);
3879 | if (tox_self_get_connection_status(tox) && off)
3880 | {
3881 | dbg(2, "Tox online, took %llu seconds\n", time(NULL) - cur_time);
3882 | off = 0;
3883 | break;
3884 | }
3885 | c_sleep(20);
3886 | loop_counter++;
3887 |
3888 | if (loop_counter > (50 * 20))
3889 | {
3890 | loop_counter = 0;
3891 | // if not yet online, bootstrap every 20 seconds
3892 | dbg(2, "Tox NOT online yet, bootstrapping again\n");
3893 | bootstrap(tox);
3894 | }
3895 | }
3896 |
3897 |
3898 | TOXAV_ERR_NEW rc;
3899 | dbg(2, "new Tox AV\n");
3900 | mytox_av = toxav_new(tox, &rc);
3901 | if (rc != TOXAV_ERR_NEW_OK)
3902 | {
3903 | dbg(0, "Error at toxav_new: %d\n", rc);
3904 | }
3905 |
3906 | CallControl mytox_CC;
3907 | memset(&mytox_CC, 0, sizeof(CallControl));
3908 |
3909 | // init AV callbacks -------------------------------
3910 | // toxav_callback_call(mytox_av, t_toxav_call_cb, &mytox_CC);
3911 | // toxav_callback_call_state(mytox_av, t_toxav_call_state_cb, &mytox_CC);
3912 | // toxav_callback_bit_rate_status(mytox_av, t_toxav_bit_rate_status_cb, &mytox_CC);
3913 | // toxav_callback_video_receive_frame(mytox_av, t_toxav_receive_video_frame_cb, &mytox_CC);
3914 | // toxav_callback_audio_receive_frame(mytox_av, t_toxav_receive_audio_frame_cb, &mytox_CC);
3915 | // init AV callbacks -------------------------------
3916 |
3917 |
3918 | // start toxav thread ------------------------------
3919 | pthread_t tid[2]; // 0 -> toxav_iterate thread, 1 -> video send thread
3920 |
3921 |
3922 | // start toxav thread ------------------------------
3923 | toxav_iterate_thread_stop = 0;
3924 | if (pthread_create(&(tid[0]), NULL, thread_av, (void *)mytox_av) != 0)
3925 | {
3926 | dbg(0, "AV iterate Thread create failed");
3927 | }
3928 | else
3929 | {
3930 | dbg(2, "AV iterate Thread successfully created");
3931 | }
3932 |
3933 | toxav_video_thread_stop = 0;
3934 | if (pthread_create(&(tid[1]), NULL, thread_video_av, (void *)mytox_av) != 0)
3935 | {
3936 | dbg(0, "AV video Thread create failed");
3937 | }
3938 | else
3939 | {
3940 | dbg(2, "AV video Thread successfully created");
3941 | }
3942 | // start toxav thread ------------------------------
3943 |
3944 |
3945 |
3946 | // start audio recoding stuff ----------------------
3947 | #ifdef HAVE_SOUND
3948 | init_sound_device();
3949 | record_from_sound_device();
3950 | close_sound_device();
3951 | #endif
3952 | // start audio recoding stuff ----------------------
3953 |
3954 |
3955 |
3956 | tox_loop_running = 1;
3957 | signal(SIGINT, sigint_handler);
3958 |
3959 | while (tox_loop_running)
3960 | {
3961 | tox_iterate(tox, NULL);
3962 | usleep(tox_iteration_interval(tox) * 1000);
3963 |
3964 | if (global_want_restart == 1)
3965 | {
3966 | // need to restart me!
3967 | break;
3968 | }
3969 | else
3970 | {
3971 | check_dir(tox);
3972 | check_friends_dir(tox);
3973 | }
3974 | }
3975 |
3976 |
3977 | kill_all_file_transfers(tox);
3978 | close_cam();
3979 | toxav_kill(mytox_av);
3980 | tox_kill(tox);
3981 |
3982 | if (logfile)
3983 | {
3984 | fclose(logfile);
3985 | logfile = NULL;
3986 | }
3987 |
3988 | return 0;
3989 | }
3990 |
3991 |
--------------------------------------------------------------------------------
/tox_tcp_relay/update_from_ci.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | #####################################################
4 | # update binary from Circle CI (master branch)
5 | #####################################################
6 |
7 | cd $(dirname "$0")
8 |
9 | pkill tox-bootstrapd_static # will stop bootstrapd
10 | cp -av tox-bootstrapd_static tox-bootstrapd_static__BACKUP
11 | wget -O tox-bootstrapd_static 'https://circleci.com/api/v1/project/zoff99/ToxTCP-RelayNode/latest/artifacts/0/$CIRCLE_ARTIFACTS/ubuntu_14_04_binaries/tox-bootstrapd_static?filter=successful&branch=master'
12 | chmod u+rwx tox-bootstrapd_static
13 |
14 |
--------------------------------------------------------------------------------
/toxstatus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zoff99/ToxTCP-RelayNode/7fc1ef4ef96d5d2b96cd021e97be4f820b70300c/toxstatus.png
--------------------------------------------------------------------------------