Compare commits

...

383 Commits

Author SHA1 Message Date
Jan Vidar Krey
8e816fd196 Update example configuration. 2010-04-05 16:53:17 +02:00
Jan Vidar Krey
88a22659a1 Update deb/rpm files. 2010-04-05 16:46:20 +02:00
Jan Vidar Krey
3393ee6a85 Updated changelog. 2010-04-05 16:43:43 +02:00
Jan Vidar Krey
58630fde08 Fixed getip to return the ip address of the target user, not self. 2010-04-05 16:35:55 +02:00
Jan Vidar Krey
8815118fde Added flood control support.
This closes bug #79: Flood control, and rate limits
2010-04-05 16:01:07 +02:00
Jan Vidar Krey
5454ae279a Fix bug #120: !getip does not work 2010-04-05 14:21:40 +02:00
Jan Vidar Krey
8e579f4601 Fix #123: accept() fails if IP is banned. 2010-04-05 13:44:17 +02:00
Jan Vidar Krey
e220357176 Added configuration option to enable support for obsolete pre-ADC/1.0 clients. 2010-04-05 13:43:28 +02:00
Jan Vidar Krey
8bed952022 Fixed nasty hub freeze caused by timers being injected for the same timestamp as it is being removed from. 2010-03-23 01:06:04 +01:00
Jan Vidar Krey
c4604a7e94 Make code clearer. 2010-03-23 00:46:25 +01:00
Jan Vidar Krey
236daeae53 Assert if inserting an invalid timer. 2010-03-15 22:59:16 +01:00
Jan Vidar Krey
862c6a1baf Reduce timeout queue window size. 2010-03-13 00:16:15 +01:00
Jan Vidar Krey
198d86a1ee Added some automatic tests for the timeout handling. 2010-02-25 17:57:50 +01:00
Jan Vidar Krey
2ded9f3e09 Make the revision file if it does not exist. 2010-02-25 16:38:05 +01:00
Jan Vidar Krey
59ed268f4d Added test cases for sid allocation.
This revealed a few bugs:
* when sid allocator is full, then uhub will loop indefinitely when allocating one more (unlikely to occur).
* looking up a user object based on a sid that is out of range (off by one) returns invalid memory.
2010-02-18 16:02:13 +01:00
Jan Vidar Krey
963416ad73 Cleanup reference adc message reference counting somewhat. 2010-02-16 20:51:10 +01:00
Jan Vidar Krey
29c162727c Added lots of new asserts which should trigger in case we double delete a ADC message. 2010-02-15 19:03:19 +01:00
Jan Vidar Krey
1ce258bccf Tidy up the certificate loading code somewhat. 2010-02-15 19:02:31 +01:00
Jan Vidar Krey
0de66286fa Partially fix bug #117 - tls_require ignored entirely in 0.3.0 released
If tls_require is enabled then the hub will simply close the connection if a
user connects without TLS.
In the future we should redirect the user either to another server or to the adcs server.
2010-02-15 19:00:48 +01:00
Jan Vidar Krey
1a98bb6810 Added optional include of local makefile. 2010-02-15 18:56:23 +01:00
Jan Vidar Krey
5e6879dffb Fix for partial read operations. 2010-02-12 20:33:17 +01:00
Jan Vidar Krey
1b56adb8c0 Fix wrong IQUI message. Partially fixes bug #4. 2010-02-12 19:25:09 +01:00
Jan Vidar Krey
685597c795 Make sure we delete the revision.h files when updating.
Also, only use annotated tags for git revision numbers.
2010-02-11 09:16:30 +01:00
Jan Vidar Krey
782f091637 Bump to 0.3.1-rc1 2010-02-11 09:03:07 +01:00
Jan Vidar Krey
82eeaa1fba Fix bug #114: FreeBSD compile error. 2010-02-11 07:54:42 +01:00
Jan Vidar Krey
977b57a385 Prefer the git-describe version number if it exists. 2010-02-11 01:21:08 +01:00
Jan Vidar Krey
19b9f72337 Make sure !version agrees with the connect time banner (same format). 2010-02-11 01:19:58 +01:00
Jan Vidar Krey
56605f7dcb Fix autotest crash. 2010-02-11 01:18:45 +01:00
Jan Vidar Krey
bf1b64db53 Write git revision to a header file, then make version.h depend on that file. 2010-02-11 01:03:09 +01:00
Jan Vidar Krey
915cb56448 Fix bug #106: Show OS/CPU info in !version.
This can be controlled by the configuration variable "show_banner_sys_info" which is enabled by default.
2010-02-10 23:45:51 +01:00
Jan Vidar Krey
6992043f9d Fix bug #113: crash when using epoll backend. 2010-02-10 22:06:49 +01:00
Jan Vidar Krey
896bbfcb5d Compile multiple network backends into the binary and choose which one to use at runtime.
This makes it possible to share more code between the backends and also work around
bugs of certain backends on some (versions of) operating systems.
2010-02-10 22:00:13 +01:00
Jan Vidar Krey
6ac78e1a10 Fix autotest 2010-02-08 00:35:58 +01:00
Jan Vidar Krey
74a2191350 Fix bug #111: Added nmdc-redirector similar to the adc-redirector. 2010-02-07 23:37:21 +01:00
Jan Vidar Krey
be8db21561 Fix bug #109: Confusing debug message for nat_ip. 2010-02-07 23:29:38 +01:00
Jan Vidar Krey
8065903604 Fix bug #108: share limits can be avoided.
This was due to updates to the share limit not being enforced after a succesful login.
2010-02-07 23:08:04 +01:00
Jan Vidar Krey
78ae9fb3ce Fix documentation about file descriptor limits. 2010-02-05 22:40:35 +01:00
root
4715815ba2 Update getstartd.txt for hub with more that 1024 users. 2010-02-05 09:40:57 +03:00
root
cb9625f6a5 update example uhub.conf 2010-02-02 13:43:10 +03:00
root
9934bde050 add in README list of compatible ADC clients 2010-02-01 15:36:46 +03:00
root
9a1c5ee548 - update .spec file; - cosmetic in init.d scripts 2010-02-01 12:22:12 +03:00
Jan Vidar Krey
11df912162 libevent is NOT needed at all (nor is it supported) 2010-01-31 23:40:11 +01:00
root
c8bc2f64fd update .ebuild ; update compile doc ; update RHEL init.d 2010-01-29 22:05:39 +03:00
Jan Vidar Krey
2dc95eca47 SunOS support. 2010-01-28 01:35:09 +01:00
Jan Vidar Krey
7637d9ba68 Added experimental Haiku OS support.
It compiles and it runs with some minor glitches.
2010-01-28 01:35:08 +01:00
Jan Vidar Krey
4e9488dd4d gcc 2.95 compile fixes. 2010-01-28 01:11:11 +01:00
Jan Vidar Krey
e0003ebbb2 Only define MIN/MAX macros if not defined by the system. 2010-01-28 01:07:05 +01:00
Jan Vidar Krey
8e7e8c68f5 gcc v2.95 compile fixes. 2010-01-28 01:06:41 +01:00
root
db32eaeafc update doc/uhub.conf for multiple ports 2010-01-28 10:53:03 +03:00
Jan Vidar Krey
1599f63134 Make sure the autotests work. 2010-01-28 00:07:42 +01:00
Jan Vidar Krey
c3ad006d07 Fix bug #76: added support for multiple server listen ports.
Use server_alt_ports and supply a comma separated list of ports.
2010-01-27 23:55:52 +01:00
Jan Vidar Krey
1faca92167 Added a generic string splitter utility function that is based on callbacks instead of populating a list. 2010-01-27 23:55:05 +01:00
Jan Vidar Krey
f0a13b4c23 Updated .ebuild and .spec files. 2010-01-27 19:01:50 +01:00
Jan Vidar Krey
ccd1c8f160 kqueue() BSD fixes 2010-01-27 17:50:02 +01:00
Jan Vidar Krey
41418f21e7 Winsock compile fix. 2010-01-27 17:48:16 +01:00
Jan Vidar Krey
7a8a737cad More kqueue work in progress. 2010-01-27 01:04:32 +01:00
Jan Vidar Krey
ac48ad01fb Work in progress on the kqueue backend. 2010-01-27 00:43:10 +01:00
Jan Vidar Krey
31a69b1f3f Thanks to E_zombie for all the Centos/RedHat contributions 2010-01-26 23:55:27 +01:00
Jan Vidar Krey
d7a1a52c1a Started working kqueue() backend for OSX and BSD. 2010-01-26 23:30:32 +01:00
Jan Vidar Krey
f54e8dbbba Moved the timeout code to where it belongs, along with the network backend code. 2010-01-26 22:55:08 +01:00
Jan Vidar Krey
de72d4ae63 Merge branch 'master' of baracus-vpn:~/git/uhub 2010-01-26 17:46:51 +01:00
Jan Vidar Krey
01efc6cc20 Fixes for debian init.d scripts. 2010-01-26 17:46:47 +01:00
Jan Vidar Krey
7cf1181e6b Merge branch 'master' of github.com:janvidar/uhub 2010-01-26 17:28:45 +01:00
Jan Vidar Krey
4b64b28777 Added proper debian package scripts. 2010-01-26 17:27:34 +01:00
root
e9f0331ca8 Merge branch 'master' of git://github.com/janvidar/uhub 2010-01-26 19:17:16 +03:00
root
f263534aaf add .ebuild 2010-01-26 19:16:28 +03:00
Jan Vidar Krey
788b644c80 Merge branch 'master' of github.com:janvidar/uhub 2010-01-26 16:16:48 +01:00
Jan Vidar Krey
2d7ffa37fe Fix problem parsing configuration file if the last line is not empty 2010-01-26 16:16:41 +01:00
root
fbaac98483 .spec Require fix 2010-01-26 17:39:57 +03:00
root
bd9d8229ff add .SPEC file for build RPM in RHEL based distrs 2010-01-26 17:32:42 +03:00
Jan Vidar Krey
dfa6d07455 Merge branch 'master' of github.com:janvidar/uhub 2010-01-26 12:04:55 +01:00
root
6bbdd24cb7 Merge branch 'master' of git://github.com/janvidar/uhub 2010-01-26 13:05:56 +03:00
root
e3a644a853 Stupid mistake in path 2010-01-26 13:00:11 +03:00
Jan Vidar Krey
928225fb7b On Mac OS X getrlimit() returns 2^(sizeof(size_t) * 8) instead of the actual number of available socket descriptors. 2010-01-26 08:40:10 +01:00
Jan Vidar Krey
e3cf41cb97 BSD/OSX compile fix. 2010-01-25 14:23:22 +01:00
Jan Vidar Krey
59f67f9e17 Updated ChangeLog and README. 2010-01-24 23:38:25 +01:00
Jan Vidar Krey
bfc7c184a7 Fix release build compile warnings. 2010-01-23 14:59:51 +01:00
Jan Vidar Krey
92c448b855 Dont use SSL by default. 2010-01-23 01:09:00 +01:00
Jan Vidar Krey
304ecda16a Enable the statistics timer again, so that !stats provide up to date network statistics. 2010-01-23 00:43:38 +01:00
Jan Vidar Krey
c670d13369 Make sure we shutdown SSL connections when an error occurs. 2010-01-23 00:20:48 +01:00
Jan Vidar Krey
b2e7a2848f Optimize epoll to never modify the epoll mask unless it actually changed. 2010-01-23 00:03:45 +01:00
Jan Vidar Krey
84bd2591d6 SSL fixes, seems to work with stunnel4 as a client but not linuxdcpp using SSL directly. 2010-01-22 23:43:23 +01:00
Jan Vidar Krey
4aa65733d0 Poll as long as possible until next timeout the earliest. 2010-01-22 23:18:59 +01:00
Jan Vidar Krey
230ca28b46 Some unfinished SSL work. 2010-01-22 18:52:38 +01:00
Jan Vidar Krey
5f353ebe28 Added script to create SSL certificate. 2010-01-22 18:22:39 +01:00
Jan Vidar Krey
68a26e1160 Added proper POSIX signal handler. 2010-01-22 16:57:30 +01:00
Jan Vidar Krey
4711d26c11 Fix broken net_address_to_string(). 2010-01-22 16:09:19 +01:00
Jan Vidar Krey
1bb3bd90c1 Use non-default port to ensure autotests work even though a hub is running on the default port. 2010-01-22 16:05:48 +01:00
Jan Vidar Krey
5e253e8442 Fix compile error. 2010-01-22 16:04:36 +01:00
Jan Vidar Krey
26a2a384b6 Bump to version 0.3.0 2010-01-22 16:01:54 +01:00
Jan Vidar Krey
8b7f09c7f4 Fixed two cases of bad connection close. 2010-01-21 23:54:38 +01:00
Jan Vidar Krey
b29da11f3b Make sure we call the timeout code. 2010-01-21 23:52:04 +01:00
Jan Vidar Krey
78ad9b8572 Fixed bad logic inside the timer scheduling. 2010-01-21 23:13:52 +01:00
Jan Vidar Krey
b04a20c66e fixed off by one bug in due to message escape. 2010-01-21 22:20:26 +01:00
Jan Vidar Krey
21a5981905 Make sure start_listening_socket does everything, this will lead the way to multiple listen ports. 2010-01-21 17:31:55 +01:00
Jan Vidar Krey
c47ea14047 Code cleanup for starting the listening socket. 2010-01-21 01:54:41 +01:00
Jan Vidar Krey
9f5aaf0148 Added a safe connection cleanup procedure for when a connection goes
down while it may be attempted to be used.
2010-01-21 01:12:57 +01:00
Jan Vidar Krey
f645811f37 Merge branch 'master' of github.com:janvidar/uhub 2010-01-20 18:42:45 +01:00
Jan Vidar Krey
2f09fcea84 Added select() backend which can be used as a fallback if epoll is not available. 2010-01-20 18:39:55 +01:00
root
5e679e2d4f - add doc/init.d.RedHat/etc/logrotator.d/uhub file 2010-01-20 11:18:16 +03:00
root
efeb36c492 - update uhub.conf example after add !rules
- add example rules.txt
- fix compile warning in  src/util/timeout.c
- add example config file for rotate log file in RHEL\CentOS
2010-01-20 11:12:43 +03:00
Jan Vidar Krey
7e60919596 sorted the commands shown in help. 2010-01-20 00:24:57 +01:00
Jan Vidar Krey
e7cb4cd277 remove extra space before !broadcast messages 2010-01-20 00:12:39 +01:00
Jan Vidar Krey
e45511827f Added the +rules command.
Also added the +motd command to see the message of the day, which is sent while connecting.
2010-01-19 23:30:26 +01:00
Jan Vidar Krey
80c6ad9d76 Added mute/unmute functionality. 2010-01-19 23:07:55 +01:00
Jan Vidar Krey
f84f3b1fff Merge branch 'master' of github.com:janvidar/uhub into sans_libevent 2010-01-19 19:35:20 +01:00
Jan Vidar Krey
f84073f7cc Various fixes for epoll handling without libevent.
This should take care of most compile issues as well as busy loops caused by unhandled recv() calls returning 0 and general cleanups.
2010-01-19 17:52:58 +01:00
Jan Vidar Krey
af8421fa47 Crash fix. 2010-01-18 21:57:51 +01:00
Jan Vidar Krey
001fa6739a Crash fix. 2010-01-18 19:38:07 +01:00
Jan Vidar Krey
7dfa3162cb Epoll fixes. 2010-01-18 19:34:18 +01:00
Jan Vidar Krey
314707f499 Epoll fixes. 2010-01-18 16:15:38 +01:00
Jan Vidar Krey
1c58a85de1 More work on epoll. 2010-01-17 23:00:28 +01:00
lv77
eb5d3936a9 Add TODO file. Some modify example uhub.conf 2010-01-14 09:49:03 +03:00
lv77
23daa42b72 Add TODO file. Some modify example uhub.conf 2010-01-14 09:46:55 +03:00
root
a643bb123d Add init.d files for RedHat\CentOS 2010-01-13 16:27:07 +03:00
Jan Vidar Krey
6a4b9c58f4 Work on removing libevent completely as a mandatory dependency. 2010-01-07 20:55:13 +01:00
Jan Vidar Krey
f35b2c35cb Fix some compile errors. 2009-12-14 16:17:59 +01:00
Jan Vidar Krey
b3aa5332c8 Work on epoll backend, and removing dependency on libevent. 2009-12-10 23:12:04 +01:00
Jan Vidar Krey
1f9cfe58c4 No need to allow users not yet logged in to send special hub commands to the hub.
Nothing bad will happen, except the hub will try to answer them even though the user is not yet fully logged in. This fix ensures that these messages are simply dropped instead.
2009-12-09 19:40:12 +01:00
Jan Vidar Krey
50f5ce9d32 Fix bug #100 - Null pointer crash if sending a chat message without the message part. 2009-12-09 19:30:08 +01:00
Jan Vidar Krey
4a4de0f2ac Make sure we have libevent enabled for now, and add macro protection around the areas of the code that still depend on libevent. 2009-12-09 17:27:46 +01:00
Jan Vidar Krey
2e2f93d0a4 Started working on new timeout handling which can be used when we remove libevent.
This will probably be used by default on UNIX platforms at some point.

The timeout handling accomplishes O(1) inserts, removes and reschedules
but the accuracy is limited to whole seconds.
2009-12-09 17:12:33 +01:00
Jan Vidar Krey
7c093dc5da Fix for very long messages that get dropped if they are sent alone (no other message before it) and does not fit inside one TCP packet.
(Thanks FleetCommand!)
2009-12-04 08:12:54 +01:00
Jan Vidar Krey
8bcdbdc061 Removed assert. 2009-11-21 11:52:25 +01:00
Jan Vidar Krey
53536f191d Crash fix. 2009-11-21 11:47:26 +01:00
Jan Vidar Krey
e994f23ea0 Crash fix part 2 2009-11-18 18:35:31 +01:00
Jan Vidar Krey
f489e77602 Crash fix? 2009-11-18 18:27:31 +01:00
Jan Vidar Krey
2526c8a9ed Silly compile error. 2009-11-18 17:43:11 +01:00
Jan Vidar Krey
4556623a87 Clarify flags as unsigned. 2009-11-18 17:41:22 +01:00
Jan Vidar Krey
828c19cfc6 Fix a wrong open() if no motd is specified. 2009-11-18 17:41:55 +01:00
Jan Vidar Krey
00995a1946 Fix potential memory leaks and crashes. 2009-11-18 17:41:28 +01:00
Jan Vidar Krey
f4e82ef503 Cleanup the net_event handler. 2009-11-18 17:40:28 +01:00
Jan Vidar Krey
eb7bec585e Fix problems with write events not being processed due to a read event taking presendence.
Conflicts:

	src/core/netevent.c
2009-11-18 17:40:23 +01:00
Jan Vidar Krey
066b3f5243 Fix protocol probe. Will detect ADC and TLS handshake - any other request
will simply cause the hub to close the connection.

Conflicts:

	src/core/netevent.c
	src/core/probe.c
2009-11-18 17:38:25 +01:00
Jan Vidar Krey
a51e8830ce Log dropped messages. 2009-10-30 18:31:27 +01:00
Jan Vidar Krey
e6cc47070c A few minor TLS fixes 2009-10-09 21:38:14 +02:00
Jan Vidar Krey
0c5d98c671 TLS compile and crash fixes. 2009-10-09 21:11:11 +02:00
Jan Vidar Krey
0f30ebf045 Some stability fixes. Removed log messages. 2009-10-09 20:35:04 +02:00
Jan Vidar Krey
4919c8f2f9 Fix compile error. 2009-10-09 00:11:09 +02:00
Jan Vidar Krey
2910c571b0 Fix protocol probe. Will detect ADC and TLS handshake - any other request
will simply cause the hub to close the connection.
Fix problems with write events not being processed due to a read event taking presendence.
Fix bug #86: Windows does not have "getrlimit()".
2009-10-08 23:16:15 +02:00
Jan Vidar Krey
11e5683a79 Cleanup code somewhat. 2009-10-06 18:33:06 +02:00
Jan Vidar Krey
17416def35 Make sure we flag JOIN/LEAVE messages as really verbose debug output. 2009-10-06 18:28:16 +02:00
Jan Vidar Krey
234f04f495 Removed extra main block. 2009-10-06 18:25:50 +02:00
Jan Vidar Krey
4898454c91 Removed redundant and ununsed operation mode for adcrush. 2009-10-06 18:24:21 +02:00
Jan Vidar Krey
255255ff20 Allow for command line specified host. 2009-10-06 18:16:38 +02:00
Jan Vidar Krey
f50b40fb92 Fix bug #85 - Do not broadcast unknown commands, but allow for commands to be broadcasted if they are double escaped with ++ or !!. 2009-10-06 18:02:37 +02:00
Jan Vidar Krey
40fc09a7ef Whitespace cleanups. 2009-10-06 17:40:09 +02:00
Jan Vidar Krey
582bb58ff9 Refactor the address parsing bits of adcrush. 2009-10-06 17:25:38 +02:00
Jan Vidar Krey
7472e9ae4a Removed some old unused macros. 2009-10-06 15:53:24 +02:00
Jan Vidar Krey
f076c67c33 Added a configurable listen() backlog (defaults to: server_listen_backlog=50) 2009-10-06 15:50:42 +02:00
Jan Vidar Krey
7eef032584 Doc update. 2009-10-06 14:39:47 +02:00
Jan Vidar Krey
de793ea9d2 Some compile fixes and memory leak fixes for ADCRush. 2009-10-06 14:36:49 +02:00
Jan Vidar Krey
20ef6f8e53 Fix to net_con_close() which allows us to either delete the connection immediately if that is safe, or delete it later. 2009-10-06 14:36:05 +02:00
Jan Vidar Krey
310ddf4e9d More work on the ADC client lib. 2009-10-06 12:39:31 +02:00
Jan Vidar Krey
8592aa80d4 Compile fix. 2009-10-06 12:24:44 +02:00
Jan Vidar Krey
c3ba8d52ee Merge branch 'master' of baracus-vpn:~/git/uhub
Conflicts:
	src/adc/message.c
2009-10-06 12:18:14 +02:00
Jan Vidar Krey
69f6d811bf Added lots of asserts, and split out the ip address from the connection object.
Still a lot of work remains and a massive network connection cleanup is needed.
2009-09-29 00:30:52 +02:00
Jan Vidar Krey
a53c219f05 Fix bug #82 - Crash writing a log larger than 2GB on a 32 bit system as _FILE_OFFSET_BITS was not declared to be 64. 2009-09-14 12:24:18 +02:00
Jan Vidar Krey
96ce64ee07 Fix memory issues in ADC client lib. 2009-09-04 17:18:52 +02:00
Jan Vidar Krey
a3d6646b99 Fix a failing autotest. 2009-08-31 20:37:47 +02:00
Jan Vidar Krey
4fd182c55e Fix compile warning. 2009-08-31 20:36:25 +02:00
Jan Vidar Krey
993d9ae33b Fix some issues regarding header extraction. 2009-08-31 19:45:47 +02:00
Jan Vidar Krey
fe9b48f14c Added new convenient adc_msg_* functions for accessing named parameters. 2009-08-31 19:42:34 +02:00
Jan Vidar Krey
1e380ecf0f Fix bug #77 - Error in ACL command parsing. 2009-08-31 19:39:09 +02:00
Jan Vidar Krey
af7b52b708 Cleanup argument extraction. 2009-08-31 12:25:06 +02:00
Jan Vidar Krey
aeba7188c0 Added a macro that can keep the line count down. 2009-08-28 18:10:41 +02:00
Jan Vidar Krey
4ca5caa52b Various fixes, the admin tool at least compiles and runs. 2009-08-28 18:05:58 +02:00
Jan Vidar Krey
5203ecdadc Split uhub.h 2009-08-28 16:18:18 +02:00
Jan Vidar Krey
11b288a669 Various build fixes. 2009-08-28 16:04:45 +02:00
Jan Vidar Krey
52cbec24b6 Started splitting up ADC rush. Need a test client before we can proceed anyway. 2009-08-28 14:29:19 +02:00
Jan Vidar Krey
29d6d59d36 Misc connection changes. 2009-08-27 14:15:18 +02:00
Jan Vidar Krey
96c006ee13 Cleanup some code. 2009-08-23 14:36:52 +02:00
Jan Vidar Krey
e67587b997 Fix output handling. 2009-08-23 14:36:17 +02:00
Jan Vidar Krey
1af613d9ce Fixed printf issues with size_t. Since Windows do not support %zu we have to use %Iu there instead.
Solved that with an ugly but needed macro.
2009-08-20 10:44:44 +02:00
Jan Vidar Krey
5bd258ca52 Move the network related flags from network.h to connection.h since that is where they are used. 2009-08-11 21:29:51 +02:00
Jan Vidar Krey
86ba3ca86f Complete moving all connection related data out of the hub_user object. 2009-08-07 00:22:30 +02:00
Jan Vidar Krey
cfb450c3fc Added net_set_nonblocking for Solaris. 2009-08-06 23:28:44 +02:00
Jan Vidar Krey
cd389742e6 Solaris fixes. 2009-08-06 23:15:55 +02:00
Jan Vidar Krey
4afa187f9a Expose SSL/TLS related config variables. 2009-08-06 23:05:53 +02:00
Jan Vidar Krey
b3c40f7443 Use -levent not -lev 2009-08-04 04:59:52 +02:00
Jan Vidar Krey
d45383fe4d Fix some asserts. 2009-08-04 04:58:55 +02:00
Jan Vidar Krey
1642b8dfbe Use new connection data structs. 2009-08-04 04:47:31 +02:00
Jan Vidar Krey
ffd455474a Fix use of wrong event types. 2009-08-04 04:47:02 +02:00
Jan Vidar Krey
5baf277f5a Various fixes. 2009-08-04 04:46:24 +02:00
Jan Vidar Krey
ab6eda2bbb Disabled SID allocation debug messages by default. 2009-08-04 03:38:12 +02:00
Jan Vidar Krey
c17ae06b93 Added some memory debugging facilities to the adc_message structures. 2009-08-04 03:37:30 +02:00
Jan Vidar Krey
faaa3d14e4 Dont clear the timer, instead set the TIMEOUT_IDLE when logging in (for now at least) 2009-08-04 01:07:12 +02:00
Jan Vidar Krey
9f784e808e Fix bug #70 - crash if client is in nat_ip zone, but does not provide an IP in the INF message. 2009-08-04 01:02:49 +02:00
Jan Vidar Krey
b9adaa4f8b Fix libevent init. 2009-08-04 00:22:08 +02:00
Jan Vidar Krey
80dee0c020 Get rid of the event_base_set() calls. 2009-08-04 00:15:04 +02:00
Jan Vidar Krey
604c2d8836 Disable SSL by default. 2009-08-03 23:59:19 +02:00
Jan Vidar Krey
eca0f931bd Fixes to shutdown... 2009-08-03 23:59:02 +02:00
Jan Vidar Krey
fbe98d6011 Move the timeout handling to the connection object. 2009-08-03 21:57:18 +02:00
Jan Vidar Krey
4a5993ccc2 Added a generic SSL handshake mechanism. 2009-08-03 20:21:59 +02:00
Jan Vidar Krey
a297c08bba Dont use DEBUG messages, instead a much lower level messages for SSL related debug messages. 2009-08-03 19:55:57 +02:00
Jan Vidar Krey
7229ad68ab Make sure we send with the same arguments again if SSL_write() fails with SSL_ERROR_WANT_READ. 2009-08-03 19:54:28 +02:00
Jan Vidar Krey
22f9be95d0 ensure we close the SSL connection if we get SSL_ERROR_ZERO_RETURN. 2009-08-03 18:20:08 +02:00
Jan Vidar Krey
4e43746c1b Moved the ipaddr object into the connection object. 2009-08-03 18:14:34 +02:00
Jan Vidar Krey
27c71a75ee Hook in the new connection work, also implemented some missing bits
and pieces of SSL.
SSL seems to work at some basic level, and is largely untested.
2009-08-03 17:25:52 +02:00
Jan Vidar Krey
1d363ed0b4 Expose the SSL_connect() and SSL_accept() functions. 2009-08-03 14:21:53 +02:00
Jan Vidar Krey
79cf5ee9db Some work on integrating OpenSSL. 2009-08-03 03:55:38 +02:00
Jan Vidar Krey
d2da49d41a Added .gitignore file. 2009-08-02 23:44:23 +02:00
Jan Vidar Krey
4666311516 Add a quit reason to the log messages printed by !log. 2009-08-02 22:53:25 +02:00
Jan Vidar Krey
1f24bd6812 Fix autotests. 2009-08-02 22:29:22 +02:00
Jan Vidar Krey
0e1cd903da Make sure we create enough sids as there are socket descriptors. 2009-08-02 22:29:12 +02:00
Jan Vidar Krey
4931dc5dcb Added call functionality to figure out the maximum number of sockets (file descriptors) available on system. 2009-08-02 22:28:34 +02:00
Jan Vidar Krey
077bffd74f Fix capped whoip/history messages due to limit of 1024 bytes imposed wrongly on outgoing server generated messages. 2009-08-02 21:58:12 +02:00
Jan Vidar Krey
cfb8a9f322 Started using the new connection abstraction. 2009-08-02 21:46:57 +02:00
Jan Vidar Krey
653cfb285e Started working on abstracting the connection data away from the user struct. 2009-08-02 21:37:55 +02:00
Jan Vidar Krey
053fb30192 Build fix. 2009-08-02 21:07:16 +02:00
Jan Vidar Krey
9bd0286c01 Fix bug #3, sid allocation overflow. May lead to double SIDs being given out. 2009-08-02 21:04:10 +02:00
Jan Vidar Krey
b78d48795b !history had a wrong help description. 2009-08-02 19:26:21 +02:00
Jan Vidar Krey
9b58ba6516 Use correct prefix for log command. 2009-07-28 02:17:57 +02:00
Jan Vidar Krey
f322fbb197 Fix !log command, split it up into multiple messages, and allow for searches. 2009-07-28 02:02:19 +02:00
Jan Vidar Krey
80348044c3 Make sure history messages are not escaped. 2009-07-26 18:22:53 +02:00
Jan Vidar Krey
31d4b0f0b1 Fix history - do not cache private messages. 2009-07-26 15:08:34 +02:00
Jan Vidar Krey
10615a9a1a Whitespace 2009-07-26 06:32:15 +02:00
Jan Vidar Krey
7b44036480 print ip address when using whoip. 2009-07-26 06:30:48 +02:00
Jan Vidar Krey
112fa2f845 Fixes to tests. 2009-07-26 06:27:16 +02:00
Jan Vidar Krey
945c6be14c Added tests for ip_convert_address_to_range 2009-07-26 06:21:22 +02:00
Jan Vidar Krey
099ed6dbe2 Fix autotest 2009-07-26 06:06:27 +02:00
Jan Vidar Krey
444f991f44 Fix bug #44 - [Request] IP log in the memory 2009-07-26 06:03:43 +02:00
Jan Vidar Krey
b125ffe3c1 Fix bug #52 - [Request] Chat history command 2009-07-26 05:23:56 +02:00
Jan Vidar Krey
76b84499bc Fix bug #46: [Request] A broadcast command.
Use !broadcast <message>
2009-07-26 04:47:43 +02:00
Jan Vidar Krey
6358c7f9cd Fix bug #45: [Request] Whoip command.
Rewrote patches from Zoltan to support ip ranges and multiple results per IP.
Needed to make sure IPv6 mapped IPv4 addresses were converted to proper IPv4 addresses after accept().
2009-07-26 04:31:36 +02:00
Jan Vidar Krey
041ce7a1fb Generalized the IP range and mask parsing code. 2009-07-26 03:56:55 +02:00
Jan Vidar Krey
78bb1d3527 Typo - compilefix. 2009-07-26 02:06:02 +02:00
Jan Vidar Krey
48f3cae22b Ensure we delete the global evtimer only if it is initialized. 2009-07-26 02:05:01 +02:00
Jan Vidar Krey
817250c528 Fix wrong #if to #ifdef 2009-07-26 01:53:53 +02:00
Jan Vidar Krey
f176e790e2 Whitespace fixes. 2009-07-26 01:53:01 +02:00
Jan Vidar Krey
367871e476 Renamed all "struct user" to hub_user in order to resolve a naming conflict on OpenWRT.
Basically: sed -i 's/struct user/struct hub_user/g' `find -type f`
2009-07-26 01:47:17 +02:00
Jan Vidar Krey
2ac5cc19cb Removed plugin.h, not in use. 2009-07-26 01:39:16 +02:00
Jan Vidar Krey
6e5d28c2d4 Rework logging code to be able to turn it off completely. 2009-07-26 01:38:38 +02:00
Jan Vidar Krey
5048ff9ae5 Whitespace fixes. 2009-07-26 00:58:25 +02:00
Jan Vidar Krey
36a07e3f7e Reorganized sources slightly. 2009-07-25 20:05:27 +02:00
Jan Vidar Krey
e281f61472 Add support for better pipelining of commands, in order to reduce the number of send() calls. 2009-07-25 03:54:59 +02:00
Jan Vidar Krey
bb27ff617c Re-fix chat_is_privileged. 2009-07-25 03:33:36 +02:00
Jan Vidar Krey
dc90245ade No need to store event mask in the user object since libevent already does it for us. 2009-07-25 03:26:59 +02:00
Jan Vidar Krey
0ec4913e15 Debug for send queue fix. 2009-07-25 03:24:06 +02:00
Jan Vidar Krey
61d639bfa2 Fix to hub_sendq_is_empty in order to prevent event_add calls. 2009-07-25 03:23:06 +02:00
Jan Vidar Krey
adeaf23f9c Kept spinning in send() 2009-07-19 14:45:15 +02:00
Jan Vidar Krey
03d3ffd20f Fix socket error due to EWOULDBLOCK. 2009-07-19 14:29:33 +02:00
Jan Vidar Krey
bbae2603b0 Make sure we detect send errors. 2009-07-19 03:39:11 +02:00
Jan Vidar Krey
5f0c84f46a Fix shutdown problem and reduce event_{add,del,set} calls. 2009-07-19 03:12:47 +02:00
Jan Vidar Krey
b02618d19c Bad mistake - never added message to send queue. 2009-07-19 02:46:01 +02:00
Jan Vidar Krey
927faf70fc Re-enabled send queue fixes. This will more aggressively prevent unimportant messages (like searches) to be forwarded to slow clients that cannot swallow what is sent to it. This should reduce memory usage somewhat on really large hubs. 2009-07-19 02:31:23 +02:00
Jan Vidar Krey
4a173bf066 Fix some nasty bugs related to read/write events and timeout events.
This would have caused users not being able to log in, and in some cases
100% cpu usage.
2009-07-19 02:12:50 +02:00
Jan Vidar Krey
abd097acf0 This is a somewhat risky patch, but it has been intended for quite some time:
Remove the libevent handler for write events, only use one common event handler for both reading and writing.
2009-07-09 17:03:31 +02:00
Jan Vidar Krey
3fdbccb028 Fix bug #47 - Enable -ggdb instead of -g for DEBUG builds.
RELEASE builds are built with -O3 instead of -Os.
2009-07-09 17:01:45 +02:00
Jan Vidar Krey
3db2ec5e22 Added macros that can possibly make it easier to optimize functions using forced inlining and regparm. 2009-07-09 17:01:30 +02:00
Jan Vidar Krey
e68cbd0cde Minor cleanups of old authentication stuff, and some documentation. 2009-07-03 01:29:04 +02:00
Jan Vidar Krey
98bffd93e9 Fix stupid crash on empty command. 2009-07-01 11:31:55 +02:00
Jan Vidar Krey
e53119e92c Server did not answer due to wrong checks. 2009-07-01 09:50:46 +02:00
Jan Vidar Krey
ee0ea5a427 Crash fix. 2009-06-30 22:15:08 +02:00
Jan Vidar Krey
aa7be1dc4b Fix a command parse error output problem, plus some minor cleaning up. 2009-06-30 11:48:58 +02:00
Jan Vidar Krey
0ef248759c Minor cleanups.
Enabled !crash command if compiled with debug (not release).
2009-06-29 23:22:13 +02:00
Jan Vidar Krey
5b5d9faf96 Bumped to 0.3.0-rc3. 2009-06-26 01:16:18 +02:00
Jan Vidar Krey
1f7f6a43f9 Fixed small memory leak. 2009-06-26 01:16:07 +02:00
Jan Vidar Krey
3cf005a08e Fixed command parsing for in hub user commands.
Added a framework for automatic syntax checks, and correct number
of arguments to commands.
2009-06-26 01:15:06 +02:00
Jan Vidar Krey
f3c5fced47 Documentation 2009-06-25 22:05:40 +02:00
Jan Vidar Krey
9c49f07826 Fixed the format of the git revision.
Removed the product title.
2009-06-25 22:04:48 +02:00
Jan Vidar Krey
0b59941102 Minor optimization. 2009-06-25 17:35:59 +02:00
Jan Vidar Krey
5f3f2d4f4d Autotest crash fix. 2009-06-25 17:31:39 +02:00
Jan Vidar Krey
a3d4c8dbc3 Windows fix. 2009-06-25 17:29:50 +02:00
Jan Vidar Krey
7e3a26b0f3 Winsock fixes for shutdown() - typo 2009-06-25 17:07:21 +02:00
Jan Vidar Krey
9ebb38ae15 Winsock fixes for shutdown() 2009-06-25 17:05:59 +02:00
Jan Vidar Krey
5b29a3b403 Bump to 0.3.0 release candidate 2. 2009-06-25 09:29:59 +02:00
Jan Vidar Krey
75c4272a1b Fix problem with the !stats byte counter. 2009-06-25 09:29:23 +02:00
Jan Vidar Krey
f272280faf Old versions of git 0.5 does not support the git show --oneline. - Maybe this works? 2009-06-24 09:18:03 +02:00
Jan Vidar Krey
b1d4b1288f Bump to 0.3.0-rc1 2009-06-23 23:29:27 +02:00
Jan Vidar Krey
ddba669af0 Some basic work on getting bans working.
Basically now it can ban a user (nick + cid), it will be added to the
ban list temporarily, and will not be enabled if you restart the hub.
A banned user will automatically be kicked.

unban does not work correctly.
2009-06-23 23:16:09 +02:00
Jan Vidar Krey
2ad2b66db3 Add a git revision to all debug builds... 2009-06-23 16:11:30 +02:00
Jan Vidar Krey
ca33461851 Suppress send() or recv() errors from logs. They happen quite often and are not considered errors. 2009-06-23 01:57:55 +02:00
Jan Vidar Krey
4abdc3edbd Cleanup read/write socket handling somewhat. 2009-06-23 01:57:26 +02:00
Jan Vidar Krey
90078ad4b6 Minor cleanups and some work to prepare SSL. 2009-06-23 01:56:37 +02:00
Jan Vidar Krey
3bd5c36455 SSL work. 2009-06-23 01:09:55 +02:00
Jan Vidar Krey
8f0943621e Dont set socket buffers. 2009-06-22 21:13:41 +02:00
Jan Vidar Krey
155350b61b Fixed crash bug #33 2009-06-22 21:05:02 +02:00
Jan Vidar Krey
1c58120c03 Oportunistic write. 2009-06-22 20:25:22 +02:00
Jan Vidar Krey
1d9acece34 Ensure we set a max recv and send buffer per user, and that it does not
exceed the one used internally by the application.
2009-06-22 19:50:10 +02:00
Jan Vidar Krey
57fd872f14 Added a state check for protocol negotiation.
Will be used to negotiate SSL.
2009-06-22 19:38:24 +02:00
Jan Vidar Krey
ca7544df9b Cleanups. 2009-06-22 19:37:56 +02:00
Jan Vidar Krey
c7777e2624 Added functions:
* net_get_recvbuf_size
* net_set_recvbuf_size
* net_get_sendbuf_size
* net_set_sendbuf_size

Did some minor cleanups.
2009-06-22 19:36:55 +02:00
Jan Vidar Krey
b2d543d433 Started work on SSL 2009-06-22 18:44:07 +02:00
Jan Vidar Krey
ff47281197 Added a generic way to reset last read/write variables. 2009-06-22 18:38:39 +02:00
Jan Vidar Krey
ddc91d1640 Make sure we close stdout, stdin and stderr after forking to background in order to properly detach from the TTY. 2009-06-22 18:36:48 +02:00
Jan Vidar Krey
0d084a5e14 Move to rc0 2009-06-22 17:32:38 +02:00
Jan Vidar Krey
e6e26a02e7 Added a known crash for the admin only to use if compiled with CRASH_DEBUG enabled. 2009-06-22 01:18:51 +02:00
Jan Vidar Krey
ea3cd1bd90 Work on optimizing send(), to use fewer send function calls. 2009-06-21 14:21:34 +02:00
Jan Vidar Krey
7f24238ab5 Disable sendq debugging. 2009-06-20 22:46:11 +02:00
Jan Vidar Krey
1d2d4e74f6 !stats did not work. 2009-06-18 01:46:17 +02:00
root
5250fdaf57 Fix bug #38 - Pid file support. 2009-06-17 12:52:49 +02:00
Jan Vidar Krey
7ddfd52dc7 Fix bug #34 - Disable admin\op account in example users.conf since it is being installed by default. 2009-06-01 19:55:03 +02:00
Jan Vidar Krey
513ab422f2 Compile fix. 2009-06-01 14:34:23 +02:00
Jan Vidar Krey
0eb91763fa Potential crash fix. 2009-06-01 01:52:57 +02:00
Jan Vidar Krey
507f429035 Fix send queue issue. 2009-05-28 23:44:28 +02:00
Jan Vidar Krey
b1ab64242e Renamed a function. 2009-05-28 01:48:31 +02:00
Jan Vidar Krey
8b90f79bac Work in progress on optimizing the send() function calls, to use as few as possible.
(Although, this does not enable that code).
2009-05-28 01:47:48 +02:00
Jan Vidar Krey
8f7cc0b7a7 Fixed MAX and MIN macros. 2009-05-28 01:45:36 +02:00
Jan Vidar Krey
4812a5968b Added an ADC redirector script, which is useful to run from inetd, xinetd
or similar in case you move your hub to another machine.
It will accept ADC connections and redirect clients to the new hub
instead.
2009-05-28 01:33:23 +02:00
Jan Vidar Krey
8b5bfdd922 Compile fix. 2009-05-27 18:05:34 +02:00
Jan Vidar Krey
860310caff Massive restructuring. 2009-05-26 21:05:06 +02:00
Jan Vidar Krey
8167d79f5a Large reorganizations of the code base. 2009-05-26 19:46:51 +02:00
Jan Vidar Krey
9706a0a501 Fix compiler warning (bug #30) 2009-05-24 21:07:16 +02:00
Jan Vidar Krey
9309c925d3 Started working on new pipelines for sending and receiving data.
This will be useful for the next step; SSL.

(NOTE: This code is very chatty about debug messages)
2009-05-19 22:57:50 +02:00
Jan Vidar Krey
9a3a5bc2de Make sure the send() signature is correct, buf should be const. 2009-05-19 22:36:45 +02:00
Jan Vidar Krey
e382e24337 Fix crash due to user->hub deref in acl handling. 2009-05-19 16:40:14 +02:00
Jan Vidar Krey
be4ff1d8cc Fix command parsing for in-hub commands. 2009-05-19 11:22:57 +02:00
Jan Vidar Krey
aa18ac047d Crash fix 2009-05-19 09:38:57 +02:00
Jan Vidar Krey
e120d5c76d Minor cleanup - this code crashes. 2009-05-19 09:15:14 +02:00
Jan Vidar Krey
6853e92f89 Move user_is_protected() and user_is_registered() into user.h/.c 2009-05-18 17:52:30 +02:00
Jan Vidar Krey
1dbf2640d2 More API fixes; remove implicit relationship between hub and user
in APIs.
2009-05-18 16:30:17 +02:00
Jan Vidar Krey
caec28f63f Warn on bad UTF-8 in the configuration file. 2009-05-16 12:48:17 +02:00
Jan Vidar Krey
5ea5efb875 Smome user manager functions did not have the uman_ prefix. 2009-05-16 12:42:30 +02:00
Jan Vidar Krey
326fcc467c Moved the update_user_info code into user_update_info 2009-05-16 12:32:48 +02:00
Jan Vidar Krey
078470ce64 Minor cleanup 2009-05-16 12:25:28 +02:00
Jan Vidar Krey
82ac450b4b Fixed further memory leaks in autotests. 2009-05-16 04:03:00 +02:00
Jan Vidar Krey
b4f24b21f9 Document bandwidth optimization potential. 2009-05-16 03:45:05 +02:00
Jan Vidar Krey
968266b22f Fix memory leaks. 2009-05-16 03:44:51 +02:00
Jan Vidar Krey
548867de10 Removed ADC_UDP_OPERATION code as it is not used or needed. on_kick is also gone. 2009-05-16 03:14:20 +02:00
Jan Vidar Krey
953db2dcbc Fixed some autotest memory leaks. 2009-05-16 03:06:14 +02:00
Jan Vidar Krey
6e4ac1355f Fix autotest crashers. 2009-05-16 02:33:43 +02:00
Jan Vidar Krey
604364ffa5 Fixed various code deprecations
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-05-15 18:45:26 +02:00
Jan Vidar Krey
6cc1af5671 Disable code to prevent warnings. 2009-05-15 16:52:55 +02:00
Jan Vidar Krey
15e2053699 Fix #28 - Request: +/! characters for command handling (FleetCommand) 2009-05-15 16:52:04 +02:00
Jan Vidar Krey
df1e832a3c Started working on a red-black tree implementation, need to speed up
certain operations, such as SID to user lookups, and nick to user.
2009-05-01 17:07:38 +02:00
Jan Vidar Krey
4c4cb4fb36 Dont allow clients that do not support BASE
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-04-13 05:31:41 +02:00
Jan Vidar Krey
e49f9d4d30 Added kick support
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-04-09 00:48:00 +02:00
Jan Vidar Krey
e73a931243 Ensure we do not allow update of certain elements.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-27 11:12:50 +01:00
Jan Vidar Krey
ae017af758 Log version and method of libevent()
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-24 23:32:39 +01:00
Jan Vidar Krey
7a02f92a4c Cleanup after creating debian packages.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-24 23:16:09 +01:00
Jan Vidar Krey
adeebb92a0 Added manual page. 2009-03-24 23:14:04 +01:00
Jan Vidar Krey
26f1864c1f Don't crash if one specify '-S' or '-s' and an invalid configuration file. 2009-03-24 23:10:51 +01:00
Jan Vidar Krey
c14fa3c3a9 Added more debugging info for mainloop bug #16 - In addition to small fixes to it.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-24 22:06:26 +01:00
Jan Vidar Krey
dfd2191103 White space cleanups. 2009-03-24 18:39:39 +01:00
Jan Vidar Krey
0042344054 Better dpkg system. 2009-03-24 18:38:59 +01:00
Jan Vidar Krey
8af965c0ca Fixed utf8 parse issue.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-24 00:21:38 +01:00
Jan Vidar Krey
b3d3dcdb44 Actually do upload.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:45:39 +01:00
Jan Vidar Krey
cb6190c5b4 FreeBSD fix.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:39:34 +01:00
Jan Vidar Krey
82ad62602d 0.2.8 release candidate.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:36:29 +01:00
Jan Vidar Krey
6d34bdd7e2 Added upload script.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:32:32 +01:00
Jan Vidar Krey
c2832e59c0 Added build script setup for easy publishing...
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:30:51 +01:00
Jan Vidar Krey
cf23c82c16 Added upload support.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 23:02:59 +01:00
Jan Vidar Krey
8bf0fd424a Added upload support. 2009-03-23 23:02:52 +01:00
Jan Vidar Krey
8f8284eb29 Ensure we build source .zip file. 2009-03-23 22:54:59 +01:00
Jan Vidar Krey
015c3368bd Added new script for building sources only.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 22:51:53 +01:00
Jan Vidar Krey
9186b441aa Minor build system tweaks.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 22:47:08 +01:00
Jan Vidar Krey
74af392e80 Stop in case of error.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 22:40:15 +01:00
Jan Vidar Krey
3a270564d2 Fixed up admin scripts.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 22:36:45 +01:00
Jan Vidar Krey
f0938e8afa Fixed up build scripts somewhat. 2009-03-23 22:33:45 +01:00
Jan Vidar Krey
156c137237 Autotest for bug #12
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 21:55:24 +01:00
Jan Vidar Krey
7aeb8651ba Fix bug #12: asserts in adc_msg_parse -> enabled strict utf8 parsing.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 21:47:05 +01:00
Jan Vidar Krey
ab4eb6db3d Document 0.2.8 changes. 2009-03-23 16:51:06 +01:00
Jan Vidar Krey
13a8700554 Make sure logs do not output configured messages, but rather code names.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 15:47:54 +01:00
Jan Vidar Krey
5d5dda2f9b Always obtain IP address during accept(), and not do it later as a call to getsockname().
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-23 15:05:27 +01:00
Jan Vidar Krey
95b741bb5e More message tests. 2009-03-23 14:58:15 +01:00
Jan Vidar Krey
90abf64e3a Do explicit logging in src/message.c 2009-03-23 08:18:25 +01:00
Jan Vidar Krey
e9915df87c remove timezone from logs, as it screws up on windows.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-21 04:11:14 +01:00
Jan Vidar Krey
408829e330 Another 0.2.7 candidate.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-21 03:59:12 +01:00
Jan Vidar Krey
1a1b5bdb38 Fixed nasty crash if a user sends a very large command to the hub.
Will overwrite heap memory.
Thanks to Toast who found this bug.

Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-21 02:58:53 +01:00
Jan Vidar Krey
abedec692a 0.2.7 release candidate
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 19:12:18 +01:00
Jan Vidar Krey
7738baf38e Log configuration reloads.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 19:09:55 +01:00
Jan Vidar Krey
3c4c52d0f9 Log configuration reloads.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 19:08:24 +01:00
Jan Vidar Krey
76588fb1bd Don't print OK or ERROR when dumping config.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 19:05:25 +01:00
Jan Vidar Krey
f9e95ec582 Minor cleanups
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 19:02:32 +01:00
Jan Vidar Krey
7985d4fed0 Cleanup credentials to string handling
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 18:54:05 +01:00
Jan Vidar Krey
77343d3c21 Remove duplicate access_denied checks.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 18:38:42 +01:00
Jan Vidar Krey
f8d5b72a89 Cleanup command list, automatically generate help list depending on user credentials. 2009-03-20 18:37:38 +01:00
Jan Vidar Krey
cf2994b570 Fix whitespace 2009-03-20 18:37:05 +01:00
Jan Vidar Krey
7a9d40d8dd Fix autotests for event queue.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 17:42:29 +01:00
Jan Vidar Krey
b1f84b5b4a Cleanup logging.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 17:40:50 +01:00
Jan Vidar Krey
998c6c36ce Fix indentation 2009-03-20 16:40:59 +01:00
Jan Vidar Krey
4112b8111a Fix problems with clients sending multiple INF messages during the login stage. Only the first one will be checked. 2009-03-20 16:40:34 +01:00
Jan Vidar Krey
1929f2fae7 Fix bug #9 - net_get_peer_address() failure on CentOS/Xen configurations.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-20 15:07:52 +01:00
Jan Vidar Krey
77e41371b5 Ensure we install to /usr/local by default.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-19 20:02:03 +01:00
Jan Vidar Krey
0266c8bb9c Libevent fixes, and memory leak fix.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-19 17:57:04 +01:00
Jan Vidar Krey
5e3eabb677 Fix help message typo
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-19 01:30:46 +01:00
Jan Vidar Krey
669ab14022 Minor cleanups and stack reduction.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-19 01:27:34 +01:00
Jan Vidar Krey
1d491055c5 Do not use event_loopexit with new event loop.
Signed-off-by: Jan Vidar Krey <janvidar@extatic.org>
2009-03-19 01:13:02 +01:00
Jan Vidar Krey
08351ea8e7 Merge branch 'event_queue_work' 2009-03-19 01:08:57 +01:00
Jan Vidar Krey
e2ac690164 Reindented code. 2009-03-19 01:01:36 +01:00
Jan Vidar Krey
3bb563b432 Cleaned up command system somewhat. Added admin commands for reload and shutdown. 2009-03-19 00:55:11 +01:00
Jan Vidar Krey
e10582fec2 Cleaned up command system slightly.
Added admin commands for reload and shutdown.
2009-03-19 00:53:44 +01:00
144 changed files with 10438 additions and 5978 deletions

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
*~
*.[oa]
*.exe
*.gch
uhub-admin
adcrush
uhub

View File

@@ -2,5 +2,5 @@ Authors of uHub
===============
Jan Vidar Krey, Design and implementation
E_zombie, Centos/RedHat customization scripts and heavy load testing

8
BSDmakefile Normal file
View File

@@ -0,0 +1,8 @@
GMAKE=gmake
all:
@${GMAKE} ${.TARGETS}
${.TARGETS}: all

View File

@@ -1,4 +1,43 @@
0.3.1:
- Fixed bug where !getip did not work.
- Added flood control configuration options.
- Added configuration options to disallow old/obsolete ADC clients.
- Fixed crash bugs, an freezes.
- SSL/TLS fix for tls_require configuration option.
- Fixed disconnect messages, so that clients can interpret them.
- Fixed bugs where share limits could be circumvented.
- Added support for listening to multiple ports.
- kqueue backend for Mac OS X, and BSD systems.
0.3.0:
- More user commands: ban, broadcast, mute, rules, history, myip, whoip, log
- Experimental SSL support
- Large rewrite of the network stack in order to support SSL.
- Added rule file for defining hub rules.
- Many crash fixes and other important bug fixes.
- Optimizations: O(1) timeout scheduler
- New sid allocation code.
- Added configurable server_listen_backlog (default 50).
- Added init.d scripts for RedHat/CentOS
0.2.8:
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
- Fix bug #10: Improve logging, ensure logs are machine readable.
- Fix bug #12: asserts in adc_msg_parse -> enabled strict utf8 parsing.
0.2.7:
- Fixed a nasty crash (bug #11), Thanks Toast for finding it.
- Fix bug #9 - net_get_peer_address() failure on CentOS/Xen configurations.
- Write a log message if an operator reloads the config file.
- Don't print OK or ERROR when using '-s' or '-S' show the configuration.
- Cleanup credential string handling
- Made sure "!help" only display accessible commands.
- Cleanup in-hub command parsing
- Fix a possible crash if multiple INF messages are sent during login.
- Rewrote the mainloop to not use a timer.
0.2.6:

View File

@@ -1,27 +1,40 @@
##
## Makefile for uhub (Use GNU make)
## Copyright (C) 2007-2008, Jan Vidar Krey <janvidar@extatic.org>
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
#
-include Makefile.private
CC = gcc
LD := $(CC)
MV := mv
RANLIB := ranlib
CFLAGS += -pipe -Wall
USE_PCH ?= YES
USE_SSL ?= NO
USE_BIGENDIAN ?= AUTO
BITS ?= AUTO
SILENT ?= YES
LDLIBS += -levent
TERSE ?= NO
STACK_PROTECT ?= NO
ifeq ($(OS), Windows_NT)
WINDOWS ?= YES
OPSYS ?= Windows
else
OPSYS ?= $(shell uname)
endif
ifeq ($(WINDOWS),YES)
ifeq ($(OPSYS),SunOS)
LDLIBS += -lsocket -lnsl
endif
ifeq ($(OPSYS),Haiku)
LDLIBS += -lnetwork
endif
CFLAGS += -I./src/
ifeq ($(OPSYS),Windows)
USE_BIGENDIAN := NO
LDLIBS += -lws2_32
UHUB_CONF_DIR ?= c:/uhub/
@@ -32,27 +45,24 @@ BIN_EXT ?= .exe
else
DESTDIR ?= /
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
UHUB_PREFIX ?= $(DESTDIR)/usr/
UHUB_PREFIX ?= $(DESTDIR)/usr/local
CFLAGS += -I/usr/local/include
LDFLAGS += -L/usr/local/lib
BIN_EXT ?=
endif
ifeq ($(SILENT),YES)
MSG_CC=@echo " CC:" $(notdir $^) &&
MSG_PCH=@echo " PCH:" $(notdir $@) &&
MSG_CC=@echo " CC:" $(notdir $<) &&
MSG_LD=@echo " LD:" $(notdir $@) &&
MSG_AR=@echo " AR:" $(notdir $@) &&
else
MSG_CC=
MSG_PCH=
MSG_LD=
MSG_AR=
endif
ifeq ($(TERSE), YES)
MSG_CC=@
MSG_PCH=@
MSG_LD=@
MSG_AR=@
MSG_CLEAN=-n ""
@@ -60,17 +70,10 @@ else
MSG_CLEAN="Clean as a whistle"
endif
CFLAGS += -I/source/libevent
LDFLAGS += -L/source/libevent
-include release_setup.mk
ifeq ($(RELEASE),YES)
CFLAGS += -Os -DNDEBUG
CFLAGS += -O3 -DNDEBUG
else
CFLAGS += -g -DDEBUG
CFLAGS += -ggdb -DDEBUG
endif
ifeq ($(STACK_PROTECT),YES)
@@ -88,13 +91,6 @@ CFLAGS += -finstrument-functions
CFLAGS += -DDEBUG_FUNCTION_TRACE
endif
ifeq ($(USE_PCH),YES)
PCHSRC=src/uhub.h
PCH=src/uhub.h.gch
else
PCH=
endif
ifneq ($(BITS), AUTO)
ifeq ($(BITS), 64)
CFLAGS += -m64
@@ -122,122 +118,123 @@ CFLAGS += -DSSL_SUPPORT
LDLIBS += -lssl
endif
ifneq ($(LIBEVENT_PATH),)
CFLAGS += -I$(LIBEVENT_PATH)
LDFLAGS += -L$(LIBEVENT_PATH)
endif
GIT_VERSION=$(shell git describe --tags 2>/dev/null || echo "")
GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " " | tr -d "\"")
# Sources
libuhub_SOURCES := \
src/auth.c \
src/commands.c \
src/config.c \
src/eventqueue.c \
src/hubevent.c \
src/hub.c \
src/inf.c \
src/ipcalc.c \
src/list.c \
src/log.c \
src/memory.c \
src/message.c \
src/misc.c \
src/netevent.c \
src/network.c \
src/route.c \
src/sid.c \
src/tiger.c \
src/user.c \
src/usermanager.c
src/core/auth.c \
src/core/commands.c \
src/core/config.c \
src/core/eventqueue.c \
src/core/floodctl.c \
src/core/hub.c \
src/core/hubevent.c \
src/core/hubio.c \
src/core/inf.c \
src/core/netevent.c \
src/core/probe.c \
src/core/route.c \
src/core/user.c \
src/core/usermanager.c \
src/network/backend.c \
src/network/connection.c \
src/network/epoll.c \
src/network/kqueue.c \
src/network/network.c \
src/network/select.c \
src/network/timeout.c \
src/network/timer.c \
src/util/ipcalc.c \
src/util/list.c \
src/util/log.c \
src/util/memory.c \
src/util/misc.c \
src/util/rbtree.c \
src/util/tiger.c
uhub_SOURCES := src/main.c
libadc_common_SOURCES := \
src/adc/message.c \
src/adc/sid.c
adcrush_SOURCES := src/adcrush.c
libadc_client_SOURCES := \
src/tools/adcclient.c
uhub_HEADERS := \
src/adcconst.h \
src/auth.h \
src/config.h \
src/eventid.h \
src/eventqueue.h \
src/hubevent.h \
src/hub.h \
src/inf.h \
src/ipcalc.h \
src/list.h \
src/log.h \
src/memory.h \
src/message.h \
src/misc.h \
src/netevent.h \
src/network.h \
src/route.h \
src/sid.h \
src/tiger.h \
src/uhub.h \
src/user.h \
src/usermanager.h
uhub_SOURCES := src/core/main.c
adcrush_SOURCES := src/tools/adcrush.c
admin_SOURCES := src/tools/admin.c
autotest_SOURCES := \
autotest/test_message.tcc \
autotest/test_eventqueue.tcc \
autotest/test_hub.tcc \
autotest/test_inf.tcc \
autotest/test_ipfilter.tcc \
autotest/test_list.tcc \
autotest/test_memory.tcc \
autotest/test_ipfilter.tcc \
autotest/test_inf.tcc \
autotest/test_hub.tcc \
autotest/test_message.tcc \
autotest/test_misc.tcc \
autotest/test_sid.tcc \
autotest/test_tiger.tcc \
autotest/test_eventqueue.tcc
autotest/test_timer.tcc \
autotest/test_usermanager.tcc
autotest_OBJECTS = autotest.o
# Source to objects
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
libadc_common_OBJECTS := $(libadc_common_SOURCES:.c=.o)
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS)
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
admin_OBJECTS := $(admin_SOURCES:.c=.o)
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
LIBUHUB=libuhub.a
uhub_BINARY=uhub$(BIN_EXT)
adcrush_BINARY=adcrush$(BIN_EXT)
admin_BINARY=uhub-admin$(BIN_EXT)
autotest_BINARY=autotest/test$(BIN_EXT)
%.o: %.c
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@.tmp $^ && \
$(MV) $@.tmp $@
.PHONY: revision.h.tmp
all: $(uhub_BINARY) $(PCH)
%.o: %.c version.h revision.h
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@ $<
$(adcrush_BINARY): $(PCH) $(LIBUHUB) $(adcrush_OBJECTS)
$(MSG_LD) $(CC) -o $@.tmp $(adcrush_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS) && \
$(MV) $@.tmp $@
all: $(uhub_BINARY)
$(uhub_BINARY): $(PCH) $(LIBUHUB) $(uhub_OBJECTS)
$(MSG_LD) $(CC) -o $@.tmp $(uhub_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS) && \
$(MV) $@.tmp $@
$(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
$(LIBUHUB): $(libuhub_OBJECTS)
$(MSG_AR) $(AR) rc $@.tmp $^ && \
$(RANLIB) $@.tmp && \
$(MV) $@.tmp $@
$(admin_BINARY): $(admin_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
ifeq ($(USE_PCH),YES)
$(PCH): $(uhub_HEADERS)
$(MSG_PCH) $(CC) $(CFLAGS) -o $@.tmp $(PCHSRC) && \
$(MV) $@.tmp $@
endif
$(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
autotest.c: $(autotest_SOURCES)
$(shell exotic --standalone $(autotest_SOURCES) > $@)
$(autotest_OBJECTS): autotest.c
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@.tmp $< && \
$(MV) $@.tmp $@
revision.h.tmp:
@rm -f $@
@echo "/* AUTOGENERATED FILE - DO NOT EDIT */" > $@
@if [ -n '$(GIT_VERSION)' ]; then echo \#define GIT_VERSION \"$(GIT_VERSION)\" >> $@; fi
@if [ -n '$(GIT_REVISION)' ]; then echo \#define GIT_REVISION \"$(GIT_REVISION)\" >> $@; fi
$(autotest_BINARY): $(autotest_OBJECTS) $(LIBUHUB)
$(MSG_LD) $(CC) -o $@.tmp $^ $(LDFLAGS) $(LDLIBS) && \
$(MV) $@.tmp $@
version.h: revision.h
revision.h: revision.h.tmp
@if [ '$(GIT_REVISION)' != '$(OLD_REVISION)' ]; then cp $@.tmp $@; fi
@if [ ! -f $@ ]; then cp $@.tmp $@; fi
$(autotest_OBJECTS): autotest.c
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
$(autotest_BINARY): $(autotest_OBJECTS) $(libuhub_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
autotest: $(autotest_BINARY)
@./$(autotest_BINARY) -s -f
@@ -257,11 +254,10 @@ install: $(uhub_BINARY)
endif
dist-clean:
@rm -rf $(all_OBJECTS) $(PCH) *~ core
@rm -rf $(all_OBJECTS) *~ core
clean:
@rm -rf $(libuhub_OBJECTS) $(PCH) *~ core $(uhub_BINARY) $(LIBUHUB) $(all_OBJECTS) && \
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) autotest.c revision.h revision.h.tmp && \
echo $(MSG_CLEAN)
-include release_targets.mk

5
README
View File

@@ -1,5 +1,8 @@
Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
For the official documentation, bugs and other information, please visit:
http://www.extatic.org/uhub/
http://www.uhub.org/
For a list of compatible ADC clients, see:
http://www.adcportal.com/wiki/index.php/ADC_Software_List#Client_Software

0
TODO Normal file
View File

View File

@@ -6,25 +6,30 @@ else
HOST_MACHINE=`uname -m | tr [:upper:] [:lower:] | sed s/i686/i386/ | sed s/x86_64/amd64/ | sed s/ppc64/powerpc/`
fi
BINSUFFIX=
MAKEARGS=
MAKE=make
WANTZIP=0
if [ "${HOST_SYSTEM}" = "mingw32_nt-5.1" ]; then
HOST_SYSTEM=win32
BINARY=uhub.exe
BINSUFFIX=.exe
WANTZIP=1
else
WANTZIP=0
BINARY=uhub
MAKEARGS="USE_BIGENDIAN=NO"
fi
BINARY=uhub${BINSUFFIX}
if [ "${HOST_SYSTEM}" = "freebsd" ]; then
MAKE=gmake
fi
VERSION=`grep define\ VERSION version.h | cut -f 3 -d " " | tr -d [=\"=]`
SNAPSHOT=`date '+%Y%m%d'`
PACKAGE=uhub-${VERSION}
PACKAGE_SRC=${PACKAGE}-src
PACKAGE_BIN=${PACKAGE}-${HOST_SYSTEM}-${HOST_MACHINE}
URL_ARCHIVE='build-archive:~/uhub/'
URL_PUBLISH='domeneshop:~/www/downloads/uhub/'
URL_SNAPSHOT='domeneshop:~/www/downloads/uhub/snapshots/'
ARCHIVE='build-archive:~/www/downloads/uhub/'
function export_source_directory
{
@@ -51,45 +56,85 @@ function package_zips
gzip -c -9 $1.tar > $1.tar.gz
bzip2 -c -9 $1.tar > $1.tar.bz2
rm -f $1.tar
zip -q -9 -r $1.zip $2
if [ $WANTZIP -eq 1 ]; then
zip -q -9 -r $1.zip $2
fi
}
function export_sources
{
export_source_directory
make autotest.c && cp autotest.c ${PACKAGE}/autotest.c
rm -Rf ${PACKAGE}/admin
if [ ! -d ${PACKAGE} ]; then
export_source_directory
fi
cd ${PACKAGE}
${MAKE} ${MAKEARGS} autotest.c
cd ..
if [ ! -f ${PACKAGE}/autotest.c ]; then
echo "Unable to create autotest.c, aborting..."
exit 1
fi
rm -Rf ${PACKAGE}/admin
package_zips ${PACKAGE_SRC} ${PACKAGE}
rm -Rf ${PACKAGE};
cp ChangeLog ChangeLog-${VERSION}
}
function build_binaries
{
if [ ! -d ${PACKAGE} ]; then
export_source_directory
fi
cd ${PACKAGE}
${MAKE} ${MAKEARGS} RELEASE=YES
cd ..
if [ ! -x ${PACKAGE}/${BINARY} ]; then
echo "Build failed, no binary found..."
exit 1
fi
}
function export_binaries
{
export_source_directory
build_binaries
rm -Rf ${PACKAGE}/admin
rm -Rf ${PACKAGE}/autotest
rm -Rf ${PACKAGE}/src
rm -Rf ${PACKAGE}/debian
rm -f ${PACKAGE}/autotest.c
rm -f ${PACKAGE}/*akefile
rm -f ${PACKAGE}/version.h
rm -f ${PACKAGE}/doc/Doxyfile
rm -f ${PACKAGE}/doc/uhub.dot
make
if [ -x ${BINARY} ]; then
cp ${BINARY} ${PACKAGE}
else
echo "No binary found!"
exit 1
fi
rm -f ${PACKAGE}/libuhub*
package_zips ${PACKAGE_BIN} ${PACKAGE}
rm -Rf ${PACKAGE}
}
rm -Rf ${PACKAGE};
function upload_pkg
{
if [ -f $1 ]; then
scp $1 ${ARCHIVE}
fi
}
function upload_packages
{
upload_pkg ${PACKAGE_SRC}.tar.gz
upload_pkg ${PACKAGE_SRC}.tar.bz2
upload_pkg ${PACKAGE_SRC}.zip
upload_pkg ChangeLog-${VERSION}
upload_pkg ${PACKAGE_BIN}.tar.gz
upload_pkg ${PACKAGE_BIN}.tar.bz2
upload_pkg ${PACKAGE_BIN}.zip
}

3
admin/export.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
. admin/common.sh
export_source_directory

95
admin/make_pkg_deb.sh Executable file
View File

@@ -0,0 +1,95 @@
#!/bin/sh
. admin/common.sh
export_source_directory
build_binaries
DEB_REVISION=1
if [ -d deb ]; then
rm -Rf deb
fi
mkdir -p \
deb/DEBIAN \
deb/usr/bin \
deb/usr/share/man/man1/ \
deb/usr/share/doc/uhub \
deb/etc/uhub \
|| exit 1
find deb -type d | xargs chmod 755
# Copy binaries...
cp ${PACKAGE}/${BINARY} deb/usr/bin
strip deb/usr/bin/${BINARY}
# Copy configuration files...
cp ${PACKAGE}/doc/uhub.conf deb/etc/uhub
cp ${PACKAGE}/doc/users.conf deb/etc/uhub
echo "Welcome to uHub" > deb/etc/uhub/motd.txt
# Copy other files
cp ${PACKAGE}/README deb/usr/share/doc/uhub
cp ${PACKAGE}/AUTHORS deb/usr/share/doc/uhub
gzip -c --best < ${PACKAGE}/ChangeLog > deb/usr/share/doc/uhub/changelog.gz
gzip -c --best < ${PACKAGE}/doc/uhub.1 > deb/usr/share/man/man1/uhub.1.gz
cat > deb/usr/share/doc/uhub/copyright <<EOF
uHub - a high performance hub for the ADC peer-to-peer network
Copyright (C) 2007-2009 Jan Vidar Krey <janvidar@extatic.org>
uHub is free and open source software, licensed under the
GNU General Public License version 3.
For details, see /usr/share/common-licenses/GPL-3
EOF
gzip -c --best > deb/usr/share/doc/uhub/changelog.Debian.gz <<EOF
uhub (${VERSION}) stable; urgency=low
* See changelog.gz for details.
-- Jan Vidar Krey <janvidar@extatic.org> `date -R`
EOF
### Write control files
cd deb
echo "/etc/uhub/uhub.conf" > DEBIAN/conffiles
echo "/etc/uhub/users.conf" >> DEBIAN/conffiles
echo "/etc/uhub/motd.txt" >> DEBIAN/conffiles
md5sum `find usr -type f` > DEBIAN/md5sums
INSTALL_SIZE=`du -s | cut -f 1`
cat > DEBIAN/control <<EOF
Package: uhub
Version: ${VERSION}-${DEB_REVISION}
Architecture: ${HOST_MACHINE}
Maintainer: Jan Vidar Krey <janvidar@extatic.org>
Installed-Size: ${INSTALL_SIZE}
Depends: libc6 (>= 2.7-1), libevent1 (>= 1.3e-1)
Section: net
Priority: optional
Description: a high performance hub for the ADC peer-to-peer network
uHub is a high performance peer-to-peer hub for the ADC network.
Its low memory footprint allows it to handle several thousand users
on high-end servers, or a small private hub on embedded hardware.
.
Homepage: http://www.extatic.org/uhub/
EOF
cd ..
### Create deb file
fakeroot dpkg-deb --build deb
mv deb.deb uhub_${VERSION}-${DEB_REVISION}_${HOST_MACHINE}.deb
### Check for errors
lintian uhub_${VERSION}-${DEB_REVISION}_${HOST_MACHINE}.deb
### Cleanup
rm -Rf deb
rm -Rf ${PACKAGE}

View File

@@ -1,11 +0,0 @@
#!/bin/bash
# set -x
ME=`dirname $0`
. ${ME}/common.sh
# Git Export
export_sources
export_binaries

3
admin/release_binaries.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
. admin/common.sh
export_binaries

4
admin/release_sources.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
. admin/common.sh
WANTZIP=1
export_sources

26
admin/setup_archive.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/bin/bash
PUB="${HOME}/.ssh/id_rsa.pub"
CFG="${HOME}/.ssh/config"
if [ ! "`grep build-archive ${CFG}`" ]; then
echo "Updating ssh config (${CFG})..."
cat >> ${CFG} <<EOF
Host build-archive
ForwardX11 no
HostName login.domeneshop.no
User extatic
EOF
else
echo "ssh config seems OK (${CFG})"
fi
if [ ! -f ${PUB} ]; then
echo "No id_rsa.pub - run ssh-keygen"
exit 1
fi
echo "Copying public key (${PUB})..."
cat ${PUB} | ssh build-archive "cat >> .ssh/authorized_keys"

3
admin/upload.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
. admin/common.sh
upload_packages

View File

@@ -2,7 +2,6 @@
static struct event_queue* eq;
static int eq_val;
struct event* libevent_handle;
static void eq_callback(void* callback_data, struct event_data* event_data)
{
@@ -17,8 +16,6 @@ EXO_TEST(eventqueue_init_1, {
EXO_TEST(eventqueue_init_2, {
/* hack */
libevent_handle = eq->event;
eq->event = 0;
return eq->callback_data == &eq_val && eq->callback == eq_callback && eq->q1 && eq->q2 && !eq->locked;
});
@@ -81,7 +78,6 @@ EXO_TEST(eventqueue_size_4, {
});
EXO_TEST(eventqueue_shutdown_1, {
eq->event = libevent_handle;
event_queue_shutdown(eq);
return 1;
});

View File

@@ -10,8 +10,8 @@ static void create_test_user()
if (g_user)
return;
g_user = (struct user*) malloc(sizeof(struct user));
memset(g_user, 0, sizeof(struct user));
g_user = (struct hub_user*) malloc(sizeof(struct hub_user));
memset(g_user, 0, sizeof(struct hub_user));
memcpy(g_user->id.nick, "exotic-tester", 13);
g_user->sid = 1;
}
@@ -23,6 +23,7 @@ EXO_TEST(hub_net_startup, {
EXO_TEST(hub_config_initialize, {
config_defaults(&g_config);
g_config.server_port = 65111;
return 1;
});
@@ -67,5 +68,5 @@ EXO_TEST(hub_service_shutdown, {
});
EXO_TEST(hub_net_shutdown, {
return (net_shutdown() != -1);
return (net_destroy() != -1);
});

View File

@@ -5,17 +5,17 @@
#define USER_NICK "Friend"
#define USER_SID "AAAB"
static struct user* inf_user = 0;
static struct hub_user* inf_user = 0;
static struct hub_info* inf_hub = 0;
extern int hub_handle_info_login(struct user* user, struct adc_message* cmd);
extern int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd);
static void inf_create_hub()
{
inf_hub = (struct hub_info*) hub_malloc_zero(sizeof(struct hub_info));
inf_hub->users = (struct user_manager*) hub_malloc_zero(sizeof(struct user_manager));
inf_hub->users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager));
inf_hub->users->list = list_create();
inf_hub->users->free_sid = 1;
inf_hub->users->sids = sid_pool_create(500);
inf_hub->acl = (struct acl_handle*) hub_malloc_zero(sizeof(struct acl_handle));
inf_hub->config = (struct hub_config*) hub_malloc_zero(sizeof(struct hub_config));
@@ -27,16 +27,22 @@ static void inf_create_hub()
static void inf_destroy_hub()
{
/* FIXME */
list_destroy(inf_hub->users->list);
sid_pool_destroy(inf_hub->users->sids);
acl_shutdown(inf_hub->acl);
free_config(inf_hub->config);
hub_free(inf_hub->users);
hub_free(inf_hub->acl);
hub_free(inf_hub->config);
hub_free(inf_hub);
}
static void inf_create_user()
{
if (inf_user) return;
inf_user = (struct user*) hub_malloc_zero(sizeof(struct user));
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
inf_user->id.sid = 1;
inf_user->sd = -1;
inf_user->hub = inf_hub;
inf_user->limits.upload_slots = 1;
}
@@ -55,13 +61,13 @@ EXO_TEST(inf_create_setup,
});
/* FIXME: MEMORY LEAK - Need to fix hub_handle_info_login */
#define CHECK_INF(MSG, EXPECT) \
struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \
int ok = hub_handle_info_login(inf_user, msg); \
int ok = hub_handle_info_login(inf_hub, inf_user, msg); /* FIXME: MEMORY LEAK */ \
adc_msg_free(msg); \
if (ok != EXPECT) \
printf("Expected %d, got %d\n", EXPECT, ok); \
if (ok == EXPECT) \
user_set_info(inf_user, 0); \
return ok == EXPECT;
@@ -106,7 +112,7 @@ EXO_TEST(inf_nick_10, {
struct adc_message* msg = adc_msg_parse_verify(inf_user, line, strlen(line));
adc_msg_add_named_argument(msg, "NI", nick);
int ok = hub_handle_info_login(inf_user, msg);
int ok = hub_handle_info_login(inf_hub, inf_user, msg);
adc_msg_free(msg);
if (ok != status_msg_inf_error_nick_not_utf8)
printf("Expected %d, got %d\n", status_msg_inf_error_nick_not_utf8, ok);

View File

@@ -9,8 +9,8 @@ static struct ip_addr_encap ip6_a;
static struct ip_addr_encap ip6_b;
static struct ip_addr_encap ip6_c;
static struct ip_addr_encap mask;
static struct ip_ban_record ban6;
static struct ip_ban_record ban4;
static struct ip_range ban6;
static struct ip_range ban4;
EXO_TEST(prepare_network, {
return net_initialize() == 0;
@@ -405,74 +405,74 @@ EXO_TEST(check_ban_setup_1, {
EXO_TEST(check_ban_ipv4_1, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.0", &addr);
return acl_check_ip_range(&addr, &ban4);
return ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_2, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.1", &addr);
return acl_check_ip_range(&addr, &ban4);
return ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_3, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.255", &addr);
return acl_check_ip_range(&addr, &ban4);
return ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_4, {
struct ip_addr_encap addr; ip_convert_to_binary("192.168.1.0", &addr);
return !acl_check_ip_range(&addr, &ban4);
return !ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv4_5, {
struct ip_addr_encap addr; ip_convert_to_binary("192.167.255.255", &addr);
return !acl_check_ip_range(&addr, &ban4);
return !ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_ipv6_1, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:0", &addr);
return acl_check_ip_range(&addr, &ban6);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_2, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:1", &addr);
return acl_check_ip_range(&addr, &ban6);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_3, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:fffe", &addr);
return acl_check_ip_range(&addr, &ban6);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_4, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:ffff", &addr);
return acl_check_ip_range(&addr, &ban6);
return ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_5, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefb:0", &addr);
return !acl_check_ip_range(&addr, &ban6);
return !ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_ipv6_6, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
return !acl_check_ip_range(&addr, &ban6);
return !ip_in_range(&addr, &ban6);
});
EXO_TEST(check_ban_afmix_1, {
if (!ipv6) return 1;
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
return !acl_check_ip_range(&addr, &ban4);
return !ip_in_range(&addr, &ban4);
});
EXO_TEST(check_ban_afmix_2, {
struct ip_addr_encap addr; ip_convert_to_binary("10.20.30.40", &addr);
return !acl_check_ip_range(&addr, &ban6);
return !ip_in_range(&addr, &ban6);
});
EXO_TEST(ip4_bitwise_AND_1, {
@@ -594,6 +594,28 @@ EXO_TEST(ip6_bitwise_OR_3, {
return !strcmp(ip_convert_to_string(&ip6_c), "7777:cccc:3333:1111:ffff:ffff:ffff:1c1c");
});
EXO_TEST(shutdown_network, {
return net_shutdown() == 0;
EXO_TEST(ip_range_1, {
struct ip_range range; memset(&range, 0, sizeof(range));
return ip_convert_address_to_range("192.168.0.1", &range) && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) == 0;
});
EXO_TEST(ip_range_2, {
struct ip_range range; memset(&range, 0, sizeof(range));
return ip_convert_address_to_range("192.168.0.0-192.168.255.255", &range) && range.lo.af == range.hi.af && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) != 0;
});
EXO_TEST(ip_range_3, {
struct ip_range range; memset(&range, 0, sizeof(range));
return ip_convert_address_to_range("192.168.0.0/16", &range) && range.lo.af == range.hi.af && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) != 0;
});
EXO_TEST(ip_range_4, {
struct ip_range range1; memset(&range1, 0, sizeof(range1));
struct ip_range range2; memset(&range2, 0, sizeof(range2));
return ip_convert_address_to_range("192.168.0.0/16", &range1) && ip_convert_address_to_range("192.168.0.0-192.168.255.255", &range2) && memcmp(&range1, &range2, sizeof(struct ip_range)) == 0;
});
EXO_TEST(shutdown_network, {
return net_destroy() == 0;
});

View File

@@ -8,27 +8,27 @@ EXO_TEST(test_message_refc_1, {
});
EXO_TEST(test_message_refc_2, {
return g_msg->references == 0; // 0
return g_msg->references == 1;
});
EXO_TEST(test_message_refc_3, {
adc_msg_incref(g_msg);
return g_msg->references == 1; // 1
return g_msg->references == 2;
});
EXO_TEST(test_message_refc_4, {
adc_msg_incref(g_msg);
return g_msg->references == 2; // 2
return g_msg->references == 3;
});
EXO_TEST(test_message_refc_5, {
adc_msg_free(g_msg);
return g_msg->references == 1; // 1
return g_msg->references == 2;
});
EXO_TEST(test_message_refc_6, {
adc_msg_free(g_msg);
return g_msg->references == 0; // 0
return g_msg->references == 1;
});
EXO_TEST(test_message_refc_7, {

View File

@@ -1,5 +1,5 @@
#include <uhub.h>
static struct user* g_user = 0;
static struct hub_user* g_user = 0;
static const char* test_string1 = "IINF AAfoo BBbar CCwhat\n";
static const char* test_string2 = "BMSG AAAB Hello\\sWorld!\n";
static const char* test_string3 = "BINF AAAB IDAN7ZMSLIEBL53OPTM7WXGSTXUS3XOY6KQS5LBGX NIFriend DEstuff SL3 SS0 SF0 VEQuickDC/0.4.17 US6430 SUADC0,TCP4,UDP4 I4127.0.0.1 HO5 HN1 AW\n";
@@ -11,12 +11,17 @@ static void create_test_user()
if (g_user)
return;
g_user = (struct user*) malloc(sizeof(struct user));
memset(g_user, 0, sizeof(struct user));
g_user = (struct hub_user*) malloc(sizeof(struct hub_user));
memset(g_user, 0, sizeof(struct hub_user));
memcpy(g_user->id.nick, "exotic-tester", 13);
g_user->id.sid = 1;
}
EXO_TEST(adc_message_first, {
create_test_user();
return g_user != 0;
});
EXO_TEST(adc_message_parse_1, {
struct adc_message* msg = adc_msg_create("IMSG Hello\\sWorld!");
int ok = msg != NULL;
@@ -26,11 +31,12 @@ EXO_TEST(adc_message_parse_1, {
EXO_TEST(adc_message_parse_2, {
struct adc_message* msg = adc_msg_create(test_string2);
return msg == NULL;
int ok = (msg != NULL);
adc_msg_free(msg);
return ok;
});
EXO_TEST(adc_message_parse_3, {
create_test_user();
struct adc_message* msg = adc_msg_parse_verify(g_user, "BMSG AAAB Hello\\sWorld!", 23);
int ok = msg != NULL;
adc_msg_free(msg);
@@ -144,12 +150,29 @@ EXO_TEST(adc_message_parse_20, {
return ok;
});
EXO_TEST(adc_message_parse_21, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAC AAAB Hello\\sthere!\n", 29);
return msg == NULL;
});
EXO_TEST(adc_message_parse_22, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "\n", 0);
return msg == NULL;
});
EXO_TEST(adc_message_parse_23, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "\r\n", 1);
return msg == NULL;
});
EXO_TEST(adc_message_parse_24, {
struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAC\0AAAB Hello\\sthere!\n", 29);
return msg == NULL;
});
EXO_TEST(adc_message_add_arg_1, {
struct adc_message* msg = adc_msg_create(test_string1);
adc_msg_add_argument(msg, "XXwtf?");
@@ -491,13 +514,22 @@ EXO_TEST(adc_message_update_3, {
return updater2 != NULL;
});
extern void update_user_info(struct user* u, struct adc_message* cmd);
EXO_TEST(adc_message_update_4, {
update_user_info(g_user, updater2);
user_update_info(g_user, updater2);
return strlen(g_user->info->cache) == 159;
});
EXO_TEST(adc_message_update_4_cleanup, {
adc_msg_free(updater1);
updater1 = 0;
adc_msg_free(updater2);
updater2 = 0;
adc_msg_free(g_user->info);
g_user->info = 0;
return 1;
});
EXO_TEST(adc_message_empty_1, {
struct adc_message* msg = adc_msg_parse_verify(g_user, test_string2, strlen(test_string2));
int ok = adc_msg_is_empty(msg) == 0;
@@ -519,3 +551,10 @@ EXO_TEST(adc_message_empty_3, {
return ok;
});
EXO_TEST(adc_message_last, {
hub_free(g_user);
g_user = 0;
return g_user == 0;
});

View File

@@ -100,4 +100,12 @@ EXO_TEST(utf8_valid_3, { return is_valid_utf8("0123456789"); });
EXO_TEST(utf8_valid_4, { return is_valid_utf8( (char[]) { 0x65, 0x00} ); });
EXO_TEST(utf8_valid_5, { return !is_valid_utf8( (char[]) { 0xD8, 0x00} ); });
EXO_TEST(utf8_valid_6, { return is_valid_utf8( (char[]) { 0x24, 0x00} ); });
EXO_TEST(utf8_valid_7, { return !is_valid_utf8( (char[]) { 0xC2, 0x24, 0x00} ); });
EXO_TEST(utf8_valid_8, { return is_valid_utf8( (char[]) { 0xC2, 0xA2, 0x00} ); });
EXO_TEST(utf8_valid_9, { return is_valid_utf8( (char[]) { 0xE2, 0x82, 0xAC, 0x00} ); });
EXO_TEST(utf8_valid_10, { return !is_valid_utf8( (char[]) { 0xC2, 0x32, 0x00} ); });
EXO_TEST(utf8_valid_11, { return !is_valid_utf8( (char[]) { 0xE2, 0x82, 0x32, 0x00} ); });
EXO_TEST(utf8_valid_12, { return !is_valid_utf8( (char[]) { 0xE2, 0x32, 0x82, 0x00} ); });

138
autotest/test_sid.tcc Normal file
View File

@@ -0,0 +1,138 @@
#include <uhub.h>
static struct sid_pool* sid_pool = 0;
struct dummy_user
{
sid_t sid;
};
static struct dummy_user* last = 0;
sid_t last_sid = 0;
EXO_TEST(sid_create_pool, {
sid_pool = sid_pool_create(4);
return sid_pool != 0;
});
EXO_TEST(sid_check_0a, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
return user == 0;
});
EXO_TEST(sid_check_0b, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 5);
return user == 0;
});
EXO_TEST(sid_alloc_1, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last = user;
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_1a, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last == user;
});
EXO_TEST(sid_check_1b, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid+1);
return user == 0;
});
EXO_TEST(sid_alloc_2, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_2, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last != user;
});
EXO_TEST(sid_alloc_3, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_3, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last != user;
});
EXO_TEST(sid_alloc_4, {
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
last_sid = user->sid;
return (user->sid > 0 && user->sid < 1048576);
});
EXO_TEST(sid_check_4, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
return last != user;
});
EXO_TEST(sid_alloc_5, {
struct dummy_user user;
sid_t sid;
sid = sid_alloc(sid_pool, (struct hub_user*) &user);
return sid == 0;
});
EXO_TEST(sid_check_6, {
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
return user == 0;
});
EXO_TEST(sid_list_all_1, {
sid_t s;
size_t n = 0;
int ok = 1;
for (s = last->sid; s <= last_sid; s++)
{
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, s);
if (s != (user ? user->sid : -1))
{
ok = 0;
break;
}
n++;
}
return ok && n == 4;
});
#define FREE_SID(N) \
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, N); \
sid_free(sid_pool, N); \
hub_free(user); \
return sid_lookup(sid_pool, N) == NULL;
EXO_TEST(sid_remove_1, {
FREE_SID(2);
});
EXO_TEST(sid_remove_2, {
FREE_SID(1);
});
EXO_TEST(sid_remove_3, {
FREE_SID(4);
});
EXO_TEST(sid_remove_4, {
FREE_SID(3);
});
EXO_TEST(sid_destroy_pool, {
sid_pool_destroy(sid_pool);
sid_pool = 0;
return sid_pool == 0;
});

119
autotest/test_timer.tcc Normal file
View File

@@ -0,0 +1,119 @@
#include <uhub.h>
#define MAX_EVENTS 15
static struct timeout_queue* g_queue;
static time_t g_now;
static size_t g_max;
static struct timeout_evt g_events[MAX_EVENTS];
static size_t g_triggered;
static void timeout_cb(struct timeout_evt* t)
{
g_triggered++;
}
/*
typedef void (*timeout_evt_cb)(struct timeout_evt*);
struct timeout_evt
{
time_t timestamp;
timeout_evt_cb callback;
void* ptr;
struct timeout_evt* prev;
struct timeout_evt* next;
};
void timeout_evt_initialize(struct timeout_evt*, timeout_evt_cb, void* ptr);
void timeout_evt_reset(struct timeout_evt*);
int timeout_evt_is_scheduled(struct timeout_evt*);
struct timeout_queue
{
time_t last;
size_t max;
struct timeout_evt** events;
};
void timeout_queue_initialize(struct timeout_queue*, time_t now, size_t max);
void timeout_queue_shutdown(struct timeout_queue*);
size_t timeout_queue_process(struct timeout_queue*, time_t now);
void timeout_queue_insert(struct timeout_queue*, struct timeout_evt*, size_t seconds);
void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*);
void timeout_queue_reschedule(struct timeout_queue*, struct timeout_evt*, size_t seconds);
size_t timeout_queue_get_next_timeout(struct timeout_queue*, time_t now);
*/
EXO_TEST(timer_setup,{
size_t n;
g_queue = hub_malloc_zero(sizeof(struct timeout_queue));
g_now = 0;
g_max = 5;
g_triggered = 0;
timeout_queue_initialize(g_queue, g_now, g_max);
memset(g_events, 0, sizeof(g_events));
for (n = 0; n < MAX_EVENTS; n++)
{
timeout_evt_initialize(&g_events[n], timeout_cb, &g_events[n]);
}
return g_queue != NULL;
});
EXO_TEST(timer_check_timeout_0,{
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
});
EXO_TEST(timer_add_event_1,{
timeout_queue_insert(g_queue, &g_events[0], 2);
return g_events[0].prev != NULL;
});
EXO_TEST(timer_check_timeout_1,{
return timeout_queue_get_next_timeout(g_queue, g_now) == 2;
});
EXO_TEST(timer_remove_event_1,{
timeout_queue_remove(g_queue, &g_events[0]);
return g_events[0].prev == NULL;
});
EXO_TEST(timer_check_timeout_2,{
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
});
/* test re-removing an event - should not crash! */
EXO_TEST(timer_remove_event_1_no_crash,{
timeout_queue_remove(g_queue, &g_events[0]);
return g_events[0].prev == NULL;
});
EXO_TEST(timer_add_5_events_1,{
timeout_queue_insert(g_queue, &g_events[0], 0);
timeout_queue_insert(g_queue, &g_events[1], 1);
timeout_queue_insert(g_queue, &g_events[2], 2);
timeout_queue_insert(g_queue, &g_events[3], 3);
timeout_queue_insert(g_queue, &g_events[4], 4);
return (g_events[0].prev != NULL &&
g_events[1].prev != NULL &&
g_events[2].prev != NULL &&
g_events[3].prev != NULL &&
g_events[4].prev != NULL);
});
EXO_TEST(timer_check_5_events_1,{
return timeout_queue_get_next_timeout(g_queue, g_now) == 1;
});
EXO_TEST(timer_process_5_events_1,{
g_now = 4;
return timeout_queue_process(g_queue, g_now) == g_triggered;
});

View File

@@ -0,0 +1,109 @@
#include <uhub.h>
#define MAX_USERS 64
static struct hub_info um_hub;
static struct hub_user um_user[MAX_USERS];
// static struct net_connection um_cons[MAX_USERS];
EXO_TEST(um_test_setup, {
int i = 0;
memset(&um_hub, 0, sizeof(um_hub));
for (i = 0; i < MAX_USERS; i++)
{
/* memset(&um_cons[i], 0, sizeof(struct net_connection));
um_cons[i].sd = -1;
memset(&um_user[i], 0, sizeof(struct hub_user));
um_user[i].id.sid = i+1;
um_user[i].connection = &um_cons[i];*/
}
return 1;
});
EXO_TEST(um_init_1, {
return uman_init(0) != 0;
});
EXO_TEST(um_init_2, {
return uman_init(&um_hub) == 0;
});
EXO_TEST(um_shutdown_1, {
return uman_shutdown(0) == -1;
});
EXO_TEST(um_shutdown_2, {
return uman_shutdown(&um_hub) == 0;
});
EXO_TEST(um_shutdown_3, {
return uman_shutdown(&um_hub) == -1;
});
EXO_TEST(um_init_3, {
return uman_init(&um_hub) == 0;
});
EXO_TEST(um_add_1, {
return uman_add(&um_hub, &um_user[0]) == 0;
});
EXO_TEST(um_size_1, {
return hub_get_user_count(&um_hub) == 1;
});
EXO_TEST(um_remove_1, {
return uman_remove(&um_hub, &um_user[0]) == 0;
});
EXO_TEST(um_size_2, {
return hub_get_user_count(&um_hub) == 0;
});
EXO_TEST(um_add_2, {
int i;
for (i = 0; i < MAX_USERS; i++)
{
if (uman_add(&um_hub, &um_user[i]) != 0)
return 0;
}
return 1;
});
EXO_TEST(um_size_3, {
return hub_get_user_count(&um_hub) == MAX_USERS;
});
EXO_TEST(um_add_3, {
return uman_add(&um_hub, &um_user[5]) != 0;
});
EXO_TEST(um_remove_2, {
int i;
for (i = 0; i < MAX_USERS; i++)
{
if (uman_remove(&um_hub, &um_user[i]) != 0)
return 0;
}
return 1;
});
/* Last test */
EXO_TEST(um_shutdown_4, {
return uman_shutdown(&um_hub) == 0;
});

20
debian/changelog vendored
View File

@@ -1,5 +1,19 @@
uhub (0.2.6-1) unstable; urgency=low
uhub (0.3.1-1) unstable; urgency=low
* Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
* Updated version number.
-- Jan Vidar Krey <janvidar@extatic.org> Mon 04 Apr 2010 16:44:21 +0200
uhub (0.3.0-2) unstable; urgency=low
* Fixed init.d scripts.
* Fixed lintian warnings.
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 19:02:02 +0100
uhub (0.3.0-1) unstable; urgency=low
* Initial Release.
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 18:59:02 +0100
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 17 Mar 2009 00:38:12 +0100

3
debian/conffiles vendored
View File

@@ -1,3 +0,0 @@
etc/uhub/uhub.conf
etc/uhub/users.conf
etc/uhub/motd.txt

27
debian/control vendored
View File

@@ -1,15 +1,24 @@
Source: uhub
Section: net
Priority: extra
Priority: optional
Maintainer: Jan Vidar Krey <janvidar@extatic.org>
Build-Depends: debhelper (>= 7)
Standards-Version: 3.8.1
Homepage: http://www.extatic.org/uhub/
Build-Depends: debhelper (>= 7.0.0)
Standards-Version: 3.8.3.0
Package: uhub
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: uHub is a high performance peer-to-peer hub for the ADC network.
Its low memory footprint allows it to handle several thousand users on high-end servers,
or a small private hub on embedded hardware.
uHub uses the ADC protocol, and is compatible with DC++, jUCy and other ADC clients.
Depends: ${shlibs:Depends}
Description: High performance ADC p2p hub
uhub is a high performance peer-to-peer hub for the ADC network.
Its low memory footprint allows it to handle several thousand users on
high-end servers, or a small private hub on embedded hardware.
.
Key features:
- High performance and low memory usage
- IPv4 and IPv6 support
- Experimental SSL support (optional)
- Advanced access control support
- Easy configuration
.
Homepage: http://www.uhub.org/

20
debian/copyright vendored
View File

@@ -1,9 +1,19 @@
Copyright:
uhub - High performance ADC p2p hub.
Copyright (C) 2010 Jan Vidar Krey <janvidar@extatic.org>
Copyright (C) 2008-2009 Jan Vidar Krey <janvidar@extatic.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
License:
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Licensed under the GPL version 3,
see `/usr/share/common-licenses/GPL-3'.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
On Debian GNU/Linux systems, the complete text of the GNU General Public
License can be found in `/usr/share/common-licenses/GPL'.

1
debian/dirs vendored
View File

@@ -1 +0,0 @@
usr/bin

3
debian/docs vendored
View File

@@ -1,3 +0,0 @@
BUGS
README
AUTHORS

1
debian/files vendored
View File

@@ -1 +0,0 @@
uhub_0.2.6-1_amd64.deb net extra

157
debian/init.d vendored
View File

@@ -1,157 +0,0 @@
#! /bin/sh
#
# skeleton example file to build /etc/init.d/ scripts.
# This file should be used to construct scripts for /etc/init.d.
#
# Written by Miquel van Smoorenburg <miquels@cistron.nl>.
# Modified for Debian
# by Ian Murdock <imurdock@gnu.ai.mit.edu>.
# Further changes by Javier Fernandez-Sanguino <jfs@debian.org>
#
# Version: @(#)skeleton 1.9 26-Feb-2001 miquels@cistron.nl
#
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/uhub
NAME=uhub
DESC=uhub
test -x $DAEMON || exit 0
LOGDIR=/var/log/uhub
PIDFILE=/var/run/$NAME.pid
DODTIME=1 # Time to wait for the server to die, in seconds
# If this value is set too low you might not
# let some servers to die gracefully and
# 'restart' will not work
# Include uhub defaults if available
if [ -f /etc/default/uhub ] ; then
. /etc/default/uhub
fi
set -e
running_pid()
{
# Check if a given process pid's cmdline matches a given name
pid=$1
name=$2
[ -z "$pid" ] && return 1
[ ! -d /proc/$pid ] && return 1
cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
# Is this the expected child?
[ "$cmd" != "$name" ] && return 1
return 0
}
running()
{
# Check if the process is running looking at /proc
# (works for all users)
# No pidfile, probably no daemon present
[ ! -f "$PIDFILE" ] && return 1
# Obtain the pid and check it against the binary name
pid=`cat $PIDFILE`
running_pid $pid $DAEMON || return 1
return 0
}
force_stop() {
# Forcefully kill the process
[ ! -f "$PIDFILE" ] && return
if running ; then
kill -15 $pid
# Is it really dead?
[ -n "$DODTIME" ] && sleep "$DODTIME"s
if running ; then
kill -9 $pid
[ -n "$DODTIME" ] && sleep "$DODTIME"s
if running ; then
echo "Cannot kill $LABEL (pid=$pid)!"
exit 1
fi
fi
fi
rm -f $PIDFILE
return 0
}
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --pidfile $PIDFILE \
--exec $DAEMON -- $DAEMON_OPTS
if running ; then
echo "$NAME."
else
echo " ERROR."
fi
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile $PIDFILE \
--exec $DAEMON
echo "$NAME."
;;
force-stop)
echo -n "Forcefully stopping $DESC: "
force_stop
if ! running ; then
echo "$NAME."
else
echo " ERROR."
fi
;;
reload)
#
# If the daemon can reload its config files on the fly
# for example by sending it SIGHUP, do it here.
#
# If the daemon responds to changes in its config file
# directly anyway, make this a do-nothing entry.
#
echo "Reloading $DESC configuration files."
start-stop-daemon --stop --signal 1 --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON
#;;
force-reload)
#
# If the "reload" option is implemented, move the "force-reload"
# option to the "reload" entry above. If not, "force-reload" is
# just the same as "restart" except that it does nothing if the
# daemon isn't already running.
# check wether $DAEMON is running. If so, restart
start-stop-daemon --stop --test --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON \
&& $0 restart \
|| exit 0
;;
restart)
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON
[ -n "$DODTIME" ] && sleep $DODTIME
start-stop-daemon --start --quiet --pidfile \
/var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
status)
echo -n "$LABEL is "
if running ; then
echo "running"
else
echo " not running."
exit 1
fi
;;
*)
N=/etc/init.d/$NAME
# echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $N {start|stop|restart|force-reload|status|force-stop}" >&2
exit 1
;;
esac
exit 0

39
debian/postinst vendored
View File

@@ -1,39 +0,0 @@
#!/bin/sh
# postinst script for uhub
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
configure)
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

37
debian/postrm vendored
View File

@@ -1,37 +0,0 @@
#!/bin/sh
# postrm script for uhub
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postrm> `remove'
# * <postrm> `purge'
# * <old-postrm> `upgrade' <new-version>
# * <new-postrm> `failed-upgrade' <old-version>
# * <new-postrm> `abort-install'
# * <new-postrm> `abort-install' <old-version>
# * <new-postrm> `abort-upgrade' <old-version>
# * <disappearer's-postrm> `disappear' <overwriter>
# <overwriter-version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
;;
*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

35
debian/preinst vendored
View File

@@ -1,35 +0,0 @@
#!/bin/sh
# preinst script for uhub
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <new-preinst> `install'
# * <new-preinst> `install' <old-version>
# * <new-preinst> `upgrade' <old-version>
# * <old-preinst> `abort-upgrade' <new-version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
install|upgrade)
;;
abort-upgrade)
;;
*)
echo "preinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

38
debian/prerm vendored
View File

@@ -1,38 +0,0 @@
#!/bin/sh
# prerm script for uhub
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <prerm> `remove'
# * <old-prerm> `upgrade' <new-version>
# * <new-prerm> `failed-upgrade' <old-version>
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
# * <deconfigured's-prerm> `deconfigure' `in-favour'
# <package-being-installed> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
remove|upgrade|deconfigure)
;;
failed-upgrade)
;;
*)
echo "prerm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

88
debian/rules vendored
View File

@@ -1,86 +1,39 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
touch configure-stamp
# export DH_VERBOSE=1
makeopts := DESTDIR=$(shell pwd)/debian/uhub/ \
UHUB_PREFIX=$(shell pwd)/debian/uhub/usr \
RELEASE=YES SILENT=YES
build: build-stamp
build-stamp: configure-stamp
build-stamp:
dh_testdir
make $(makeopts)
touch build-stamp
# Add here commands to compile the package.
$(MAKE)
#docbook-to-man debian/uhub.sgml > uhub.1
touch $@
clean:
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
rm -f build-stamp
make clean
dh_clean
# Add here commands to clean up after the build process.
$(MAKE) clean
binary-indep: build
dh_clean
install: build
binary-arch: build
dh_testdir
dh_testroot
dh_prep
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/uhub.
$(MAKE) DESTDIR=$(CURDIR)/debian/uhub install
# Build architecture-independent files here.
binary-indep: install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: install
dh_testdir
dh_testroot
dh_installchangelogs ChangeLog
$(MAKE) install $(makeopts)
dh_installdocs
dh_installexamples
# dh_install
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_python
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
dh_link
dh_installinit
dh_installlogrotate
dh_installman -A
dh_installchangelogs ChangeLog
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
@@ -88,4 +41,5 @@ binary-arch: install
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure
.PHONY: build clean binary-indep binary-arch binary

12
debian/uhub.default vendored
View File

@@ -1,10 +1,4 @@
# Defaults for uhub initscript
# sourced by /etc/init.d/uhub
# installed at /etc/default/uhub by the maintainer scripts
# uhub - high performance adc hub.
UHUB_ENABLE=0
# Additional options that are passed to the Daemon.
ENABLED=1
LOGFILE="/var/log/uhug.log"
USER=nobody
GROUP=nogroup
DAEMON_OPTS="-f -l ${LOGFILE} -u ${USER} -g {GROUP}"

6
debian/uhub.dirs vendored Normal file
View File

@@ -0,0 +1,6 @@
etc/default
etc/init.d
etc/logrotate.d
etc/uhub
usr/bin
var/log/uhub

5
debian/uhub.docs vendored Normal file
View File

@@ -0,0 +1,5 @@
AUTHORS
README
BUGS
TODO
doc/getstarted.txt

92
debian/uhub.init vendored Normal file
View File

@@ -0,0 +1,92 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: uhub
# Required-Start: $remote_fs $network
# Required-Stop: $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: uhub - High performance ADC p2p hub.
### END INIT INFO
PATH=/sbin:/bin:/usr/sbin:/usr/bin
NAME=uhub
DESC="ADC hub"
DAEMON=/usr/bin/uhub
PIDFILE=/var/run/uhub/uhub.pid
LOGFILE=/var/log/uhub/uhub.log
SCRIPTNAME=/etc/init.d/uhub
DEFAULTFILE=/etc/default/uhub
[ -r $DEFAULTFILE ] && . $DEFAULTFILE
DAEMON_ENABLE="${UHUB_ENABLE}"
DAEMON_OPTS="-l ${LOGFILE} -f -p ${PIDFILE}"
test -x $DAEMON || exit 0
. /lib/lsb/init-functions
ulimit -n 65536
mkdir -p /var/run/uhub/
set -e
case "$1" in
start)
if [ "$DAEMON_ENABLE" != "true" ]; then
log_daemon_msg "Disabled $DESC" $NAME
log_end_msg 0
exit 0
fi
log_daemon_msg "Starting $DESC" $NAME
if ! start-stop-daemon --start --quiet --oknodo \
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
then
log_end_msg 1
else
log_end_msg 0
fi
;;
stop)
log_daemon_msg "Stopping $DESC" $NAME
if start-stop-daemon --quiet --stop --oknodo --retry 30 --oknodo \
--pidfile $PIDFILE --exec $DAEMON
then
rm -f $PIDFILE
log_end_msg 0
else
log_end_msg 1
fi
;;
reload)
log_daemon_msg "Reloading $DESC configuration" $NAME
if start-stop-daemon --stop --signal 2 --oknodo --retry 30 --oknodo \
--quiet --pidfile $PIDFILE --exec $DAEMON
then
if start-stop-daemon --start --quiet \
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS ; then
log_end_msg 0
else
log_end_msg 1
fi
else
log_end_msg 1
fi
;;
restart|force-reload)
$0 stop
$0 start
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
exit 1
;;
esac
exit 0

9
debian/uhub.logrotate vendored Normal file
View File

@@ -0,0 +1,9 @@
/var/log/uhub/*.log
{
compress
size 10M
rotate 10
missingok
notifempty
}

1
debian/uhub.manpages vendored Normal file
View File

@@ -0,0 +1 @@
doc/uhub.1

27
debian/uhub.postinst vendored Normal file
View File

@@ -0,0 +1,27 @@
#!/bin/sh
set -e
case "$1" in
configure)
chmod 0750 /var/log/uhub
if [ -x /etc/init.d/uhub ]; then
update-rc.d uhub defaults >/dev/null
if [ -x /usr/sbin/invoke-rc.d ]; then
invoke-rc.d uhub restart
else
/etc/init.d/uhub restart
fi
fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst: error: unknown argument: $1" >&2
exit 1
;;
esac

6
debian/uhub.postrm vendored Normal file
View File

@@ -0,0 +1,6 @@
#!/bin/sh -e
if [ "$1" = purge ]; then
update-rc.d uhub remove >/dev/null
fi

10
debian/uhub.prerm vendored Normal file
View File

@@ -0,0 +1,10 @@
#!/bin/sh -e
if [ "$1" = remove ]; then
if command -v invoke-rc.d >/dev/null 2>&1; then
invoke-rc.d uhub stop || true
else
/etc/init.d/uhub stop
fi
fi

View File

@@ -8,19 +8,13 @@ Prerequisites
Before you try to compile µHub, please make sure the following prerequisites are met.
* GNU make
* gcc > 3.0 (or MinGW on Windows)
* libevent >= 1.3
* Perl 5
Linux and Mac OSX
-----------------
Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD
-------------------------------------------
Simply, run:
% make
FreeBSD, NetBSD and OpenBSD
---------------------------
Use GNU make, not BSD make:
% gmake
If you have an old gcc compiler, try disabling pre-compiled headers like this:
gmake USE_PCH=NO

View File

@@ -43,4 +43,15 @@ if one wishes to run uhub as a specific user using the -u and -g switches.
Example:
% uhub -f -l mylog.txt -u nobody -g nogroup
If you are planning to more than 1024 users on hub, you must increase the max number of file descriptors allowed.
This limit needs to be higher than the configured max_users in uhub.conf.
In linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users)
* soft nofile 4096
* hard nofile 4096
Or, you can use (as root):
% ulimit -n 4096
Your mileage may vary -- Good luck!

101
doc/init.d.RedHat/etc/init.d/uhub Executable file
View File

@@ -0,0 +1,101 @@
#!/bin/sh
#
# chkconfig: - 91 35
# description: Starts and stops the Uhub ( http://www.extatic.org/uhub ) daemons on RHEL\CentOS \
# used to provide p2p network services.
#
# pidfile: /var/run/uhub.pid
# config: /etc/uhub/uhub.conf
# Source function library.
if [ -f /etc/init.d/functions ] ; then
. /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ] ; then
. /etc/rc.d/init.d/functions
else
exit 1
fi
# Avoid using root's TMPDIR
unset TMPDIR
# Source networking configuration.
. /etc/sysconfig/network
if [ -f /etc/sysconfig/uhub ]; then
. /etc/sysconfig/uhub
fi
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 1
# Check that uhub.conf exists.
[ -f /etc/uhub/uhub.conf ] || exit 6
RETVAL=0
start() {
KIND="Uhub"
echo -n $"Starting $KIND services: "
daemon uhub $UHUBOPTIONS
RETVAL=$?
echo ""
return $RETVAL
}
stop() {
KIND="Uhub"
echo -n $"Shutting down $KIND services: "
killproc uhub
RETVAL=$?
echo ""
return $RETVAL
}
restart() {
stop
start
}
reload() {
echo -n $"Reloading uhub.conf / user.conf file: "
killproc uhub -HUP
RETVAL=$?
echo ""
return $RETVAL
}
rhstatus() {
status uhub
RETVAL=$?
if [ $RETVAL -ne 0 ] ; then
return $RETVAL
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
reload)
reload
;;
status)
rhstatus
;;
*)
echo $"Usage: $0 {start|stop|restart|reload|status}"
exit 2
esac
exit $?

View File

@@ -0,0 +1,14 @@
# Log rotate for Uhub
# see man logrotate
#
#
/var/log/uhub.log {
compress
size 10M
rotate 10
missingok
notifempty
}

View File

@@ -0,0 +1,13 @@
# Options to UHUB
# -v Verbose mode. Add more -v's for higher verbosity.
# -q Quiet mode - no output
# -f Fork to background
# -l <file> Log messages to given file (default: stderr)
# -L Log messages to syslog
# -c <file> Specify configuration file (default: /etc/uhub/uhub.conf)
# -S Show configuration parameters, but ignore defaults
# -u <user> Run as given user
# -g <group> Run with given group permissions
# -p <file> Store pid in file (process id)
UHUBOPTIONS=" -u uhub -f -p /var/run/uhub.pid -l /var/log/uhub.log"

5
doc/rules.txt Normal file
View File

@@ -0,0 +1,5 @@
1. rule #1
2. rule #2
3. rule #3
......
34. Rule #34

72
doc/uhub.1 Normal file
View File

@@ -0,0 +1,72 @@
.TH UHUB 1 "March 2009"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
.\" .nh disable hyphenation
.\" .hy enable hyphenation
.\" .ad l left justify
.\" .ad b justify to both left and right margins
.\" .nf disable filling
.\" .fi enable filling
.\" .br insert line break
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
uhub \- a high performance ADC peer-to-peer hub
.SH SYNOPSIS
.B uhub
.RI [ options ]
.SH DESCRIPTION
uHub is a high performance peer-to-peer hub for the ADC network.
Its low memory footprint allows it to handle several thousand users
on high-end servers, or a small private hub on embedded hardware.
.SH "OPTIONS"
.TP
.BI \^\-v
Verbose mode, add more -v's for higher verbosity.
.TP
.BI \^\-q
Quiet mode, if quiet mode is enabled no output or logs are made.
.TP
.BI \^\-f
Fork uhub to background in order to run it as a daemon.
.TP
.BI \^\-l " logfile"
Log messages to the given logfile (default: stderr)
.TP
.BI \^\-L
Log messages to syslog.
.TP
.BI \^\-c " config"
Specify configuration file (default: /etc/uhub/uhub.conf)
.TP
.BI \^\-C
Check configuration files and return. Will print either \"OK\" or \"ERROR\".
.TP
.BI \^\-s
Show all configuration parameters. In a format that is compatible with
the configuration files.
.TP
.BI \^\-S
Show all non-default configuration parameters.
.TP
.BI \^\-h
Show the help message.
.TP
.BI \^\-u " user"
Drop privileges and run as the given user.
.TP
.BI \^\-g " group"
Drop privileges and run with the given group permissions.
.TP
.BI \^\-V
Show the version number
.SH EXAMPLES
To run uhub as a daemon, and log to a file:
.TP
.B uhub " -f -l /var/log/uhub/uhub.log"
.SH AUTHOR
This program was written by Jan Vidar Krey <janvidar@extatic.org>
.SH "BUG REPORTS"
If you find a bug in uhub please report it to
.B http://bugs.extatic.org/

View File

@@ -4,7 +4,8 @@
#
# This file is read only to the uhub deamon, and if you
# make changes to it while uhub is running you can send a
# HUP signal to it, to reparse configuration (only on UNIX).
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
# All configuration directives: http://www.uhub.org/config.php
# Bind to this port and address
# server_bind_addr=any means listen to "::" if IPv6 is supported
@@ -12,12 +13,18 @@
server_port=1511
server_bind_addr=any
# Alternative server ports
# server_alt_ports = 1512, 1513
# The maximum amount of users allowed on the hub.
max_users=500
# If 1, will show a "This hub is running uhub/version".
# If 1, will show a "Powered by uHub/{VERSION}".
show_banner=1
# If enabled then operating system and cpu architecture is part of the banner.
show_banner_sys_info=1
# Allow only registered users on the hub if set to 1.
registered_users_only=0
@@ -38,6 +45,47 @@ file_acl=/etc/uhub/users.conf
# Normally this message is sent to clients when connecting.
file_motd=/etc/uhub/motd.txt
# This file can contain a rules of the hub.
# Normally this message is sent to clients when write in chat !rules
file_rules=/etc/uhub/rules.txt
# Slots/share/hubs limits
limit_max_hubs_user = 0
limit_max_hubs_reg = 0
limit_max_hubs_op = 0
limit_max_hubs = 0
limit_min_hubs_user = 0
limit_min_hubs_reg = 0
limit_min_hubs_op = 0
limit_min_share = 0
# Example:
# To require users to share at least 1 GB in order to enter the hub:
# limit_min_share = 1024
limit_max_share = 0
limit_min_slots = 0
limit_max_slots = 0
# Flood control support:
# set the interval to 5 seconds
flood_ctl_interval = 5
# Then the maximum chat, connect, search, updates etc will be measured over 5 seconds.
# So, 3 chat messages per 5 seconds allowed.
flood_ctl_chat=3
flood_ctl_connect=20
flood_ctl_search=1
flood_ctl_update=2
flood_ctl_extras=5
# chat control
# if chat_is_privileged=yes only registered users may write in main chat
chat_is_privileged = no
# if chat_only = yes then search and transfer functionality is disabled for
# non-operator users.
chat_only = no
# Configure status message as sent to clients in different circumstances.
msg_hub_full = Hub is full
msg_hub_disabled = Hub is disabled
@@ -61,6 +109,23 @@ msg_ban_permanently = Banned permanently
msg_ban_temporarily = Banned temporarily
msg_auth_invalid_password = Password is wrong
msg_auth_user_not_found = User not found in password database
msg_user_share_size_low = User is not sharing enough
msg_user_share_size_high = User is sharing too much
msg_user_slots_low = User have too few upload slots
msg_user_slots_high = User have too many upload slots
msg_user_hub_limit_low = User is on too few hubs
msg_user_hub_limit_high = User is on too many hubs
msg_error_no_memory = No memory
msg_user_flood_chat = Chat flood detected, messages are dropped.
msg_user_flood_connect = Connect flood detected, connection refused.
msg_user_flood_search = Search flood detected, search is stopped.
msg_user_flood_update = Update flood detected.
msg_user_flood_extras = Flood detected.
# If a client that supports ADC but not a compatible hash algorithm (tiger),
# then the hub cannot accept the client:
msg_proto_no_common_hash = No common hash algorithm.
# Message to be shown to old clients using an older version of ADC than ADC/1.0
msg_proto_obsolete_adc0 = Client is using an obsolete ADC protocol version.

42
doc/uhub.ebuild Normal file
View File

@@ -0,0 +1,42 @@
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
inherit eutils
if [ "$PV" != "9999" ]; then
SRC_URI="http://www.extatic.org/downloads/uhub/${P}-src.tar.bz2"
KEYWORDS="~amd64 ~x86"
else
inherit git
SRC_URI=""
EGIT_REPO_URI="git://github.com/janvidar/uhub.git"
KEYWORDS=""
fi
EAPI="2"
DESCRIPTION="High performance ADC hub"
HOMEPAGE="http://www.uhub.org/"
LICENSE="GPL-3"
SLOT="0"
IUSE="+ssl"
DEPEND="=dev-lang/perl-5*
ssl? ( >=dev-libs/openssl-0.9.8 )
"
RDEPEND="${DEPEND}"
src_compile() {
$opts=""
use ssl && opts="USE_SSL=YES $opts"
emake $opts
}
src_install() {
dodir /usr/bin
dodir /etc/uhub
emake DESTDIR="${D}" UHUB_PREFIX="${D}/usr" install || die "install failed"
newinitd doc/uhub.gentoo.rc uhub || newinitd ${FILESDIR}/uhub.rc uhub
}
pkg_postinst() {
enewuser uhub
}

85
doc/uhub.spec Normal file
View File

@@ -0,0 +1,85 @@
Summary: High performance ADC p2p hub.
Name: uhub
Version: 0.3.1
Release: 3
License: GPLv3
Group: Networking/File transfer
Source: uhub-%{version}.tar.gz
URL: http://www.uhub.org
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
%description
uhub is a high performance peer-to-peer hub for the ADC network.
Its low memory footprint allows it to handle several thousand users on
high-end servers, or a small private hub on embedded hardware.
Key features:
- High performance and low memory usage
- IPv4 and IPv6 support
- Experimental SSL support (optional)
- Advanced access control support
- Easy configuration
%prep
%setup -q -n %{name}-%{version}
%build
echo RPM_BUILD_ROOT = $RPM_BUILD_ROOT
make
%install
mkdir -p $RPM_BUILD_ROOT/usr/bin
mkdir -p $RPM_BUILD_ROOT/etc/uhub
mkdir -p $RPM_BUILD_ROOT/etc/init.d
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1
install uhub $RPM_BUILD_ROOT/usr/bin/
> doc/motd.txt
install -m644 doc/uhub.conf doc/users.conf doc/rules.txt doc/motd.txt $RPM_BUILD_ROOT/etc/uhub
install doc/init.d.RedHat/etc/init.d/uhub $RPM_BUILD_ROOT/etc/init.d
install -m644 doc/init.d.RedHat/etc/sysconfig/uhub $RPM_BUILD_ROOT/etc/sysconfig/
install -m644 doc/init.d.RedHat/etc/logrotate.d/uhub $RPM_BUILD_ROOT/etc/logrotate.d/
/bin/gzip -9c doc/uhub.1 > doc/uhub.1.gz &&
install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1
%files
%defattr(-,root,root)
%doc AUTHORS BUGS COPYING ChangeLog README TODO doc/Doxyfile doc/architecture.txt doc/compile.txt doc/extensions.txt doc/getstarted.txt doc/uhub.dot
%config(noreplace) /etc/uhub/uhub.conf
#%{_sysconfdir}/uhub/uhub.conf
%config(noreplace) %{_sysconfdir}/uhub/users.conf
%config(noreplace) %{_sysconfdir}/uhub/motd.txt
%config(noreplace) %{_sysconfdir}/uhub/rules.txt
%{_sysconfdir}/init.d/uhub
%config(noreplace) %{_sysconfdir}/logrotate.d/uhub
%config(noreplace) %{_sysconfdir}/sysconfig/uhub
/usr/share/man/man1/uhub.1.gz
%{_bindir}/uhub
%clean
rm -rf $RPM_BUILD_ROOT
%post
/sbin/chkconfig --add uhub
if [ $1 -gt 1 ] ; then
/etc/rc.d/init.d/uhub restart >/dev/null || :
fi
# need more informations about add services and users in system
/usr/sbin/adduser -M -d /tmp -G nobody -s /sbin/nologin -c 'The Uhub ADC p2p hub Daemon' uhub >/dev/null 2>&1 ||:
%changelog
* Tue Jan 31 2010 E_zombie
- change GROUP
- chmod for files
- add postinstall scripts
- fix "License"
* Tue Jan 26 2010 E_zombie
- first .spec release

View File

@@ -12,8 +12,8 @@
# 'ban_cid' - banned user by cid
# Administrator
user_admin Dj_Offset:uhub
user_op janvidar:password
# user_admin userA:password1
# user_op userB:password2
# We don't want users with these names
deny_nick Hub-Security

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,16 +26,51 @@
uhub_assert(X->capacity); \
uhub_assert(X->length); \
uhub_assert(X->length <= X->capacity); \
uhub_assert(X->length == strlen(X->cache)); \
uhub_assert(X->references >= 0);
uhub_assert(X->references > 0); \
uhub_assert(X->length == strlen(X->cache));
#define ADC_MSG_NULL_ON_FREE
#else
#define ADC_MSG_ASSERT(X) do { } while(0)
#endif
#endif /* DEBUG */
#ifdef MSG_MEMORY_DEBUG
#undef msg_malloc
#undef msg_malloc_zero
#undef msg_free
static void* msg_malloc(size_t size)
{
void* ptr = valloc(size);
LOG_MEMORY("msg_malloc: %p %d", ptr, (int) size);
return ptr;
}
static void* msg_malloc_zero(size_t size)
{
void* ptr = msg_malloc(size);
memset(ptr, 0, size);
return ptr;
}
static void msg_free(void* ptr)
{
LOG_MEMORY("msg_free: %p", ptr);
hub_free(ptr);
}
#else
#define msg_malloc(X) hub_malloc(X)
#define msg_malloc_zero(X) hub_malloc_zero(X)
#define msg_free(X) hub_free(X)
#endif /* MSG_MEMORY_DEBUG */
struct adc_message* adc_msg_incref(struct adc_message* msg)
{
#ifndef ADC_MESSAGE_INCREF
msg->references++;
#ifdef MSG_MEMORY_DEBUG
adc_msg_protect(msg);
#endif
return msg;
#else
struct adc_message* copy = adc_msg_copy(msg);
@@ -55,24 +90,25 @@ static int adc_msg_grow(struct adc_message* msg, size_t size)
if (msg->capacity > size)
return 1;
/* Make sure we align our data */
newsize = size;
newsize += 2; /* termination */
newsize += (newsize % sizeof(size_t)); /* alignment padding */
buf = hub_malloc_zero(newsize);
buf = msg_malloc_zero(newsize);
if (!buf)
return 0;
if (msg->cache)
{
memcpy(buf, msg->cache, msg->length);
hub_free(msg->cache);
msg_free(msg->cache);
}
msg->cache = buf;
msg->capacity = newsize;
return 1;
}
@@ -84,10 +120,10 @@ static int adc_msg_cache_append(struct adc_message* msg, const char* string, siz
/* FIXME: OOM! */
return 0;
}
memcpy(&msg->cache[msg->length], string, len);
adc_msg_set_length(msg, msg->length + len);
assert(msg->capacity > msg->length);
msg->cache[msg->length] = 0;
return 1;
@@ -145,32 +181,36 @@ int adc_msg_is_empty(struct adc_message* msg)
void adc_msg_free(struct adc_message* msg)
{
if (!msg) return;
ADC_MSG_ASSERT(msg);
if (msg->references > 0)
msg->references--;
if (msg->references == 0)
{
msg->references--;
}
else
{
hub_free(msg->cache);
#ifdef ADC_MSG_NULL_ON_FREE
if (msg->cache)
{
*msg->cache = 0;
}
#endif
msg_free(msg->cache);
if (msg->feature_cast_include)
{
list_clear(msg->feature_cast_include, &hub_free);
list_destroy(msg->feature_cast_include);
msg->feature_cast_include = 0;
}
if (msg->feature_cast_exclude)
{
list_clear(msg->feature_cast_exclude, &hub_free);
list_destroy(msg->feature_cast_exclude);
msg->feature_cast_exclude = 0;
}
hub_free(msg);
msg_free(msg);
}
}
@@ -178,11 +218,11 @@ void adc_msg_free(struct adc_message* msg)
struct adc_message* adc_msg_copy(const struct adc_message* cmd)
{
char* tmp = 0;
struct adc_message* copy = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
struct adc_message* copy = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
if (!copy) return NULL; /* OOM */
ADC_MSG_ASSERT(cmd);
/* deep copy */
copy->cmd = cmd->cmd;
copy->source = cmd->source;
@@ -191,10 +231,10 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
copy->length = cmd->length;
copy->capacity = 0;
copy->priority = cmd->priority;
copy->references = 0;
copy->references = 1;
copy->feature_cast_include = 0;
copy->feature_cast_exclude = 0;
if (cmd->cache)
{
if (!adc_msg_grow(copy, copy->length))
@@ -205,7 +245,7 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
memcpy(copy->cache, cmd->cache, cmd->length);
copy->cache[copy->length] = 0;
}
if (cmd->feature_cast_include)
{
copy->feature_cast_include = list_create();
@@ -216,7 +256,7 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
tmp = list_get_next(cmd->feature_cast_include);
}
}
if (cmd->feature_cast_exclude)
{
copy->feature_cast_exclude = list_create();
@@ -227,14 +267,14 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
tmp = list_get_next(cmd->feature_cast_exclude);
}
}
ADC_MSG_ASSERT(copy);
return copy;
}
struct adc_message* adc_msg_parse_verify(struct user* u, const char* line, size_t length)
struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* line, size_t length)
{
struct adc_message* command = adc_msg_parse(line, length);
@@ -243,6 +283,7 @@ struct adc_message* adc_msg_parse_verify(struct user* u, const char* line, size_
if (command->source && (!u || command->source != u->id.sid))
{
LOG_DEBUG("Command does not match user's SID (command->source=%d, user->id.sid=%d)", command->source, (u ? u->id.sid : 0));
adc_msg_free(command);
return 0;
}
@@ -253,7 +294,7 @@ struct adc_message* adc_msg_parse_verify(struct user* u, const char* line, size_
struct adc_message* adc_msg_parse(const char* line, size_t length)
{
struct adc_message* command = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
struct adc_message* command = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
char prefix = line[0];
size_t n = 0;
char temp_sid[5];
@@ -264,6 +305,13 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
if (command == NULL)
return NULL; /* OOM */
if (!is_printable_utf8(line, length))
{
LOG_DEBUG("Dropped message with non-printable UTF-8 characters.");
msg_free(command);
return NULL;
}
if (line[length-1] != '\n')
{
need_terminate = 1;
@@ -271,20 +319,21 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
if (!adc_msg_grow(command, length + need_terminate))
{
hub_free(command);
msg_free(command);
return NULL; /* OOM */
}
adc_msg_set_length(command, length + need_terminate);
memcpy(command->cache, line, length);
/* Ensure we are zero terminated */
command->cache[length] = 0;
command->cache[length+need_terminate] = 0;
command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
command->priority = 0;
command->references = 1;
switch (prefix)
{
case 'U':
@@ -292,12 +341,12 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
/* these should never be seen on a hub */
ok = 0;
break;
case 'I':
case 'H':
ok = (length > 3);
break;
case 'B':
ok = (length > 8 &&
is_space(line[4]) &&
@@ -305,18 +354,18 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
is_valid_base32_char(line[6]) &&
is_valid_base32_char(line[7]) &&
is_valid_base32_char(line[8]));
if (!ok) break;
temp_sid[0] = line[5];
temp_sid[1] = line[6];
temp_sid[2] = line[7];
temp_sid[3] = line[8];
temp_sid[4] = '\0';
command->source = string_to_sid(temp_sid);
break;
case 'F':
ok = (length > 8 &&
is_space(line[4]) &&
@@ -324,30 +373,30 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
is_valid_base32_char(line[6]) &&
is_valid_base32_char(line[7]) &&
is_valid_base32_char(line[8]));
if (!ok) break;
temp_sid[0] = line[5];
temp_sid[1] = line[6];
temp_sid[2] = line[7];
temp_sid[3] = line[8];
temp_sid[4] = '\0';
command->source = string_to_sid(temp_sid);
/* Create feature cast lists */
command->feature_cast_include = list_create();
command->feature_cast_exclude = list_create();
if (!command->feature_cast_include || !command->feature_cast_exclude)
{
list_destroy(command->feature_cast_include);
list_destroy(command->feature_cast_exclude);
hub_free(command->cache);
hub_free(command);
msg_free(command->cache);
msg_free(command);
return NULL; /* OOM */
}
n = 10;
while (line[n] == '+' || line[n] == '-')
{
@@ -355,21 +404,20 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
feature_cast_list = command->feature_cast_include;
else
feature_cast_list = command->feature_cast_exclude;
temp_sid[0] = line[n++];
temp_sid[1] = line[n++];
temp_sid[2] = line[n++];
temp_sid[3] = line[n++];
temp_sid[4] = '\0';
list_append(feature_cast_list, hub_strdup(temp_sid));
}
if (n == 10)
ok = 0;
break;
case 'D':
case 'E':
ok = (length > 13 &&
@@ -383,41 +431,41 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
is_valid_base32_char(line[11]) &&
is_valid_base32_char(line[12]) &&
is_valid_base32_char(line[13]));
if (!ok) break;
temp_sid[0] = line[5];
temp_sid[1] = line[6];
temp_sid[2] = line[7];
temp_sid[3] = line[8];
temp_sid[4] = '\0';
command->source = string_to_sid(temp_sid);
temp_sid[0] = line[10];
temp_sid[1] = line[11];
temp_sid[2] = line[12];
temp_sid[3] = line[13];
temp_sid[4] = '\0';
command->target = string_to_sid(temp_sid);
break;
default:
ok = 0;
}
if (need_terminate)
{
command->cache[length] = '\n';
}
if (!ok)
{
adc_msg_free(command);
return NULL;
}
/* At this point the arg_offset should point to a space, or the end of message */
n = adc_msg_get_arg_offset(command);
if (command->cache[n] == ' ')
@@ -426,29 +474,27 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
}
else if (command->cache[n] == '\n') ok = 1;
else ok = 0;
if (!ok)
{
adc_msg_free(command);
return NULL;
}
ADC_MSG_ASSERT(command);
return command;
}
struct adc_message* adc_msg_create(const char* line)
{
return adc_msg_parse_verify(NULL, line, strlen(line));
return adc_msg_parse(line, strlen(line));
}
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
{
struct adc_message* msg = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
if (!msg)
return NULL; /* OOM */
@@ -456,10 +502,10 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
if (!adc_msg_grow(msg, size+1))
{
hub_free(msg);
msg_free(msg);
return NULL; /* OOM */
}
if (fourcc)
{
msg->cache[0] = (char) ((fourcc >> 24) & 0xff);
@@ -467,15 +513,15 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
msg->cache[2] = (char) ((fourcc >> 8) & 0xff);
msg->cache[3] = (char) ((fourcc ) & 0xff);
msg->cache[4] = '\n';
/* Ensure we are zero terminated */
adc_msg_set_length(msg, 5);
msg->cache[msg->length] = 0;
}
msg->cmd = fourcc;
msg->priority = 0;
msg->references = 1;
return msg;
}
@@ -511,7 +557,6 @@ int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix_[2]
{
temp_len = &end[0] - &start[0]; // strlen(start);
/* hub_log(log_trace, " length=%d", (int) (temp_len)); */
endlen = strlen(end);
memmove(start, end, endlen);
@@ -543,7 +588,7 @@ int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix_[2])
int arg_offset = adc_msg_get_arg_offset(cmd);
ADC_MSG_ASSERT(cmd);
start = memmem(&cmd->cache[arg_offset], (cmd->length - arg_offset), prefix, 3);
while (start)
{
@@ -553,7 +598,7 @@ int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix_[2])
else
start = NULL;
}
return count;
}
@@ -566,25 +611,25 @@ char* adc_msg_get_named_argument(struct adc_message* cmd, const char prefix_[2])
size_t length;
char prefix[4] = { ' ', prefix_[0], prefix_[1], '\0' };
int arg_offset = adc_msg_get_arg_offset(cmd);
ADC_MSG_ASSERT(cmd);
start = memmem(&cmd->cache[arg_offset], cmd->length - arg_offset, prefix, 3);
if (!start)
return NULL;
start = &start[3];
end = strchr(start, ' ');
if (!end) end = &cmd->cache[cmd->length];
length = &end[0] - &start[0];
argument = hub_strndup(start, length);
if (length > 0 && argument[length-1] == '\n')
{
argument[length-1] = 0;
}
return argument;
}
@@ -602,9 +647,9 @@ int adc_msg_replace_named_argument(struct adc_message* cmd, const char prefix[2]
{
return -1;
}
ADC_MSG_ASSERT(cmd);
return 0;
}
@@ -622,7 +667,7 @@ void adc_msg_terminate(struct adc_message* cmd)
void adc_msg_unterminate(struct adc_message* cmd)
{
ADC_MSG_ASSERT(cmd);
if (cmd->length > 0 && cmd->cache[cmd->length-1] == '\n')
{
cmd->length--;
@@ -635,9 +680,9 @@ int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], co
int ret = 0;
if (!string)
return -1;
ADC_MSG_ASSERT(cmd);
adc_msg_unterminate(cmd);
adc_msg_cache_append(cmd, " ", 1);
adc_msg_cache_append(cmd, prefix, 2);
@@ -646,11 +691,32 @@ int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], co
return ret;
}
int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string)
{
char* escaped = adc_msg_escape(string);
int ret = adc_msg_add_named_argument(cmd, prefix, escaped);
hub_free(escaped);
return ret;
}
int adc_msg_add_named_argument_int(struct adc_message* cmd, const char prefix[2], int num)
{
const char* s = uhub_itoa(num);
int ret = adc_msg_add_named_argument(cmd, prefix, s);
return ret;
}
int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix[2], uint64_t num)
{
const char* s = uhub_ulltoa(num);
int ret = adc_msg_add_named_argument(cmd, prefix, s);
return ret;
}
int adc_msg_add_argument(struct adc_message* cmd, const char* string)
{
ADC_MSG_ASSERT(cmd);
adc_msg_unterminate(cmd);
adc_msg_cache_append(cmd, " ", 1);
adc_msg_cache_append(cmd, string, strlen(string));
@@ -665,16 +731,15 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
char* end;
char* argument;
int count = 0;
ADC_MSG_ASSERT(cmd);
adc_msg_unterminate(cmd);
start = strchr(&cmd->cache[adc_msg_get_arg_offset(cmd)-1], ' ');
while (start)
{
end = strchr(&start[1], ' ');
if (count == offset)
{
if (end)
@@ -684,21 +749,27 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
else
{
argument = hub_strdup(&start[1]);
if (argument[strlen(argument)-1] == '\n')
if (argument && argument[strlen(argument)-1] == '\n')
argument[strlen(argument)-1] = 0;
}
if (!argument)
return 0; // FIXME: OOM
if (*argument)
{
adc_msg_terminate(cmd);
return argument;
}
else
{
hub_free(argument);
}
}
count++;
start = end;
}
adc_msg_terminate(cmd);
return 0;
}
@@ -711,11 +782,11 @@ int adc_msg_get_argument_index(struct adc_message* cmd, const char prefix[2])
char* start;
char* end;
int count = 0;
ADC_MSG_ASSERT(cmd);
adc_msg_unterminate(cmd);
start = strchr(&cmd->cache[adc_msg_get_arg_offset(cmd)-1], ' ');
while (start)
{
@@ -768,16 +839,13 @@ int adc_msg_unescape_length(const char* str)
}
char* adc_msg_unescape(const char* string)
{
char* new_string = hub_malloc(adc_msg_unescape_length(string)+1);
char* new_string = msg_malloc(adc_msg_unescape_length(string)+1);
char* ptr = (char*) new_string;
char* str = (char*) string;
int escaped = 0;
while (*str)
{
if (escaped) {
@@ -789,14 +857,12 @@ char* adc_msg_unescape(const char* string)
*ptr++ = '\n';
else
*ptr++ = *str;
escaped = 0;
} else {
if (*str == '\\')
escaped = 1;
else
*ptr++ = *str;
}
str++;
}

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@
#ifndef HAVE_UHUB_COMMAND_H
#define HAVE_UHUB_COMMAND_H
struct user;
struct hub_user;
struct adc_message
{
@@ -70,7 +70,7 @@ extern struct adc_message* adc_msg_copy(const struct adc_message* cmd);
* The message is only considered valid if the user who sent it
* is the rightful origin of the message.
*/
extern struct adc_message* adc_msg_parse_verify(struct user* u, const char* string, size_t length);
extern struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* string, size_t length);
/**
* This will parse 'string' and return it as a adc_message struct, or
@@ -173,6 +173,22 @@ extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
*/
extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
/**
* Append a string as a named argument.
* The string will automatcally be escaped, if you do not wish to escape th string use adc_msg_add_named_argument() instead.
*
* @arg prefix a 2 character argument prefix
* @arg string must NOT be escaped
* @return 0 if successful, or -1 if an error occured (out of memory).
*/
extern int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string);
/**
* Append an integer as a named argument.
*/
extern int adc_msg_add_named_argument_int(struct adc_message* cmd, const char prefix[2], int integer);
extern int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix[2], uint64_t num);
/**
* Convert a ADC command escaped string to a regular string.
* @return string or NULL if out of memory

154
src/adc/sid.c Normal file
View File

@@ -0,0 +1,154 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
const char* BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
char* sid_to_string(sid_t sid_)
{
static char t_sid[5];
sid_t sid = (sid_ & 0xFFFFF); /* 20 bits only */
sid_t A, B, C, D = 0;
D = (sid % 32);
sid = (sid - D) / 32;
C = (sid % 32);
sid = (sid - C) / 32;
B = (sid % 32);
sid = (sid - B) / 32;
A = (sid % 32);
t_sid[0] = BASE32_ALPHABET[A];
t_sid[1] = BASE32_ALPHABET[B];
t_sid[2] = BASE32_ALPHABET[C];
t_sid[3] = BASE32_ALPHABET[D];
t_sid[4] = 0;
return t_sid;
}
sid_t string_to_sid(const char* sid)
{
sid_t nsid = 0;
sid_t n, x;
sid_t factors[] = { 32768, 1024, 32, 1};
if (!sid || strlen(sid) != 4) return 0;
for (n = 0; n < 4; n++) {
for (x = 0; x < strlen(BASE32_ALPHABET); x++)
if (sid[n] == BASE32_ALPHABET[x]) break;
if (x == 32) return 0;
nsid += x * factors[n];
}
return nsid;
}
/*
* Session IDs are heavily reused, since they are a fairly scarce
* resource. Only one (2^10)-1 exist, since it is a four byte base32-encoded
* value and 'AAAA' (0) is reserved for the hub.
*
* Initialize with sid_initialize(), which sets min and max to one, and count to 0.
*
* When allocating a session ID:
* - If 'count' is less than the pool size (max-min), then allocate within the pool
* - Increase the pool size (see below)
* - If unable to do that, hub is really full - don't let anyone in!
*
* When freeing a session ID:
* - If the session ID being freed is 'max', then decrease the pool size by one.
*
*/
struct sid_pool
{
sid_t min;
sid_t max;
sid_t count;
struct hub_user** map;
};
struct sid_pool* sid_pool_create(sid_t max)
{
struct sid_pool* pool = hub_malloc(sizeof(struct sid_pool));
if (!pool)
return 0;
pool->min = 1;
pool->max = max + 1;
pool->count = 0;
pool->map = hub_malloc_zero(sizeof(struct hub_user*) * pool->max);
if (!pool->map)
{
hub_free(pool);
return 0;
}
pool->map[0] = (struct hub_user*) pool; /* hack to reserve the first sid. */
#ifdef DEBUG_SID
LOG_DUMP("SID_POOL: max=%d", (int) pool->max);
#endif
return pool;
}
void sid_pool_destroy(struct sid_pool* pool)
{
#ifdef DEBUG_SID
LOG_DUMP("SID_POOL: destroying, current allocs=%d", (int) pool->count);
#endif
hub_free(pool->map);
hub_free(pool);
}
sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
{
if (pool->count >= (pool->max - pool->min))
{
#ifdef DEBUG_SID
LOG_DUMP("SID_POOL: alloc, sid pool is full.");
#endif
return 0;
}
sid_t n = (++pool->count);
for (; (pool->map[n % pool->max]); n++) ;
#ifdef DEBUG_SID
LOG_DUMP("SID_ALLOC: %d, user=%p", (int) n, user);
#endif
pool->map[n] = user;
return n;
}
void sid_free(struct sid_pool* pool, sid_t sid)
{
#ifdef DEBUG_SID
LOG_DUMP("SID_FREE: %d", (int) sid);
#endif
pool->map[sid] = 0;
pool->count--;
}
struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid)
{
if (!sid || (sid >= pool->max))
return 0;
return pool->map[sid];
}

View File

@@ -22,44 +22,19 @@
#define SID_MAX 1048576
struct sid_pool;
struct hub_user;
extern const char* BASE32_ALPHABET;
extern char* sid_to_string(sid_t sid_);
extern sid_t string_to_sid(const char* sid);
struct sid_map
{
struct user* ptr;
struct sid_map* next;
};
extern struct sid_pool* sid_pool_create(sid_t max);
extern void sid_pool_destroy(struct sid_pool*);
/**
* Session IDs are heavily reused, since they are a fairly scarce
* resource. Only one (2^10)-1 exist, since it is a four byte base32-encoded
* value and 'AAAA' (0) is reserved for the hub.
*
* Initialize with sid_initialize(), which sets min and max to one, and count to 0.
*
* When allocating a session ID:
* - If 'count' is less than the pool size (max-min), then allocate within the pool
* - Increase the pool size (see below)
* - If unable to do that, hub is really full - don't let anyone in!
*
* When freeing a session ID:
* - If the session ID being freed is 'max', then decrease the pool size by one.
*
*/
struct sid_pool
{
sid_t min;
sid_t max;
sid_t count;
struct sid_map* map;
};
extern void sid_initialize(struct sid_pool*);
extern sid_t sid_alloc(struct sid_pool*, struct user*);
extern sid_t sid_alloc(struct sid_pool*, struct hub_user*);
extern void sid_free(struct sid_pool*, sid_t);
extern struct hub_user* sid_lookup(struct sid_pool*, sid_t);

View File

@@ -1,951 +0,0 @@
/**
* An ADC client emulator.
*/
#include "uhub.h"
#define ADC_CLIENTS_DEFAULT 100
#define ADC_MAX_CLIENTS 25000
#define ADC_BUFSIZE 16384
#define ADC_SIDSIZE 4
#define ADC_CID_SIZE 39
#define BIG_BUFSIZE 131072
#define TIGERSIZE 24
#define ADC_HANDSHAKE "HSUP ADBASE ADTIGR\n"
#define ADCRUSH "adcrush/0.2"
#define ADC_NICK "[BOT]adcrush"
#define ADC_DESC "crash\\stest\\sdummy"
struct ADC_client;
static void ADC_client_on_disconnected(struct ADC_client*);
static void ADC_client_on_connected(struct ADC_client*);
static void ADC_client_on_login(struct ADC_client*);
static void ADC_client_connect(struct ADC_client*);
static void ADC_client_disconnect(struct ADC_client*);
static int ADC_client_create(struct ADC_client* client, int num);
static void ADC_client_destroy(struct ADC_client* client);
static int cfg_mode = 0; // See enum operationMode
static char* cfg_host = 0;
static int cfg_port = 0;
static int cfg_debug = 0; /* debug level */
static int cfg_level = 1; /* activity level (0..3) */
static int cfg_chat = 0; /* chat mode, allow sending chat messages */
static int cfg_quiet = 0; /* quiet mode (no output) */
static int cfg_clients = ADC_CLIENTS_DEFAULT; /* number of clients */
static int running = 1;
static struct sockaddr_in saddr;
enum commandMode
{
cm_bcast = 0x01, /* B - broadcast */
cm_dir = 0x02, /* D - direct message */
cm_echo = 0x04, /* E - echo message */
cm_fcast = 0x08, /* F - feature cast message */
cm_c2h = 0x10, /* H - client to hub message */
cm_h2c = 0x20, /* I - hub to client message */
cm_c2c = 0x40, /* C - client to client message */
cm_udp = 0x80, /* U - udp message (client to client) */
};
enum commandValidity
{
cv_protocol = 0x01,
cv_identify = 0x02,
cv_verify = 0x04,
cv_normal = 0x08,
};
enum protocolState
{
ps_none = 0x00, /* none or disconnected */
ps_conn = 0x01, /* connecting... */
ps_protocol = 0x02,
ps_identify = 0x04,
ps_verify = 0x08,
ps_normal = 0x10,
};
enum operationMode
{
mode_performance = 0x01,
mode_bugs = 0x02,
mode_security = 0x04,
mode_log = 0x08,
};
struct commandPattern
{
unsigned char mode; /* see enum commandMode */
char cmd[3];
unsigned char validity; /* see enum commandValidity */
};
const struct commandPattern patterns[] =
{
{ cm_c2h | cm_c2c | cm_h2c, "SUP", cv_protocol | cv_normal }, /* protocol support */
{ cm_bcast | cm_h2c | cm_c2c, "INF", cv_identify | cv_verify | cv_normal }, /* info message */
{ cm_bcast | cm_h2c | cm_c2c | cm_c2h | cm_udp, "STA", cv_protocol | cv_identify | cv_verify | cv_normal }, /* status message */
{ cm_bcast | cm_dir | cm_echo | cm_h2c, "MSG", cv_normal }, /* chat message */
{ cm_bcast | cm_dir | cm_echo | cm_fcast, "SCH", cv_normal }, /* search */
{ cm_dir | cm_udp, "RES", cv_normal }, /* search result */
{ cm_dir | cm_echo, "CTM", cv_normal }, /* connect to me */
{ cm_dir | cm_echo, "RCM", cv_normal }, /* reversed, connect to me */
{ cm_h2c, "QUI", cv_normal }, /* quit message */
{ cm_h2c, "GPA", cv_identify }, /* password request */
{ cm_c2h, "PAS", cv_verify } /* password response */
};
#define MAX_CHAT_MSGS 35
const char* chat_messages[MAX_CHAT_MSGS] = {
"hello",
"I'm an annoying robot, configured to chat in order to measure performance of the hub.",
"I apologize for the inconvenience.",
".",
":)",
"can anyone help me, pls?",
"wtf?",
"bullshit",
"resistance is futile.",
"You crossed the line first, sir. You squeezed them, you hammered them to the point of desperation. And in their desperation they turned to a man they didn't fully understand.",
"beam me up, scotty",
"morning",
"You know where Harvey is? You know who he is?",
"gtg",
"thanks",
"*punt*",
"*nudge*",
"that's ok",
"...anyway",
"hola",
"hey",
"hi",
"nevermind",
"i think so",
"dunno",
"debian ftw",
"oops",
"how do I search?",
"how do I enable active mode?",
"home, sweet home...",
"later",
"Good evening, ladies and gentlemen. We are tonight's entertainment! I only have one question. Where is Harvey Dent?",
"You know where I can find Harvey? I need to talk to him about something. Just something, a little.",
"We really should stop fighting, we'll miss the fireworks!",
"Wanna know how I got these scars?",
};
#define MAX_SEARCH_MSGS 10
const char* search_messages[MAX_SEARCH_MSGS] = {
"ANmp3 TOauto",
"ANxxx TOauto",
"ANdivx TOauto",
"ANtest ANfoo TOauto",
"ANwmv TO1289718",
"ANbabe TO8981884",
"ANpr0n TOauto",
"ANmusic TOauto",
"ANvideo TOauto",
"ANburnout ANps3 TOauto",
};
struct ADC_client
{
int sd;
int num;
sid_t sid;
enum protocolState state;
char info[ADC_BUFSIZE];
char recvbuf[BIG_BUFSIZE];
char sendbuf[BIG_BUFSIZE];
size_t s_offset;
size_t r_offset;
struct event ev_read;
struct event ev_write;
struct event ev_timer;
size_t timeout;
};
static void bot_output(struct ADC_client* client, const char* format, ...)
{
char logmsg[1024];
va_list args;
va_start(args, format);
vsnprintf(logmsg, 1024, format, args);
va_end(args);
if (cfg_mode == mode_log)
{
fprintf(stdout, "%s\n", logmsg);
}
else
{
if (cfg_debug)
fprintf(stdout, "* [%4d] %s\n", client->num, logmsg);
}
}
static void adc_cid_pid(struct ADC_client* client)
{
char seed[64];
char pid[64];
char cid[64];
uint64_t tiger_res1[3];
uint64_t tiger_res2[3];
/* create cid+pid pair */
memset(seed, 0, 64);
snprintf(seed, 64, ADCRUSH "%p/%d", client, (int) client->num);
tiger((uint64_t*) seed, strlen(seed), tiger_res1);
base32_encode((unsigned char*) tiger_res1, TIGERSIZE, pid);
tiger((uint64_t*) tiger_res1, TIGERSIZE, tiger_res2);
base32_encode((unsigned char*) tiger_res2, TIGERSIZE, cid);
cid[ADC_CID_SIZE] = 0;
pid[ADC_CID_SIZE] = 0;
strcat(client->info, " PD");
strcat(client->info, pid);
strcat(client->info, " ID");
strcat(client->info, cid);
}
static size_t get_wait_rand(size_t max)
{
static size_t next = 0;
if (next == 0) next = (size_t) time(0);
next = (next * 1103515245) + 12345;
return ((size_t )(next / 65536) % max);
}
static void client_reschedule_timeout(struct ADC_client* client)
{
size_t next_timeout = 0;
struct timeval timeout = { 0, 0 };
switch (client->state)
{
case ps_conn: next_timeout = 30; break;
case ps_protocol: next_timeout = 30; break;
case ps_identify: next_timeout = 30; break;
case ps_verify: next_timeout = 30; break;
case ps_normal: next_timeout = 120; break;
case ps_none: next_timeout = 120; break;
}
if (client->state == ps_normal || client->state == ps_none)
{
switch (cfg_level)
{
case 0: /* polite */
next_timeout *= 4;
break;
case 1: /* normal */
break;
case 2: /* aggressive */
next_timeout /= 8;
break;
case 3: /* excessive */
next_timeout /= 16;
case 4: /* excessive */
next_timeout /= 32;
}
}
if (client->state == ps_conn)
client->timeout = MAX(next_timeout, 1);
else
client->timeout = get_wait_rand(MAX(next_timeout, 1));
if (!client->timeout) client->timeout++;
timeout.tv_sec = (time_t) client->timeout;
evtimer_add(&client->ev_timer, &timeout);
}
static void set_state_timeout(struct ADC_client* client, enum protocolState state)
{
client->state = state;
client_reschedule_timeout(client);
}
static void send_client(struct ADC_client* client, char* msg)
{
int ret = net_send(client->sd, msg, strlen(msg), UHUB_SEND_SIGNAL);
if (cfg_debug > 1)
{
char* dump = strdup(msg);
dump[strlen(msg) - 1] = 0;
bot_output(client, "- SEND: '%s'", dump);
free(dump);
}
if (ret != strlen(msg))
{
if (ret == -1)
{
if (net_error() != EWOULDBLOCK)
ADC_client_on_disconnected(client);
}
else
{
/* FIXME: Not all data sent! */
printf("ret (%d) != msg->length (%d)\n", ret, (int) strlen(msg));
}
}
}
static void ADC_client_on_connected(struct ADC_client* client)
{
send_client(client, ADC_HANDSHAKE);
set_state_timeout(client, ps_protocol);
bot_output(client, "connected.");
}
static void ADC_client_on_disconnected(struct ADC_client* client)
{
event_del(&client->ev_read);
event_del(&client->ev_write);
net_close(client->sd);
client->sd = -1;
bot_output(client, "disconnected.");
set_state_timeout(client, ps_none);
}
static void ADC_client_on_login(struct ADC_client* client)
{
bot_output(client, "logged in.");
set_state_timeout(client, ps_normal);
}
static void send_client_info(struct ADC_client* client)
{
client->info[0] = 0;
strcat(client->info, "BINF ");
strcat(client->info, sid_to_string(client->sid));
strcat(client->info, " NI" ADC_NICK);
if (cfg_clients > 1)
{
strcat(client->info, "_");
strcat(client->info, uhub_itoa(client->num));
}
strcat(client->info, " VE" ADCRUSH);
strcat(client->info, " DE" ADC_DESC);
strcat(client->info, " I40.0.0.0");
strcat(client->info, " EMuhub@extatic.org");
strcat(client->info, " SL3");
strcat(client->info, " HN1");
strcat(client->info, " HR1");
strcat(client->info, " HO1");
adc_cid_pid(client);
strcat(client->info, "\n");
send_client(client, client->info);
}
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token);
static int recv_client(struct ADC_client* client)
{
ssize_t size = 0;
if (cfg_mode != mode_performance || (cfg_mode == mode_performance && (get_wait_rand(100) < (90 - (15 * cfg_level)))))
{
size = net_recv(client->sd, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset, 0);
}
else
{
if (get_wait_rand(1000) == 99)
return -1; /* Can break tings badly! :-) */
else
return 0;
}
if (size == 0 || ((size == -1 && net_error() != EWOULDBLOCK)))
return -1;
client->recvbuf[client->r_offset + size] = 0;
char* start = client->recvbuf;
char* pos;
char* lastPos;
while ((pos = strchr(start, '\n')))
{
lastPos = pos;
pos[0] = 0;
if (cfg_debug > 1)
{
bot_output(client, "- RECV: '%s'", start);
}
fourcc_t cmd = 0;
if (strlen(start) < 4)
{
bot_output(client, "Unexpected response from hub: '%s'", start);
start = &pos[1];
continue;
}
cmd = FOURCC(start[0], start[1], start[2], start[3]);
switch (cmd)
{
case ADC_CMD_ISUP:
break;
case ADC_CMD_ISID:
if (client->state == ps_protocol)
{
client->sid = string_to_sid(&start[5]);
client->state = ps_identify;
send_client_info(client);
}
break;
case ADC_CMD_IINF:
break;
case ADC_CMD_BSCH:
case ADC_CMD_FSCH:
{
if (get_wait_rand(100) > (90 - (10 * cfg_level)) && cfg_mode == mode_performance)
{
sid_t target = string_to_sid(&start[5]);
const char* what = strstr(&start[5], " AN");
const char* token = strstr(&start[5], " TO");
char* split = 0;
if (!token || !what) break;
token += 3;
what += 3;
split = strchr(what, ' ');
if (!split) break;
else split[0] = '0';
split = strchr(token, ' ');
if (split) split[0] = '0';
perf_result(client, target, what, token);
}
break;
}
case ADC_CMD_BINF:
{
if (strlen(start) > 9)
{
char t = start[9]; start[9] = 0; sid_t sid = string_to_sid(&start[5]); start[9] = t;
if (sid == client->sid)
{
if (client->state == ps_verify || client->state == ps_identify)
{
ADC_client_on_login(client);
}
}
}
break;
}
case ADC_CMD_ISTA:
if (strncmp(start, "ISTA 000", 8))
{
bot_output(client, "status: '%s'\n", (start + 9));
}
break;
default:
break;
}
start = &pos[1];
}
client->r_offset = strlen(lastPos);
memmove(client->recvbuf, lastPos, strlen(lastPos));
memset(&client->recvbuf[client->r_offset], 0, ADC_BUFSIZE-client->r_offset);
return 0;
}
void ADC_client_connect(struct ADC_client* client)
{
struct timeval timeout = { TIMEOUT_IDLE, 0 };
net_connect(client->sd, (struct sockaddr*) &saddr, sizeof(struct sockaddr_in));
set_state_timeout(client, ps_conn);
event_add(&client->ev_read, &timeout);
event_add(&client->ev_write, &timeout);
bot_output(client, "connecting...");
}
void ADC_client_wait_connect(struct ADC_client* client)
{
set_state_timeout(client, ps_none);
}
void ADC_client_disconnect(struct ADC_client* client)
{
if (client->sd != -1)
{
net_close(client->sd);
client->sd = -1;
event_del(&client->ev_read);
event_del(&client->ev_write);
bot_output(client, "disconnected.");
if (running)
{
ADC_client_destroy(client);
ADC_client_create(client, client->num);
ADC_client_connect(client);
}
}
}
static void perf_chat(struct ADC_client* client, int priv)
{
char buf[1024] = { 0, };
size_t r = get_wait_rand(MAX_CHAT_MSGS-1);
char* msg = adc_msg_escape(chat_messages[r]);
if (priv)
{
strcat(buf, "EMSG ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(client->sid));
}
else
{
strcat(buf, "BMSG ");
strcat(buf, sid_to_string(client->sid));
}
strcat(buf, " ");
strcat(buf, msg);
hub_free(msg);
strcat(buf, "\n");
send_client(client, buf);
}
static void perf_search(struct ADC_client* client)
{
char buf[1024] = { 0, };
size_t r = get_wait_rand(MAX_SEARCH_MSGS-1);
size_t pst = get_wait_rand(100);
if (pst > 80)
{
strcat(buf, "FSCH ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " +TCP4 ");
}
else
{
strcat(buf, "BSCH ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
}
strcat(buf, search_messages[r]);
strcat(buf, "\n");
send_client(client, buf);
}
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token)
{
char buf[1024] = { 0, };
strcat(buf, "DRES ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(target));
strcat(buf, " FN" "test/");
strcat(buf, what);
strcat(buf, ".dat");
strcat(buf, " SL" "0");
strcat(buf, " SI" "908987128912");
strcat(buf, " TR" "5T6YJYKO3WECS52BKWVSOP5VUG4IKNSZBZ5YHBA");
strcat(buf, " TO");
strcat(buf, token);
strcat(buf, "\n");
send_client(client, buf);
}
static void perf_ctm(struct ADC_client* client)
{
char buf[1024] = { 0, };
strcat(buf, "DCTM ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " ");
strcat(buf, "ADC/1.0");
strcat(buf, " TOKEN111");
strcat(buf, sid_to_string(client->sid));
strcat(buf, "\n");
send_client(client, buf);
}
static void perf_update(struct ADC_client* client)
{
char buf[1024] = { 0, };
int n = (int) get_wait_rand(10)+1;
strcat(buf, "BINF ");
strcat(buf, sid_to_string(client->sid));
strcat(buf, " HN");
strcat(buf, uhub_itoa(n));
strcat(buf, "\n");
send_client(client, buf);
}
static void perf_normal_action(struct ADC_client* client)
{
size_t r = get_wait_rand(5);
size_t p = get_wait_rand(100);
switch (r)
{
case 0:
if (p > (90 - (10 * cfg_level)))
{
if (cfg_debug > 1) bot_output(client, "timeout -> disconnect");
ADC_client_disconnect(client);
}
break;
case 1:
if (cfg_chat)
{
if (cfg_debug > 1) bot_output(client, "timeout -> chat");
perf_chat(client, 0);
}
break;
case 2:
if (cfg_debug > 1) bot_output(client, "timeout -> search");
perf_search(client);
break;
case 3:
if (cfg_debug > 1) bot_output(client, "timeout -> update");
perf_update(client);
break;
case 4:
if (cfg_debug > 1) bot_output(client, "timeout -> privmsg");
perf_chat(client, 1);
break;
case 5:
if (cfg_debug > 1) bot_output(client, "timeout -> ctm/rcm");
perf_ctm(client);
break;
}
client_reschedule_timeout(client);
}
void event_callback(int fd, short ev, void *arg)
{
struct ADC_client* client = (struct ADC_client*) arg;
if (ev & EV_READ)
{
if (recv_client(client) == -1)
{
ADC_client_on_disconnected(client);
}
}
if (ev & EV_TIMEOUT)
{
if (client->state == ps_none)
{
if (client->sd == -1)
{
ADC_client_create(client, client->num);
}
ADC_client_connect(client);
}
if (fd == -1)
{
if (client->state == ps_normal && cfg_mode == mode_performance)
{
perf_normal_action(client);
}
}
}
if (ev & EV_WRITE)
{
if (client->state == ps_conn)
{
ADC_client_on_connected(client);
}
else
{
/* FIXME: Call send again */
}
}
}
int ADC_client_create(struct ADC_client* client, int num)
{
struct timeval timeout = { 0, 0 };
memset(client, 0, sizeof(struct ADC_client));
client->num = num;
client->sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client->sd == -1) return -1;
event_set(&client->ev_write, client->sd, EV_WRITE, event_callback, client);
event_set(&client->ev_read, client->sd, EV_READ | EV_PERSIST, event_callback, client);
net_set_nonblocking(client->sd, 1);
timeout.tv_sec = client->timeout;
evtimer_set(&client->ev_timer, event_callback, client);
set_state_timeout(client, ps_none);
return 0;
}
void ADC_client_destroy(struct ADC_client* client)
{
ADC_client_disconnect(client);
evtimer_del(&client->ev_timer);
}
void runloop(size_t clients)
{
size_t n = 0;
struct ADC_client* client[ADC_MAX_CLIENTS];
for (n = 0; n < clients; n++)
{
struct ADC_client* c = malloc(sizeof(struct ADC_client));
client[n] = c;
ADC_client_create(c, n);
if (n == 0)
{
ADC_client_connect(c);
}
else
{
ADC_client_wait_connect(c);
}
}
event_dispatch();
for (n = 0; n < clients; n++)
{
ADC_client_destroy(client[n]);
free(client[n]);
}
}
static void print_version()
{
printf(ADCRUSH "\n");
printf("Copyright (C) 2008-2009, Jan Vidar Krey\n");
printf("\n");
}
static void print_usage(const char* program)
{
print_version();
printf("Usage: %s <mode> (adc://<host>:<port>) [options]\n", program);
printf("\n");
printf(" Modes\n");
printf(" perf Do performance testing using multiple clients\n");
printf(" bugs Bugs mode, use fuzzer to construct pseudo-random commands.\n");
printf(" security Perform security tests for the hub.\n");
printf(" log Connect one client to the hub and log the output hub.\n");
printf("\n");
printf(" General options\n");
printf(" -c Allow broadcasting chat messages.\n");
printf(" -d Enable debug output.\n");
printf(" -q Quiet mode (no output).\n");
printf("\n");
printf(" Performance options:\n");
printf(" -l <0-3> Level: 0=polite, 1=normal (default), 2=aggressive, 3=excessive.\n");
printf(" -n <num> Number of concurrent connections\n");
printf("\n");
exit(0);
}
int set_defaults()
{
switch (cfg_mode)
{
case mode_performance:
break;
case mode_bugs:
break;
case mode_security:
break;
case mode_log:
cfg_quiet = 0;
cfg_debug = 2;
cfg_clients = 1;
break;
}
return 1;
}
int parse_mode(const char* arg)
{
cfg_mode = 0;
if (!strcmp(arg, "perf"))
cfg_mode = mode_performance;
else if (!strcmp(arg, "bugs"))
cfg_mode = mode_bugs;
else if (!strcmp(arg, "security"))
cfg_mode = mode_security;
else if (!strcmp(arg, "log"))
cfg_mode = mode_log;
return cfg_mode;
}
int parse_address(const char* arg)
{
char* split;
struct hostent* dns;
struct in_addr* addr;
if (!arg)
return 0;
if (strlen(arg) < 9)
return 0;
if (strncmp(arg, "adc://", 6))
return 0;
split = strrchr(arg+6, ':');
if (split == 0 || strlen(split) < 2 || strlen(split) > 6)
return 0;
cfg_port = strtol(split+1, NULL, 10);
if (cfg_port <= 0 || cfg_port > 65535)
return 0;
split[0] = 0;
dns = gethostbyname(arg+6);
if (dns)
{
addr = (struct in_addr*) dns->h_addr_list[0];
cfg_host = strdup(inet_ntoa(*addr));
}
if (!cfg_host)
return 0;
return 1;
}
int parse_arguments(int argc, char** argv)
{
int ok = 1;
int opt;
for (opt = 3; opt < argc; opt++)
{
if (!strcmp(argv[opt], "-c"))
cfg_chat = 1;
else if (!strncmp(argv[opt], "-d", 2))
cfg_debug += strlen(argv[opt]) - 1;
else if (!strcmp(argv[opt], "-q"))
cfg_quiet = 1;
else if (!strcmp(argv[opt], "-l") && (++opt) < argc)
{
cfg_level = MIN(MAX(uhub_atoi(argv[opt]), 0), 3);
}
else if (!strcmp(argv[opt], "-n") && (++opt) < argc)
{
cfg_clients = MIN(MAX(uhub_atoi(argv[opt]), 1), ADC_MAX_CLIENTS);
}
}
return ok;
}
void parse_command_line(int argc, char** argv)
{
if (argc < 2 ||
!parse_mode(argv[1]) ||
!set_defaults() ||
!parse_address(argv[2]) ||
!parse_arguments(argc, argv))
{
print_usage(argv[0]);
}
}
int main(int argc, char** argv)
{
parse_command_line(argc, argv);
net_initialize();
event_init();
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(cfg_port);
net_string_to_address(AF_INET, cfg_host, &saddr.sin_addr);
runloop(cfg_clients);
net_shutdown();
return 0;
}

View File

@@ -1,183 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
static int command_access_denied(struct user* user)
{
struct adc_message* command;
char* buffer = adc_msg_escape("Access denied.");
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0;
}
static int command_stats(struct user* user, const char* message)
{
struct adc_message* command;
if (user->credentials < cred_super)
return command_access_denied(user);
char temp[128];
snprintf(temp, 128, "*** Stats: %zu users, peak: %zu. Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
user->hub->users->count,
user->hub->users->count_peak,
(int) user->hub->stats.net_tx / 1024,
(int) user->hub->stats.net_rx / 1024,
(int) user->hub->stats.net_tx_peak / 1024,
(int) user->hub->stats.net_rx_peak / 1024);
char* buffer = adc_msg_escape(temp);
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0;
}
static int command_help(struct user* user, const char* message)
{
struct adc_message* command;
char* buffer = adc_msg_escape("\n"
"*** Available commands:\n"
"!help - Show this help message\n"
"!stats - Show hub stats (super)\n"
"!version - Show this help message\n"
"!uptime - Display hub uptime\n"
"!kick <user> - Kick user (operator)\n"
);
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0;
}
static int command_uptime(struct user* user, const char* message)
{
struct adc_message* command;
char tmp[128];
size_t d;
size_t h;
size_t m;
size_t D = (size_t) difftime(time(0), user->hub->tm_started);
d = D / (24 * 3600);
D = D % (24 * 3600);
h = D / 3600;
D = D % 3600;
m = D / 60;
tmp[0] = 0;
strcat(tmp, "*** Uptime: ");
if (d)
{
strcat(tmp, uhub_itoa((int) d));
strcat(tmp, " day");
if (d != 1) strcat(tmp, "s");
strcat(tmp, ", ");
}
if (h < 10) strcat(tmp, "0");
strcat(tmp, uhub_itoa((int) h));
strcat(tmp, ":");
if (m < 10) strcat(tmp, "0");
strcat(tmp, uhub_itoa((int) m));
char* buffer = adc_msg_escape(tmp);
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0;
}
static int command_kick(struct user* user, const char* message)
{
struct adc_message* command;
if (user->credentials < cred_operator)
return command_access_denied(user);
char* buffer = adc_msg_escape("*** Kick not implemented!");
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0;
}
static int command_version(struct user* user, const char* message)
{
struct adc_message* command;
char* buffer = adc_msg_escape("*** Powered by " PRODUCT "/" VERSION);
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0;
}
static int command_myip(struct user* user, const char* message)
{
struct adc_message* command;
char tmp[128];
char* buffer;
tmp[0] = 0;
strcat(tmp, "*** Your IP: ");
strcat(tmp, ip_convert_to_string(&user->ipaddr));
buffer = adc_msg_escape(tmp);
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(user, command);
adc_msg_free(command);
hub_free(buffer);
return 0;
}
int command_dipatcher(struct user* user, const char* message)
{
if (!strncmp(message, "!stats", 6)) command_stats(user, message);
else if (!strncmp(message, "!help", 5)) command_help(user, message);
else if (!strncmp(message, "!kick", 5)) command_kick(user, message);
else if (!strncmp(message, "!version", 8)) command_version(user, message);
else if (!strncmp(message, "!uptime", 7)) command_uptime(user, message);
else if (!strncmp(message, "+myip", 5)) command_myip(user, message);
else
return 1;
return 0;
}

View File

@@ -23,7 +23,7 @@
#define ACL_ADD_BOOL(S, L) do { ret = check_cmd_bool(S, L, line, line_count); if (ret != 0) return ret; } while(0)
#define ACL_ADD_ADDR(S, L) do { ret = check_cmd_addr(S, L, line, line_count); if (ret != 0) return ret; } while(0)
static const char* get_user_credential_string(enum user_credentials cred)
const char* get_user_credential_string(enum user_credentials cred)
{
switch (cred)
{
@@ -55,12 +55,12 @@ static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line,
data = strip_white_space(data);
if (!*data)
{
hub_log(log_fatal, "ACL parse error on line %d", line_count);
LOG_FATAL("ACL parse error on line %d", line_count);
return -1;
}
list_append(list, hub_strdup(data));
hub_log(log_debug, "ACL: Deny access for: '%s' (%s)", data, cmd);
LOG_DEBUG("ACL: Deny access for: '%s' (%s)", data, cmd);
return 1;
}
return 0;
@@ -70,7 +70,7 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
{
char* data;
char* data_extra;
struct user_access_info* info = 0;
struct hub_user_access_info* info = 0;
if (!strncmp(line, cmd, strlen(cmd)))
{
@@ -82,15 +82,15 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
data = strip_white_space(data);
if (!*data)
{
hub_log(log_fatal, "ACL parse error on line %d", line_count);
LOG_FATAL("ACL parse error on line %d", line_count);
return -1;
}
info = hub_malloc_zero(sizeof(struct user_access_info));
info = hub_malloc_zero(sizeof(struct hub_user_access_info));
if (!info)
{
hub_log(log_error, "ACL parse error. Out of memory!");
LOG_ERROR("ACL parse error. Out of memory!");
return -1;
}
@@ -108,18 +108,18 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
info->password = data_extra ? hub_strdup(data_extra) : 0;
info->status = status;
list_append(list, info);
hub_log(log_debug, "ACL: Added user '%s' (%s)", info->username, get_user_credential_string(info->status));
LOG_DEBUG("ACL: Added user '%s' (%s)", info->username, get_user_credential_string(info->status));
return 1;
}
return 0;
}
static void add_ip_range(struct linked_list* list, struct ip_ban_record* info)
static void add_ip_range(struct linked_list* list, struct ip_range* info)
{
char buf1[INET6_ADDRSTRLEN+1];
char buf2[INET6_ADDRSTRLEN+1];
if (info->lo.af == AF_INET)
{
net_address_to_string(AF_INET, &info->lo.internal_ip_data.in.s_addr, buf1, INET6_ADDRSTRLEN);
@@ -130,125 +130,44 @@ static void add_ip_range(struct linked_list* list, struct ip_ban_record* info)
net_address_to_string(AF_INET6, &info->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
}
hub_log(log_debug, "ACL: Deny access for: %s-%s", buf1, buf2);
LOG_DEBUG("ACL: Added ip range: %s-%s", buf1, buf2);
list_append(list, info);
}
static int check_ip_range(const char* lo, const char* hi, struct ip_ban_record* info)
{
int ret1, ret2;
if ((ip_is_valid_ipv4(lo) && ip_is_valid_ipv4(hi)) ||
(ip_is_valid_ipv6(lo) && ip_is_valid_ipv6(hi)))
{
ret1 = ip_convert_to_binary(lo, &info->lo);
ret2 = ip_convert_to_binary(hi, &info->hi);
if (ret1 == -1 || ret2 == -1 || ret1 != ret2)
{
return -1;
}
return 0;
}
return -1;
}
static int check_ip_mask(const char* text_addr, int bits, struct ip_ban_record* info)
{
hub_log(log_debug, "ACL: Deny access for: %s/%d", text_addr, bits);
if (ip_is_valid_ipv4(text_addr) ||
ip_is_valid_ipv6(text_addr))
{
struct ip_addr_encap addr;
struct ip_addr_encap mask1;
struct ip_addr_encap mask2;
int af = ip_convert_to_binary(text_addr, &addr); /* 192.168.1.2 */
int maxbits = af == AF_INET6 ? 128 : 32;
ip_mask_create_left(af, bits, &mask1); /* 255.255.255.0 */
ip_mask_create_right(af, maxbits - bits, &mask2); /* 0.0.0.255 */
ip_mask_apply_AND(&addr, &mask1, &info->lo); /* 192.168.1.0 */
ip_mask_apply_OR(&info->lo, &mask2, &info->hi); /* 192.168.1.255 */
return 0;
}
return -1;
}
static int check_cmd_addr(const char* cmd, struct linked_list* list, char* line, int line_count)
{
char* data1;
char* data2;
struct ip_ban_record* info = 0;
int cidr_bits = 0;
char* data;
struct ip_range* range = 0;
if (!strncmp(line, cmd, strlen(cmd)))
{
data1 = &line[strlen(cmd)];
data2 = 0;
data1[0] = '\0';
data1++;
data1 = strip_white_space(data1);
if (!*data1)
{
hub_log(log_fatal, "ACL parse error on line %d", line_count);
return -1;
}
info = hub_malloc_zero(sizeof(struct ip_ban_record));
if (!info)
{
hub_log(log_error, "ACL parse error. Out of memory!");
return -1;
}
/* Extract IP-range */
data2 = strrchr(data1, '-');
if (data2)
{
cidr_bits = -1;
data2[0] = 0;
data2++;
if (check_ip_range(data1, data2, info) == -1)
{
hub_free(info);
return 0;
}
add_ip_range(list, info);
data = &line[strlen(cmd)];
data[0] = '\0';
data++;
return 1;
}
else
data = strip_white_space(data);
if (!*data)
{
/* Extract IP-bitmask */
data2 = strrchr(data1, '/');
if (data2)
{
data2[0] = 0;
data2++;
cidr_bits = uhub_atoi(data2);
}
else
{
cidr_bits = 128;
}
if (check_ip_mask(data1, cidr_bits, info) == -1)
{
hub_free(info);
return 0;
}
add_ip_range(list, info);
LOG_FATAL("ACL parse error on line %d", line_count);
return -1;
}
range = hub_malloc_zero(sizeof(struct ip_range));
if (!range)
{
LOG_ERROR("ACL parse error. Out of memory!");
return -1;
}
if (ip_convert_address_to_range(data, range))
{
add_ip_range(list, range);
return 1;
}
hub_free(range);
}
return 0;
}
@@ -260,30 +179,18 @@ static int acl_parse_line(char* line, int line_count, void* ptr_data)
char* pos;
struct acl_handle* handle = (struct acl_handle*) ptr_data;
int ret;
if ((pos = strchr(line, '#')) != NULL)
{
pos[0] = 0;
}
line = strip_white_space(line);
if (!*line)
return 0;
#ifdef ACL_DEBUG
hub_log(log_trace, "acl_parse_line(): '%s'", line);
#endif
line = strip_white_space(line);
if (!*line)
{
hub_log(log_fatal, "ACL parse error on line %d", line_count);
return -1;
}
LOG_DEBUG("acl_parse_line: '%s'", line);
#ifdef ACL_DEBUG
hub_log(log_trace, "acl_parse_line: '%s'", line);
#endif
ACL_ADD_USER("bot", handle->users, cred_bot);
ACL_ADD_USER("user_admin", handle->users, cred_admin);
ACL_ADD_USER("user_super", handle->users, cred_super);
@@ -295,8 +202,8 @@ static int acl_parse_line(char* line, int line_count, void* ptr_data)
ACL_ADD_BOOL("ban_cid", handle->cids);
ACL_ADD_ADDR("deny_ip", handle->networks);
ACL_ADD_ADDR("nat_ip", handle->nat_override);
hub_log(log_error, "Unknown ACL command on line %d: '%s'", line_count, line);
LOG_ERROR("Unknown ACL command on line %d: '%s'", line_count, line);
return -1;
}
@@ -315,7 +222,7 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
if (!handle->users || !handle->cids || !handle->networks || !handle->users_denied || !handle->users_banned || !handle->nat_override)
{
hub_log(log_fatal, "acl_initialize: Out of memory");
LOG_FATAL("acl_initialize: Out of memory");
list_destroy(handle->users);
list_destroy(handle->users_denied);
@@ -340,7 +247,7 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
static void acl_free_access_info(void* ptr)
{
struct user_access_info* info = (struct user_access_info*) ptr;
struct hub_user_access_info* info = (struct hub_user_access_info*) ptr;
if (info)
{
hub_free(info->username);
@@ -404,22 +311,22 @@ int acl_shutdown(struct acl_handle* handle)
}
struct user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name)
struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name)
{
struct user_access_info* info = (struct user_access_info*) list_get_first(handle->users);
struct hub_user_access_info* info = (struct hub_user_access_info*) list_get_first(handle->users);
while (info)
{
if (strcasecmp(info->username, name) == 0)
{
return info;
}
info = (struct user_access_info*) list_get_next(handle->users);
info = (struct hub_user_access_info*) list_get_next(handle->users);
}
return NULL;
}
#define STR_LIST_CONTAINS(LIST, STR) \
char* str = (char*) list_get_first(LIST); \
str = (char*) list_get_first(LIST); \
while (str) \
{ \
if (strcasecmp(str, STR) == 0) \
@@ -430,35 +337,94 @@ struct user_access_info* acl_get_access_info(struct acl_handle* handle, const ch
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
{
char* str;
if (!handle) return 0;
STR_LIST_CONTAINS(handle->cids, data);
}
int acl_is_user_banned(struct acl_handle* handle, const char* data)
{
char* str;
if (!handle) return 0;
STR_LIST_CONTAINS(handle->users_banned, data);
}
int acl_is_user_denied(struct acl_handle* handle, const char* data)
{
char* str;
if (!handle) return 0;
STR_LIST_CONTAINS(handle->users_denied, data);
}
int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
{
char* data = 0;
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
if (!info)
{
LOG_ERROR("ACL error: Out of memory!");
return -1;
}
data = hub_strdup(nick);
if (!data)
{
LOG_ERROR("ACL error: Out of memory!");
hub_free(info);
return -1;
}
list_append(handle->users_banned, data);
return 0;
}
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
{
char* data;
struct hub_user_access_info* info = hub_malloc_zero(sizeof(struct hub_user_access_info));
if (!info)
{
LOG_ERROR("ACL error: Out of memory!");
return -1;
}
data = hub_strdup(cid);
if (!data)
{
LOG_ERROR("ACL error: Out of memory!");
hub_free(info);
return -1;
}
list_append(handle->cids, data);
return 0;
}
int acl_user_unban_nick(struct acl_handle* handle, const char* nick)
{
return -1;
}
int acl_user_unban_cid(struct acl_handle* handle, const char* cid)
{
return -1;
}
int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
{
struct ip_addr_encap raw;
struct ip_ban_record* info = (struct ip_ban_record*) list_get_first(handle->networks);
struct ip_range* info = (struct ip_range*) list_get_first(handle->networks);
ip_convert_to_binary(ip_address, &raw);
while (info)
{
if (acl_check_ip_range(&raw, info))
if (ip_in_range(&raw, info))
{
return 1;
}
info = (struct ip_ban_record*) list_get_next(handle->networks);
info = (struct ip_range*) list_get_next(handle->networks);
}
return 0;
}
@@ -466,71 +432,63 @@ int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
{
struct ip_addr_encap raw;
struct ip_ban_record* info = (struct ip_ban_record*) list_get_first(handle->nat_override);
struct ip_range* info = (struct ip_range*) list_get_first(handle->nat_override);
ip_convert_to_binary(ip_address, &raw);
while (info)
{
if (acl_check_ip_range(&raw, info))
if (ip_in_range(&raw, info))
{
return 1;
}
info = (struct ip_ban_record*) list_get_next(handle->nat_override);
info = (struct ip_range*) list_get_next(handle->nat_override);
}
return 0;
}
int acl_check_ip_range(struct ip_addr_encap* addr, struct ip_ban_record* info)
{
return (addr->af == info->lo.af && ip_compare(&info->lo, addr) <= 0 && ip_compare(addr, &info->hi) <= 0);
}
/*
* This will generate the same challenge to the same user, always.
* The challenge is made up of the time of the user connected
* seconds since the unix epoch (modulus 1 million)
* and the SID of the user (0-1 million).
*/
const char* password_generate_challenge(struct user* user)
const char* acl_password_generate_challenge(struct acl_handle* acl, struct hub_user* user)
{
char buf[32];
char buf[64];
uint64_t tiger_res[3];
static char tiger_buf[MAX_CID_LEN+1];
snprintf(buf, 32, "%d%d%d", (int) user->tm_connected, (int) user->id.sid, (int) user->sd);
// FIXME: Generate a better nonce scheme.
snprintf(buf, 64, "%p%d%d", user, (int) user->id.sid, (int) net_con_get_sd(user->connection));
tiger((uint64_t*) buf, strlen(buf), (uint64_t*) tiger_res);
base32_encode((unsigned char*) tiger_res, TIGERSIZE, tiger_buf);
tiger_buf[MAX_CID_LEN] = 0;
#ifdef ACL_DEBUG
hub_log(log_trace, "Generating challenge for user %s: '%s'", user->id.nick, tiger_buf);
#endif
return (const char*) tiger_buf;
}
int password_verify(struct user* user, const char* password)
int acl_password_verify(struct acl_handle* acl, struct hub_user* user, const char* password)
{
char buf[1024];
struct user_access_info* access;
struct hub_user_access_info* access;
const char* challenge;
char raw_challenge[64];
char password_calc[64];
uint64_t tiger_res[3];
if (!password || !user || strlen(password) != MAX_CID_LEN)
return password_invalid;
return 0;
access = acl_get_access_info(user->hub->acl, user->id.nick);
access = acl_get_access_info(acl, user->id.nick);
if (!access || !access->password)
return password_invalid;
return 0;
if (TIGERSIZE+strlen(access->password) >= 1024)
return password_invalid;
return 0;
challenge = password_generate_challenge(user);
challenge = acl_password_generate_challenge(acl, user);
base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN);
@@ -541,14 +499,11 @@ int password_verify(struct user* user, const char* password)
base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc);
password_calc[MAX_CID_LEN] = 0;
#ifdef ACL_DEBUG
hub_log(log_trace, "Checking password %s against %s", password, password_calc);
#endif
if (strcasecmp(password, password_calc) == 0)
{
return password_ok;
return 1;
}
return password_invalid;
return 0;
}

View File

@@ -21,21 +21,9 @@
#define HAVE_UHUB_ACL_H
struct hub_config;
struct user;
struct hub_user;
struct ip_addr_encap;
enum password_status
{
password_invalid = 0,
password_ok = 1,
};
enum acl_status
{
acl_not_found = 0,
acl_found = 1,
};
enum user_credentials
{
cred_none, /**<<< "User has no credentials (not yet logged in)" */
@@ -48,19 +36,15 @@ enum user_credentials
cred_link, /**<<< "User is a link (not used currently)" */
};
struct user_access_info
const char* get_user_credential_string(enum user_credentials cred);
struct hub_user_access_info
{
char* username; /* name of user, cid or IP range */
char* password; /* password */
enum user_credentials status;
};
struct ip_ban_record
{
struct ip_addr_encap lo;
struct ip_addr_encap hi;
};
struct acl_handle
{
struct linked_list* users; /* Known users. See enum user_status */
@@ -75,7 +59,7 @@ struct acl_handle
extern int acl_initialize(struct hub_config* config, struct acl_handle* handle);
extern int acl_shutdown(struct acl_handle* handle);
extern struct user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name);
extern struct hub_user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name);
extern int acl_is_cid_banned(struct acl_handle* handle, const char* cid);
extern int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address);
extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address);
@@ -83,9 +67,19 @@ extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_addr
extern int acl_is_user_banned(struct acl_handle* handle, const char* name);
extern int acl_is_user_denied(struct acl_handle* handle, const char* name);
extern int acl_check_ip_range(struct ip_addr_encap* addr, struct ip_ban_record* info);
extern int acl_user_ban_nick(struct acl_handle* handle, const char* nick);
extern int acl_user_ban_cid(struct acl_handle* handle, const char* cid);
extern int acl_user_unban_nick(struct acl_handle* handle, const char* nick);
extern int acl_user_unban_cid(struct acl_handle* handle, const char* cid);
extern const char* password_generate_challenge(struct user* user);
extern int password_verify(struct user* user, const char* password);
extern const char* acl_password_generate_challenge(struct acl_handle* acl, struct hub_user* user);
/**
* Verify a password.
*
* @param password the hashed password (based on the nonce).
* @return 1 if the password matches, or 0 if the password is incorrect.
*/
extern int acl_password_verify(struct acl_handle* acl, struct hub_user* user, const char* password);
#endif /* HAVE_UHUB_ACL_H */

626
src/core/commands.c Normal file
View File

@@ -0,0 +1,626 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#ifdef DEBUG
#define CRASH_DEBUG
#endif
#define MAX_HELP_MSG 1024
struct hub_command
{
const char* message;
char* prefix;
size_t prefix_len;
struct linked_list* args;
};
typedef int (*command_handler)(struct hub_info* hub, struct hub_user* user, struct hub_command*);
struct commands_handler
{
const char* prefix;
size_t length;
const char* args;
enum user_credentials cred;
command_handler handler;
const char* description;
};
static struct commands_handler command_handlers[];
static void command_destroy(struct hub_command* cmd)
{
if (!cmd) return;
hub_free(cmd->prefix);
if (cmd->args)
{
list_clear(cmd->args, &hub_free);
list_destroy(cmd->args);
}
hub_free(cmd);
}
static struct hub_command* command_create(const char* message)
{
char* prefix;
int n;
struct hub_command* cmd = hub_malloc_zero(sizeof(struct hub_command));
if (!cmd) return 0;
cmd->message = message;
cmd->args = list_create();
n = split_string(message, "\\s", cmd->args, 0);
if (n <= 0)
{
command_destroy(cmd);
return 0;
}
prefix = list_get_first(cmd->args);
if (prefix && prefix[0] && prefix[1])
{
cmd->prefix = hub_strdup(&prefix[1]);
cmd->prefix_len = strlen(cmd->prefix);
}
else
{
command_destroy(cmd);
return 0;
}
list_remove(cmd->args, prefix);
hub_free(prefix);
return cmd;
}
static void send_message(struct hub_info* hub, struct hub_user* user, const char* message)
{
char* buffer = adc_msg_escape(message);
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
adc_msg_add_argument(command, buffer);
route_to_user(hub, user, command);
adc_msg_free(command);
hub_free(buffer);
}
static int command_access_denied(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char temp[128];
snprintf(temp, 128, "*** %s: Access denied.", cmd->prefix);
send_message(hub, user, temp);
return 0;
}
static int command_not_found(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char temp[128];
snprintf(temp, 128, "*** %s: Command not found", cmd->prefix);
send_message(hub, user, temp);
return 0;
}
static int command_status_user_not_found(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd, const char* nick)
{
char temp[128];
snprintf(temp, 128, "*** %s: No user \"%s\"", cmd->prefix, nick);
send_message(hub, user, temp);
return 0;
}
const char* command_get_syntax(struct commands_handler* handler)
{
static char args[128];
size_t n = 0;
args[0] = 0;
if (handler->args)
{
for (n = 0; n < strlen(handler->args); n++)
{
if (n > 0) strcat(args, " ");
switch (handler->args[n])
{
case 'n': strcat(args, "<nick>"); break;
case 'c': strcat(args, "<cid>"); break;
case 'a': strcat(args, "<addr>"); break;
case 'm': strcat(args, "<message>"); break;
}
}
}
return args;
}
static int command_arg_mismatch(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd, struct commands_handler* handler)
{
char temp[256];
const char* args = command_get_syntax(handler);
if (args) snprintf(temp, 256, "*** %s: Use: !%s %s", cmd->prefix, cmd->prefix, args);
else snprintf(temp, 256, "*** %s: Use: !%s", cmd->prefix, cmd->prefix);
send_message(hub, user, temp);
return 0;
}
static int command_status(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd, const char* message)
{
char temp[1024];
snprintf(temp, 1024, "*** %s: %s", cmd->prefix, message);
send_message(hub, user, temp);
return 0;
}
static int command_stats(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char temp[128];
snprintf(temp, 128, PRINTF_SIZE_T " users, peak: " PRINTF_SIZE_T ". Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
hub->users->count,
hub->users->count_peak,
(int) hub->stats.net_tx / 1024,
(int) hub->stats.net_rx / 1024,
(int) hub->stats.net_tx_peak / 1024,
(int) hub->stats.net_rx_peak / 1024);
return command_status(hub, user, cmd, temp);
}
static int command_help(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
size_t n;
char msg[MAX_HELP_MSG];
msg[0] = 0;
strcat(msg, "Available commands:\n");
for (n = 0; command_handlers[n].prefix; n++)
{
if (command_handlers[n].cred <= user->credentials)
{
strcat(msg, "!");
strcat(msg, command_handlers[n].prefix);
strcat(msg, " - ");
strcat(msg, command_handlers[n].description);
strcat(msg, "\n");
}
}
return command_status(hub, user, cmd, msg);
}
static int command_uptime(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char tmp[128];
size_t d;
size_t h;
size_t m;
size_t D = (size_t) difftime(time(0), hub->tm_started);
d = D / (24 * 3600);
D = D % (24 * 3600);
h = D / 3600;
D = D % 3600;
m = D / 60;
tmp[0] = 0;
if (d)
{
strcat(tmp, uhub_itoa((int) d));
strcat(tmp, " day");
if (d != 1) strcat(tmp, "s");
strcat(tmp, ", ");
}
if (h < 10) strcat(tmp, "0");
strcat(tmp, uhub_itoa((int) h));
strcat(tmp, ":");
if (m < 10) strcat(tmp, "0");
strcat(tmp, uhub_itoa((int) m));
return command_status(hub, user, cmd, tmp);
}
static int command_kick(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char* nick = list_get_first(cmd->args);
struct hub_user* target;
if (!nick)
return -1; // FIXME: bad syntax.
target = uman_get_user_by_nick(hub, nick);
if (!target)
return command_status_user_not_found(hub, user, cmd, nick);
if (target == user)
return command_status(hub, user, cmd, "Cannot kick yourself");
hub_disconnect_user(hub, target, quit_kicked);
return command_status(hub, user, cmd, nick);
}
static int command_ban(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char* nick = list_get_first(cmd->args);
struct hub_user* target;
if (!nick)
return -1; // FIXME: bad syntax.
target = uman_get_user_by_nick(hub, nick);
if (!target)
return command_status_user_not_found(hub, user, cmd, nick);
if (target == user)
return command_status(hub, user, cmd, "Cannot kick/ban yourself");
hub_disconnect_user(hub, target, quit_kicked);
acl_user_ban_nick(hub->acl, target->id.nick);
acl_user_ban_cid(hub->acl, target->id.cid);
return command_status(hub, user, cmd, nick);
}
static int command_unban(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
return command_status(hub, user, cmd, "Not implemented");
}
static int command_mute(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char* nick = list_get_first(cmd->args);
struct hub_user* target;
if (!nick)
return -1; // FIXME: bad syntax.
target = uman_get_user_by_nick(hub, nick);
if (!target)
return command_status_user_not_found(hub, user, cmd, nick);
if (strlen(cmd->prefix) == 4)
{
user_flag_set(target, flag_muted);
}
else
{
user_flag_unset(target, flag_muted);
}
return command_status(hub, user, cmd, nick);
}
static int command_reload(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
hub->status = hub_status_restart;
return command_status(hub, user, cmd, "Reloading configuration...");
}
static int command_shutdown(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
hub->status = hub_status_shutdown;
return command_status(hub, user, cmd, "Hub shutting down...");
}
static int command_version(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
const char* tmp;
if (hub->config->show_banner_sys_info)
tmp = "Powered by " PRODUCT_STRING " on " OPSYS "/" CPUINFO;
else
tmp = "Powered by " PRODUCT_STRING;
return command_status(hub, user, cmd, tmp);
}
static int command_myip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char tmp[128];
snprintf(tmp, 128, "Your address is \"%s\"", user_get_address(user));
return command_status(hub, user, cmd, tmp);
}
static int command_getip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char tmp[128];
char* nick = list_get_first(cmd->args);
struct hub_user* target;
if (!nick)
return -1; // FIXME: bad syntax/OOM
target = uman_get_user_by_nick(hub, nick);
if (!target)
return command_status_user_not_found(hub, user, cmd, nick);
snprintf(tmp, 128, "%s has address \"%s\"", nick, user_get_address(target));
return command_status(hub, user, cmd, tmp);
}
static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char* address = list_get_first(cmd->args);
struct ip_range range;
struct linked_list* users;
struct hub_user* u;
int ret = 0;
char tmp[128];
char* buffer;
if (!address)
return -1; // FIXME: bad syntax.
ret = ip_convert_address_to_range(address, &range);
if (!ret)
return command_status(hub, user, cmd, "Invalid IP address/range/mask");
users = (struct linked_list*) list_create();
if (!users)
return -1; // FIXME: OOM
ret = uman_get_user_by_addr(hub, users, &range);
if (!ret)
{
list_destroy(users);
return command_status(hub, user, cmd, "No users found.");
}
snprintf(tmp, 128, "*** %s: Found %d match%s:", cmd->prefix, ret, ((ret != 1) ? "es" : ""));
buffer = hub_malloc(((MAX_NICK_LEN + INET6_ADDRSTRLEN + 5) * ret) + strlen(tmp) + 3);
if (!buffer)
{
list_destroy(users);
return -1; // FIXME: OOM
}
buffer[0] = 0;
strcat(buffer, tmp);
strcat(buffer, "\n");
u = (struct hub_user*) list_get_first(users);
while (u)
{
strcat(buffer, u->id.nick);
strcat(buffer, " (");
strcat(buffer, user_get_address(u));
strcat(buffer, ")\n");
u = (struct hub_user*) list_get_next(users);
}
strcat(buffer, "\n");
send_message(hub, user, buffer);
hub_free(buffer);
list_destroy(users);
return 0;
}
static int command_broadcast(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen((cmd->message + 12)) + 6);
adc_msg_add_argument(command, (cmd->message + 12));
route_to_all(hub, command);
adc_msg_free(command);
return 0;
}
static int command_history(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
char* buffer;
struct linked_list* messages = hub->chat_history;
char* message = 0;
int ret = (int) list_size(messages);
size_t bufsize;
char tmp[128];
if (!ret)
{
return command_status(hub, user, cmd, "No messages.");
}
snprintf(tmp, 128, "*** %s: Found %d message%s:", cmd->prefix, ret, ((ret != 1) ? "s" : ""));
bufsize = strlen(tmp);
message = (char*) list_get_first(messages);
while (message)
{
bufsize += strlen(message);
message = (char*) list_get_next(messages);
}
buffer = hub_malloc(bufsize+4);
if (!buffer)
{
return command_status(hub, user, cmd, "Not enough memory.");
}
buffer[0] = 0;
strcat(buffer, tmp);
strcat(buffer, "\n");
message = (char*) list_get_first(messages);
while (message)
{
strcat(buffer, message);
message = (char*) list_get_next(messages);
}
strcat(buffer, "\n");
send_message(hub, user, buffer);
hub_free(buffer);
return 0;
}
static int command_log(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
struct linked_list* messages = hub->logout_info;
struct hub_logout_info* log;
char tmp[1024];
char* search = 0;
size_t search_len = 0;
size_t search_hits = 0;
if (!list_size(messages))
{
return command_status(hub, user, cmd, "No entries logged.");
}
search = list_get_first(cmd->args);
if (search)
{
search_len = strlen(search);
}
if (search_len)
{
sprintf(tmp, "Logged entries: " PRINTF_SIZE_T ", searching for \"%s\"", list_size(messages), search);
}
else
{
sprintf(tmp, "Logged entries: " PRINTF_SIZE_T, list_size(messages));
}
command_status(hub, user, cmd, tmp);
log = (struct hub_logout_info*) list_get_first(messages);
while (log)
{
const char* address = ip_convert_to_string(&log->addr);
int show = 0;
if (search_len)
{
if (memmem(log->cid, MAX_CID_LEN, search, search_len) || memmem(log->nick, MAX_NICK_LEN, search, search_len) || memmem(address, strlen(address), search, search_len))
{
search_hits++;
show = 1;
}
}
else
{
show = 1;
}
if (show)
{
sprintf(tmp, "* %s %s, %s [%s] - %s", get_timestamp(log->time), log->cid, log->nick, ip_convert_to_string(&log->addr), user_get_quit_reason_string(log->reason));
send_message(hub, user, tmp);
}
log = (struct hub_logout_info*) list_get_next(messages);
}
if (search_len)
{
sprintf(tmp, PRINTF_SIZE_T " entries shown.", search_hits);
command_status(hub, user, cmd, tmp);
}
return 0;
}
static int command_rules(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
if (!hub_send_rules(hub, user))
return command_status(hub, user, cmd, "no rules defined.");
return 0;
}
static int command_motd(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
if (!hub_send_motd(hub, user))
return command_status(hub, user, cmd, "no motd defined.");
return 0;
}
#ifdef CRASH_DEBUG
static int command_crash(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
{
void (*crash)(void) = NULL;
crash();
return 0;
}
#endif
int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* message)
{
size_t n = 0;
int rc;
/* Parse and validate the command */
struct hub_command* cmd = command_create(message);
if (!cmd) return 0;
for (n = 0; command_handlers[n].prefix; n++)
{
struct commands_handler* handler = &command_handlers[n];
if (cmd->prefix_len != handler->length)
continue;
if (!strncmp(cmd->prefix, handler->prefix, handler->length))
{
if (handler->cred <= user->credentials)
{
if (!handler->args || (handler->args && list_size(cmd->args) >= strlen(handler->args)))
{
rc = handler->handler(hub, user, cmd);
}
else
{
rc = command_arg_mismatch(hub, user, cmd, handler);
}
command_destroy(cmd);
return rc;
}
else
{
rc = command_access_denied(hub, user, cmd);
command_destroy(cmd);
return rc;
}
}
}
command_not_found(hub, user, cmd);
command_destroy(cmd);
return 0;
}
static struct commands_handler command_handlers[] = {
{ "ban", 3, "n", cred_operator, command_ban, "Ban a user" },
{ "broadcast", 9, "m", cred_operator, command_broadcast,"Send a message to all users" },
#ifdef CRASH_DEBUG
{ "crash", 5, 0, cred_admin, command_crash, "Crash the hub (DEBUG)." },
#endif
{ "getip", 5, "n", cred_operator, command_getip, "Show IP address for a user" },
{ "help", 4, 0, cred_guest, command_help, "Show this help message." },
{ "history", 7, 0, cred_guest, command_history, "Show the last chat messages." },
{ "kick", 4, "n", cred_operator, command_kick, "Kick a user" },
{ "log", 3, 0, cred_operator, command_log, "Display log" },
{ "motd", 4, 0, cred_guest, command_motd, "Show the message of the day" },
{ "mute", 4, "n", cred_operator, command_mute, "Mute user" },
{ "myip", 4, 0, cred_guest, command_myip, "Show your own IP." },
{ "reload", 6, 0, cred_admin, command_reload, "Reload configuration files." },
{ "rules", 5, 0, cred_guest, command_rules, "Show the hub rules" },
{ "shutdown", 8, 0, cred_admin, command_shutdown, "Shutdown hub." },
{ "stats", 5, 0, cred_super, command_stats, "Show hub statistics." },
{ "unban", 5, "n", cred_operator, command_unban, "Lift ban on a user" },
{ "unmute", 6, "n", cred_operator, command_mute, "Unmute user" },
{ "uptime", 6, 0, cred_guest, command_uptime, "Display hub uptime info." },
{ "version", 7, 0, cred_guest, command_version, "Show hub version info." },
{ "whoip", 5, "a", cred_operator, command_whoip, "Show users matching IP range" },
{ 0, 0, 0, cred_none, command_help, "" }
};

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,17 +19,4 @@
#include "uhub.h"
#define CHAT_MSG_HANDLED 1
#define CHAT_MSG_IGNORED 0
#define CHAT_MSG_INVALID -1
typedef int (*plugin_event_chat_message)(struct hub_info*, struct user*, struct adc_message*);
struct command_info
{
const char* prefix;
enum user_credentials cred;
plugin_event_chat_message function;
};
int command_dipatcher(struct user* user, const char* message);
extern int command_dipatcher(struct hub_info* hub, struct hub_user* user, const char* message);

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -42,7 +42,7 @@
else if (strncasecmp(data, "off", 3) == 0) TARGET = 0; \
else\
{ \
hub_log(log_fatal, "Configuration error on line %d: '%s' must be either '1' or '0'", line_count, key); \
LOG_FATAL("Configuration error on line %d: '%s' must be either '1' or '0'", line_count, key); \
return -1; \
} \
TARGET |= 0x80000000; \
@@ -65,7 +65,7 @@
errno = 0; \
val = strtol(data, &endptr, 10); \
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data) { \
hub_log(log_fatal, "Configuration error on line %d: '%s' must be a number", line_count, key); \
LOG_FATAL("Configuration error on line %d: '%s' must be a number", line_count, key); \
return -1; \
} \
TARGET = val; \
@@ -103,24 +103,31 @@
#define IGNORED(NAME) \
if (strcmp(#NAME, key) == 0) \
{ \
hub_log(log_warning, "Configuration option %s deprecated and ingnored.", key); \
LOG_WARN("Configuration option %s deprecated and ingnored.", key); \
return 0; \
} \
/* default configuration values */
#define DEF_SERVER_BIND_ADDR "any"
#define DEF_SERVER_PORT 1511
#define DEF_SERVER_BACKLOG 50
#define DEF_SERVER_ALT_PORTS ""
#define DEF_HUB_NAME "uhub"
#define DEF_HUB_DESCRIPTION ""
#define DEF_HUB_ENABLED 1
#define DEF_FILE_ACL ""
#define DEF_FILE_MOTD ""
#define DEF_FILE_RULES ""
#define DEF_MAX_USERS 500
#define DEF_MAX_CHAT_HISTORY 20
#define DEF_MAX_LOGOUT_LOG 100
#define DEF_MAX_RECV_BUFFER 4096
#define DEF_MAX_SEND_BUFFER 131072
#define DEF_MAX_SEND_BUFFER_SOFT 98304
#define DEF_SHOW_BANNER 1
#define DEF_SHOW_BANNER_SYS_INFO 1
#define DEF_REGISTERED_USERS_ONLY 0
#define DEF_OBSOLETE_CLIENTS 0
#define DEF_CHAT_ONLY 0
#define DEF_CHAT_IS_PRIVILEGED 0
#define DEF_LOW_BANDWIDTH_MODE 0
@@ -135,6 +142,16 @@
#define DEF_LIMIT_MAX_SHARE 0
#define DEF_LIMIT_MIN_SLOTS 0
#define DEF_LIMIT_MAX_SLOTS 0
#define DEF_FLOOD_INTERVAL 0
#define DEF_FLOOD_CHAT 0
#define DEF_FLOOD_CONNECT 0
#define DEF_FLOOD_SEARCH 0
#define DEF_FLOOD_UPDATE 0
#define DEF_FLOOD_EXTRAS 0
#define DEF_TLS_ENABLE 0
#define DEF_TLS_REQUIRE 1
#define DEF_TLS_PRIVATE_KEY ""
#define DEF_TLS_CERTIFICATE ""
#define DEF_MSG_HUB_FULL "Hub is full"
#define DEF_MSG_HUB_DISABLED "Hub is disabled"
#define DEF_MSG_HUB_REGISTERED_USERS_ONLY "Hub is for registered users only"
@@ -164,6 +181,13 @@
#define DEF_MSG_USER_SLOTS_HIGH "User have too many upload slots."
#define DEF_MSG_USER_HUB_LIMIT_LOW "User is on too few hubs."
#define DEF_MSG_USER_HUB_LIMIT_HIGH "User is on too many hubs."
#define DEF_MSG_FLOOD_CHAT "Chat flood detected, messages are dropped."
#define DEF_MSG_FLOOD_CONNECT "Connect flood detected, connection refused."
#define DEF_MSG_FLOOD_SEARCH "Search flood detected, search is stopped."
#define DEF_MSG_FLOOD_UPDATE "Update flood detected."
#define DEF_MSG_FLOOD_EXTRAS "Flood detected."
#define DEF_MSG_PROTO_NO_COMMON_HASH "No common hash algorithm."
#define DEF_MSG_PROTO_OBSOLETE_ADC0 "Your client does not support ADC/1.0."
void config_defaults(struct hub_config* config)
{
@@ -173,17 +197,24 @@ void config_defaults(struct hub_config* config)
DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED);
DEFAULT_STRING (file_acl, DEF_FILE_ACL);
DEFAULT_STRING (file_motd, DEF_FILE_MOTD);
DEFAULT_STRING (file_rules, DEF_FILE_RULES);
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
DEFAULT_INTEGER(server_listen_backlog, DEF_SERVER_BACKLOG);
DEFAULT_STRING (server_alt_ports, DEF_SERVER_ALT_PORTS);
DEFAULT_INTEGER(max_users, DEF_MAX_USERS);
DEFAULT_INTEGER(max_chat_history, DEF_MAX_CHAT_HISTORY);
DEFAULT_INTEGER(max_logout_log, DEF_MAX_LOGOUT_LOG);
DEFAULT_INTEGER(max_recv_buffer, DEF_MAX_RECV_BUFFER);
DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER);
DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER);
DEFAULT_BOOLEAN(show_banner_sys_info, DEF_SHOW_BANNER_SYS_INFO);
DEFAULT_BOOLEAN(obsolete_clients, DEF_OBSOLETE_CLIENTS);
DEFAULT_BOOLEAN(chat_only, DEF_CHAT_ONLY);
DEFAULT_BOOLEAN(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
DEFAULT_BOOLEAN(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
DEFAULT_BOOLEAN(registered_users_only, DEF_REGISTERED_USERS_ONLY);
/* Limits enforced on users */
DEFAULT_INTEGER(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
DEFAULT_INTEGER(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
@@ -197,6 +228,14 @@ void config_defaults(struct hub_config* config)
DEFAULT_INTEGER(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
DEFAULT_INTEGER(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
/* Flood control */
DEFAULT_INTEGER(flood_ctl_interval, DEF_FLOOD_INTERVAL);
DEFAULT_INTEGER(flood_ctl_chat, DEF_FLOOD_CHAT);
DEFAULT_INTEGER(flood_ctl_connect, DEF_FLOOD_CONNECT);
DEFAULT_INTEGER(flood_ctl_search, DEF_FLOOD_SEARCH);
DEFAULT_INTEGER(flood_ctl_update, DEF_FLOOD_UPDATE);
DEFAULT_INTEGER(flood_ctl_extras, DEF_FLOOD_EXTRAS);
/* Status/error strings */
DEFAULT_STRING (msg_hub_full, DEF_MSG_HUB_FULL);
DEFAULT_STRING (msg_hub_disabled, DEF_MSG_HUB_DISABLED)
@@ -227,11 +266,18 @@ void config_defaults(struct hub_config* config)
DEFAULT_STRING (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
DEFAULT_STRING (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
DEFAULT_STRING (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
DEFAULT_STRING (msg_user_flood_chat, DEF_MSG_FLOOD_CHAT);
DEFAULT_STRING (msg_user_flood_connect, DEF_MSG_FLOOD_CONNECT);
DEFAULT_STRING (msg_user_flood_search, DEF_MSG_FLOOD_SEARCH);
DEFAULT_STRING (msg_user_flood_update, DEF_MSG_FLOOD_UPDATE);
DEFAULT_STRING (msg_user_flood_extras, DEF_MSG_FLOOD_EXTRAS);
DEFAULT_STRING (msg_proto_no_common_hash, DEF_MSG_PROTO_NO_COMMON_HASH);
DEFAULT_STRING (msg_proto_obsolete_adc0, DEF_MSG_PROTO_OBSOLETE_ADC0);
DEFAULT_INTEGER(tls_enable, 0);
DEFAULT_INTEGER(tls_require, 0);
DEFAULT_STRING (tls_certificate, "");
DEFAULT_STRING (tls_private_key, "");
DEFAULT_INTEGER(tls_enable, DEF_TLS_ENABLE);
DEFAULT_INTEGER(tls_require, DEF_TLS_REQUIRE);
DEFAULT_STRING (tls_certificate, DEF_TLS_CERTIFICATE);
DEFAULT_STRING (tls_private_key, DEF_TLS_PRIVATE_KEY);
}
@@ -239,16 +285,23 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
{
GET_STR (file_acl);
GET_STR (file_motd);
GET_STR (file_rules);
GET_STR (server_bind_addr);
GET_INT (server_port);
GET_INT (server_listen_backlog);
GET_STR (server_alt_ports);
GET_STR (hub_name);
GET_STR (hub_description);
GET_BOOL(hub_enabled);
GET_INT (max_users);
GET_INT (max_chat_history);
GET_INT (max_logout_log);
GET_INT (max_recv_buffer);
GET_INT (max_send_buffer);
GET_INT (max_send_buffer_soft);
GET_BOOL(show_banner);
GET_BOOL(show_banner_sys_info);
GET_BOOL(obsolete_clients);
GET_BOOL(chat_only);
GET_BOOL(chat_is_privileged);
GET_BOOL(low_bandwidth_mode);
@@ -266,7 +319,14 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
GET_INT(limit_max_share);
GET_INT(limit_min_slots);
GET_INT(limit_max_slots);
GET_INT(flood_ctl_interval);
GET_INT(flood_ctl_chat);
GET_INT(flood_ctl_connect);
GET_INT(flood_ctl_search);
GET_INT(flood_ctl_update);
GET_INT(flood_ctl_extras);
/* Status/error strings */
GET_STR (msg_hub_full);
GET_STR (msg_hub_disabled);
@@ -297,14 +357,22 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
GET_STR (msg_user_slots_high);
GET_STR (msg_user_hub_limit_low);
GET_STR (msg_user_hub_limit_high);
GET_STR (msg_user_flood_chat);
GET_STR (msg_user_flood_connect);
GET_STR (msg_user_flood_search);
GET_STR (msg_user_flood_update);
GET_STR (msg_user_flood_extras);
GET_STR (msg_proto_no_common_hash);
GET_STR (msg_proto_obsolete_adc0);
/* TLS/SSL related */
GET_BOOL(tls_enable);
GET_BOOL(tls_require);
GET_STR (tls_certificate);
GET_STR (tls_private_key);
/* Still here -- unknown directive */
hub_log(log_fatal, "Unknown configuration directive: '%s'", key);
/* Still here -- unknown directive */
LOG_ERROR("Unknown configuration directive: '%s'", key);
return -1;
}
@@ -312,11 +380,13 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
void free_config(struct hub_config* config)
{
hub_free(config->server_bind_addr);
hub_free(config->server_alt_ports);
hub_free(config->file_motd);
hub_free(config->file_acl);
hub_free(config->file_rules);
hub_free(config->hub_name);
hub_free(config->hub_description);
hub_free(config->msg_hub_full);
hub_free(config->msg_hub_disabled);
hub_free(config->msg_hub_registered_users_only);
@@ -346,7 +416,14 @@ void free_config(struct hub_config* config)
hub_free(config->msg_user_slots_high);
hub_free(config->msg_user_hub_limit_low);
hub_free(config->msg_user_hub_limit_high);
hub_free(config->msg_user_flood_chat);
hub_free(config->msg_user_flood_connect);
hub_free(config->msg_user_flood_search);
hub_free(config->msg_user_flood_update);
hub_free(config->msg_user_flood_extras);
hub_free(config->msg_proto_no_common_hash);
hub_free(config->msg_proto_obsolete_adc0);
hub_free(config->tls_certificate);
hub_free(config->tls_private_key);
@@ -385,21 +462,35 @@ void dump_config(struct hub_config* config, int ignore_defaults)
{
DUMP_STR (file_acl, DEF_FILE_ACL);
DUMP_STR (file_motd, DEF_FILE_MOTD);
DUMP_STR (file_rules, DEF_FILE_RULES);
DUMP_STR (server_bind_addr, DEF_SERVER_BIND_ADDR);
DUMP_INT (server_port, DEF_SERVER_PORT);
DUMP_INT (server_listen_backlog, DEF_SERVER_BACKLOG);
DUMP_STR (server_alt_ports, DEF_SERVER_ALT_PORTS);
DUMP_STR (hub_name, DEF_HUB_NAME);
DUMP_STR (hub_description, DEF_HUB_DESCRIPTION);
DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED);
DUMP_INT (max_users, DEF_MAX_USERS);
DUMP_INT (max_chat_history, DEF_MAX_CHAT_HISTORY);
DUMP_INT (max_logout_log, DEF_MAX_LOGOUT_LOG);
DUMP_INT (max_recv_buffer, DEF_MAX_RECV_BUFFER);
DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER);
DUMP_INT (max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
DUMP_BOOL(show_banner, DEF_SHOW_BANNER);
DUMP_BOOL(show_banner_sys_info, DEF_SHOW_BANNER_SYS_INFO);
DUMP_BOOL(obsolete_clients, DEF_OBSOLETE_CLIENTS);
DUMP_BOOL(chat_only, DEF_CHAT_ONLY);
DUMP_BOOL(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
DUMP_BOOL(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
DUMP_BOOL(registered_users_only, DEF_REGISTERED_USERS_ONLY);
#ifdef SSL_SUPPORT
DUMP_BOOL(tls_enable, DEF_TLS_ENABLE);
DUMP_BOOL(tls_require, DEF_TLS_REQUIRE);
DUMP_STR (tls_certificate, DEF_TLS_CERTIFICATE);
DUMP_STR (tls_private_key, DEF_TLS_PRIVATE_KEY);
#endif
/* Limits enforced on users */
DUMP_INT(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
DUMP_INT(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
@@ -412,7 +503,14 @@ void dump_config(struct hub_config* config, int ignore_defaults)
DUMP_INT(limit_max_share, DEF_LIMIT_MAX_SHARE);
DUMP_INT(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
DUMP_INT(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
DUMP_INT(flood_ctl_interval, DEF_FLOOD_INTERVAL);
DUMP_INT(flood_ctl_chat, DEF_FLOOD_CHAT);
DUMP_INT(flood_ctl_connect, DEF_FLOOD_CONNECT);
DUMP_INT(flood_ctl_search, DEF_FLOOD_SEARCH);
DUMP_INT(flood_ctl_update, DEF_FLOOD_UPDATE);
DUMP_INT(flood_ctl_extras, DEF_FLOOD_EXTRAS);
/* Status/error strings */
DUMP_STR (msg_hub_full, DEF_MSG_HUB_FULL);
DUMP_STR (msg_hub_disabled, DEF_MSG_HUB_DISABLED);
@@ -443,6 +541,13 @@ void dump_config(struct hub_config* config, int ignore_defaults)
DUMP_STR (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
DUMP_STR (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
DUMP_STR (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
DUMP_STR (msg_user_flood_chat, DEF_MSG_FLOOD_CHAT);
DUMP_STR (msg_user_flood_connect, DEF_MSG_FLOOD_CONNECT);
DUMP_STR (msg_user_flood_search, DEF_MSG_FLOOD_SEARCH);
DUMP_STR (msg_user_flood_update, DEF_MSG_FLOOD_UPDATE);
DUMP_STR (msg_user_flood_extras, DEF_MSG_FLOOD_EXTRAS);
DUMP_STR (msg_proto_no_common_hash, DEF_MSG_PROTO_NO_COMMON_HASH);
DUMP_STR (msg_proto_obsolete_adc0, DEF_MSG_PROTO_OBSOLETE_ADC0);
}
@@ -460,9 +565,12 @@ static int config_parse_line(char* line, int line_count, void* ptr_data)
if (!*line) return 0;
#ifdef CONFIG_DUMP
hub_log(log_trace, "config_parse_line(): '%s'", line);
#endif
LOG_DUMP("config_parse_line(): '%s'", line);
if (!is_valid_utf8(line))
{
LOG_WARN("Invalid utf-8 characters on line %d", line_count);
}
if ((pos = strchr(line, '=')) != NULL)
{
@@ -481,13 +589,11 @@ static int config_parse_line(char* line, int line_count, void* ptr_data)
if (!*key || !*data)
{
hub_log(log_fatal, "Configuration parse error on line %d", line_count);
LOG_FATAL("Configuration parse error on line %d", line_count);
return -1;
}
#ifdef CONFIG_DUMP
hub_log(log_trace, "config_parse_line: '%s' => '%s'", key, data);
#endif
LOG_DUMP("config_parse_line: '%s' => '%s'", key, data);
return apply_config(config, key, data, line_count);
}
@@ -504,7 +610,7 @@ int read_config(const char* file, struct hub_config* config, int allow_missing)
{
if (allow_missing && ret == -2)
{
hub_log(log_debug, "Using default configuration.");
LOG_DUMP("Using default configuration.");
}
else
{

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,21 +24,29 @@ struct hub_config
{
int server_port; /**<<< "Server port to bind to (default: 1511)" */
char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */
int server_listen_backlog; /**<<< "Server listen backlog (default: 50)" */
char* server_alt_ports; /**<<< "Comma separated list of alternative ports to listen to (default: '')" */
int hub_enabled; /**<<< "Is server enabled (default: 1)" */
int show_banner; /**<<< "Show banner on connect (default: 1)" */
int show_banner_sys_info; /**<<< "Show banner system information (default: 1). Has no effect unless show_banner is enabled." */
int max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
int obsolete_clients; /**<<< "Support obsolete clients using a ADC protocol prior to 1.0 (default: off)" */
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */
char* file_acl; /**<<< "File containing user database (default: '' - no known users)" */
char* file_rules; /**<<< "File containing the rules (default: '' - no rules)" */
char* hub_name; /**<<< "Name of hub (default: 'My uhub hub')" */
char* hub_description; /**<<< "Name of hub (default: 'no description')" */
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
int max_send_buffer; /**<<< "Max send buffer before disconnect, per user (default: 128K)" */
int max_send_buffer_soft; /**<<< "Max send buffer before message drops, per user (default: 96K)" */
int low_bandwidth_mode; /**<<< "If this is enabled, the hub will strip off elements from each user's info message to reduce bandwidth usage" */
int max_chat_history; /**<<< "Number of chat messages kept in history (default: 20)" */
int max_logout_log; /**<<< "Number of log entries for people leaving the hub. (default: 100) */
/* Limits enforced on users */
int limit_max_hubs_user; /**<<< "Max concurrent hubs as a user. (0=off, default: 10)" */
int limit_max_hubs_reg; /**<<< "Max concurrent hubs as registered user. (0=off, default: 10)" */
@@ -51,7 +59,14 @@ struct hub_config
int limit_max_share; /**<<< "Limit maximum share size in megabytes (MiB) (0=off, default: 0)" */
int limit_min_slots; /**<<< "Limit minimum number of slots open per user (0=off, default: 0)" */
int limit_max_slots; /**<<< "Limit maximum number of slots open per user (0=off, default: 0)" */
int flood_ctl_interval; /**<<< "Time interval in seconds for flood control check. If 0 then all flood control is disabled. (0=off, default: 0)" */
int flood_ctl_chat; /**<<< "Max chat messages allowed inside the time interval (0=off, default: 0)" */
int flood_ctl_connect; /**<<< "Max connect requests allowed inside the time interval (0=off, default: 0)" */
int flood_ctl_search; /**<<< "Max search requests allowed inside the time interval (0=off, default: 0)" */
int flood_ctl_update; /**<<< "Max updates allowed inside the time interval (0=off, default: 0)" */
int flood_ctl_extras; /**<<< "Max extra protocol messages allowed inside the time interval (0=off, default: 0)" */
/* Messages that can be sent to a user */
char* msg_hub_full; /**<<< "hub is full" */
char* msg_hub_disabled; /**<<< "hub is disabled" */
@@ -82,6 +97,13 @@ struct hub_config
char* msg_user_slots_high; /**<<< "User have too many upload slots." */
char* msg_user_hub_limit_low; /**<<< "User is on too few hubs." */
char* msg_user_hub_limit_high; /**<<< "User is on too many hubs." */
char* msg_user_flood_chat; /**<<< "Chat flood detected, messages are dropped." */
char* msg_user_flood_connect; /**<<< "Connect flood detected, connection refused." */
char* msg_user_flood_search; /**<<< "Search flood detected, search is stopped." */
char* msg_user_flood_update; /**<<< "Update flood detected." */
char* msg_user_flood_extras; /**<<< "Flood detected." */
char* msg_proto_no_common_hash; /**<<< "No common hash algorithm." */
char* msg_proto_obsolete_adc0; /**<<< "Client is using an obsolete ADC protocol version." */
int tls_enable; /**<<< "Enable SSL/TLS support (default: 0)" */
int tls_require; /**<<< "If SSL/TLS enabled, should it be required (default: 0) */

View File

@@ -28,10 +28,14 @@
/* Send a broadcast message */
#define UHUB_EVENT_BROADCAST 0x2000
/* Shutdown hub */
#define UHUB_EVENT_HUB_SHUTDOWN 0x3001
/* Statistics, OOM, reconfigure */
#define UHUB_EVENT_STATISTICS 0x4000
#define UHUB_EVENT_OUT_OF_MEMORY 0x4001
#define UHUB_EVENT_RECONFIGURE 0x4002
#endif /* HAVE_UHUB_EVENT_ID_H */

View File

@@ -22,7 +22,7 @@
#ifdef EQ_DEBUG
static void eq_debug(const char* prefix, struct event_data* data)
{
printf(">>> %s: %p, id: %x, flags=%d\n", prefix, data, data->id, data->flags);
LOG_DUMP(">>> %s: %p, id: %x, flags=%d\n", prefix, data, data->id, data->flags);
}
#endif
@@ -130,7 +130,7 @@ void event_queue_post(struct event_queue* queue, struct event_data* message)
}
else
{
hub_log(log_error, "event_queue_post: OUT OF MEMORY");
LOG_ERROR("event_queue_post: OUT OF MEMORY");
}
}

55
src/core/floodctl.c Normal file
View File

@@ -0,0 +1,55 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
void flood_control_reset(struct flood_control* data)
{
memset(data, 0, sizeof(struct flood_control));
}
int flood_control_check(struct flood_control* data, size_t max_count, size_t time_delay, time_t now)
{
// Is flood control disabled?
if (!time_delay || !max_count)
return 0;
if (!data->time)
{
data->time = now;
data->count = 0;
return 0;
}
if ((now - data->time) > time_delay)
{
data->time = now;
data->count = 0;
return 0;
}
if (data->count <= max_count)
{
data->count++;
return 0;
}
return 1;
}

47
src/core/floodctl.h Normal file
View File

@@ -0,0 +1,47 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_FLOOD_CTL_H
#define HAVE_UHUB_FLOOD_CTL_H
struct flood_control
{
time_t time;
size_t count;
};
/**
* Reset flood control statistics
*/
void flood_control_reset(struct flood_control*);
/**
* @param ctl Flood control data structure
* @param max_count Max count for flood control
* @param window Time window for max_count to appear.
* @param now The current time.
*
* @return 0 if flood no flood detected.
* 1 if flood detected.
*/
int flood_control_check(struct flood_control* ctl, size_t max_count, size_t window, time_t now);
#endif /* HAVE_UHUB_FLOOD_CTL_H */

1274
src/core/hub.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -45,7 +45,7 @@ enum status_message
status_msg_auth_invalid_password = -21, /* Password is wrong */
status_msg_auth_user_not_found = -22, /* User not found in password database */
status_msg_error_no_memory = -23, /* Hub is out of memory */
status_msg_user_share_size_low = -40, /* User is not sharing enough. */
status_msg_user_share_size_high = -41, /* User is sharing too much. */
status_msg_user_slots_low = -42, /* User has too few slots open. */
@@ -53,6 +53,10 @@ enum status_message
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
status_msg_proto_no_common_hash = -50, /* No common hash algorithms */
status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */
};
@@ -79,29 +83,37 @@ struct hub_stats
size_t net_rx_total;
};
struct hub_logout_info
{
time_t time;
char cid[MAX_CID_LEN+1];
char nick[MAX_NICK_LEN+1];
struct ip_addr_encap addr;
enum user_quit_reason reason;
};
struct hub_info
{
int fd_tcp;
#ifdef ADC_UDP_OPERATION
int fd_udp;
#endif
struct event ev_accept;
struct event ev_timer;
#ifdef ADC_UDP_OPERATION
struct event ev_datagram;
#endif
struct net_connection* server;
struct linked_list* server_alt_ports;
struct hub_stats stats;
struct event_queue* queue;
struct event_base* evbase;
struct hub_config* config;
struct user_manager* users;
struct hub_user_manager* users;
struct acl_handle* acl;
struct adc_message* command_info; /* The hub's INF command */
struct adc_message* command_support; /* The hub's SUP command */
struct adc_message* command_motd; /* The message of the day */
struct adc_message* command_rules; /* The hub rules */
struct adc_message* command_banner; /* The default welcome message */
time_t tm_started;
int status;
char* recvbuf; /* Global receive buffer */
char* sendbuf; /* Global send buffer */
struct linked_list* chat_history; /* Chat history */
struct linked_list* logout_info; /* Log of people logging out. */
#ifdef SSL_SUPPORT
SSL_METHOD* ssl_method;
SSL_CTX* ssl_ctx;
@@ -116,106 +128,116 @@ struct hub_info
*
* @return 0 on success, -1 on error
*/
extern int hub_handle_message(struct user* u, const char* message, size_t length);
extern int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* message, size_t length);
/**
* Handle protocol support/subscription messages received clients.
*
* @return 0 on success, -1 on error
*/
extern int hub_handle_support(struct user* u, struct adc_message* cmd);
extern int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
/**
* Handle password messages received from clients.
*
* @return 0 on success, -1 on error
*/
extern int hub_handle_password(struct user* u, struct adc_message* cmd);
extern int hub_handle_password(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
/**
* Handle chat messages received from clients.
* @return 0 on success, -1 on error.
*/
extern int hub_handle_chat_message(struct user* u, struct adc_message* cmd);
extern int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
/**
* Add a chat message to the chat history
*/
extern void hub_chat_history_add(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd);
/**
* Clear the chat history.
*/
extern void hub_chat_history_clear(struct hub_info* hub);
/**
* Used internally by hub_handle_info
* @return 1 if nickname is OK, or 0 if nickname is not accepted.
*/
extern int hub_handle_info_check_nick(struct user* u, struct adc_message* cmd);
extern int hub_handle_info_check_nick(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
/**
* Used internally by hub_handle_info
* @return 1 if CID/PID is OK, or 0 if not valid.
*/
extern int hub_handle_info_check_cid(struct user* u, struct adc_message* cmd);
/**
* Can only be used by administrators or operators.
*
* @return 0 on success, -1 on error
*/
extern int hub_handle_kick(struct user* u, struct adc_message* cmd);
#ifdef ADC_UDP_OPERATION
/**
* Handle incoming autocheck message.
*/
extern int hub_handle_autocheck(struct user* u, struct adc_message* cmd);
#endif
extern int hub_handle_info_check_cid(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
/**
* Send the support line for the hub to a particular user.
* Only used during the initial handshake.
*/
extern void hub_send_support(struct user* u);
extern void hub_send_support(struct hub_info* hub, struct hub_user* u);
/**
* Send a message assigning a SID for a user.
* This is only sent after hub_send_support() during initial handshake.
*/
extern void hub_send_sid(struct user* u);
extern void hub_send_sid(struct hub_info* hub, struct hub_user* u);
/**
* Send a 'ping' message to user.
*/
extern void hub_send_ping(struct user* user);
extern void hub_send_ping(struct hub_info* hub, struct hub_user* user);
/**
* Send a message containing hub information to a particular user.
* This is sent during user connection, but can safely be sent at any
* point later.
*/
extern void hub_send_hubinfo(struct user* u);
extern void hub_send_hubinfo(struct hub_info* hub, struct hub_user* u);
/**
* Send handshake. This basically calls
* hub_send_support() and hub_send_sid()
*/
extern void hub_send_handshake(struct user* u);
extern void hub_send_handshake(struct hub_info* hub, struct hub_user* u);
/**
* Send a welcome message containing the message of the day to
* one particular user. This can be sent in any point in time.
* @return 1 if the motd were sent.
*/
extern void hub_send_motd(struct user* u);
extern int hub_send_motd(struct hub_info* hub, struct hub_user* u);
/**
* Send the rules if configured.
* @return 1 if the rules were sent.
*/
extern int hub_send_rules(struct hub_info* hub, struct hub_user* u);
/**
* Send a password challenge to a user.
* This is only used if the user tries to access the hub using a
* password protected nick name.
*/
extern void hub_send_password_challenge(struct user* u);
extern void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u);
/**
* Send an autocheck message to a user.
* This is basically a UDP message. The user's client can then determine
* if UDP communication works by either hole punching or configuring UPnP.
* Sends a status_message to a user.
*/
extern void hub_send_autocheck(struct user* u, uint16_t port, const char* token);
extern void hub_send_status(struct hub_info*, struct hub_user* user, enum status_message msg, enum msg_status_level level);
/**
* This starts the hub.
* Warn user about flooding.
*/
extern void hub_send_flood_warning(struct hub_info*, struct hub_user* user, const char* message);
/**
* Allocates memory, initializes the hub based on the configuration,
* and returns a hub handle.
* This hub handle must be passed to hub_shutdown_service() in order to cleanup before exiting.
*
* @return a pointer to the hub info.
*/
extern struct hub_info* hub_start_service(struct hub_config* config);
@@ -238,11 +260,7 @@ extern void hub_free_variables(struct hub_info* hub);
* Returns a string for the given status_message (See enum status_message).
*/
extern const char* hub_get_status_message(struct hub_info* hub, enum status_message msg);
/**
* Sends a status_message to a user.
*/
extern void hub_send_status(struct user* user, enum status_message msg, enum msg_status_level level);
extern const char* hub_get_status_message_log(struct hub_info* hub, enum status_message msg);
/**
* Returns the number of logged in users on the hub.
@@ -340,6 +358,21 @@ extern void hub_schedule_runslice(struct hub_info* hub);
*/
extern void hub_event_loop(struct hub_info* hub);
/**
* Schedule destroying a user.
*/
extern void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user);
/**
* Disconnect a user from the hub.
*/
extern void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason);
/**
* Log a user logging out.
*/
extern void hub_logout_log(struct hub_info* hub, struct hub_user* user);
#endif /* HAVE_UHUB_HUB_H */

114
src/core/hubevent.c Normal file
View File

@@ -0,0 +1,114 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
static void log_user_login(struct hub_user* u)
{
const char* cred = get_user_credential_string(u->credentials);
const char* addr = user_get_address(u);
LOG_USER("LoginOK %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, cred, u->user_agent);
}
static void log_user_login_error(struct hub_user* u, enum status_message msg)
{
const char* addr = user_get_address(u);
const char* message = hub_get_status_message_log(u->hub, msg);
LOG_USER("LoginError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
}
static void log_user_update_error(struct hub_user* u, enum status_message msg)
{
const char* addr = user_get_address(u);
const char* message = hub_get_status_message_log(u->hub, msg);
LOG_USER("UpdateError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent);
}
static void log_user_logout(struct hub_user* u, const char* message)
{
const char* addr = user_get_address(u);
LOG_USER("Logout %s/%s %s \"%s\" (%s)", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message);
}
static void log_user_nick_change(struct hub_user* u, const char* nick)
{
const char* addr = user_get_address(u);
LOG_USER("NickChange %s/%s %s \"%s\" -> \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, nick);
}
/* Send MOTD, do logging etc */
void on_login_success(struct hub_info* hub, struct hub_user* u)
{
/* Send user list of all existing users */
if (!uman_send_user_list(hub, u))
return;
/* Mark as being in the normal state, and add user to the user list */
user_set_state(u, state_normal);
uman_add(hub, u);
/* Print log message */
log_user_login(u);
/* Announce new user to all connected users */
if (user_is_logged_in(u))
route_info_message(hub, u);
/* Send message of the day (if any) */
if (user_is_logged_in(u)) /* Previous send() can fail! */
hub_send_motd(hub, u);
/* Send message of the day (if any) */
if (user_is_logged_in(u)) /* Previous send() can fail! */
hub_send_rules(hub, u);
/* reset timeout */
net_con_clear_timeout(u->connection);
}
void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
{
log_user_login_error(u, msg);
hub_send_status(hub, u, msg, status_level_fatal);
hub_disconnect_user(hub, u, quit_logon_error);
}
void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
{
log_user_update_error(u, msg);
hub_send_status(hub, u, msg, status_level_fatal);
hub_disconnect_user(hub, u, quit_update_error);
}
void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick)
{
if (user_is_logged_in(u))
{
log_user_nick_change(u, nick);
}
}
void on_logout_user(struct hub_info* hub, struct hub_user* user)
{
const char* reason = user_get_quit_reason_string(user->quit_reason);
log_user_logout(user, reason);
hub_logout_log(hub, user);
}

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,22 +23,23 @@
/**
* This event is triggered whenever a user successfully logs in to the hub.
*/
extern void on_login_success(struct user* u);
extern void on_login_success(struct hub_info* hub, struct hub_user* u);
/**
* This event is triggered whenever a user failed to log in to the hub.
*/
extern void on_login_failure(struct user* u, enum status_message msg);
extern void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
extern void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
/**
* This event is triggered whenever a previously logged in user leaves the hub.
*/
extern void on_logout_user(struct user* u);
extern void on_logout_user(struct hub_info* hub, struct hub_user* u);
/**
* This event is triggered whenever a user changes his/her nickname.
*/
extern void on_nick_change(struct user* u, const char* nick);
extern void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick);
#endif /* HAVE_UHUB_HUB_EVENT_H */

173
src/core/hubio.c Normal file
View File

@@ -0,0 +1,173 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#include "hubio.h"
#ifdef DEBUG_SENDQ
static void debug_msg(const char* prefix, struct adc_message* msg)
{
size_t n;
char* buf = strdup(msg->cache);
for (n = 0; n < msg->length; n++)
{
if (buf[n] == '\r' || buf[n] == '\n')
buf[n] = '_';
}
LOG_TRACE("%s: [%s] (%d bytes)", prefix, buf, (int) msg->length);
free(buf);
}
#endif
struct hub_recvq* hub_recvq_create()
{
struct hub_recvq* q = hub_malloc_zero(sizeof(struct hub_recvq));
return q;
}
void hub_recvq_destroy(struct hub_recvq* q)
{
if (q)
{
hub_free(q->buf);
hub_free(q);
}
}
size_t hub_recvq_get(struct hub_recvq* q, void* buf, size_t bufsize)
{
assert(bufsize >= q->size);
if (q->size)
{
size_t n = q->size;
memcpy(buf, q->buf, n);
hub_free(q->buf);
q->buf = 0;
q->size = 0;
return n;
}
return 0;
}
size_t hub_recvq_set(struct hub_recvq* q, void* buf, size_t bufsize)
{
if (q->buf)
{
hub_free(q->buf);
q->buf = 0;
q->size = 0;
}
if (!bufsize)
{
return 0;
}
q->buf = hub_malloc(bufsize);
if (!q->buf)
return 0;
q->size = bufsize;
memcpy(q->buf, buf, bufsize);
return bufsize;
}
struct hub_sendq* hub_sendq_create()
{
struct hub_sendq* q = hub_malloc_zero(sizeof(struct hub_sendq));
if (!q)
return 0;
q->queue = list_create();
if (!q->queue)
{
hub_free(q);
return 0;
}
return q;
}
static void clear_send_queue_callback(void* ptr)
{
adc_msg_free((struct adc_message*) ptr);
}
void hub_sendq_destroy(struct hub_sendq* q)
{
if (q)
{
list_clear(q->queue, &clear_send_queue_callback);
list_destroy(q->queue);
hub_free(q);
}
}
void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
{
struct adc_message* msg = adc_msg_incref(msg_);
#ifdef DEBUG_SENDQ
debug_msg("hub_sendq_add", msg);
#endif
assert(msg->cache && *msg->cache);
list_append(q->queue, msg);
q->size += msg->length;
}
void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
{
#ifdef DEBUG_SENDQ
debug_msg("hub_sendq_remove", msg);
#endif
list_remove(q->queue, msg);
q->size -= msg->length;
adc_msg_free(msg);
q->offset = 0;
}
int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
{
int ret;
struct adc_message* msg = list_get_first(q->queue);
if (!msg) return 0;
assert(msg->cache && *msg->cache);
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
if (ret > 0)
{
q->offset += ret;
if (msg->length - q->offset > 0)
return 0;
hub_sendq_remove(q, msg);
return 1;
}
return ret;
}
int hub_sendq_is_empty(struct hub_sendq* q)
{
return (q->size - q->offset) == 0;
}
size_t hub_sendq_get_bytes(struct hub_sendq* q)
{
return q->size - q->offset;
}

106
src/core/hubio.h Normal file
View File

@@ -0,0 +1,106 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_HUB_IO_H
#define HAVE_UHUB_HUB_IO_H
struct adc_message;
struct linked_list;
typedef int (*hub_recvq_write)(void* desc, const void* buf, size_t len);
typedef int (*hub_recvq_read)(void* desc, void* buf, size_t len);
struct hub_sendq
{
size_t size; /** Size of send queue (in bytes, not messages) */
size_t offset; /** Queue byte offset in the first message. Should be 0 unless a partial write. */
#ifdef SSL_SUPPORT
size_t last_send; /** When using SSL, one have to send the exact same buffer and length if a write cannot complete. */
#endif
struct linked_list* queue; /** List of queued messages */
};
struct hub_recvq
{
char* buf;
size_t size;
};
/**
* Create a send queue
*/
extern struct hub_sendq* hub_sendq_create();
/**
* Destroy a send queue, and delete any queued messages.
*/
extern void hub_sendq_destroy(struct hub_sendq*);
/**
* Add a message to the send queue.
*/
extern void hub_sendq_add(struct hub_sendq*, struct adc_message* msg);
/**
* Process the send queue, and send as many messages as possible.
* @returns -1 on error, 0 if unable to send more, 1 if more can be sent.
*/
extern int hub_sendq_send(struct hub_sendq*, struct hub_user*);
/**
* @returns 1 if send queue is empty, 0 otherwise.
*/
extern int hub_sendq_is_empty(struct hub_sendq*);
/**
* @returns the number of bytes remaining to be sent in the queue.
*/
extern size_t hub_sendq_get_bytes(struct hub_sendq*);
/**
* Create a receive queue.
*/
extern struct hub_recvq* hub_recvq_create();
/**
* Destroy a receive queue.
*/
extern void hub_recvq_destroy(struct hub_recvq*);
/**
* Gets the buffer, copies it into buf and deallocates it.
* NOTE: bufsize *MUST* be larger than the buffer, otherwise it asserts.
* @return the number of bytes copied into buf.
*/
extern size_t hub_recvq_get(struct hub_recvq*, void* buf, size_t bufsize);
/**
* Sets the buffer
*/
extern size_t hub_recvq_set(struct hub_recvq*, void* buf, size_t bufsize);
/**
* @return 1 if size is zero, 0 otherwise.
*/
extern int hub_recvq_is_empty(struct hub_recvq* buf);
#endif /* HAVE_UHUB_HUB_IO_H */

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -39,17 +39,18 @@ static void remove_server_restricted_flags(struct adc_message* cmd)
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_REFERER);
}
static int user_is_protected(struct user* user);
static int set_feature_cast_supports(struct user* u, struct adc_message* cmd)
static int set_feature_cast_supports(struct hub_user* u, struct adc_message* cmd)
{
char *it, *tmp;
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_SUPPORT))
{
tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT);
if (!tmp)
return -1; // FIXME: OOM
user_clear_feature_cast_support(u);
it = tmp;
while (strlen(it) > 4)
{
@@ -57,7 +58,7 @@ static int set_feature_cast_supports(struct user* u, struct adc_message* cmd)
user_set_feature_cast_support(u, it);
it = &it[5];
}
if (*it)
{
user_set_feature_cast_support(u, it);
@@ -73,9 +74,9 @@ static int check_hash_tiger(const char* cid, const char* pid)
char x_pid[64];
char raw_pid[64];
uint64_t tiger_res[3];
memset(x_pid, 0, MAX_CID_LEN+1);
base32_decode(pid, (unsigned char*) raw_pid, MAX_CID_LEN);
tiger((uint64_t*) raw_pid, TIGERSIZE, (uint64_t*) tiger_res);
base32_encode((unsigned char*) tiger_res, TIGERSIZE, x_pid);
@@ -89,7 +90,7 @@ static int check_hash_tiger(const char* cid, const char* pid)
/*
* FIXME: Only works for tiger hash. If a client doesnt support tiger we cannot let it in!
*/
static int check_cid(struct user* user, struct adc_message* cmd)
static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
size_t pos;
char* cid = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
@@ -101,7 +102,7 @@ static int check_cid(struct user* user, struct adc_message* cmd)
hub_free(pid);
return status_msg_error_no_memory;
}
if (strlen(cid) != MAX_CID_LEN)
{
hub_free(cid);
@@ -124,7 +125,7 @@ static int check_cid(struct user* user, struct adc_message* cmd)
hub_free(pid);
return status_msg_inf_error_cid_invalid;
}
if (!is_valid_base32_char(pid[pos]))
{
hub_free(cid);
@@ -150,7 +151,7 @@ static int check_cid(struct user* user, struct adc_message* cmd)
}
static int check_required_login_flags(struct user* user, struct adc_message* cmd)
static int check_required_login_flags(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
int num = 0;
@@ -186,15 +187,15 @@ static int check_required_login_flags(struct user* user, struct adc_message* cmd
* remove any wrong address, and replace it with the correct one
* as seen by the hub.
*/
int check_network(struct user* user, struct adc_message* cmd)
static int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
const char* address = ip_convert_to_string(&user->ipaddr);
const char* address = user_get_address(user);
/* Check for NAT override address */
if (acl_is_ip_nat_override(user->hub->acl, address))
if (acl_is_ip_nat_override(hub->acl, address))
{
char* client_given_ip = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
if (strcmp(client_given_ip, "0.0.0.0") != 0)
if (client_given_ip && strcmp(client_given_ip, "0.0.0.0") != 0)
{
user_set_nat_override(user);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
@@ -222,6 +223,13 @@ int check_network(struct user* user, struct adc_message* cmd)
return 0;
}
static void strip_network(struct hub_user* user, struct adc_message* cmd)
{
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_UDP_PORT);
}
static int nick_length_ok(const char* nick)
{
@@ -269,7 +277,7 @@ static int nick_is_utf8(const char* nick)
}
static int check_nick(struct user* user, struct adc_message* cmd)
static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
char* nick;
char* tmp;
@@ -317,10 +325,10 @@ static int check_nick(struct user* user, struct adc_message* cmd)
}
static int check_logged_in(struct user* user, struct adc_message* cmd)
static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
struct user* lookup1 = get_user_by_nick(user->hub, user->id.nick);
struct user* lookup2 = get_user_by_cid(user->hub, user->id.cid);
struct hub_user* lookup1 = uman_get_user_by_nick(hub, user->id.nick);
struct hub_user* lookup2 = uman_get_user_by_cid(hub, user->id.cid);
if (lookup1 == user)
{
@@ -331,20 +339,20 @@ static int check_logged_in(struct user* user, struct adc_message* cmd)
{
if (lookup1 == lookup2)
{
hub_log(log_debug, "check_logged_in: exact same user is logged in: %s", user->id.nick);
user_disconnect(lookup1, quit_timeout);
LOG_DEBUG("check_logged_in: exact same user is logged in: %s", user->id.nick);
hub_disconnect_user(hub, lookup1, quit_ghost_timeout);
return 0;
}
else
{
if (lookup1)
{
hub_log(log_debug, "check_logged_in: nickname is in use: %s", user->id.nick);
LOG_DEBUG("check_logged_in: nickname is in use: %s", user->id.nick);
return status_msg_inf_error_nick_taken;
}
else
{
hub_log(log_debug, "check_logged_in: CID is in use: %s", user->id.cid);
LOG_DEBUG("check_logged_in: CID is in use: %s", user->id.cid);
return status_msg_inf_error_cid_taken;
}
}
@@ -358,7 +366,7 @@ static int check_logged_in(struct user* user, struct adc_message* cmd)
* But this is not something we want to do, and is deprecated in the ADC specification.
* One should rather look at capabilities/features.
*/
static int check_user_agent(struct user* user, struct adc_message* cmd)
static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
char* ua_encoded = 0;
char* ua = 0;
@@ -379,19 +387,19 @@ static int check_user_agent(struct user* user, struct adc_message* cmd)
}
static int check_acl(struct user* user, struct adc_message* cmd)
static int check_acl(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
if (acl_is_cid_banned(user->hub->acl, user->id.cid))
if (acl_is_cid_banned(hub->acl, user->id.cid))
{
return status_msg_ban_permanently;
}
if (acl_is_user_banned(user->hub->acl, user->id.nick))
if (acl_is_user_banned(hub->acl, user->id.nick))
{
return status_msg_ban_permanently;
}
if (acl_is_user_denied(user->hub->acl, user->id.nick))
if (acl_is_user_denied(hub->acl, user->id.nick))
{
return status_msg_inf_error_nick_restricted;
}
@@ -399,7 +407,7 @@ static int check_acl(struct user* user, struct adc_message* cmd)
return 0;
}
static int check_limits(struct user* user, struct adc_message* cmd)
static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
char* arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_SIZE);
if (arg)
@@ -407,34 +415,34 @@ static int check_limits(struct user* user, struct adc_message* cmd)
int64_t shared_size = atoll(arg);
if (shared_size < 0)
shared_size = 0;
if (user_is_logged_in(user))
{
user->hub->users->shared_size -= user->limits.shared_size;
user->hub->users->shared_size += shared_size;
hub->users->shared_size -= user->limits.shared_size;
hub->users->shared_size += shared_size;
}
user->limits.shared_size = shared_size;
hub_free(arg);
arg = 0;
}
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
if (arg)
{
ssize_t shared_files = atoll(arg);
if (shared_files < 0)
shared_files = 0;
if (user_is_logged_in(user))
{
user->hub->users->shared_files -= user->limits.shared_files;
user->hub->users->shared_files += shared_files;
hub->users->shared_files -= user->limits.shared_files;
hub->users->shared_files += shared_files;
}
user->limits.shared_files = shared_files;
hub_free(arg);
arg = 0;
}
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
if (arg)
{
@@ -480,37 +488,37 @@ static int check_limits(struct user* user, struct adc_message* cmd)
if (!user_is_protected(user))
{
if (user->limits.shared_size < hub_get_min_share(user->hub) && hub_get_min_share(user->hub))
if (user->limits.shared_size < hub_get_min_share(hub) && hub_get_min_share(hub))
{
return status_msg_user_share_size_low;
}
if (user->limits.shared_size > hub_get_max_share(user->hub) && hub_get_max_share(user->hub))
if (user->limits.shared_size > hub_get_max_share(hub) && hub_get_max_share(hub))
{
return status_msg_user_share_size_high;
}
if ((user->limits.hub_count_user > hub_get_max_hubs_user(user->hub) && hub_get_max_hubs_user(user->hub)) ||
(user->limits.hub_count_registered > hub_get_max_hubs_reg(user->hub) && hub_get_max_hubs_reg(user->hub)) ||
(user->limits.hub_count_operator > hub_get_max_hubs_op(user->hub) && hub_get_max_hubs_op(user->hub)) ||
(user->limits.hub_count_total > hub_get_max_hubs_total(user->hub) && hub_get_max_hubs_total(user->hub)))
if ((user->limits.hub_count_user > hub_get_max_hubs_user(hub) && hub_get_max_hubs_user(hub)) ||
(user->limits.hub_count_registered > hub_get_max_hubs_reg(hub) && hub_get_max_hubs_reg(hub)) ||
(user->limits.hub_count_operator > hub_get_max_hubs_op(hub) && hub_get_max_hubs_op(hub)) ||
(user->limits.hub_count_total > hub_get_max_hubs_total(hub) && hub_get_max_hubs_total(hub)))
{
return status_msg_user_hub_limit_high;
}
if ((user->limits.hub_count_user < hub_get_min_hubs_user(user->hub) && hub_get_min_hubs_user(user->hub)) ||
(user->limits.hub_count_registered < hub_get_min_hubs_reg(user->hub) && hub_get_min_hubs_reg(user->hub)) ||
(user->limits.hub_count_operator < hub_get_min_hubs_op(user->hub) && hub_get_min_hubs_op(user->hub)))
if ((user->limits.hub_count_user < hub_get_min_hubs_user(hub) && hub_get_min_hubs_user(hub)) ||
(user->limits.hub_count_registered < hub_get_min_hubs_reg(hub) && hub_get_min_hubs_reg(hub)) ||
(user->limits.hub_count_operator < hub_get_min_hubs_op(hub) && hub_get_min_hubs_op(hub)))
{
return status_msg_user_hub_limit_low;
}
if (user->limits.upload_slots < hub_get_min_slots(user->hub) && hub_get_min_slots(user->hub))
if (user->limits.upload_slots < hub_get_min_slots(hub) && hub_get_min_slots(hub))
{
return status_msg_user_slots_low;
}
if (user->limits.upload_slots > hub_get_max_slots(user->hub) && hub_get_max_slots(user->hub))
if (user->limits.upload_slots > hub_get_max_slots(hub) && hub_get_max_slots(hub))
{
return status_msg_user_slots_high;
}
@@ -518,17 +526,16 @@ static int check_limits(struct user* user, struct adc_message* cmd)
return 0;
}
/*
* Set the expected credentials, and returns 1 if authentication is needed,
* or 0 if not.
* If the hub is configured to allow only registered users and the user
* is not recognized this will return 1.
*/
static int set_credentials(struct user* user, struct adc_message* cmd)
static int set_credentials(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
int ret = 0;
struct user_access_info* info = acl_get_access_info(user->hub->acl, user->id.nick);
struct hub_user_access_info* info = acl_get_access_info(hub->acl, user->id.nick);
if (info)
{
@@ -552,11 +559,11 @@ static int set_credentials(struct user* user, struct adc_message* cmd)
case cred_guest:
/* Nothing to be added to the info message */
break;
case cred_user:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_REGISTERED_USER);
break;
case cred_operator:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR);
break;
@@ -564,11 +571,11 @@ static int set_credentials(struct user* user, struct adc_message* cmd)
case cred_super:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER);
break;
case cred_admin:
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_ADMIN);
break;
case cred_link:
break;
}
@@ -577,84 +584,14 @@ static int set_credentials(struct user* user, struct adc_message* cmd)
}
/**
* Determines if a user is to be let into the hub even if the hub is "full".
*/
static int user_is_protected(struct user* user)
{
switch (user->credentials)
{
case cred_bot:
case cred_operator:
case cred_super:
case cred_admin:
case cred_link:
return 1;
default:
break;
}
return 0;
}
/**
* Returns 1 if a user is registered.
* Only registered users will be let in if the hub is configured for registered
* users only.
*/
static int user_is_registered(struct user* user)
{
switch (user->credentials)
{
case cred_bot:
case cred_user:
case cred_operator:
case cred_super:
case cred_admin:
case cred_link:
return 1;
default:
break;
}
return 0;
}
void update_user_info(struct user* u, struct adc_message* cmd)
{
char prefix[2];
char* argument;
size_t n = 0;
struct adc_message* cmd_new = adc_msg_copy(u->info);
if (!cmd_new)
{
/* FIXME: OOM! */
return;
}
argument = adc_msg_get_argument(cmd, n++);
while (argument)
{
if (strlen(argument) >= 2)
{
prefix[0] = argument[0];
prefix[1] = argument[1];
adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
}
hub_free(argument);
argument = adc_msg_get_argument(cmd, n++);
}
user_set_info(u, cmd_new);
}
static int check_is_hub_full(struct user* user)
static int check_is_hub_full(struct hub_info* hub, struct hub_user* user)
{
/*
* If hub is full, don't let users in, but we still want to allow
* operators and admins to enter the hub.
*/
if (user->hub->config->max_users && user->hub->users->count >= user->hub->config->max_users && !user_is_protected(user))
if (hub->config->max_users && hub->users->count >= hub->config->max_users && !user_is_protected(user))
{
return 1;
}
@@ -662,23 +599,16 @@ static int check_is_hub_full(struct user* user)
}
static int check_registered_users_only(struct user* user)
static int check_registered_users_only(struct hub_info* hub, struct hub_user* user)
{
if (user->hub->config->registered_users_only && !user_is_registered(user))
if (hub->config->registered_users_only && !user_is_registered(user))
{
return 1;
}
return 0;
}
#define INF_CHECK(FUNC, USER, CMD) \
do { \
int ret = FUNC(USER, CMD); \
if (ret < 0) \
return ret; \
} while(0)
static int hub_handle_info_common(struct user* user, struct adc_message* cmd)
static int hub_handle_info_common(struct hub_user* user, struct adc_message* cmd)
{
/* Remove server restricted flags */
remove_server_restricted_flags(cmd);
@@ -689,9 +619,9 @@ static int hub_handle_info_common(struct user* user, struct adc_message* cmd)
return 0;
}
static int hub_handle_info_low_bandwidth(struct user* user, struct adc_message* cmd)
static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
if (user->hub->config->low_bandwidth_mode)
if (hub->config->low_bandwidth_mode)
{
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
@@ -710,45 +640,62 @@ static int hub_handle_info_low_bandwidth(struct user* user, struct adc_message*
return 0;
}
int hub_handle_info_login(struct user* user, struct adc_message* cmd)
#define INF_CHECK(FUNC, HUB, USER, CMD) \
do { \
int ret = FUNC(HUB, USER, CMD); \
if (ret < 0) \
return ret; \
} while(0)
static int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
int need_auth = 0;
/* Make syntax checks. */
INF_CHECK(check_required_login_flags, user, cmd);
INF_CHECK(check_cid, user, cmd);
INF_CHECK(check_nick, user, cmd);
INF_CHECK(check_network, user, cmd);
INF_CHECK(check_user_agent, user, cmd);
INF_CHECK(check_acl, user, cmd);
INF_CHECK(check_logged_in, user, cmd);
INF_CHECK(check_required_login_flags, hub, user, cmd);
INF_CHECK(check_cid, hub, user, cmd);
INF_CHECK(check_nick, hub, user, cmd);
INF_CHECK(check_network, hub, user, cmd);
INF_CHECK(check_user_agent, hub, user, cmd);
INF_CHECK(check_acl, hub, user, cmd);
INF_CHECK(check_logged_in, hub, user, cmd);
return 0;
}
/**
* Perform additional INF checks used at time of login.
*
* @return 0 if success, <0 if error, >0 if authentication needed.
*/
int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
{
int code = 0;
INF_CHECK(hub_perform_login_checks, hub, user, cmd);
/* Private ID must never be broadcasted - drop it! */
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
/* FIXME: This needs some cleaning up */
need_auth = set_credentials(user, cmd);
code = set_credentials(hub, user, cmd);
/* Note: this must be done *after* set_credentials. */
if (check_is_hub_full(user))
if (check_is_hub_full(hub, user))
{
return status_msg_hub_full;
}
if (check_registered_users_only(user))
if (check_registered_users_only(hub, user))
{
return status_msg_hub_registered_users_only;
}
INF_CHECK(check_limits, user, cmd);
INF_CHECK(check_limits, hub, user, cmd);
/* strip off stuff if low_bandwidth_mode is enabled */
hub_handle_info_low_bandwidth(user, cmd);
hub_handle_info_low_bandwidth(hub, user, cmd);
/* Set initial user info */
user_set_info(user, cmd);
return need_auth;
return code;
}
/*
@@ -764,9 +711,10 @@ int hub_handle_info_login(struct user* user, struct adc_message* cmd)
* - CID/PID (valid, not taken, etc).
* - IP addresses (IPv4 and IPv6)
*/
int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified)
{
struct adc_message* cmd = adc_msg_copy(cmd_unmodified); /* FIXME: Have a small memory leak here! */
int ret;
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
if (!cmd) return -1; /* OOM */
cmd->priority = 1;
@@ -778,10 +726,20 @@ int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
*/
if (user_is_connecting(user))
{
int ret = hub_handle_info_login(user, cmd);
/*
* Don't allow the user to send multiple INF messages in this stage!
* Since that can have serious side-effects.
*/
if (user->info)
{
adc_msg_free(cmd);
return 0;
}
ret = hub_handle_info_login(hub, user, cmd);
if (ret < 0)
{
on_login_failure(user, ret);
on_login_failure(hub, user, ret);
adc_msg_free(cmd);
return -1;
}
@@ -793,7 +751,7 @@ int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
post.id = UHUB_EVENT_USER_JOIN;
post.ptr = user;
post.flags = ret; /* 0 - all OK, 1 - need authentication */
event_queue_post(user->hub->queue, &post);
event_queue_post(hub->queue, &post);
adc_msg_free(cmd);
return 0;
}
@@ -803,31 +761,41 @@ int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
/* These must not be allowed updated, let's remove them! */
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
/*
* If the nick is not accepted, do not relay it.
* Otherwise, the nickname will be updated.
*/
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_NICK))
{
#if ALLOW_CHANGE_NICK
if (!check_nick(user, cmd))
#ifdef ALLOW_CHANGE_NICK
if (!check_nick(hub, user, cmd))
#endif
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
}
/* FIXME - What if limits are not met ? */
check_limits(user, cmd);
hub_handle_info_low_bandwidth(user, cmd);
update_user_info(user, cmd);
ret = check_limits(hub, user, cmd);
if (ret < 0)
{
on_update_failure(hub, user, ret);
adc_msg_free(cmd);
return -1;
}
strip_network(user, cmd);
hub_handle_info_low_bandwidth(hub, user, cmd);
user_update_info(user, cmd);
if (!adc_msg_is_empty(cmd))
{
route_message(user, cmd);
route_message(hub, user, cmd);
}
adc_msg_free(cmd);
}
return 0;
}

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,7 +47,7 @@ enum nick_status
*
* @return 0 on success, -1 on error
*/
extern int hub_handle_info(struct user* u, const struct adc_message* cmd);
extern int hub_handle_info(struct hub_info* hub, struct hub_user* u, const struct adc_message* cmd);
#endif /* HAVE_UHUB_INF_PARSER_H */

View File

@@ -29,95 +29,75 @@ static const char* arg_uid = 0;
static const char* arg_gid = 0;
static const char* arg_config = 0;
static const char* arg_log = 0;
static const char* arg_pid = 0;
static int arg_log_syslog = 0;
#ifndef WIN32
void hub_handle_signal(int fd, short events, void* arg)
#if !defined(WIN32)
extern struct hub_info* g_hub;
void hub_handle_signal(int sig)
{
struct hub_info* hub = (struct hub_info*) arg;
int signal = fd;
struct timeval now = {0, 0};
struct hub_info* hub = g_hub;
switch (signal)
switch (sig)
{
case SIGINT:
hub_log(log_info, "Interrupted. Shutting down...");
LOG_INFO("Interrupted. Shutting down...");
hub->status = hub_status_shutdown;
event_loopexit(&now);
break;
case SIGTERM:
hub_log(log_info, "Terminated. Shutting down...");
LOG_INFO("Terminated. Shutting down...");
hub->status = hub_status_shutdown;
event_loopexit(&now);
break;
case SIGPIPE:
hub_log(log_trace, "hub_handle_signal(): caught SIGPIPE (ignoring)");
break;
case SIGHUP:
hub_log(log_info, "Caught hangup signal. Reloading configuration files...");
hub->status = hub_status_restart;
event_loopexit(&now);
break;
case SIGUSR1:
hub_log(log_trace, "hub_handle_signal(): caught SIGUSR1 -- FIXME");
break;
case SIGUSR2:
hub_log(log_trace, "hub_handle_signal(): caught SIGUSR2");
{
user_manager_print_stats(hub);
}
break;
default:
hub_log(log_trace, "hub_handle_signal(): caught unknown signal: %d", signal);
LOG_TRACE("hub_handle_signal(): caught unknown signal: %d", signal);
hub->status = hub_status_shutdown;
event_loopexit(&now);
break;
}
}
static struct event signal_events[10];
static int signals[] =
{
SIGINT, /* Interrupt the application */
SIGTERM, /* Terminate the application */
SIGPIPE, /* prevent sigpipe from kills the application */
SIGHUP, /* reload configuration */
SIGUSR1, /* dump statistics */
SIGUSR2, /* (unused) */
0
};
void setup_signal_handlers(struct hub_info* hub)
{
int i = 0;
sigset_t sig_set;
struct sigaction act;
int i;
sigemptyset(&sig_set);
act.sa_mask = sig_set;
act.sa_flags = SA_ONSTACK | SA_RESTART;
act.sa_handler = hub_handle_signal;
for (i = 0; signals[i]; i++)
{
signal_set(&signal_events[i], signals[i], hub_handle_signal, hub);
event_base_set(hub->evbase, &signal_events[i]);
if (signal_add(&signal_events[i], NULL))
if (sigaction(signals[i], &act, 0) != 0)
{
hub_log(log_error, "Error setting signal handler %d", signals[i]);
LOG_ERROR("Error setting signal handler %d", signals[i]);
}
}
}
}
void shutdown_signal_handlers(struct hub_info* hub)
{
int i = 0;
for (i = 0; signals[i]; i++)
{
signal_del(&signal_events[i]);
}
}
#endif /* WIN32 */
#endif /* !WIN32 */
int main_loop()
@@ -131,6 +111,12 @@ int main_loop()
do
{
if (hub)
{
LOG_INFO("Reloading configuration files...");
LOG_DEBUG("Hub status: %d", (int) hub->status);
}
if (read_config(arg_config, &configuration, !arg_have_config) == -1)
return -1;
@@ -147,7 +133,7 @@ int main_loop()
hub = hub_start_service(&configuration);
if (!hub)
return -1;
#ifndef WIN32
#if !defined(WIN32)
setup_signal_handlers(hub);
#endif
}
@@ -160,9 +146,9 @@ int main_loop()
acl_shutdown(&acl);
free_config(&configuration);
} while(hub->status != hub_status_shutdown);
} while (hub->status == hub_status_restart);
#ifndef WIN32
#if !defined(WIN32)
shutdown_signal_handlers(hub);
#endif
@@ -171,7 +157,7 @@ int main_loop()
hub_shutdown_service(hub);
}
net_shutdown();
net_destroy();
hub_log_shutdown();
return 0;
}
@@ -181,18 +167,22 @@ int check_configuration(int dump)
{
struct hub_config configuration;
int ret = read_config(arg_config, &configuration, 0);
if (dump)
{
dump_config(&configuration, dump > 1);
puts("");
if (ret != -1)
{
dump_config(&configuration, dump > 1);
}
return 0;
}
if (ret == -1)
{
fprintf(stderr, "ERROR\n");
return 1;
}
fprintf(stdout, "OK\n");
return 0;
}
@@ -200,8 +190,8 @@ int check_configuration(int dump)
void print_version()
{
fprintf(stdout, "" PRODUCT " " VERSION " " PRODUCT_TITLE "\n");
fprintf(stdout, "Copyright (C) 2007-2009, Jan Vidar Krey <janvidar@extatic.org>\n"
fprintf(stdout, PRODUCT_STRING "\n");
fprintf(stdout, COPYRIGHT "\n"
"This is free software with ABSOLUTELY NO WARRANTY.\n\n");
exit(0);
}
@@ -225,6 +215,7 @@ void print_usage(char* program)
#ifndef WIN32
" -u <user> Run as given user\n"
" -g <group> Run with given group permissions\n"
" -p <file> Store pid in file (process id)\n"
#endif
" -V Show version number.\n"
);
@@ -236,7 +227,7 @@ void print_usage(char* program)
void parse_command_line(int argc, char** argv)
{
int opt;
while ((opt = getopt(argc, argv, "vqfc:l:hu:g:VCsSL")) != -1)
while ((opt = getopt(argc, argv, "vqfc:l:hu:g:VCsSLp:")) != -1)
{
switch (opt)
{
@@ -296,6 +287,10 @@ void parse_command_line(int argc, char** argv)
arg_gid = optarg;
break;
case 'p':
arg_pid = optarg;
break;
default:
print_usage(argv[0]);
break;
@@ -339,15 +334,15 @@ int drop_privileges()
if (!ret)
{
hub_log(log_fatal, "Unable to determine group id, check group name.");
LOG_FATAL("Unable to determine group id, check group name.");
return -1;
}
hub_log(log_trace, "Setting group id %d (%s)", (int) perm_gid, arg_gid);
LOG_TRACE("Setting group id %d (%s)", (int) perm_gid, arg_gid);
ret = setgid(perm_gid);
if (ret == -1)
{
hub_log(log_fatal, "Unable to change group id, permission denied.");
LOG_FATAL("Unable to change group id, permission denied.");
return -1;
}
gid_ok = 1;
@@ -372,31 +367,58 @@ int drop_privileges()
if (!ret)
{
hub_log(log_fatal, "Unable to determine user id, check user name.");
LOG_FATAL("Unable to determine user id, check user name.");
return -1;
}
if (!gid_ok) {
hub_log(log_trace, "Setting group id %d (%s)", (int) perm_gid, arg_gid);
LOG_TRACE("Setting group id %d (%s)", (int) perm_gid, arg_gid);
ret = setgid(perm_gid);
if (ret == -1)
{
hub_log(log_fatal, "Unable to change group id, permission denied.");
LOG_FATAL("Unable to change group id, permission denied.");
return -1;
}
}
hub_log(log_trace, "Setting user id %d (%s)", (int) perm_uid, arg_uid);
LOG_TRACE("Setting user id %d (%s)", (int) perm_uid, arg_uid);
ret = setuid(perm_uid);
if (ret == -1)
{
hub_log(log_fatal, "Unable to change user id, permission denied.");
LOG_FATAL("Unable to change user id, permission denied.");
return -1;
}
}
return 0;
}
int pidfile_create()
{
if (arg_pid)
{
FILE* pidfile = fopen(arg_pid, "w");
if (!pidfile)
{
LOG_FATAL("Unable to write pid file: %s\n", arg_pid);
return -1;
}
fprintf(pidfile, "%d", (int) getpid());
fclose(pidfile);
}
return 0;
}
int pidfile_destroy()
{
if (arg_pid)
{
return unlink(arg_pid);
}
return 0;
}
#endif /* WIN32 */
@@ -417,26 +439,40 @@ int main(int argc, char** argv)
ret = fork();
if (ret == -1)
{
hub_log(log_fatal, "Unable to fork to background!");
LOG_FATAL("Unable to fork to background!");
return -1;
}
else if (ret == 0)
{
/* child process */
/* child process - detatch from TTY */
fclose(stdin);
fclose(stdout);
fclose(stderr);
close(0);
close(1);
close(2);
}
else
{
/* parent process */
hub_log(log_debug, "Forked to background\n");
LOG_DEBUG("Forked to background\n");
return 0;
}
}
if (pidfile_create() == -1)
return -1;
if (drop_privileges() == -1)
return -1;
#endif /* WIN32 */
ret = main_loop();
#ifndef WIN32
pidfile_destroy();
#endif
return ret;
}

219
src/core/netevent.c Normal file
View File

@@ -0,0 +1,219 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <uhub.h>
#include "hubio.h"
#include "probe.h"
/* FIXME: This should not be needed! */
extern struct hub_info* g_hub;
int handle_net_read(struct hub_user* user)
{
static char buf[MAX_RECV_BUF];
struct hub_recvq* q = user->recv_queue;
size_t buf_size = hub_recvq_get(q, buf, MAX_RECV_BUF);
ssize_t size;
if (user_flag_get(user, flag_maxbuf))
buf_size = 0;
size = net_con_recv(user->connection, buf + buf_size, MAX_RECV_BUF - buf_size);
if (size > 0)
buf_size += size;
if (size < 0)
{
if (size == -1)
return quit_disconnected;
else
return quit_socket_error;
}
else if (size == 0)
{
return 0;
}
else
{
char* lastPos = 0;
char* start = buf;
char* pos = 0;
size_t remaining = buf_size;
while ((pos = memchr(start, '\n', remaining)))
{
lastPos = pos;
pos[0] = '\0';
#ifdef DEBUG_SENDQ
LOG_DUMP("PROC: \"%s\" (%d)\n", start, (int) (pos - start));
#endif
if (user_flag_get(user, flag_maxbuf))
{
user_flag_unset(user, flag_maxbuf);
}
else
{
if (((pos - start) > 0) && g_hub->config->max_recv_buffer > (pos - start))
{
if (hub_handle_message(g_hub, user, start, (pos - start)) == -1)
{
return quit_protocol_error;
}
}
}
pos[0] = '\n'; /* FIXME: not needed */
pos ++;
remaining -= (pos - start);
start = pos;
}
if (lastPos || remaining)
{
if (remaining < g_hub->config->max_recv_buffer)
{
hub_recvq_set(q, lastPos ? lastPos : buf, remaining);
}
else
{
hub_recvq_set(q, 0, 0);
user_flag_set(user, flag_maxbuf);
LOG_WARN("Received message past max_recv_buffer, dropping message.");
}
}
else
{
hub_recvq_set(q, 0, 0);
}
}
return 0;
}
int handle_net_write(struct hub_user* user)
{
int ret = 0;
while (hub_sendq_get_bytes(user->send_queue))
{
ret = hub_sendq_send(user->send_queue, user);
if (ret <= 0)
break;
}
if (ret < 0)
return quit_socket_error;
if (hub_sendq_get_bytes(user->send_queue))
{
user_net_io_want_write(user);
}
else
{
user_net_io_want_read(user);
}
return 0;
}
void net_event(struct net_connection* con, int event, void *arg)
{
struct hub_user* user = (struct hub_user*) arg;
int flag_close = 0;
#ifdef DEBUG_SENDQ
LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", con->sd, (int) event, arg);
#endif
if (event == NET_EVENT_TIMEOUT)
{
if (user_is_connecting(user))
{
hub_disconnect_user(g_hub, user, quit_timeout);
}
return;
}
if (event & NET_EVENT_READ)
{
flag_close = handle_net_read(user);
if (flag_close)
{
hub_disconnect_user(g_hub, user, flag_close);
return;
}
}
if (event & NET_EVENT_WRITE)
{
flag_close = handle_net_write(user);
if (flag_close)
{
hub_disconnect_user(g_hub, user, flag_close);
return;
}
}
}
void net_on_accept(struct net_connection* con, int event, void *arg)
{
struct hub_info* hub = (struct hub_info*) arg;
struct hub_probe* probe = 0;
struct ip_addr_encap ipaddr;
const char* addr;
int server_fd = net_con_get_sd(con);
for (;;)
{
int fd = net_accept(server_fd, &ipaddr);
if (fd == -1)
{
if (net_error() == EWOULDBLOCK)
{
break;
}
else
{
LOG_ERROR("Accept error: %d %s", net_error(), strerror(net_error()));
break;
}
}
addr = ip_convert_to_string(&ipaddr);
/* FIXME: Should have a plugin log this */
LOG_TRACE("Got connection from %s", addr);
/* FIXME: A plugin should perform this check: is IP banned? */
if (acl_is_ip_banned(hub->acl, addr))
{
LOG_INFO("Denied [%s] (IP banned)", addr);
net_close(fd);
continue;
}
probe = probe_create(hub, fd, &ipaddr);
if (!probe)
{
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
net_close(fd);
break;
}
}
}

View File

@@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,32 +20,14 @@
#ifndef HAVE_UHUB_NET_EVENT_H
#define HAVE_UHUB_NET_EVENT_H
/**
* Network callback for reading data from a socket.
*/
extern void net_on_read(int fd, short ev, void *arg);
/**
* Network callback for writing data to a socket.
*/
extern void net_on_write(int fd, short ev, void *arg);
/**
* Network callback for timers.
*/
extern void net_on_read_timeout(int fd, short ev, void* arg);
/**
* Network callback to accept incoming connections.
*/
extern void net_on_accept(int fd, short ev, void *arg);
extern void net_on_accept(struct net_connection* con, int event, void *arg);
extern void net_event(struct net_connection* con, int event, void *arg);
#ifdef ADC_UDP_OPERATION
/**
* Network callback to receive incoming UDP datagram.
*/
extern void net_on_packet(int fd, short ev, void *arg);
#endif
extern int handle_net_read(struct hub_user* user);
extern int handle_net_write(struct hub_user* user);
#endif /* HAVE_UHUB_NET_EVENT_H */

126
src/core/probe.c Normal file
View File

@@ -0,0 +1,126 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#include "probe.h"
#define PROBE_RECV_SIZE 12
static char probe_recvbuf[PROBE_RECV_SIZE];
static void probe_net_event(struct net_connection* con, int events, void *arg)
{
struct hub_probe* probe = (struct hub_probe*) net_con_get_ptr(con);
if (events == NET_EVENT_TIMEOUT)
{
probe_destroy(probe);
return;
}
if (events & NET_EVENT_READ)
{
int bytes = net_con_peek(con, probe_recvbuf, PROBE_RECV_SIZE);
if (bytes < 0)
{
probe_destroy(probe);
return;
}
if (bytes >= 4)
{
if (memcmp(probe_recvbuf, "HSUP", 4) == 0)
{
LOG_TRACE("Probed ADC");
#ifdef SSL_SUPPORT
if (probe->hub->config->tls_enable && probe->hub->config->tls_require)
{
LOG_TRACE("Not TLS connection - closing connection.");
}
else
#endif
if (user_create(probe->hub, probe->connection, &probe->addr))
{
probe->connection = 0;
}
probe_destroy(probe);
return;
}
#ifdef SSL_SUPPORT
if (bytes >= 11 &&
probe_recvbuf[0] == 22 &&
probe_recvbuf[1] == 3 && /* protocol major version */
probe_recvbuf[5] == 1 && /* message type */
probe_recvbuf[9] == probe_recvbuf[1] &&
probe_recvbuf[10] == probe_recvbuf[2])
{
if (probe->hub->config->tls_enable)
{
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
if (user_create(probe->hub, probe->connection, &probe->addr))
{
probe->connection = 0;
}
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
}
else
{
LOG_TRACE("Probed TLS %d.%d connection. TLS disabled in hub.", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
}
probe_destroy(probe);
return;
}
else
{
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
return;
}
#endif
probe_destroy(probe);
return;
}
}
}
struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr)
{
struct hub_probe* probe = (struct hub_probe*) hub_malloc_zero(sizeof(struct hub_probe));
if (probe == NULL)
return NULL; /* OOM */
probe->hub = hub;
probe->connection = net_con_create();
net_con_initialize(probe->connection, sd, probe_net_event, probe, NET_EVENT_READ);
net_con_set_timeout(probe->connection, TIMEOUT_CONNECTED);
memcpy(&probe->addr, addr, sizeof(struct ip_addr_encap));
return probe;
}
void probe_destroy(struct hub_probe* probe)
{
if (probe->connection)
{
net_con_close(probe->connection);
probe->connection = 0;
}
hub_free(probe);
}

35
src/core/probe.h Normal file
View File

@@ -0,0 +1,35 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_PROBE_H
#define HAVE_UHUB_PROBE_H
#include "uhub.h"
struct hub_probe
{
struct hub_info* hub; /** The hub instance this probe belong to */
struct net_connection* connection; /** Connection data */
struct ip_addr_encap addr; /** IP address */
};
extern struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr);
extern void probe_destroy(struct hub_probe* probe);
#endif /* HAVE_UHUB_PROBE_H */

230
src/core/route.c Normal file
View File

@@ -0,0 +1,230 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message* msg)
{
struct hub_user* target = NULL;
switch (msg->cache[0])
{
case 'B': /* Broadcast to all logged in clients */
route_to_all(hub, msg);
break;
case 'D':
target = uman_get_user_by_sid(hub, msg->target);
if (target)
{
route_to_user(hub, target, msg);
}
break;
case 'E':
target = uman_get_user_by_sid(hub, msg->target);
if (target)
{
route_to_user(hub, target, msg);
route_to_user(hub, u, msg);
}
break;
case 'F':
route_to_subscribers(hub, msg);
break;
default:
/* Ignore the message */
break;
}
return 0;
}
static inline size_t get_max_send_queue(struct hub_info* hub)
{
/* TODO: More dynamic send queue limit, for instance:
* return MAX(hub->config->max_send_buffer, (hub->config->max_recv_buffer * hub_get_user_count(hub)));
*/
return hub->config->max_send_buffer;
}
static inline size_t get_max_send_queue_soft(struct hub_info* hub)
{
return hub->config->max_send_buffer_soft;
}
/*
* @return 1 if send queue is OK.
* -1 if send queue is overflowed
* 0 if soft send queue is overflowed (not implemented at the moment)
*/
static inline int check_send_queue(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
{
if (user_flag_get(user, flag_user_list))
return 1;
if ((user->send_queue->size + msg->length) > get_max_send_queue(hub))
{
LOG_WARN("send queue overflowed, message discarded.");
return -1;
}
if (user->send_queue->size > get_max_send_queue_soft(hub))
{
LOG_WARN("send queue soft overflowed.");
return 0;
}
return 1;
}
int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
{
#ifdef DEBUG_SENDQ
char* data = strndup(msg->cache, msg->length-1);
LOG_PROTO("send %s: \"%s\"", sid_to_string(user->id.sid), data);
free(data);
#endif
if (!user->connection)
return 0;
assert(msg->cache && *msg->cache);
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
{
/* Perform oportunistic write */
hub_sendq_add(user->send_queue, msg);
handle_net_write(user);
}
else
{
if (check_send_queue(hub, user, msg) >= 0)
{
hub_sendq_add(user->send_queue, msg);
if (!user_flag_get(user, flag_pipeline))
user_net_io_want_write(user);
}
}
return 1;
}
int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
{
if (hub_sendq_is_empty(u->send_queue))
return 0;
handle_net_write(u);
user_flag_unset(u, flag_pipeline);
return 1;
}
int route_to_all(struct hub_info* hub, struct adc_message* command) /* iterate users */
{
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{
route_to_user(hub, user, command);
user = (struct hub_user*) list_get_next(hub->users->list);
}
return 0;
}
int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* iterate users */
{
int do_send;
char* tmp;
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{
if (user->feature_cast)
{
do_send = 1;
tmp = list_get_first(command->feature_cast_include);
while (tmp)
{
if (!user_have_feature_cast_support(user, tmp))
{
do_send = 0;
break;
}
tmp = list_get_next(command->feature_cast_include);;
}
if (!do_send) {
user = (struct hub_user*) list_get_next(hub->users->list);
continue;
}
tmp = list_get_first(command->feature_cast_exclude);
while (tmp)
{
if (user_have_feature_cast_support(user, tmp))
{
do_send = 0;
break;
}
tmp = list_get_next(command->feature_cast_exclude);
}
if (do_send)
{
route_to_user(hub, user, command);
}
}
user = (struct hub_user*) list_get_next(hub->users->list);
}
return 0;
}
int route_info_message(struct hub_info* hub, struct hub_user* u)
{
if (!user_is_nat_override(u))
{
return route_to_all(hub, u->info);
}
else
{
struct adc_message* cmd = adc_msg_copy(u->info);
const char* address = user_get_address(u);
struct hub_user* user = 0;
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
user = (struct hub_user*) list_get_first(hub->users->list);
while (user)
{
if (user_is_nat_override(user))
route_to_user(hub, user, cmd);
else
route_to_user(hub, user, u->info);
user = (struct hub_user*) list_get_next(hub->users->list);
}
adc_msg_free(cmd);
}
return 0;
}

View File

@@ -23,12 +23,17 @@
/**
* Route a message by sending it to it's final destination.
*/
extern int route_message(struct user* u, struct adc_message* msg);
extern int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message* msg);
/**
* Send queued messages.
*/
extern int route_flush_pipeline(struct hub_info* hub, struct hub_user* u);
/**
* Transmit message directly to one user.
*/
extern int route_to_user(struct user*, struct adc_message* command);
extern int route_to_user(struct hub_info* hub, struct hub_user*, struct adc_message* command);
/**
* Broadcast message to all users.
@@ -45,7 +50,7 @@ extern int route_to_subscribers(struct hub_info* hub, struct adc_message* comman
* This will ensure the correct IP is seen by other users
* in case nat override is in use.
*/
extern int route_info_message(struct user* user);
extern int route_info_message(struct hub_info* hub, struct hub_user* user);
#endif /* HAVE_UHUB_ROUTE_H */

362
src/core/user.c Normal file
View File

@@ -0,0 +1,362 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#ifdef DEBUG_SENDQ
static const char* user_log_str(struct hub_user* user)
{
static char buf[128];
if (user)
{
snprintf(buf, 128, "user={ %p, \"%s\", %s/%s}", user, user->id.nick, sid_to_string(user->id.sid), user->id.cid);
}
else
{
snprintf(buf, 128, "user={ %p }", user);
}
return buf;
}
#endif
struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr)
{
struct hub_user* user = NULL;
LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con));
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
if (user == NULL)
return NULL; /* OOM */
user->send_queue = hub_sendq_create();
user->recv_queue = hub_recvq_create();
user->connection = con;
net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ);
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
user_set_state(user, state_protocol);
flood_control_reset(&user->flood_chat);
flood_control_reset(&user->flood_connect);
flood_control_reset(&user->flood_search);
flood_control_reset(&user->flood_update);
flood_control_reset(&user->flood_extras);
return user;
}
void user_destroy(struct hub_user* user)
{
LOG_TRACE("user_destroy(), user=%p", user);
hub_recvq_destroy(user->recv_queue);
hub_sendq_destroy(user->send_queue);
adc_msg_free(user->info);
user_clear_feature_cast_support(user);
hub_free(user);
}
void user_set_state(struct hub_user* user, enum user_state state)
{
if ((user->state == state_cleanup && state != state_disconnected) || (user->state == state_disconnected))
{
return;
}
user->state = state;
}
void user_set_info(struct hub_user* user, struct adc_message* cmd)
{
adc_msg_free(user->info);
if (cmd)
{
user->info = adc_msg_incref(cmd);
}
else
{
user->info = 0;
}
}
void user_update_info(struct hub_user* u, struct adc_message* cmd)
{
char prefix[2];
char* argument;
size_t n = 0;
struct adc_message* cmd_new = adc_msg_copy(u->info);
if (!cmd_new)
{
/* FIXME: OOM! */
return;
}
/*
* FIXME: Optimization potential:
*
* remove parts of cmd that do not really change anything in cmd_new.
* this can save bandwidth if clients send multiple updates for information
* that does not really change anything.
*/
argument = adc_msg_get_argument(cmd, n++);
while (argument)
{
if (strlen(argument) >= 2)
{
prefix[0] = argument[0];
prefix[1] = argument[1];
adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
}
hub_free(argument);
argument = adc_msg_get_argument(cmd, n++);
}
user_set_info(u, cmd_new);
adc_msg_free(cmd_new);
}
static int convert_support_fourcc(int fourcc)
{
switch (fourcc)
{
case FOURCC('B','A','S','0'):
return feature_bas0;
case FOURCC('B','A','S','E'):
return feature_base;
case FOURCC('A','U','T','0'):
return feature_auto;
case FOURCC('U','C','M','0'):
case FOURCC('U','C','M','D'):
return feature_ucmd;
case FOURCC('Z','L','I','F'):
return feature_zlif;
case FOURCC('B','B','S','0'):
return feature_bbs;
case FOURCC('T','I','G','R'):
return feature_tiger;
case FOURCC('B','L','O','M'):
case FOURCC('B','L','O','0'):
return feature_bloom;
case FOURCC('P','I','N','G'):
return feature_ping;
case FOURCC('L','I','N','K'):
return feature_link;
case FOURCC('A','D','C','S'):
return feature_adcs;
default:
LOG_DEBUG("Unknown extension: %x", fourcc);
return 0;
}
}
void user_support_add(struct hub_user* user, int fourcc)
{
int feature_mask = convert_support_fourcc(fourcc);
user->flags |= feature_mask;
}
int user_flag_get(struct hub_user* user, enum user_flags flag)
{
return user->flags & flag;
}
void user_flag_set(struct hub_user* user, enum user_flags flag)
{
user->flags |= flag;
}
void user_flag_unset(struct hub_user* user, enum user_flags flag)
{
user->flags &= ~flag;
}
void user_set_nat_override(struct hub_user* user)
{
user_flag_set(user, flag_nat);
}
int user_is_nat_override(struct hub_user* user)
{
return user_flag_get(user, flag_nat);
}
void user_support_remove(struct hub_user* user, int fourcc)
{
int feature_mask = convert_support_fourcc(fourcc);
user->flags &= ~feature_mask;
}
int user_have_feature_cast_support(struct hub_user* user, char feature[4])
{
char* tmp = list_get_first(user->feature_cast);
while (tmp)
{
if (strncmp(tmp, feature, 4) == 0)
return 1;
tmp = list_get_next(user->feature_cast);
}
return 0;
}
int user_set_feature_cast_support(struct hub_user* u, char feature[4])
{
if (!u->feature_cast)
{
u->feature_cast = list_create();
}
if (!u->feature_cast)
{
return 0; /* OOM! */
}
list_append(u->feature_cast, hub_strndup(feature, 4));
return 1;
}
void user_clear_feature_cast_support(struct hub_user* u)
{
if (u->feature_cast)
{
list_clear(u->feature_cast, &hub_free);
list_destroy(u->feature_cast);
u->feature_cast = 0;
}
}
int user_is_logged_in(struct hub_user* user)
{
if (user->state == state_normal)
return 1;
return 0;
}
int user_is_connecting(struct hub_user* user)
{
if (user->state == state_protocol || user->state == state_identify || user->state == state_verify)
return 1;
return 0;
}
int user_is_protocol_negotiating(struct hub_user* user)
{
if (user->state == state_protocol)
return 1;
return 0;
}
int user_is_disconnecting(struct hub_user* user)
{
if (user->state == state_cleanup || user->state == state_disconnected)
return 1;
return 0;
}
int user_is_protected(struct hub_user* user)
{
switch (user->credentials)
{
case cred_bot:
case cred_operator:
case cred_super:
case cred_admin:
case cred_link:
return 1;
default:
break;
}
return 0;
}
/**
* Returns 1 if a user is registered.
* Only registered users will be let in if the hub is configured for registered
* users only.
*/
int user_is_registered(struct hub_user* user)
{
switch (user->credentials)
{
case cred_bot:
case cred_user:
case cred_operator:
case cred_super:
case cred_admin:
case cred_link:
return 1;
default:
break;
}
return 0;
}
void user_net_io_want_write(struct hub_user* user)
{
net_con_update(user->connection, NET_EVENT_READ | NET_EVENT_WRITE);
}
void user_net_io_want_read(struct hub_user* user)
{
net_con_update(user->connection, NET_EVENT_READ);
}
const char* user_get_quit_reason_string(enum user_quit_reason reason)
{
switch (reason)
{
case quit_unknown: return "unknown"; break;
case quit_disconnected: return "disconnected"; break;
case quit_kicked: return "kicked"; break;
case quit_banned: return "banned"; break;
case quit_timeout: return "timeout"; break;
case quit_send_queue: return "send queue"; break;
case quit_memory_error: return "out of memory"; break;
case quit_socket_error: return "socket error"; break;
case quit_protocol_error: return "protocol error"; break;
case quit_logon_error: return "login error"; break;
case quit_update_error: return "update error"; break;
case quit_hub_disabled: return "hub disabled"; break;
case quit_ghost_timeout: return "ghost"; break;
}
return "unknown";
}
const char* user_get_address(struct hub_user* user)
{
return ip_convert_to_string(&user->id.addr);
}

278
src/core/user.h Normal file
View File

@@ -0,0 +1,278 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_USER_H
#define HAVE_UHUB_USER_H
struct hub_info;
struct hub_iobuf;
struct flood_control;
enum user_state
{
state_protocol = 0, /**<< "User must send a valid protocol handshake" */
state_identify = 1, /**<< "User must send identification message (INF) " */
state_verify = 2, /**<< "User must send password to verify identification" */
state_normal = 3, /**<< "User is logged in." */
state_cleanup = 4, /**<< "User is disconnected, but other users need to be notified." */
state_disconnected = 5, /**<< "User is disconnected" */
};
enum user_flags
{
feature_base = 0x00000001, /** BASE: Basic configuration (required by all clients) */
feature_auto = 0x00000002, /** AUT0: Automatic nat detection traversal */
feature_bbs = 0x00000004, /** BBS0: Bulletin board system (not supported) */
feature_ucmd = 0x00000008, /** UCMD: User commands (not supported by this software) */
feature_zlif = 0x00000010, /** ZLIF: gzip stream compression (not supported) */
feature_tiger = 0x00000020, /** TIGR: Client supports the tiger hash algorithm */
feature_bloom = 0x00000040, /** BLO0: Bloom filter (not supported) */
feature_ping = 0x00000080, /** PING: Hub pinger information extension */
feature_link = 0x00000100, /** LINK: Hub link (not supported) */
feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */
feature_bas0 = 0x00000400, /** BAS0: Obsolete pre-ADC/1.0 protocol version */
flag_flood = 0x00400000, /** User has been notified about flooding. */
flag_muted = 0x00800000, /** User is muted (cannot chat) */
flag_ignore = 0x01000000, /** Ignore further reads */
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */
flag_want_read = 0x08000000, /** Need to read (SSL) */
flag_want_write = 0x10000000, /** Need to write (SSL) */
flag_user_list = 0x20000000, /** Send queue bypass (when receiving the send queue) */
flag_pipeline = 0x40000000, /** Hub message pipelining */
flag_nat = 0x80000000, /** nat override enabled */
};
enum user_quit_reason
{
quit_unknown = 0,
quit_disconnected = 1, /** User disconnected */
quit_kicked = 2, /** User was kicked */
quit_banned = 3, /** User was banned */
quit_timeout = 4, /** User timed out (no data for a while) */
quit_send_queue = 5, /** User's send queue was overflowed */
quit_memory_error = 6, /** Not enough memory available */
quit_socket_error = 7, /** A socket error occured */
quit_protocol_error = 8, /** Fatal protocol error */
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
quit_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */
quit_hub_disabled = 11, /** Hub is disabled. No new connections allowed */
quit_ghost_timeout = 12, /** The user is a ghost, and trying to login from another connection */
};
/** Returns an apropriate string for the given quit reason */
extern const char* user_get_quit_reason_string(enum user_quit_reason);
struct hub_user_info
{
sid_t sid; /** session ID */
char cid[MAX_CID_LEN+1]; /** global client ID */
char nick[MAX_NICK_LEN+1]; /** User's nick name */
struct ip_addr_encap addr; /** User's IP address */
};
/**
* This struct contains additional information about the user, such
* as the number of bytes and files shared, and the number of hubs the
* user is connected to, etc.
*/
struct hub_user_limits
{
uint64_t shared_size; /** Shared size in bytes */
size_t shared_files; /** The number of shared files */
size_t upload_slots; /** The number of upload slots */
size_t hub_count_user; /** The number of hubs connected as user */
size_t hub_count_registered; /** The number of hubs connected as registered user */
size_t hub_count_operator; /** The number of hubs connected as operator */
size_t hub_count_total; /** The number of hubs connected to in total */
};
struct hub_user
{
enum user_state state; /** see enum user_state */
enum user_credentials credentials; /** see enum user_credentials */
struct hub_user_info id; /** Contains nick name and CID */
uint32_t flags; /** see enum user_features */
char user_agent[MAX_UA_LEN+1];/** User agent string */
struct linked_list* feature_cast; /** Features supported by feature cast */
struct adc_message* info; /** ADC 'INF' message (broadcasted to everyone joining the hub) */
struct hub_info* hub; /** The hub instance this user belong to */
struct hub_recvq* recv_queue;
struct hub_sendq* send_queue;
struct net_connection* connection; /** Connection data */
struct hub_user_limits limits; /** Data used for limitation */
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
struct flood_control flood_chat;
struct flood_control flood_connect;
struct flood_control flood_search;
struct flood_control flood_update;
struct flood_control flood_extras;
};
/**
* Create a user with the given socket descriptor.
* This basically only allocates memory and initializes all variables
* to an initial state.
*
* state is set to state_protocol.
*
* @param sd socket descriptor associated with the user
* @return User object or NULL if not enough memory is available.
*/
extern struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr);
/**
* Delete a user.
*
* !WRONG! If the user is logged in a quit message is issued.
*/
extern void user_destroy(struct hub_user* user);
/**
* This associates a INF message to the user.
* If the user already has a INF message associated, then this is
* released before setting the new one.
*
* @param info new inf message (can be NULL)
*/
extern void user_set_info(struct hub_user* user, struct adc_message* info);
/**
* Update a user's INF message.
* Will parse replace all ellements in the user's inf message with
* the parameters from the cmd (merge operation).
*/
extern void user_update_info(struct hub_user* user, struct adc_message* cmd);
/**
* Specify a user's state.
* NOTE: DON'T, unless you know what you are doing.
*/
extern void user_set_state(struct hub_user* user, enum user_state);
/**
* Returns 1 if the user is in state state_normal, or 0 otherwise.
*/
extern int user_is_logged_in(struct hub_user* user);
/**
* Returns 1 if the user is in state_protocol.
* Returns 0 otherwise.
*/
extern int user_is_protocol_negotiating(struct hub_user* user);
/**
* Returns 1 if the user is in state_protocol, state_identify or state_verify.
* Returns 0 otherwise.
*/
extern int user_is_connecting(struct hub_user* user);
/**
* Returns 1 only if the user is in state_cleanup or state_disconnected.
*/
extern int user_is_disconnecting(struct hub_user* user);
/**
* Returns 1 if a user is protected, which includes users
* having any form of elevated privileges.
*/
extern int user_is_protected(struct hub_user* user);
/**
* Returns 1 if a user is registered, with or without privileges.
*/
extern int user_is_registered(struct hub_user* user);
/**
* User supports the protocol extension as given in fourcc.
* This is usually set while the user is connecting, but can
* also be used to subscribe to a new class of messages from the
* hub.
*
* @see enum user_flags
*/
extern void user_support_add(struct hub_user* user, int fourcc);
/**
* User no longer supports the protocol extension as given in fourcc.
* This can be used to unsubscribe to certain messages generated by
* the hub.
* @see enum user_flags
*/
extern void user_support_remove(struct hub_user* user, int fourcc);
extern const char* user_get_address(struct hub_user* user);
/**
* Sets the nat override flag for a user, this allows users on the same
* subnet as a natted hub to spoof their IP in order to use active mode
* on a natted hub.
*/
extern void user_set_nat_override(struct hub_user* user);
extern int user_is_nat_override(struct hub_user* user);
/**
* Set a flag. @see enum user_flags
*/
extern void user_flag_set(struct hub_user* user, enum user_flags flag);
extern void user_flag_unset(struct hub_user* user, enum user_flags flag);
/**
* Get a flag. @see enum user_flags
*/
extern int user_flag_get(struct hub_user* user, enum user_flags flag);
/**
* Check if a user supports 'feature' for feature casting (basis for 'Fxxx' messages)
* The feature cast is specified as the 'SU' argument to the user's
* INF-message.
*
* @param feature a feature to lookup (example: 'TCP4' or 'UDP4')
* @return 1 if 'feature' supported, or 0 otherwise
*/
extern int user_have_feature_cast_support(struct hub_user* user, char feature[4]);
/**
* Set feature cast support for feature.
*
* @param feature a feature to lookup (example: 'TCP4' or 'UDP4')
* @return 1 if 'feature' supported, or 0 otherwise
*/
extern int user_set_feature_cast_support(struct hub_user* u, char feature[4]);
/**
* Remove all feature cast support features.
*/
extern void user_clear_feature_cast_support(struct hub_user* u);
/**
* Mark the user with a want-write flag, meaning it should poll for writability.
*/
extern void user_net_io_want_write(struct hub_user* user);
/**
* Mark the user with a want read flag, meaning it should poll for readability.
*/
extern void user_net_io_want_read(struct hub_user* user);
#endif /* HAVE_UHUB_USER_H */

270
src/core/usermanager.c Normal file
View File

@@ -0,0 +1,270 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
/*
* This callback function is used to clear user objects from the userlist.
* Should only be used in uman_shutdown().
*/
static void clear_user_list_callback(void* ptr)
{
if (ptr)
{
struct hub_user* u = (struct hub_user*) ptr;
/* Mark the user as already being disconnected.
* This prevents the hub from trying to send
* quit messages to other users.
*/
u->credentials = cred_none;
user_destroy(u);
}
}
void uman_update_stats(struct hub_info* hub)
{
const int factor = TIMEOUT_STATS;
struct net_statistics* total;
struct net_statistics* intermediate;
net_stats_get(&intermediate, &total);
hub->stats.net_tx = (intermediate->tx / factor);
hub->stats.net_rx = (intermediate->rx / factor);
hub->stats.net_tx_peak = MAX(hub->stats.net_tx, hub->stats.net_tx_peak);
hub->stats.net_rx_peak = MAX(hub->stats.net_rx, hub->stats.net_rx_peak);
hub->stats.net_tx_total = total->tx;
hub->stats.net_rx_total = total->rx;
net_stats_reset();
}
void uman_print_stats(struct hub_info* hub)
{
LOG_INFO("Statistics users=" PRINTF_SIZE_T " (peak_users=" PRINTF_SIZE_T "), net_tx=%d KB/s, net_rx=%d KB/s (peak_tx=%d KB/s, peak_rx=%d KB/s)",
hub->users->count,
hub->users->count_peak,
(int) hub->stats.net_tx / 1024,
(int) hub->stats.net_rx / 1024,
(int) hub->stats.net_tx_peak / 1024,
(int) hub->stats.net_rx_peak / 1024);
}
static void timer_statistics(struct timeout_evt* t)
{
struct hub_info* hub = (struct hub_info*) t->ptr;
uman_update_stats(hub);
timeout_queue_reschedule(net_backend_get_timeout_queue(), hub->users->timeout, TIMEOUT_STATS);
}
int uman_init(struct hub_info* hub)
{
struct hub_user_manager* users = NULL;
if (!hub)
return -1;
users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager));
if (!users)
return -1;
users->list = list_create();
users->sids = sid_pool_create(net_get_max_sockets());
if (!users->list)
{
list_destroy(users->list);
hub_free(users);
return -1;
}
if (net_backend_get_timeout_queue())
{
users->timeout = hub_malloc_zero(sizeof(struct timeout_evt));
timeout_evt_initialize(users->timeout, timer_statistics, hub);
timeout_queue_insert(net_backend_get_timeout_queue(), users->timeout, TIMEOUT_STATS);
}
hub->users = users;
return 0;
}
int uman_shutdown(struct hub_info* hub)
{
if (!hub || !hub->users)
return -1;
if (net_backend_get_timeout_queue())
{
timeout_queue_remove(net_backend_get_timeout_queue(), hub->users->timeout);
hub_free(hub->users->timeout);
}
if (hub->users->list)
{
list_clear(hub->users->list, &clear_user_list_callback);
list_destroy(hub->users->list);
}
sid_pool_destroy(hub->users->sids);
hub_free(hub->users);
hub->users = 0;
return 0;
}
int uman_add(struct hub_info* hub, struct hub_user* user)
{
if (!hub || !user)
return -1;
if (user->hub)
return -1;
list_append(hub->users->list, user);
hub->users->count++;
hub->users->count_peak = MAX(hub->users->count, hub->users->count_peak);
hub->users->shared_size += user->limits.shared_size;
hub->users->shared_files += user->limits.shared_files;
user->hub = hub;
return 0;
}
int uman_remove(struct hub_info* hub, struct hub_user* user)
{
if (!hub || !user)
return -1;
list_remove(hub->users->list, user);
if (hub->users->count > 0)
{
hub->users->count--;
}
else
{
assert(!"negative count!");
}
hub->users->shared_size -= user->limits.shared_size;
hub->users->shared_files -= user->limits.shared_files;
user->hub = 0;
return 0;
}
struct hub_user* uman_get_user_by_sid(struct hub_info* hub, sid_t sid)
{
return sid_lookup(hub->users->sids, sid);
}
struct hub_user* uman_get_user_by_cid(struct hub_info* hub, const char* cid)
{
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
while (user)
{
if (strcmp(user->id.cid, cid) == 0)
return user;
user = (struct hub_user*) list_get_next(hub->users->list);
}
return NULL;
}
struct hub_user* uman_get_user_by_nick(struct hub_info* hub, const char* nick)
{
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
while (user)
{
if (strcmp(user->id.nick, nick) == 0)
return user;
user = (struct hub_user*) list_get_next(hub->users->list);
}
return NULL;
}
size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, struct ip_range* range)
{
size_t num = 0;
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
while (user)
{
if (ip_in_range(&user->id.addr, range))
{
list_append(users, user);
num++;
}
user = (struct hub_user*) list_get_next(hub->users->list);
}
return num;
}
int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
{
int ret = 1;
struct hub_user* user;
user_flag_set(target, flag_user_list);
user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on INF or PAS msg */
while (user)
{
if (user_is_logged_in(user))
{
ret = route_to_user(hub, target, user->info);
if (!ret)
break;
}
user = (struct hub_user*) list_get_next(hub->users->list);
}
#if 0
FIXME: FIXME FIXME handle send queue excess
if (!target->send_queue_size)
{
user_flag_unset(target, flag_user_list);
}
#endif
return ret;
}
void uman_send_quit_message(struct hub_info* hub, struct hub_user* leaving)
{
struct adc_message* command = adc_msg_construct(ADC_CMD_IQUI, 6);
adc_msg_add_argument(command, (const char*) sid_to_string(leaving->id.sid));
if (leaving->quit_reason == quit_banned || leaving->quit_reason == quit_kicked)
{
adc_msg_add_argument(command, ADC_QUI_FLAG_DISCONNECT);
}
route_to_all(hub, command);
adc_msg_free(command);
}
sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user)
{
sid_t sid = sid_alloc(hub->users->sids, user);
user->id.sid = sid;
return sid;
}

View File

@@ -20,69 +20,92 @@
#ifndef HAVE_UHUB_USER_MANAGER_H
#define HAVE_UHUB_USER_MANAGER_H
struct user_manager
struct hub_user_manager
{
size_t count; /**<< "Number of all fully connected and logged in users" */
size_t count_peak; /**<< "Peak number of users" */
sid_t free_sid; /**<< "The next available SID." */
struct sid_pool* sids;
uint64_t shared_size; /**<< "The total number of shared bytes among fully connected users." */
uint64_t shared_files; /**<< "The total number of shared files among fully connected users." */
struct linked_list* list; /**<< "Contains all users" */
struct linked_list* list; /**<< "Contains all logged in users" */
struct timeout_evt* timeout; /**<< "Timeout handler for statistics" */
};
/**
* Initializes the user manager.
* @return 0 on success, or -1 if error (out of memory).
*/
extern int user_manager_init(struct hub_info* hub);
extern int uman_init(struct hub_info* hub);
/**
* Shuts down the user manager.
* All users will be disconnected and deleted as part of this.
*
* @return 0 on success, or -1 in an error occured (hub is invalid).
*/
extern void user_manager_shutdown(struct hub_info* hub);
extern int uman_shutdown(struct hub_info* hub);
/**
* Generate statistics for logfiles.
*/
extern void user_manager_update_stats(struct hub_info* hub);
extern void user_manager_print_stats(struct hub_info* hub);
extern void uman_update_stats(struct hub_info* hub);
extern void uman_print_stats(struct hub_info* hub);
/**
* Add a new user to the user manager.
* Add a user to the user manager.
*
* @param hub The hub to add the user to
* @param user The user to be added to the hub.
*/
extern void user_manager_add(struct user* user);
extern int uman_add(struct hub_info* hub, struct hub_user* user);
/**
* Remove a user from the user manager.
* This user is connected, and will be moved to the leaving queue, pending
* all messages in the message queue, and resource cleanup.
*
* @return 0 if successfully removed, -1 if error.
*/
extern void user_manager_remove(struct user* user);
extern int uman_remove(struct hub_info* hub, struct hub_user* user);
/**
* Returns a free sid for a new user.
* Returns and allocates an unused session ID (SID).
*/
extern sid_t user_manager_get_free_sid(struct hub_info* hub);
extern sid_t uman_get_free_sid(struct hub_info* hub, struct hub_user* user);
/**
* Lookup a user based on the session ID (sid).
* NOTE: This will only search connected users.
* Lookup a user based on the session ID (SID).
*
* NOTE: This function will only search connected users, which means
* that SIDs assigned to users who are not yet completely logged in,
* or are in the process of being disconnected will result in this
* function returning NULL even though the sid is not freely available.
*
* FIXME: Is that really safe / sensible ?
* - Makes sense from a message routing point of view.
*
* @return a user if found, or NULL if not found
*/
extern struct user* get_user_by_sid(struct hub_info* hub, sid_t sid);
extern struct hub_user* uman_get_user_by_sid(struct hub_info* hub, sid_t sid);
/**
* Lookup a user based on the client ID (cid).
* Lookup a user based on the client ID (CID).
* @return a user if found, or NULL if not found
*/
extern struct user* get_user_by_cid(struct hub_info* hub, const char* cid);
extern struct hub_user* uman_get_user_by_cid(struct hub_info* hub, const char* cid);
/**
* Lookup a user based on the nick name.
* @return a user if found, or NULL if not found
*/
extern struct user* get_user_by_nick(struct hub_info* hub, const char* nick);
extern struct hub_user* uman_get_user_by_nick(struct hub_info* hub, const char* nick);
/**
* Lookup users based on an ip address range.
*
* @return The number of users matching the addressess, or -1 on error (mask is wrong).
*/
extern size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, struct ip_range* range);
/**
* Send the user list of connected clients to 'user'.
@@ -90,13 +113,13 @@ extern struct user* get_user_by_nick(struct hub_info* hub, const char* nick);
*
* @return 1 if sending the user list succeeded, 0 otherwise.
*/
extern int send_user_list(struct user* user);
extern int uman_send_user_list(struct hub_info* hub, struct hub_user* user);
/**
* Send a quit message to all connected users when 'user' is
* leaving the hub (for whatever reason).
*/
extern void send_quit_message(struct user* user);
extern void uman_send_quit_message(struct hub_info* hub, struct hub_user* user);
#endif /* HAVE_UHUB_USER_MANAGER_H */

988
src/hub.c
View File

@@ -1,988 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
int hub_handle_message(struct user* u, const char* line, size_t length)
{
int ret = 0;
struct adc_message* cmd = 0;
#ifdef NETWORK_DUMP_DEBUG
hub_log(log_protocol, "recv %s: %s", sid_to_string(u->id.sid), line);
#endif
if (user_is_disconnecting(u))
return -1;
cmd = adc_msg_parse_verify(u, line, length);
if (cmd)
{
switch (cmd->cmd)
{
case ADC_CMD_HSUP: ret = hub_handle_support(u, cmd); break;
case ADC_CMD_HPAS: ret = hub_handle_password(u, cmd); break;
case ADC_CMD_BINF: ret = hub_handle_info(u, cmd); break;
#ifdef ADC_UDP_OPERATION
case ADC_CMD_HCHK: ret = hub_handle_autocheck(u, cmd); break;
#endif
case ADC_CMD_DINF:
case ADC_CMD_EINF:
case ADC_CMD_FINF:
/* these must never be allowed for security reasons,
so we ignore them. */
break;
case ADC_CMD_EMSG:
case ADC_CMD_DMSG:
case ADC_CMD_BMSG:
case ADC_CMD_FMSG:
ret = hub_handle_chat_message(u, cmd);
break;
case ADC_CMD_BSCH:
case ADC_CMD_DSCH:
case ADC_CMD_ESCH:
case ADC_CMD_FSCH:
case ADC_CMD_DRES:
case ADC_CMD_DRCM:
case ADC_CMD_DCTM:
cmd->priority = -1;
if (u->hub->config->chat_only && u->credentials < cred_operator)
{
/* These below aren't allowed in chat only hubs */
break;
}
default:
if (user_is_logged_in(u))
{
ret = route_message(u, cmd);
}
else
{
ret = -1;
}
break;
}
adc_msg_free(cmd);
}
else
{
if (!user_is_logged_in(u))
{
ret = -1;
}
}
return ret;
}
int hub_handle_support(struct user* u, struct adc_message* cmd)
{
int ret = 0;
int index = 0;
int ok = 1;
char* arg = adc_msg_get_argument(cmd, index);
struct timeval timeout = { TIMEOUT_HANDSHAKE, 0 };
if (u->hub->status == hub_status_disabled && u->state == state_protocol)
{
on_login_failure(u, status_msg_hub_disabled);
return -1;
}
while (arg)
{
if (strlen(arg) == 6)
{
fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]);
if (strncmp(arg, ADC_SUP_FLAG_ADD, 2) == 0)
{
user_support_add(u, fourcc);
}
else if (strncmp(arg, ADC_SUP_FLAG_REMOVE, 2) == 0)
{
user_support_remove(u, fourcc);
}
else
{
ok = 0;
}
}
else
{
ok = 0;
}
index++;
hub_free(arg);
arg = adc_msg_get_argument(cmd, index);
}
if (u->state == state_protocol)
{
if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
if (ok)
{
hub_send_handshake(u);
if (u->ev_read)
event_add(u->ev_read, &timeout);
}
else
{
/* disconnect user. Do not send crap during initial handshake! */
user_disconnect(u, quit_logon_error);
ret = -1;
}
}
return ret;
}
int hub_handle_password(struct user* u, struct adc_message* cmd)
{
char* password = adc_msg_get_argument(cmd, 0);
int ret = 0;
if (u->state == state_verify)
{
if (password_verify(u, password))
{
on_login_success(u);
}
else
{
on_login_failure(u, status_msg_auth_invalid_password);
ret = -1;
}
}
hub_free(password);
return ret;
}
int hub_handle_chat_message(struct user* u, struct adc_message* cmd)
{
char* message = adc_msg_get_argument(cmd, 0);
int ret = 0;
int relay = 1;
/* TODO: Check for hub-commands here. Set relay to 0 and the message will not be sent to other users. */
if (message[0] == '!' || message[0] == '+')
{
relay = command_dipatcher(u, message);
}
if (relay && user_is_logged_in(u))
{
/* adc_msg_remove_named_argument(cmd, "PM"); */
ret = route_message(u, cmd);
}
free(message);
return ret;
}
int on_kick(struct user* u, struct adc_message* cmd)
{
hub_log(log_error, "on_kick() not implemented");
return -1;
}
#ifdef ADC_UDP_OPERATION
int hub_handle_autocheck(struct user* u, struct adc_message* cmd)
{
char* port_str = adc_msg_get_argument(cmd, 0);
char* token = adc_msg_get_argument(cmd, 1);
int port = 0;
if (!port_str || !token || strlen(token) != 4)
{
hub_free(port_str);
hub_free(token);
return -1;
}
port = uhub_atoi(port_str);
if (port == 0 || port > 65535)
{
hub_free(port_str);
hub_free(token);
return -1;
}
hub_send_autocheck(u, port, token);
hub_free(port_str);
hub_free(token);
return 0;
}
#endif
void hub_send_autocheck(struct user* u, uint16_t port, const char* token)
{
}
void hub_send_support(struct user* u)
{
if (user_is_connecting(u) || user_is_logged_in(u))
{
route_to_user(u, u->hub->command_support);
}
}
void hub_send_sid(struct user* u)
{
struct adc_message* command;
if (user_is_connecting(u))
{
command = adc_msg_construct(ADC_CMD_ISID, 10);
u->id.sid = user_manager_get_free_sid(u->hub);
adc_msg_add_argument(command, (const char*) sid_to_string(u->id.sid));
route_to_user(u, command);
adc_msg_free(command);
}
}
void hub_send_ping(struct user* user)
{
/* This will just send a newline, despite appearing to do more below. */
struct adc_message* ping = adc_msg_construct(0, 0);
ping->cache[0] = '\n';
ping->cache[1] = 0;
ping->length = 1;
ping->priority = 1;
route_to_user(user, ping);
adc_msg_free(ping);
}
void hub_send_hubinfo(struct user* u)
{
struct adc_message* info = adc_msg_copy(u->hub->command_info);
int value = 0;
if (user_flag_get(u, feature_ping))
{
/*
FIXME: These are missing:
HH - Hub Host address ( DNS or IP )
WS - Hub Website
NE - Hub Network
OW - Hub Owner name
*/
adc_msg_add_named_argument(info, "UC", uhub_itoa(hub_get_user_count(u->hub)));
adc_msg_add_named_argument(info, "MC", uhub_itoa(hub_get_max_user_count(u->hub)));
adc_msg_add_named_argument(info, "SS", uhub_ulltoa(hub_get_shared_size(u->hub)));
adc_msg_add_named_argument(info, "SF", uhub_itoa(hub_get_shared_files(u->hub)));
/* Maximum/minimum share size */
value = hub_get_max_share(u->hub);
if (value) adc_msg_add_named_argument(info, "XS", uhub_itoa(value));
value = hub_get_min_share(u->hub);
if (value) adc_msg_add_named_argument(info, "MS", uhub_itoa(value));
/* Maximum/minimum upload slots allowed per user */
value = hub_get_max_slots(u->hub);
if (value) adc_msg_add_named_argument(info, "XL", uhub_itoa(value));
value = hub_get_min_slots(u->hub);
if (value) adc_msg_add_named_argument(info, "ML", uhub_itoa(value));
/* guest users must be on min/max hubs */
value = hub_get_max_hubs_user(u->hub);
if (value) adc_msg_add_named_argument(info, "XU", uhub_itoa(value));
value = hub_get_min_hubs_user(u->hub);
if (value) adc_msg_add_named_argument(info, "MU", uhub_itoa(value));
/* registered users must be on min/max hubs */
value = hub_get_max_hubs_reg(u->hub);
if (value) adc_msg_add_named_argument(info, "XR", uhub_itoa(value));
value = hub_get_min_hubs_reg(u->hub);
if (value) adc_msg_add_named_argument(info, "MR", uhub_itoa(value));
/* operators must be on min/max hubs */
value = hub_get_max_hubs_op(u->hub);
if (value) adc_msg_add_named_argument(info, "XO", uhub_itoa(value));
value = hub_get_min_hubs_op(u->hub);
if (value) adc_msg_add_named_argument(info, "MO", uhub_itoa(value));
/* uptime in seconds */
adc_msg_add_named_argument(info, "UP", uhub_itoa((int) difftime(time(0), u->hub->tm_started)));
}
if (user_is_connecting(u) || user_is_logged_in(u))
{
route_to_user(u, info);
}
adc_msg_free(info);
/* Only send banner when connecting */
if (u->hub->config->show_banner && user_is_connecting(u))
{
route_to_user(u, u->hub->command_banner);
}
}
void hub_send_handshake(struct user* u)
{
hub_send_support(u);
hub_send_sid(u);
hub_send_hubinfo(u);
if (!user_is_disconnecting(u))
{
user_set_state(u, state_identify);
}
}
void hub_send_motd(struct user* u)
{
if (u->hub->command_motd)
{
route_to_user(u, u->hub->command_motd);
}
}
void hub_send_password_challenge(struct user* u)
{
struct adc_message* igpa;
igpa = adc_msg_construct(ADC_CMD_IGPA, 38);
adc_msg_add_argument(igpa, password_generate_challenge(u));
user_set_state(u, state_verify);
route_to_user(u, igpa);
adc_msg_free(igpa);
}
static void hub_event_dispatcher(void* callback_data, struct event_data* message)
{
/*
struct hub_info* hub = (struct hub_info*) callback_data;
hub_log(log_trace, "hub_event_dispatcher: %x (ptr=%p)", message->id, message->ptr);
*/
switch (message->id)
{
case UHUB_EVENT_USER_JOIN:
{
if (user_is_disconnecting((struct user*) message->ptr))
break;
if (message->flags)
{
hub_send_password_challenge((struct user*) message->ptr);
}
else
{
on_login_success((struct user*) message->ptr);
}
break;
}
case UHUB_EVENT_USER_QUIT:
{
user_manager_remove((struct user*) message->ptr);
send_quit_message((struct user*) message->ptr);
on_logout_user((struct user*) message->ptr);
user_schedule_destroy((struct user*) message->ptr);
break;
}
case UHUB_EVENT_USER_DESTROY:
{
hub_log(log_trace, "hub_event_dispatcher: UHUB_EVENT_USER_DESTROY (ptr=%p)", message->ptr);
user_destroy((struct user*) message->ptr);
break;
}
default:
/* FIXME: ignored */
break;
}
}
struct hub_info* hub_start_service(struct hub_config* config)
{
struct hub_info* hub = 0;
int server_tcp, ret, ipv6_supported, af;
#ifdef ADC_UDP_OPERATION
int server_udp;
#endif
struct sockaddr_storage addr;
socklen_t sockaddr_size;
char address_buf[INET6_ADDRSTRLEN+1];
hub = hub_malloc_zero(sizeof(struct hub_info));
if (!hub)
{
hub_log(log_fatal, "Unable to allocate memory for hub");
return 0;
}
hub->tm_started = time(0);
ipv6_supported = net_is_ipv6_supported();
if (ipv6_supported)
hub_log(log_debug, "IPv6 supported.");
else
hub_log(log_debug, "IPv6 not supported.");
if (ip_convert_address(config->server_bind_addr, config->server_port, (struct sockaddr*) &addr, &sockaddr_size) == -1)
{
hub_free(hub);
return 0;
}
af = addr.ss_family;
if (af == AF_INET)
{
net_address_to_string(AF_INET, &((struct sockaddr_in*) &addr)->sin_addr, address_buf, INET6_ADDRSTRLEN);
}
else if (af == AF_INET6)
{
net_address_to_string(AF_INET6, &((struct sockaddr_in6*) &addr)->sin6_addr, address_buf, INET6_ADDRSTRLEN);
}
hub->evbase = event_base_new();
if (!hub->evbase)
{
hub_log(log_error, "Unable to initialize libevent.");
hub_free(hub);
return 0;
}
hub_log(log_info, "Starting server, listening on %s:%d...", address_buf, config->server_port);
server_tcp = net_socket_create(af, SOCK_STREAM, IPPROTO_TCP);
if (server_tcp == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
return 0;
}
#ifdef ADC_UDP_OPERATION
server_udp = net_socket_create(af, SOCK_DGRAM, IPPROTO_UDP);
if (server_udp == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
return 0;
}
#endif
ret = net_set_reuseaddress(server_tcp, 1);
if (ret == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0;
}
#ifdef ADC_UDP_OPERATION
ret = net_set_reuseaddress(server_udp, 1);
if (ret == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
net_close(server_udp);
return 0;
}
#endif
ret = net_set_nonblocking(server_tcp, 1);
if (ret == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0;
}
#ifdef ADC_UDP_OPERATION
ret = net_set_nonblocking(server_udp, 1);
if (ret == -1)
{
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
net_close(server_udp);
return 0;
}
#endif
ret = net_bind(server_tcp, (struct sockaddr*) &addr, sockaddr_size);
if (ret == -1)
{
hub_log(log_fatal, "hub_start_service(): Unable to bind to TCP local address. errno=%d, str=%s", net_error(), net_error_string(net_error()));
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0;
}
#ifdef ADC_UDP_OPERATION
ret = net_bind(server_udp, (struct sockaddr*) &addr, sockaddr_size);
if (ret == -1)
{
hub_log(log_fatal, "hub_start_service(): Unable to bind to UDP local address. errno=%d, str=%s", net_error(), net_error_string(net_error()));
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
net_close(server_udp);
return 0;
}
#endif
ret = net_listen(server_tcp, SERVER_BACKLOG);
if (ret == -1)
{
hub_log(log_fatal, "hub_start_service(): Unable to listen to socket");
event_base_free(hub->evbase);
hub_free(hub);
net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0;
}
hub->fd_tcp = server_tcp;
#ifdef ADC_UDP_OPERATION
hub->fd_udp = server_udp;
#endif
hub->config = config;
hub->users = NULL;
if (user_manager_init(hub) == -1)
{
hub_free(hub);
net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0;
}
event_set(&hub->ev_accept, hub->fd_tcp, EV_READ | EV_PERSIST, net_on_accept, hub);
event_base_set(hub->evbase, &hub->ev_accept);
if (event_add(&hub->ev_accept, NULL) == -1)
{
user_manager_shutdown(hub);
hub_free(hub);
net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0;
}
#ifdef ADC_UDP_OPERATION
event_set(&hub->ev_datagram, hub->fd_udp, EV_READ | EV_PERSIST, net_on_packet, hub);
event_base_set(hub->evbase, &hub->ev_datagram);
if (event_add(&hub->ev_datagram, NULL) == -1)
{
user_manager_shutdown(hub);
hub_free(hub);
net_close(server_tcp);
net_close(server_udp);
return 0;
}
#endif
if (event_queue_initialize(&hub->queue, hub_event_dispatcher, (void*) hub) == -1)
{
user_manager_shutdown(hub);
hub_free(hub);
net_close(server_tcp);
#ifdef ADC_UDP_OPERATION
net_close(server_udp);
#endif
return 0;
}
hub->status = hub_status_running;
return hub;
}
void hub_shutdown_service(struct hub_info* hub)
{
hub_log(log_trace, "hub_shutdown_service()");
event_queue_shutdown(hub->queue);
event_del(&hub->ev_accept);
#ifdef ADC_UDP_OPERATION
event_del(&hub->ev_datagram);
net_close(hub->fd_udp);
#endif
net_close(hub->fd_tcp);
user_manager_shutdown(hub);
hub->status = hub_status_stopped;
event_base_free(hub->evbase);
hub_free(hub);
hub = 0;
}
#define SERVER "" PRODUCT "/" VERSION ""
void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
{
int fd, ret;
char buf[MAX_RECV_BUF];
char* tmp;
hub->acl = acl;
hub->command_info = adc_msg_construct(ADC_CMD_IINF, 15 + strlen(SERVER));
if (hub->command_info)
{
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_CLIENT_TYPE, ADC_CLIENT_TYPE_HUB);
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_USER_AGENT, SERVER);
tmp = adc_msg_escape(hub->config->hub_name);
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_NICK, tmp);
hub_free(tmp);
tmp = adc_msg_escape(hub->config->hub_description);
adc_msg_add_named_argument(hub->command_info, ADC_INF_FLAG_DESCRIPTION, tmp);
hub_free(tmp);
}
/* (Re-)read the message of the day */
hub->command_motd = 0;
fd = open(hub->config->file_motd, 0);
if (fd != -1)
{
ret = read(fd, buf, MAX_RECV_BUF);
if (ret > 0)
{
buf[ret] = 0;
tmp = adc_msg_escape(buf);
hub->command_motd = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
adc_msg_add_argument(hub->command_motd, tmp);
hub_free(tmp);
}
else
{
}
close(fd);
}
hub->command_support = adc_msg_construct(ADC_CMD_ISUP, 6 + strlen(ADC_PROTO_SUPPORT));
if (hub->command_support)
{
adc_msg_add_argument(hub->command_support, ADC_PROTO_SUPPORT);
}
hub->command_banner = adc_msg_construct(ADC_CMD_ISTA, 25 + strlen(SERVER));
if (hub->command_banner)
{
adc_msg_add_argument(hub->command_banner, "000 Powered\\sby\\s" SERVER);
}
hub->status = (hub->config->hub_enabled ? hub_status_running : hub_status_disabled);
}
void hub_free_variables(struct hub_info* hub)
{
adc_msg_free(hub->command_info);
adc_msg_free(hub->command_banner);
if (hub->command_motd)
adc_msg_free(hub->command_motd);
adc_msg_free(hub->command_support);
}
/**
* @return 1 if nickname is in use, or 0 if not used.
*/
static inline int is_nick_in_use(struct hub_info* hub, const char* nick)
{
struct user* lookup = get_user_by_nick(hub, nick);
if (lookup)
{
return 1;
}
return 0;
}
/**
* @return 1 if CID is in use, or 0 if not used.
*/
static inline int is_cid_in_use(struct hub_info* hub, const char* cid)
{
struct user* lookup = get_user_by_cid(hub, cid);
if (lookup)
{
return 1;
}
return 0;
}
static void set_status_code(enum msg_status_level level, int code, char buffer[4])
{
buffer[0] = ('0' + (int) level);
buffer[1] = ('0' + (code / 10));
buffer[2] = ('0' + (code % 10));
buffer[3] = 0;
}
/**
* @param hub The hub instance this message is sent from.
* @param user The user this message is sent to.
* @param msg See enum status_message
* @param level See enum status_level
*/
void hub_send_status(struct user* user, enum status_message msg, enum msg_status_level level)
{
struct hub_config* cfg = user->hub->config;
struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6);
if (!cmd) return;
char code[4];
const char* text = 0;
const char* flag = 0;
char* escaped_text = 0;
#define STATUS(CODE, MSG, FLAG) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; break
switch (msg)
{
STATUS(11, msg_hub_full, 0);
STATUS(12, msg_hub_disabled, 0);
STATUS(26, msg_hub_registered_users_only, 0);
STATUS(43, msg_inf_error_nick_missing, 0);
STATUS(43, msg_inf_error_nick_multiple, 0);
STATUS(21, msg_inf_error_nick_invalid, 0);
STATUS(21, msg_inf_error_nick_long, 0);
STATUS(21, msg_inf_error_nick_short, 0);
STATUS(21, msg_inf_error_nick_spaces, 0);
STATUS(21, msg_inf_error_nick_bad_chars, 0);
STATUS(21, msg_inf_error_nick_not_utf8, 0);
STATUS(22, msg_inf_error_nick_taken, 0);
STATUS(21, msg_inf_error_nick_restricted, 0);
STATUS(43, msg_inf_error_cid_invalid, "FBID");
STATUS(43, msg_inf_error_cid_missing, "FMID");
STATUS(24, msg_inf_error_cid_taken, 0);
STATUS(43, msg_inf_error_pid_missing, "FMPD");
STATUS(27, msg_inf_error_pid_invalid, "FBPD");
STATUS(31, msg_ban_permanently, 0);
STATUS(32, msg_ban_temporarily, "TL600"); /* FIXME: Use a proper timeout */
STATUS(23, msg_auth_invalid_password, 0);
STATUS(20, msg_auth_user_not_found, 0);
STATUS(30, msg_error_no_memory, 0);
STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE);
STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE);
STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS);
STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS);
STATUS(43, msg_user_hub_limit_low, 0);
STATUS(43, msg_user_hub_limit_high, 0);
}
#undef STATUS
escaped_text = adc_msg_escape(text);
adc_msg_add_argument(cmd, code);
adc_msg_add_argument(cmd, escaped_text);
hub_free(escaped_text);
if (flag)
{
adc_msg_add_argument(cmd, flag);
}
route_to_user(user, cmd);
adc_msg_free(cmd);
}
const char* hub_get_status_message(struct hub_info* hub, enum status_message msg)
{
#define STATUS(MSG) case status_ ## MSG : return cfg->MSG; break
struct hub_config* cfg = hub->config;
switch (msg)
{
STATUS(msg_hub_full);
STATUS(msg_hub_disabled);
STATUS(msg_hub_registered_users_only);
STATUS(msg_inf_error_nick_missing);
STATUS(msg_inf_error_nick_multiple);
STATUS(msg_inf_error_nick_invalid);
STATUS(msg_inf_error_nick_long);
STATUS(msg_inf_error_nick_short);
STATUS(msg_inf_error_nick_spaces);
STATUS(msg_inf_error_nick_bad_chars);
STATUS(msg_inf_error_nick_not_utf8);
STATUS(msg_inf_error_nick_taken);
STATUS(msg_inf_error_nick_restricted);
STATUS(msg_inf_error_cid_invalid);
STATUS(msg_inf_error_cid_missing);
STATUS(msg_inf_error_cid_taken);
STATUS(msg_inf_error_pid_missing);
STATUS(msg_inf_error_pid_invalid);
STATUS(msg_ban_permanently);
STATUS(msg_ban_temporarily);
STATUS(msg_auth_invalid_password);
STATUS(msg_auth_user_not_found);
STATUS(msg_error_no_memory);
STATUS(msg_user_share_size_low);
STATUS(msg_user_share_size_high);
STATUS(msg_user_slots_low);
STATUS(msg_user_slots_high);
STATUS(msg_user_hub_limit_low);
STATUS(msg_user_hub_limit_high);
}
#undef STATUS
return "Unknown";
}
size_t hub_get_user_count(struct hub_info* hub)
{
return hub->users->count;
}
size_t hub_get_max_user_count(struct hub_info* hub)
{
return hub->config->max_users;
}
uint64_t hub_get_shared_size(struct hub_info* hub)
{
return hub->users->shared_size;
}
uint64_t hub_get_shared_files(struct hub_info* hub)
{
return hub->users->shared_files;
}
uint64_t hub_get_min_share(struct hub_info* hub)
{
return 1024 * 1024 * hub->config->limit_min_share;
}
uint64_t hub_get_max_share(struct hub_info* hub)
{
return 1024 * 1024 * hub->config->limit_max_share;
}
size_t hub_get_min_slots(struct hub_info* hub)
{
return hub->config->limit_min_slots;
}
size_t hub_get_max_slots(struct hub_info* hub)
{
return hub->config->limit_max_slots;
}
size_t hub_get_max_hubs_total(struct hub_info* hub)
{
return hub->config->limit_max_hubs;
}
size_t hub_get_max_hubs_user(struct hub_info* hub)
{
return hub->config->limit_max_hubs_user;
}
size_t hub_get_min_hubs_user(struct hub_info* hub)
{
return hub->config->limit_min_hubs_user;
}
size_t hub_get_max_hubs_reg(struct hub_info* hub)
{
return hub->config->limit_max_hubs_reg;
}
size_t hub_get_min_hubs_reg(struct hub_info* hub)
{
return hub->config->limit_min_hubs_reg;
}
size_t hub_get_max_hubs_op(struct hub_info* hub)
{
return hub->config->limit_max_hubs_op;
}
size_t hub_get_min_hubs_op(struct hub_info* hub)
{
return hub->config->limit_min_hubs_op;
}
void hub_event_loop(struct hub_info* hub)
{
#if 0
event_dispatch();
#endif
int ret;
do
{
ret = event_base_loop(hub->evbase, EVLOOP_ONCE);
if (ret != 0)
break;
event_queue_process(hub->queue);
}
while (hub->status == hub_status_running);
}

View File

@@ -1,107 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
/* Send MOTD, do logging etc */
void on_login_success(struct user* u)
{
/* Logging - FIXME: Move this to a plugin */
const char* addr = ip_convert_to_string(&u->ipaddr);
const char* credentials_string[] = { "!none!", "link", "guest", "user", "operator", "super", "admin" };
struct timeval timeout = { TIMEOUT_IDLE, 0 };
/* Send user list of all existing users */
if (!send_user_list(u))
return;
/* Mark as being in the normal state, and add user to the user list */
user_set_state(u, state_normal);
user_manager_add(u);
/* Print log message */
hub_log(log_user, "Login OK %s/%s \"%s\" [%s] (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, u->id.nick, addr, credentials_string[u->credentials], u->user_agent);
/* Announce new user to all connected users */
if (user_is_logged_in(u))
route_info_message(u);
/* Send message of the day (if any) */
if (user_is_logged_in(u)) /* Previous send() can fail! */
hub_send_motd(u);
/* reset to idle timeout */
if (u->ev_read)
event_add(u->ev_read, &timeout);
}
void on_login_failure(struct user* u, enum status_message msg)
{
const char* addr = ip_convert_to_string(&u->ipaddr);
const char* message = hub_get_status_message(u->hub, msg);
hub_log(log_user, "Login FAIL %s/%s \"%s\" [%s] (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, u->id.nick, addr, message, u->user_agent);
hub_send_status(u, msg, status_level_fatal);
user_disconnect(u, quit_logon_error);
}
void on_nick_change(struct user* u, const char* nick)
{
if (user_is_logged_in(u))
{
hub_log(log_user, "Nick change %s/%s \"%s\" -> \"%s\"", sid_to_string(u->id.sid), u->id.cid, u->id.nick, nick);
}
}
void on_logout_user(struct user* user)
{
const char* reason = "";
const char* addr;
/* These are used for logging purposes */
switch (user->quit_reason)
{
case quit_disconnected: reason = "disconnected"; break;
case quit_kicked: reason = "kicked"; break;
case quit_banned: reason = "banned"; break;
case quit_timeout: reason = "timeout"; break;
case quit_send_queue: reason = "send queue"; break;
case quit_memory_error: reason = "out of memory"; break;
case quit_socket_error: reason = "socket error"; break;
case quit_protocol_error: reason = "protocol error"; break;
case quit_logon_error: reason = "login error"; break;
case quit_hub_disabled: reason = "hub disabled"; break;
default:
if (user->hub->status == hub_status_shutdown)
reason = "hub shutdown";
else
reason = "unknown error";
break;
}
addr = ip_convert_to_string(&user->ipaddr);
hub_log(log_user, "Logout %s/%s \"%s\" [%s] (%s)", sid_to_string(user->id.sid), user->id.cid, user->id.nick, addr, reason);
user->quit_reason = 0;
}

View File

@@ -1,316 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
void net_on_read(int fd, short ev, void *arg)
{
static char buf[MAX_RECV_BUF];
struct user* user = (struct user*) arg;
char* pos;
char* start;
ssize_t offset;
ssize_t size;
ssize_t buflen;
int more = 1;
int flag_close = 0;
hub_log(log_trace, "net_on_read() : fd=%d, ev=%d, arg=%p", fd, (int) ev, arg);
if (ev == EV_TIMEOUT)
{
more = 0;
if (user_is_connecting(user))
{
flag_close = quit_timeout;
}
else
{
hub_send_ping(user);
}
}
while (more)
{
offset = 0;
if (user->recv_buf)
{
memcpy(buf, user->recv_buf, user->recv_buf_offset);
offset = user->recv_buf_offset;
}
else
{
offset = 0;
}
size = net_recv(fd, &buf[offset], MAX_RECV_BUF - offset, 0);
if (size == -1)
{
if (net_error() != EWOULDBLOCK)
flag_close = quit_socket_error;
break;
}
else if (size == 0)
{
flag_close = quit_disconnected;
break;
}
else
{
buflen = offset + size;
start = buf;
while ((pos = strchr(start, '\n')))
{
pos[0] = '\0';
if (*start && strlen(start) < user->hub->config->max_recv_buffer)
{
if (hub_handle_message(user, start, &pos[0]-&start[0]) == -1)
{
flag_close = quit_protocol_error;
more = 0;
break;
}
}
start = &pos[1];
}
if (!more) break;
if (&buf[offset + size] > &start[0])
{
if (!user->recv_buf)
{
user->recv_buf = hub_malloc(user->hub->config->max_recv_buffer);
}
if (!user->recv_buf)
{
flag_close = quit_memory_error;
break;
}
else
{
memcpy(user->recv_buf, start, &buf[offset + size] - &start[0]);
user->recv_buf_offset = &buf[offset + size] - &start[0];
}
}
else
{
if (user->recv_buf)
{
hub_free(user->recv_buf);
user->recv_buf = 0;
user->recv_buf_offset = 0;
}
}
}
}
if (flag_close)
{
user_disconnect(user, flag_close);
return;
}
if (user_is_logged_in(user))
{
if (user->ev_read)
{
struct timeval timeout = { TIMEOUT_IDLE, 0 };
event_add(user->ev_read, &timeout);
}
}
else if (user_is_connecting(user))
{
if (user->ev_read)
{
struct timeval timeout = { TIMEOUT_HANDSHAKE, 0 };
event_add(user->ev_read, &timeout);
}
}
}
void net_on_write(int fd, short ev, void *arg)
{
struct user* user = (struct user*) arg;
struct adc_message* msg;
int ret;
int length;
int close_flag = 0;
msg = list_get_first(user->send_queue);
while (msg)
{
length = msg->length - user->send_queue_offset;
ret = net_send(user->sd, &msg->cache[user->send_queue_offset], length, UHUB_SEND_SIGNAL);
if (ret == 0 || (ret == -1 && net_error() == EWOULDBLOCK))
{
close_flag = 0;
break;
}
else if (ret > 0)
{
user->tm_last_write = time(NULL);
if (ret == length)
{
#ifdef DEBUG_SENDQ
hub_log(log_error, "SENDQ: sent=%d bytes/%d (all), send_queue_size=%d, offset=%d", ret, (int) msg->length, user->send_queue_size, user->send_queue_offset);
#endif
user->send_queue_size -= ret;
user->send_queue_offset = 0;
#ifdef DEBUG_SENDQ
if ((user->send_queue_size < 0) || (user->send_queue_offset < 0))
{
hub_log(log_error, "INVALID: send_queue_size=%d, send_queue_offset=%d", user->send_queue_size, user->send_queue_offset);
}
#endif
list_remove(user->send_queue, msg);
if (user_flag_get(user, flag_user_list) && (msg == user->info || user->send_queue_size == 0))
{
user_flag_unset(user, flag_user_list);
}
adc_msg_free(msg);
msg = 0;
if (user->send_queue_size == 0)
break;
}
else
{
#ifdef DEBUG_SENDQ
hub_log(log_error, "SENDQ: sent=%d bytes/%d (part), send_queue_size=%d, offset=%d", ret, (int) msg->length, user->send_queue_size, user->send_queue_offset);
#endif
user->send_queue_size -= ret;
user->send_queue_offset += ret;
#ifdef DEBUG_SENDQ
if ((user->send_queue_size < 0) || (user->send_queue_offset < 0) || (user->send_queue_offset > msg->length))
{
hub_log(log_error, "INVALID: send_queue_size=%d, send_queue_offset=%d", user->send_queue_size, user->send_queue_offset);
}
#endif
break;
}
}
else
{
close_flag = quit_socket_error;
break;
}
msg = list_get_first(user->send_queue);
}
if (close_flag)
{
user_disconnect(user, close_flag);
}
else
{
if (user->send_queue_size > 0 && user->ev_write)
event_add(user->ev_write, NULL);
}
}
void net_on_accept(int server_fd, short ev, void *arg)
{
struct hub_info* hub = (struct hub_info*) arg;
struct user* user = 0;
int accept_more = 1;
const char* addr;
struct timeval timeout = { TIMEOUT_CONNECTED, 0 };
while (accept_more)
{
int fd = net_accept(server_fd);
if (fd == -1)
{
if (net_error() == EWOULDBLOCK)
{
break;
}
else
{
hub_log(log_error, "Accept error: %d %s", net_error(), strerror(net_error()));
break;
}
}
addr = net_get_peer_address(fd);
/* FIXME: Should have a plugin log this */
hub_log(log_trace, "Got connection from %s", addr);
/* FIXME: A plugin should perform this check: is IP banned? */
if (acl_is_ip_banned(hub->acl, addr))
{
hub_log(log_info, "Denied [%s] (IP banned)", addr);
net_close(fd);
continue;
}
user = user_create(hub, fd);
if (!user)
{
hub_log(log_error, "Unable to create user after socket accepted. Out of memory?");
net_close(fd);
break;
}
/* Store IP address in user object */
ip_convert_to_binary(addr, &user->ipaddr);
net_set_nonblocking(fd, 1);
net_set_nosigpipe(fd, 1);
event_set(user->ev_read, fd, EV_READ | EV_PERSIST, net_on_read, user);
event_set(user->ev_write, fd, EV_WRITE, net_on_write, user);
event_base_set(hub->evbase, user->ev_read);
event_base_set(hub->evbase, user->ev_write);
event_add(user->ev_read, &timeout);
}
}
#ifdef ADC_UDP_OPERATION
extern void net_on_packet(int fd, short ev, void *arg)
{
static char buffer[1024] = {0,};
// struct hub_info* hub = (struct hub_info*) arg;
// struct user* user = 0;
ssize_t size;
struct sockaddr_storage from;
socklen_t fromlen;
size = recvfrom(fd, buffer, 1024, 0, (struct sockaddr*) &from, &fromlen);
// FIXME: A plugin should handle this!
hub_log(log_info, "Datagram [%s] (%d bytes)", buffer, (int) size);
}
#endif

View File

@@ -1,326 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#ifdef HAVE_EPOLL
// #define DEBUG_EPOLL
static struct epoll_event* events = 0;
static int epfd = -1;
#ifdef DEBUG_EPOLL
static void dump_listeners()
{
int i;
struct net_event_listener* listener;
hub_log(log_dump, "listeners: number=%d", num_connections);
for (i = 0; i < num_connections; i++)
{
listener = &listeners[i];
if (listener)
{
if (listener->fd != -1)
{
hub_log(log_dump, "epoll_dump_listeners: pos=%d/%d fd=%d, ptr=%p", i, num_connections, listeners->fd, listeners);
}
else
{
hub_log(log_dump, "epoll_dump_listeners: pos=%d/%d (unused)", i, num_connections);
}
listener = 0;
}
}
getc(stdin);
}
#endif
static void set_poll_events(struct epoll_event* handle, short trigger)
{
memset(handle, 0, sizeof(struct epoll_event));
if (trigger & evt_accept || trigger & evt_read || trigger & evt_close)
handle->events |= EPOLLIN;
if (trigger & evt_write)
handle->events |= EPOLLOUT;
if (trigger & evt_urgent)
handle->events |= EPOLLPRI;
#ifdef EPOLLRDHUP
if (triggers & evt_close)
handle->events |= EPOLLRDHUP;
#endif
}
static short get_poll_events(struct epoll_event* handle)
{
short trig = handle->events;
short evt = 0;
if (trig & EPOLLIN)
evt |= evt_read;
if (trig & EPOLLPRI)
evt |= evt_urgent;
if (trig & EPOLLOUT)
evt |= evt_write;
if (trig & EPOLLHUP)
evt |= evt_close;
if (trig & EPOLLERR)
evt |= evt_error;
#ifdef EPOLLRDHUP
if (trig & EPOLLRDHUP)
evt |= evt_close;
#endif
return evt;
}
int net_initialize(int capacity)
{
int i;
max_connections = capacity;
num_connections = 0;
epfd = epoll_create(max_connections);
if (epfd == -1)
{
hub_log(log_error, "net_initialize(): epoll_create failed");
return -1;
}
events = hub_malloc_zero(sizeof(struct epoll_event) * max_connections);
if (!events)
{
hub_log(log_error, "net_initialize(): hub_malloc failed");
return -1;
}
monitor_allocate((size_t) capacity);
#ifdef DEBUG_EPOLL
dump_listeners();
#endif
net_stats_initialize();
return 0;
}
int net_shutdown()
{
hub_log(log_trace, "Shutting down network monitor");
if (epfd != -1)
{
close(epfd);
}
hub_free(events);
hub_free(listeners);
return 0;
}
#ifdef DEBUG_EPOLL
uint64_t get_time_difference_in_msec(struct timeval before, struct timeval after)
{
uint64_t seconds = (after.tv_sec - before.tv_sec);
uint64_t out = seconds*1000;
if (seconds > 0)
out += ((after.tv_usec / 1000) + (1000 - (before.tv_usec / 1000)));
else
out += ((after.tv_usec - before.tv_usec) / 1000);
return out;
}
#endif
int net_wait(int timeout_ms)
{
int fired, n, max, ret;
struct net_event_listener* listener;
#ifdef DEBUG_EPOLL
struct timeval tm_before;
struct timeval tm_after;
gettimeofday(&tm_before, NULL);
dump_listeners();
#endif
fired = epoll_wait(epfd, events, num_connections, timeout_ms);
if (fired == -1) {
if (errno != EINTR)
{
hub_log(log_error, "net_wait(): epoll_wait failed");
}
return -1;
}
for (n = 0; n < fired; n++)
{
listener = (struct net_event_listener*) events[n].data.ptr;
listener->revents = get_poll_events(&events[n]);
hub_log(log_dump, "net_wait(): epoll event detected (fd=%d, evt=%d, ptr=%p)", listener->fd, listener->revents, listener);
}
max = num_connections;
for (n = 0; n < max; n++)
{
listener = &listeners[n];
if (listener && listener->fd != -1 && listener->revents)
{
hub_log(log_dump, "net_wait(): epoll trigger call (fd=%d, evt=%d, ptr=%p)", listener->fd, listener->revents, listener);
ret = listener->handler(listener);
listener->revents = 0;
}
#ifdef DEBUG_EPOLL
else
{
if (listener)
hub_log(log_dump, "net_wait(): epoll trigger ignore (fd=%d, evt=%d, ptr=%p)", listener->fd, listener->revents, listener);
}
#endif
}
#ifdef DEBUG_EPOLL
gettimeofday(&tm_after, NULL);
size_t diff = (size_t) get_time_difference_in_msec(tm_before, tm_after);
dump_listeners();
hub_log(log_debug, "net_wait(): time=%dms, triggered=%d", diff, fired);
#endif
return 0;
}
int net_add(int fd, short events, void* data, net_event_handler_t handler)
{
struct epoll_event ev;
struct net_event_listener* listener = monitor_get_free_listener();
hub_log(log_trace, "net_add(): adding socket (fd=%d, pos=%d)", fd, pos);
if (!listener)
{
hub_log(log_error, "net_add(): unable to poll more sockets");
return -1;
}
net_event_listener_set(listener, fd, events, data, handler);
set_poll_events(&ev, events);
ev.data.ptr = listener;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0)
{
hub_log(log_error, "net_add(): epoll_ctl error while adding socket (fd=%d)", fd);
net_event_listener_clear(listener);
return -1;
}
num_connections++;
#ifdef DEBUG_EPOLL
dump_listeners();
#endif
return 0;
}
int net_modify(int fd, short events)
{
struct epoll_event ev;
struct net_event_listener* listener = monitor_get_listener(fd);
hub_log(log_trace, "net_modify(): modifying socket events (fd=%d)", fd);
if (!listener)
{
hub_log(log_error, "net_modify(): unable to find socket.");
return -1;
}
listener->events = events;
set_poll_events(&ev, events);
ev.data.ptr = listener;
if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev) < 0)
{
hub_log(log_error, "net_add(): epoll_ctl error while modifying socket (fd=%d)", fd);
return -1;
}
#ifdef DEBUG_EPOLL
dump_listeners();
#endif
return 0;
}
int net_remove(int fd)
{
struct epoll_event ev;
struct net_event_listener* listener = monitor_get_listener(fd);
hub_log(log_trace, "net_remove(): removing socket (fd=%d, pos=%d)", fd, pos);
if (!listener)
{
/* The socket is not being monitored */
hub_log(log_error, "net_remove(): unable to remove socket (fd=%d)", fd);
return -1;
}
net_event_listener_clear(listener);
if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev) < 0)
{
hub_log(log_error, "net_remove(): epoll_ctl error while removing socket (fd=%d)", fd);
return -1;
}
num_connections--;
#ifdef DEBUG_EPOLL
dump_listeners();
#endif
return 0;
}
#endif /* HAVE_EPOLL */

View File

@@ -1,290 +0,0 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2009, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#ifdef HAVE_KQUEUE
static struct kevent* events = 0;
static struct kevent* change = 0;
static int kfd = -1;
static void set_poll_events(struct kevent* handle, short trigger)
{
if (!handle) {
hub_log(log_error, "OOOPS!!");
return;
}
memset(handle, 0, sizeof(struct kevent));
if (trigger & evt_accept || trigger & evt_read || trigger & evt_close)
handle->filter |= EVFILT_READ;
if (trigger & evt_write /* || trigger & evt_accept*/)
handle->filter |= EVFILT_WRITE;
}
static short get_poll_events(struct kevent* handle)
{
short trig = handle->flags;
short evt = 0;
if (trig & EVFILT_READ)
evt |= evt_read;
if (trig & EVFILT_WRITE)
evt |= evt_write;
if (trig & EV_EOF)
{
evt |= evt_close;
if (handle->fflags)
evt |= evt_error;
}
if (handle->filter == -1)
{
evt |= evt_error;
}
if (handle->data)
{
evt |= evt_accept;
}
if (evt)
{
hub_log(log_error, "Evt: fd=%d, filter=%d, flags=%d, fflags=%d, data=%d evt=%#x", handle->ident, handle->filter, handle->flags, handle->fflags, (int) handle->data, evt);
}
return evt;
}
int net_initialize(int capacity)
{
int i;
max_connections = capacity;
num_connections = 0;
kfd = kqueue();
if (kfd == -1)
{
hub_log(log_error, "net_initialize(): kqueue failed");
return -1;
}
events = (void*) hub_malloc_zero(sizeof(struct kevent) * max_connections);
if (!events)
{
hub_log(log_error, "net_initialize(): hub_malloc failed");
return -1;
}
change = (void*) hub_malloc_zero(sizeof(struct kevent) * max_connections);
if (!events)
{
hub_log(log_error, "net_initialize(): hub_malloc failed");
hub_free(events);
return -1;
}
listeners = (void*) hub_malloc_zero(sizeof(struct net_event_listener) * max_connections);
if (!listeners)
{
hub_log(log_error, "net_initialize(): hub_malloc failed");
hub_free(change);
hub_free(events);
return -1;
}
for (i = 0; i < max_connections; i++)
{
listeners[i].fd = -1;
}
net_stats_initialize();
return 0;
}
int net_shutdown()
{
if (kfd != -1) {
return close(kfd);
}
hub_free(events);
hub_free(change);
hub_free(listeners);
return 0;
}
int net_wait(int timeout_ms)
{
int fired, n, max, ret;
struct net_event_listener* listener;
struct timespec timeout = { (timeout_ms / 1000), (timeout_ms % 1000) * 1000 };
fired = kevent(kfd, events, num_connections, change, num_connections, &timeout);
if (fired == -1) {
if (errno != EINTR)
{
hub_log(log_error, "net_wait(): kevent failed");
}
return -1;
}
for (n = 0; n < fired; n++)
{
listener = (struct net_event_listener*) events[n].udata;
if (listener)
{
listener->revents = get_poll_events(&events[n]);
hub_log(log_dump, "net_wait(): kqueue event detected (fd=%d, evt=%d, ptr=%p)", listener->fd, listener->revents, listener);
}
}
max = num_connections;
for (n = 0; n < max; n++)
{
listener = &listeners[n];
if (listener && listener->fd != -1 && listener->revents != 0)
{
hub_log(log_dump, "net_wait(): kqueue trigger call (fd=%d, evt=%d, ptr=%p)", listener->fd, listener->revents, listener);
ret = listener->handler(listener);
listener->revents = 0;
}
}
return 0;
}
int net_add(int fd, short events_, void* data, net_event_handler_t handler)
{
struct kevent* event;
struct net_event_listener* listener = monitor_get_listener(fd);
hub_log(log_trace, "net_add(): adding socket (fd=%d)", fd);
if (listener)
{
/* Already added! */
return -1;
}
listener = monitor_get_free_listener();
if (!listener)
{
hub_log(log_error, "net_add(): unable to poll more sockets");
return -1;
}
net_event_listener_set(listener, fd, events_, data, handler);
event = &events[pos];
set_poll_events(event, events_);
event->ident = fd;
event->flags |= EV_ADD;
event->flags |= EV_ONESHOT;
#ifdef __APPLE__
event->flags |= EV_ENABLE;
#endif
event->udata = listener;
num_connections++;
return 0;
}
int net_modify(int fd, short events_)
{
struct kevent* event;
struct net_event_listener* listener = monitor_get_listener(fd);
hub_log(log_trace, "net_modify(): modifying socket (fd=%d)", fd);
if (!listener)
{
/* The socket is not being monitored */
hub_log(log_error, "net_modify(): unable to find socket (fd=%d)", fd);
return -1;
}
event = &events[pos];
// set_poll_events(event, events_);
event->ident = fd;
event->flags |= EV_ADD;
event->flags |= EV_ONESHOT;
#ifdef __APPLE__
event->flags |= EV_ENABLE;
#endif
return 0;
}
int net_remove(int fd)
{
struct kevent* event;
struct net_event_listener* listener = monitor_get_listener(fd);
hub_log(log_trace, "net_remove(): removing socket (fd=%d)", fd);
if (!listener)
{
/* The socket is not being monitored */
hub_log(log_error, "net_remove(): unable to remove socket (fd=%d)", fd);
return -1;
}
net_event_listener_clear(listener);
event = &events[pos];
event->ident = fd;
event->filter = 0;
event->flags = EV_DELETE;
#ifdef __APPLE__
event->flasg |= EV_DISABLE;
#endif
event->fflags = 0;
event->data = 0;
event->udata = 0;
num_connections--;
return 0;
}
#endif /* HAVE_KQUEUE */

Some files were not shown because too many files have changed in this diff Show More