[READ-ONLY] Mirror of https://github.com/VibeDevelopers/Comet.
0

Configure Feed

Select the types of activity you want to include in your feed.

Remove WebSocket support

Aaron Jones (Jun 12, 2024, 7:35 PM UTC) 484fd905 746ced23

+11 -1882
-1
.gitignore
··· 55 55 ircd/version.c 56 56 ircd/version.c.last 57 57 ssld/ssld 58 - wsockd/wsockd 59 58 testsuite/ircd.pid.* 60 59 tools/solanum-mkpasswd 61 60 tools/solanum-mkfingerprint
-1
Makefile.am
··· 9 9 10 10 SUBDIRS += ircd \ 11 11 ssld \ 12 - wsockd \ 13 12 authd \ 14 13 bandb \ 15 14 tests \
+1
NEWS.md
··· 76 76 be disconnected on registration 77 77 78 78 ### misc 79 + - **Breaking:** WebSocket support has been removed. 79 80 - **Breaking:** WEBIRC now processes the "secure" option as specified by IRCv3. Web gateways that 80 81 do not set this option will need to be updated or their connections will show as insecure. 81 82 - Successfully changing IP with WEBIRC now drops an identd username
-1
configure.ac
··· 624 624 authd/Makefile \ 625 625 bandb/Makefile \ 626 626 ssld/Makefile \ 627 - wsockd/Makefile \ 628 627 extensions/Makefile \ 629 628 ircd/Makefile \ 630 629 modules/Makefile \
-6
doc/ircd.conf.example
··· 160 160 #host = "2001:db8:2::6"; 161 161 #port = 5000, 6665 .. 6669; 162 162 #sslport = 6697; 163 - 164 - /* wsock: listeners defined with this option enabled will be websocket listeners, 165 - * and will not accept normal clients. 166 - */ 167 - wsock = yes; 168 - sslport = 9999; 169 163 }; 170 164 171 165 /* auth {}: allow users to connect to the ircd (OLD I:)
-6
doc/reference.conf
··· 336 336 host = "2001:db8:2::6"; 337 337 port = 7002; 338 338 sslport = 9002; 339 - 340 - /* wsock: listeners defined with this option enabled will be websocket listeners, 341 - * and will not accept normal clients. 342 - */ 343 - wsock = yes; 344 - sslport = 9999; 345 339 }; 346 340 347 341 /* auth {}: allow users to connect to the ircd (OLD I:) */
-2
include/client.h
··· 62 62 struct PreClient; 63 63 struct ListClient; 64 64 struct scache_entry; 65 - struct ws_ctl; 66 65 67 66 typedef int SSL_OPEN_CB(struct Client *, int status); 68 67 ··· 264 263 265 264 struct _ssl_ctl *ssl_ctl; /* which ssl daemon we're associate with */ 266 265 struct _ssl_ctl *z_ctl; /* second ctl for ssl+zlib */ 267 - struct ws_ctl *ws_ctl; /* ctl for wsockd */ 268 266 SSL_OPEN_CB *ssl_callback; /* ssl connection is now open */ 269 267 uint32_t localflags; 270 268 uint16_t cork_count; /* used for corking/uncorking connections */
+2 -3
include/listener.h
··· 39 39 int ssl; /* ssl listener */ 40 40 int defer_accept; /* use TCP_DEFER_ACCEPT */ 41 41 bool sctp; /* use SCTP */ 42 - int wsock; /* wsock listener */ 43 42 struct rb_sockaddr_storage addr[2]; 44 43 char vhost[(HOSTLEN * 2) + 1]; /* virtual name of listener */ 45 44 }; 46 45 47 - extern void add_tcp_listener(int port, const char *vaddr_ip, int family, int ssl, int defer_accept, int wsock); 48 - extern void add_sctp_listener(int port, const char *vaddr_ip1, const char *vaddr_ip2, int ssl, int wsock); 46 + extern void add_tcp_listener(int port, const char *vaddr_ip, int family, int ssl, int defer_accept); 47 + extern void add_sctp_listener(int port, const char *vaddr_ip1, const char *vaddr_ip2, int ssl); 49 48 extern void close_listener(struct Listener *listener); 50 49 extern void close_listeners(void); 51 50 extern const char *get_listener_name(const struct Listener *listener);
-1
include/s_conf.h
··· 323 323 char *ssl_dh_params; 324 324 char *ssl_cipher_list; 325 325 int ssld_count; 326 - int wsockd_count; 327 326 }; 328 327 329 328 struct admin_info
-44
include/wsproc.h
··· 1 - /* 2 - * wsproc.h: An interface to the solanum websocket helper daemon 3 - * Copyright (C) 2007 Aaron Sethman <androsyn@ratbox.org> 4 - * Copyright (C) 2007 ircd-ratbox development team 5 - * Copyright (C) 2016 Ariadne Conill <ariadne@dereferenced.org> 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License as published by 9 - * the Free Software Foundation; either version 2 of the License, or 10 - * (at your option) any later version. 11 - * 12 - * This program is distributed in the hope that it will be useful, 13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 - * GNU General Public License for more details. 16 - * 17 - * You should have received a copy of the GNU General Public License 18 - * along with this program; if not, write to the Free Software 19 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 20 - * USA 21 - */ 22 - 23 - #ifndef INCLUDED_wsproc_h 24 - #define INCLUDED_wsproc_h 25 - 26 - struct ws_ctl; 27 - typedef struct ws_ctl ws_ctl_t; 28 - 29 - enum wsockd_status { 30 - WSOCKD_ACTIVE, 31 - WSOCKD_SHUTDOWN, 32 - WSOCKD_DEAD, 33 - }; 34 - 35 - void init_wsockd(void); 36 - void restart_wsockd(void); 37 - int start_wsockd(int count); 38 - ws_ctl_t *start_wsockd_accept(rb_fde_t *wsF, rb_fde_t *plainF, uint32_t id); 39 - void wsockd_decrement_clicount(ws_ctl_t *ctl); 40 - int get_wsockd_count(void); 41 - void wsockd_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum wsockd_status status), void *data); 42 - 43 - #endif 44 -
+2 -2
ircd/Makefile.am
··· 59 59 supported.c \ 60 60 tgchange.c \ 61 61 version.c \ 62 - whowas.c \ 63 - wsproc.c 62 + whowas.c 63 + 64 64 libircd_la_LDFLAGS = $(EXTRA_FLAGS) -avoid-version -no-undefined 65 65 libircd_la_LIBADD = @LIBLTDL@ -L$(top_srcdir)/librb/src -lrb 66 66 libircd_LTLIBRARIES = libircd.la
-4
ircd/client.c
··· 51 51 #include "scache.h" 52 52 #include "rb_dictionary.h" 53 53 #include "sslproc.h" 54 - #include "wsproc.h" 55 54 #include "s_assert.h" 56 55 57 56 #define DEBUG_EXITED_CLIENTS ··· 306 305 ssld_decrement_clicount(client_p->localClient->ssl_ctl); 307 306 308 307 rb_free(client_p->localClient->cipher_string); 309 - 310 - if (client_p->localClient->ws_ctl != NULL) 311 - wsockd_decrement_clicount(client_p->localClient->ws_ctl); 312 308 313 309 rb_bh_free(lclient_heap, client_p->localClient); 314 310 client_p->localClient = NULL;
-2
ircd/ircd.c
··· 59 59 #include "patchlevel.h" 60 60 #include "serno.h" 61 61 #include "sslproc.h" 62 - #include "wsproc.h" 63 62 #include "chmode.h" 64 63 #include "privilege.h" 65 64 #include "bandbi.h" ··· 668 667 669 668 init_bandb(); 670 669 init_ssld(); 671 - init_wsockd(); 672 670 673 671 rehash_bans(); 674 672
+2 -25
ircd/listener.c
··· 39 39 #include "reject.h" 40 40 #include "hostmask.h" 41 41 #include "sslproc.h" 42 - #include "wsproc.h" 43 42 #include "hash.h" 44 43 #include "s_assert.h" 45 44 #include "logger.h" ··· 285 284 * the format "255.255.255.255" 286 285 */ 287 286 void 288 - add_tcp_listener(int port, const char *vhost_ip, int family, int ssl, int defer_accept, int wsock) 287 + add_tcp_listener(int port, const char *vhost_ip, int family, int ssl, int defer_accept) 289 288 { 290 289 struct Listener *listener; 291 290 struct rb_sockaddr_storage vaddr[ARRAY_SIZE(listener->addr)]; ··· 347 346 listener->ssl = ssl; 348 347 listener->defer_accept = defer_accept; 349 348 listener->sctp = 0; 350 - listener->wsock = wsock; 351 349 352 350 if (inetport(listener)) { 353 351 listener->active = 1; ··· 362 360 * vhost_ip1/2 - if non-null must contain a valid IP address string 363 361 */ 364 362 void 365 - add_sctp_listener(int port, const char *vhost_ip1, const char *vhost_ip2, int ssl, int wsock) 363 + add_sctp_listener(int port, const char *vhost_ip1, const char *vhost_ip2, int ssl) 366 364 { 367 365 struct Listener *listener; 368 366 struct rb_sockaddr_storage vaddr[ARRAY_SIZE(listener->addr)]; ··· 417 415 listener->ssl = ssl; 418 416 listener->defer_accept = 0; 419 417 listener->sctp = 1; 420 - listener->wsock = wsock; 421 418 422 419 if (inetport(listener)) { 423 420 listener->active = 1; ··· 536 533 537 534 if (aconf != NULL) 538 535 SetSecure(new_client); 539 - } 540 - 541 - if (listener->wsock) 542 - { 543 - rb_fde_t *xF[2]; 544 - if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming wsockd Connection") == -1) 545 - { 546 - SetIOError(new_client); 547 - exit_client(new_client, new_client, new_client, "Fatal Error"); 548 - return; 549 - } 550 - new_client->localClient->ws_ctl = start_wsockd_accept(F, xF[1], connid_get(new_client)); /* this will close F for us */ 551 - if(new_client->localClient->ws_ctl == NULL) 552 - { 553 - SetIOError(new_client); 554 - exit_client(new_client, new_client, new_client, "Service Unavailable"); 555 - return; 556 - } 557 - F = xF[0]; 558 - new_client->localClient->F = F; 559 536 } 560 537 561 538 new_client->localClient->listener = listener;
+4 -15
ircd/newconf.c
··· 30 30 #include "ircd.h" 31 31 #include "snomask.h" 32 32 #include "sslproc.h" 33 - #include "wsproc.h" 34 33 #include "privilege.h" 35 34 #include "chmode.h" 36 35 #include "certfp.h" ··· 38 37 #define CF_TYPE(x) ((x) & CF_MTYPE) 39 38 40 39 static int yy_defer_accept = 1; 41 - static int yy_wsock = 0; 42 40 43 41 struct TopConf *conf_cur_block; 44 42 static char *conf_cur_block_name = NULL; ··· 890 888 rb_free(listener_address[i]); 891 889 listener_address[i] = NULL; 892 890 } 893 - yy_wsock = 0; 894 891 yy_defer_accept = 0; 895 892 return 0; 896 893 } ··· 902 899 rb_free(listener_address[i]); 903 900 listener_address[i] = NULL; 904 901 } 905 - yy_wsock = 0; 906 902 yy_defer_accept = 0; 907 903 return 0; 908 904 } ··· 911 907 conf_set_listen_defer_accept(void *data) 912 908 { 913 909 yy_defer_accept = *(unsigned int *) data; 914 - } 915 - 916 - static void 917 - conf_set_listen_wsock(void *data) 918 - { 919 - yy_wsock = *(unsigned int *) data; 920 910 } 921 911 922 912 static void ··· 935 925 if (sctp) { 936 926 conf_report_error("listener::sctp_port has no addresses -- ignoring."); 937 927 } else { 938 - add_tcp_listener(args->v.number, NULL, AF_INET, ssl, ssl || yy_defer_accept, yy_wsock); 939 - add_tcp_listener(args->v.number, NULL, AF_INET6, ssl, ssl || yy_defer_accept, yy_wsock); 928 + add_tcp_listener(args->v.number, NULL, AF_INET, ssl, ssl || yy_defer_accept); 929 + add_tcp_listener(args->v.number, NULL, AF_INET6, ssl, ssl || yy_defer_accept); 940 930 } 941 931 } 942 932 else ··· 949 939 950 940 if (sctp) { 951 941 #ifdef HAVE_LIBSCTP 952 - add_sctp_listener(args->v.number, listener_address[0], listener_address[1], ssl, yy_wsock); 942 + add_sctp_listener(args->v.number, listener_address[0], listener_address[1], ssl); 953 943 #else 954 944 conf_report_error("Warning -- ignoring listener::sctp_port -- SCTP support not available."); 955 945 #endif 956 946 } else { 957 - add_tcp_listener(args->v.number, listener_address[0], family, ssl, ssl || yy_defer_accept, yy_wsock); 947 + add_tcp_listener(args->v.number, listener_address[0], family, ssl, ssl || yy_defer_accept); 958 948 } 959 949 } 960 950 } ··· 2851 2841 2852 2842 add_top_conf("listen", conf_begin_listen, conf_end_listen, NULL); 2853 2843 add_conf_item("listen", "defer_accept", CF_YESNO, conf_set_listen_defer_accept); 2854 - add_conf_item("listen", "wsock", CF_YESNO, conf_set_listen_wsock); 2855 2844 add_conf_item("listen", "port", CF_INT | CF_FLIST, conf_set_listen_port); 2856 2845 add_conf_item("listen", "sslport", CF_INT | CF_FLIST, conf_set_listen_sslport); 2857 2846 add_conf_item("listen", "sctp_port", CF_INT | CF_FLIST, conf_set_listen_sctp_port);
-10
ircd/s_conf.c
··· 46 46 #include "cache.h" 47 47 #include "privilege.h" 48 48 #include "sslproc.h" 49 - #include "wsproc.h" 50 49 #include "bandbi.h" 51 50 #include "operhash.h" 52 51 #include "chmode.h" ··· 907 906 if(ServerInfo.ssld_count < 1) 908 907 ServerInfo.ssld_count = 1; 909 908 910 - /* XXX: configurable? */ 911 - ServerInfo.wsockd_count = 1; 912 - 913 909 if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list)) 914 910 { 915 911 ilog(L_MAIN, "WARNING: Unable to setup SSL."); ··· 924 920 int start = ServerInfo.ssld_count - get_ssld_count(); 925 921 /* start up additional ssld if needed */ 926 922 start_ssldaemon(start); 927 - } 928 - 929 - if(ServerInfo.wsockd_count > get_wsockd_count()) 930 - { 931 - int start = ServerInfo.wsockd_count - get_wsockd_count(); 932 - start_wsockd(start); 933 923 } 934 924 935 925 /* General conf */
-583
ircd/wsproc.c
··· 1 - /* 2 - * sslproc.c: An interface to wsockd 3 - * Copyright (C) 2007 Aaron Sethman <androsyn@ratbox.org> 4 - * Copyright (C) 2007 ircd-ratbox development team 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; either version 2 of the License, or 9 - * (at your option) any later version. 10 - * 11 - * This program is distributed in the hope that it will be useful, 12 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 - * GNU General Public License for more details. 15 - * 16 - * You should have received a copy of the GNU General Public License 17 - * along with this program; if not, write to the Free Software 18 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 19 - * USA 20 - */ 21 - 22 - #include <rb_lib.h> 23 - #include "stdinc.h" 24 - 25 - 26 - #include "s_conf.h" 27 - #include "logger.h" 28 - #include "listener.h" 29 - #include "wsproc.h" 30 - #include "s_serv.h" 31 - #include "ircd.h" 32 - #include "hash.h" 33 - #include "client.h" 34 - #include "send.h" 35 - #include "packet.h" 36 - 37 - static void ws_read_ctl(rb_fde_t * F, void *data); 38 - static int wsockd_count; 39 - 40 - #define MAXPASSFD 4 41 - #define READSIZE 1024 42 - typedef struct _ws_ctl_buf 43 - { 44 - rb_dlink_node node; 45 - char *buf; 46 - size_t buflen; 47 - rb_fde_t *F[MAXPASSFD]; 48 - int nfds; 49 - } ws_ctl_buf_t; 50 - 51 - 52 - struct ws_ctl 53 - { 54 - rb_dlink_node node; 55 - int cli_count; 56 - rb_fde_t *F; 57 - rb_fde_t *P; 58 - pid_t pid; 59 - rb_dlink_list readq; 60 - rb_dlink_list writeq; 61 - uint8_t shutdown; 62 - uint8_t dead; 63 - }; 64 - 65 - static rb_dlink_list wsock_daemons; 66 - 67 - static inline uint32_t 68 - buf_to_uint32(char *buf) 69 - { 70 - uint32_t x; 71 - memcpy(&x, buf, sizeof(x)); 72 - return x; 73 - } 74 - 75 - static inline void 76 - uint32_to_buf(char *buf, uint32_t x) 77 - { 78 - memcpy(buf, &x, sizeof(x)); 79 - return; 80 - } 81 - 82 - static ws_ctl_t * 83 - allocate_ws_daemon(rb_fde_t * F, rb_fde_t * P, int pid) 84 - { 85 - ws_ctl_t *ctl; 86 - 87 - if(F == NULL || pid < 0) 88 - return NULL; 89 - ctl = rb_malloc(sizeof(ws_ctl_t)); 90 - ctl->F = F; 91 - ctl->P = P; 92 - ctl->pid = pid; 93 - wsockd_count++; 94 - rb_dlinkAdd(ctl, &ctl->node, &wsock_daemons); 95 - return ctl; 96 - } 97 - 98 - static void 99 - free_ws_daemon(ws_ctl_t * ctl) 100 - { 101 - rb_dlink_node *ptr; 102 - ws_ctl_buf_t *ctl_buf; 103 - int x; 104 - if(ctl->cli_count) 105 - return; 106 - 107 - RB_DLINK_FOREACH(ptr, ctl->readq.head) 108 - { 109 - ctl_buf = ptr->data; 110 - for(x = 0; x < ctl_buf->nfds; x++) 111 - rb_close(ctl_buf->F[x]); 112 - 113 - rb_free(ctl_buf->buf); 114 - rb_free(ctl_buf); 115 - } 116 - 117 - RB_DLINK_FOREACH(ptr, ctl->writeq.head) 118 - { 119 - ctl_buf = ptr->data; 120 - for(x = 0; x < ctl_buf->nfds; x++) 121 - rb_close(ctl_buf->F[x]); 122 - 123 - rb_free(ctl_buf->buf); 124 - rb_free(ctl_buf); 125 - } 126 - rb_close(ctl->F); 127 - rb_close(ctl->P); 128 - rb_dlinkDelete(&ctl->node, &wsock_daemons); 129 - rb_free(ctl); 130 - } 131 - 132 - static char *wsockd_path; 133 - 134 - static int wsockd_spin_count = 0; 135 - static time_t last_spin; 136 - static int wsockd_wait = 0; 137 - 138 - void 139 - restart_wsockd(void) 140 - { 141 - rb_dlink_node *ptr, *next; 142 - ws_ctl_t *ctl; 143 - 144 - RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head) 145 - { 146 - ctl = ptr->data; 147 - if(ctl->dead) 148 - continue; 149 - if(ctl->shutdown) 150 - continue; 151 - ctl->shutdown = 1; 152 - wsockd_count--; 153 - if(!ctl->cli_count) 154 - { 155 - rb_kill(ctl->pid, SIGKILL); 156 - free_ws_daemon(ctl); 157 - } 158 - } 159 - 160 - start_wsockd(ServerInfo.wsockd_count); 161 - } 162 - 163 - #if 0 164 - static void 165 - ws_killall(void) 166 - { 167 - rb_dlink_node *ptr, *next; 168 - ws_ctl_t *ctl; 169 - RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head) 170 - { 171 - ctl = ptr->data; 172 - if(ctl->dead) 173 - continue; 174 - ctl->dead = 1; 175 - if(!ctl->shutdown) 176 - wsockd_count--; 177 - rb_kill(ctl->pid, SIGKILL); 178 - if(!ctl->cli_count) 179 - free_ws_daemon(ctl); 180 - } 181 - } 182 - #endif 183 - 184 - static void 185 - ws_dead(ws_ctl_t * ctl) 186 - { 187 - if(ctl->dead) 188 - return; 189 - 190 - ctl->dead = 1; 191 - rb_kill(ctl->pid, SIGKILL); /* make sure the process is really gone */ 192 - 193 - if(!ctl->shutdown) 194 - { 195 - wsockd_count--; 196 - ilog(L_MAIN, "wsockd helper died - attempting to restart"); 197 - sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "wsockd helper died - attempting to restart"); 198 - start_wsockd(1); 199 - } 200 - } 201 - 202 - static void 203 - ws_do_pipe(rb_fde_t * F, void *data) 204 - { 205 - int retlen; 206 - ws_ctl_t *ctl = data; 207 - retlen = rb_write(F, "0", 1); 208 - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) 209 - { 210 - ws_dead(ctl); 211 - return; 212 - } 213 - rb_setselect(F, RB_SELECT_READ, ws_do_pipe, data); 214 - } 215 - 216 - static void 217 - restart_wsockd_event(void *unused) 218 - { 219 - wsockd_spin_count = 0; 220 - last_spin = 0; 221 - wsockd_wait = 0; 222 - if(ServerInfo.wsockd_count > get_wsockd_count()) 223 - { 224 - int start = ServerInfo.wsockd_count - get_wsockd_count(); 225 - ilog(L_MAIN, "Attempting to restart wsockd processes"); 226 - sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Attempting to restart wsockd processes"); 227 - start_wsockd(start); 228 - } 229 - } 230 - 231 - int 232 - start_wsockd(int count) 233 - { 234 - rb_fde_t *F1, *F2; 235 - rb_fde_t *P1, *P2; 236 - char fullpath[PATH_MAX + 1]; 237 - char fdarg[6]; 238 - const char *parv[2]; 239 - char buf[128]; 240 - char s_pid[10]; 241 - pid_t pid; 242 - int started = 0, i; 243 - 244 - if(wsockd_wait) 245 - return 0; 246 - 247 - if(wsockd_spin_count > 20 && (rb_current_time() - last_spin < 5)) 248 - { 249 - ilog(L_MAIN, "wsockd helper is spinning - will attempt to restart in 1 minute"); 250 - sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, 251 - "wsockd helper is spinning - will attempt to restart in 1 minute"); 252 - rb_event_add("restart_wsockd_event", restart_wsockd_event, NULL, 60); 253 - wsockd_wait = 1; 254 - return 0; 255 - } 256 - 257 - wsockd_spin_count++; 258 - last_spin = rb_current_time(); 259 - 260 - if(wsockd_path == NULL) 261 - { 262 - snprintf(fullpath, sizeof(fullpath), "%s/wsockd", ircd_paths[IRCD_PATH_LIBEXEC]); 263 - 264 - if(access(fullpath, X_OK) == -1) 265 - { 266 - snprintf(fullpath, sizeof(fullpath), "%s/bin/wsockd", ConfigFileEntry.dpath); 267 - if(access(fullpath, X_OK) == -1) 268 - { 269 - ilog(L_MAIN, 270 - "Unable to execute wsockd in %s or %s/bin", 271 - ircd_paths[IRCD_PATH_LIBEXEC], ConfigFileEntry.dpath); 272 - return 0; 273 - } 274 - } 275 - wsockd_path = rb_strdup(fullpath); 276 - } 277 - rb_strlcpy(buf, "-ircd wsockd daemon", sizeof(buf)); 278 - parv[0] = buf; 279 - parv[1] = NULL; 280 - 281 - for(i = 0; i < count; i++) 282 - { 283 - ws_ctl_t *ctl; 284 - if(rb_socketpair(AF_UNIX, SOCK_DGRAM, 0, &F1, &F2, "wsockd handle passing socket") == -1) 285 - { 286 - ilog(L_MAIN, "Unable to create wsockd - rb_socketpair failed: %s", strerror(errno)); 287 - return started; 288 - } 289 - 290 - rb_set_buffers(F1, READBUF_SIZE); 291 - rb_set_buffers(F2, READBUF_SIZE); 292 - snprintf(fdarg, sizeof(fdarg), "%d", rb_get_fd(F2)); 293 - rb_setenv("CTL_FD", fdarg, 1); 294 - if(rb_pipe(&P1, &P2, "wsockd pipe") == -1) 295 - { 296 - ilog(L_MAIN, "Unable to create wsockd - rb_pipe failed: %s", strerror(errno)); 297 - return started; 298 - } 299 - snprintf(fdarg, sizeof(fdarg), "%d", rb_get_fd(P1)); 300 - rb_setenv("CTL_PIPE", fdarg, 1); 301 - snprintf(s_pid, sizeof(s_pid), "%d", (int)getpid()); 302 - rb_setenv("CTL_PPID", s_pid, 1); 303 - 304 - rb_clear_cloexec(F2); 305 - rb_clear_cloexec(P1); 306 - 307 - pid = rb_spawn_process(wsockd_path, (const char **) parv); 308 - if(pid == -1) 309 - { 310 - ilog(L_MAIN, "Unable to create wsockd: %s\n", strerror(errno)); 311 - rb_close(F1); 312 - rb_close(F2); 313 - rb_close(P1); 314 - rb_close(P2); 315 - return started; 316 - } 317 - started++; 318 - rb_close(F2); 319 - rb_close(P1); 320 - ctl = allocate_ws_daemon(F1, P2, pid); 321 - ws_read_ctl(ctl->F, ctl); 322 - ws_do_pipe(P2, ctl); 323 - 324 - } 325 - ilog(L_MAIN, "wsockd helper started"); 326 - sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "wsockd helper started"); 327 - return started; 328 - } 329 - 330 - static void 331 - ws_process_dead_fd(ws_ctl_t * ctl, ws_ctl_buf_t * ctl_buf) 332 - { 333 - struct Client *client_p; 334 - char reason[256]; 335 - uint32_t fd; 336 - 337 - if(ctl_buf->buflen < 6) 338 - return; /* bogus message..drop it.. XXX should warn here */ 339 - 340 - fd = buf_to_uint32(&ctl_buf->buf[1]); 341 - rb_strlcpy(reason, &ctl_buf->buf[5], sizeof(reason)); 342 - client_p = find_cli_connid_hash(fd); 343 - if(client_p == NULL) 344 - return; 345 - if(IsAnyServer(client_p) || IsRegistered(client_p)) 346 - { 347 - /* read any last moment ERROR, QUIT or the like -- jilles */ 348 - if (!strcmp(reason, "Remote host closed the connection")) 349 - read_packet(client_p->localClient->F, client_p); 350 - if (IsAnyDead(client_p)) 351 - return; 352 - } 353 - exit_client(client_p, client_p, &me, reason); 354 - } 355 - 356 - 357 - static void 358 - ws_process_cmd_recv(ws_ctl_t * ctl) 359 - { 360 - rb_dlink_node *ptr, *next; 361 - ws_ctl_buf_t *ctl_buf; 362 - 363 - if(ctl->dead) 364 - return; 365 - 366 - RB_DLINK_FOREACH_SAFE(ptr, next, ctl->readq.head) 367 - { 368 - ctl_buf = ptr->data; 369 - switch (*ctl_buf->buf) 370 - { 371 - case 'D': 372 - ws_process_dead_fd(ctl, ctl_buf); 373 - break; 374 - default: 375 - ilog(L_MAIN, "Received invalid command from wsockd: %s", ctl_buf->buf); 376 - sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Received invalid command from wsockd"); 377 - break; 378 - } 379 - rb_dlinkDelete(ptr, &ctl->readq); 380 - rb_free(ctl_buf->buf); 381 - rb_free(ctl_buf); 382 - } 383 - 384 - } 385 - 386 - 387 - static void 388 - ws_read_ctl(rb_fde_t * F, void *data) 389 - { 390 - ws_ctl_buf_t *ctl_buf; 391 - ws_ctl_t *ctl = data; 392 - int retlen; 393 - 394 - if(ctl->dead) 395 - return; 396 - do 397 - { 398 - ctl_buf = rb_malloc(sizeof(ws_ctl_buf_t)); 399 - ctl_buf->buf = rb_malloc(READSIZE); 400 - retlen = rb_recv_fd_buf(ctl->F, ctl_buf->buf, READSIZE, ctl_buf->F, 4); 401 - ctl_buf->buflen = retlen; 402 - if(retlen <= 0) 403 - { 404 - rb_free(ctl_buf->buf); 405 - rb_free(ctl_buf); 406 - } 407 - else 408 - rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->readq); 409 - } 410 - while(retlen > 0); 411 - 412 - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) 413 - { 414 - ws_dead(ctl); 415 - return; 416 - } 417 - ws_process_cmd_recv(ctl); 418 - rb_setselect(ctl->F, RB_SELECT_READ, ws_read_ctl, ctl); 419 - } 420 - 421 - static ws_ctl_t * 422 - which_wsockd(void) 423 - { 424 - ws_ctl_t *ctl, *lowest = NULL; 425 - rb_dlink_node *ptr; 426 - 427 - RB_DLINK_FOREACH(ptr, wsock_daemons.head) 428 - { 429 - ctl = ptr->data; 430 - if(ctl->dead) 431 - continue; 432 - if(ctl->shutdown) 433 - continue; 434 - if(lowest == NULL) 435 - { 436 - lowest = ctl; 437 - continue; 438 - } 439 - if(ctl->cli_count < lowest->cli_count) 440 - lowest = ctl; 441 - } 442 - 443 - return (lowest); 444 - } 445 - 446 - static void 447 - ws_write_ctl(rb_fde_t * F, void *data) 448 - { 449 - ws_ctl_t *ctl = data; 450 - ws_ctl_buf_t *ctl_buf; 451 - rb_dlink_node *ptr, *next; 452 - int retlen, x; 453 - 454 - if(ctl->dead) 455 - return; 456 - 457 - RB_DLINK_FOREACH_SAFE(ptr, next, ctl->writeq.head) 458 - { 459 - ctl_buf = ptr->data; 460 - /* in theory unix sock_dgram shouldn't ever short write this.. */ 461 - retlen = rb_send_fd_buf(ctl->F, ctl_buf->F, ctl_buf->nfds, ctl_buf->buf, ctl_buf->buflen, ctl->pid); 462 - if(retlen > 0) 463 - { 464 - rb_dlinkDelete(ptr, &ctl->writeq); 465 - for(x = 0; x < ctl_buf->nfds; x++) 466 - rb_close(ctl_buf->F[x]); 467 - rb_free(ctl_buf->buf); 468 - rb_free(ctl_buf); 469 - 470 - } 471 - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) 472 - { 473 - ws_dead(ctl); 474 - return; 475 - } 476 - else 477 - { 478 - rb_setselect(ctl->F, RB_SELECT_WRITE, ws_write_ctl, ctl); 479 - } 480 - } 481 - } 482 - 483 - static void 484 - ws_cmd_write_queue(ws_ctl_t * ctl, rb_fde_t ** F, int count, const void *buf, size_t buflen) 485 - { 486 - ws_ctl_buf_t *ctl_buf; 487 - int x; 488 - 489 - /* don't bother */ 490 - if(ctl->dead) 491 - return; 492 - 493 - ctl_buf = rb_malloc(sizeof(ws_ctl_buf_t)); 494 - ctl_buf->buf = rb_malloc(buflen); 495 - memcpy(ctl_buf->buf, buf, buflen); 496 - ctl_buf->buflen = buflen; 497 - 498 - for(x = 0; x < count && x < MAXPASSFD; x++) 499 - { 500 - ctl_buf->F[x] = F[x]; 501 - } 502 - ctl_buf->nfds = count; 503 - rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->writeq); 504 - ws_write_ctl(ctl->F, ctl); 505 - } 506 - 507 - ws_ctl_t * 508 - start_wsockd_accept(rb_fde_t * sslF, rb_fde_t * plainF, uint32_t id) 509 - { 510 - rb_fde_t *F[2]; 511 - ws_ctl_t *ctl; 512 - char buf[5]; 513 - F[0] = sslF; 514 - F[1] = plainF; 515 - 516 - buf[0] = 'A'; 517 - uint32_to_buf(&buf[1], id); 518 - ctl = which_wsockd(); 519 - if(!ctl) 520 - return NULL; 521 - ctl->cli_count++; 522 - ws_cmd_write_queue(ctl, F, 2, buf, sizeof(buf)); 523 - return ctl; 524 - } 525 - 526 - void 527 - wsockd_decrement_clicount(ws_ctl_t * ctl) 528 - { 529 - if(ctl == NULL) 530 - return; 531 - 532 - ctl->cli_count--; 533 - if(ctl->shutdown && !ctl->cli_count) 534 - { 535 - ctl->dead = 1; 536 - rb_kill(ctl->pid, SIGKILL); 537 - } 538 - if(ctl->dead && !ctl->cli_count) 539 - { 540 - free_ws_daemon(ctl); 541 - } 542 - } 543 - 544 - static void 545 - cleanup_dead_ws(void *unused) 546 - { 547 - rb_dlink_node *ptr, *next; 548 - ws_ctl_t *ctl; 549 - RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head) 550 - { 551 - ctl = ptr->data; 552 - if(ctl->dead && !ctl->cli_count) 553 - { 554 - free_ws_daemon(ctl); 555 - } 556 - } 557 - } 558 - 559 - int 560 - get_wsockd_count(void) 561 - { 562 - return wsockd_count; 563 - } 564 - 565 - void 566 - wsockd_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum wsockd_status status), void *data) 567 - { 568 - rb_dlink_node *ptr, *next; 569 - ws_ctl_t *ctl; 570 - RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head) 571 - { 572 - ctl = ptr->data; 573 - func(data, ctl->pid, ctl->cli_count, 574 - ctl->dead ? WSOCKD_DEAD : 575 - (ctl->shutdown ? WSOCKD_SHUTDOWN : WSOCKD_ACTIVE)); 576 - } 577 - } 578 - 579 - void 580 - init_wsockd(void) 581 - { 582 - rb_event_addish("cleanup_dead_ws", cleanup_dead_ws, NULL, 60); 583 - }
-1
tests/Makefile.am
··· 39 39 ../authd/authd \ 40 40 ../bandb/bandb \ 41 41 ../ssld/ssld \ 42 - ../wsockd/wsockd \ 43 42 $(patsubst ../modules/%.c,../modules/.libs/%.so,$(wildcard ../modules/*.c)) \ 44 43 $(patsubst ../modules/core/%.c,../modules/core/.libs/%.so,$(wildcard ../modules/core/*.c)) 45 44
-1
tests/client_util.c
··· 40 40 .ssl = 1, 41 41 .defer_accept = 0, 42 42 .sctp = false, 43 - .wsock = 0, 44 43 .addr = { 45 44 { .ss_family = AF_INET6 }, 46 45 { .ss_family = AF_INET6 },
-1
tests/runtime/bin/wsockd
··· 1 - ../../../wsockd/wsockd
-7
wsockd/Makefile.am
··· 1 - pkglibexec_PROGRAMS = wsockd 2 - AM_CFLAGS=$(WARNFLAGS) 3 - AM_CPPFLAGS = -I../include -I../librb/include 4 - 5 - 6 - wsockd_SOURCES = wsockd.c sha1.c 7 - wsockd_LDADD = ../librb/src/librb.la
-138
wsockd/sha1.c
··· 1 - /* 2 - * Based on the SHA-1 C implementation by Steve Reid <steve@edmweb.com> 3 - * 100% Public Domain 4 - * 5 - * Test Vectors (from FIPS PUB 180-1) 6 - * "abc" 7 - * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 8 - * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 9 - * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 10 - * A million repetitions of "a" 11 - * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 12 - */ 13 - 14 - #include "stdinc.h" 15 - #include <netinet/in.h> // for htonl() 16 - #include "sha1.h" 17 - 18 - #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 19 - 20 - // blk0() and blk() perform the initial expand. blk0() deals with host endianess 21 - #define blk0(i) (block[i] = htonl(block[i])) 22 - #define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15]^block[(i+2)&15]^block[i&15],1)) 23 - 24 - // (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 25 - #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); 26 - #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); 27 - #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); 28 - #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); 29 - #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); 30 - 31 - // hash a single 512-bit block. this is the core of the algorithm 32 - static uint32_t sha1_transform(SHA1 *sha1, const uint8_t buffer[SHA1_BLOCK_LENGTH]) { 33 - uint32_t a, b, c, d, e; 34 - uint32_t block[SHA1_BLOCK_LENGTH / 4]; 35 - 36 - memcpy(&block, buffer, SHA1_BLOCK_LENGTH); 37 - 38 - // copy sha1->state[] to working variables 39 - a = sha1->state[0]; 40 - b = sha1->state[1]; 41 - c = sha1->state[2]; 42 - d = sha1->state[3]; 43 - e = sha1->state[4]; 44 - 45 - // 4 rounds of 20 operations each (loop unrolled) 46 - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); 47 - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); 48 - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); 49 - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); 50 - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); 51 - 52 - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); 53 - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); 54 - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); 55 - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); 56 - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); 57 - 58 - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); 59 - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); 60 - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); 61 - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); 62 - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); 63 - 64 - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); 65 - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); 66 - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); 67 - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); 68 - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); 69 - 70 - // add the working variables back into sha1->state[] 71 - sha1->state[0] += a; 72 - sha1->state[1] += b; 73 - sha1->state[2] += c; 74 - sha1->state[3] += d; 75 - sha1->state[4] += e; 76 - 77 - // wipe variables 78 - a = b = c = d = e = 0; 79 - 80 - return a; // return a to avoid dead-store warning from clang static analyzer 81 - } 82 - 83 - void sha1_init(SHA1 *sha1) { 84 - sha1->state[0] = 0x67452301; 85 - sha1->state[1] = 0xEFCDAB89; 86 - sha1->state[2] = 0x98BADCFE; 87 - sha1->state[3] = 0x10325476; 88 - sha1->state[4] = 0xC3D2E1F0; 89 - sha1->count = 0; 90 - } 91 - 92 - void sha1_update(SHA1 *sha1, const uint8_t *data, size_t length) { 93 - size_t i, j; 94 - 95 - j = (size_t)((sha1->count >> 3) & 63); 96 - sha1->count += (length << 3); 97 - 98 - if ((j + length) > 63) { 99 - i = 64 - j; 100 - 101 - memcpy(&sha1->buffer[j], data, i); 102 - sha1_transform(sha1, sha1->buffer); 103 - 104 - for (; i + 63 < length; i += 64) { 105 - sha1_transform(sha1, &data[i]); 106 - } 107 - 108 - j = 0; 109 - } else { 110 - i = 0; 111 - } 112 - 113 - memcpy(&sha1->buffer[j], &data[i], length - i); 114 - } 115 - 116 - void sha1_final(SHA1 *sha1, uint8_t digest[SHA1_DIGEST_LENGTH]) { 117 - uint32_t i; 118 - uint8_t count[8]; 119 - 120 - for (i = 0; i < 8; i++) { 121 - // this is endian independent 122 - count[i] = (uint8_t)((sha1->count >> ((7 - (i & 7)) * 8)) & 255); 123 - } 124 - 125 - sha1_update(sha1, (uint8_t *)"\200", 1); 126 - 127 - while ((sha1->count & 504) != 448) { 128 - sha1_update(sha1, (uint8_t *)"\0", 1); 129 - } 130 - 131 - sha1_update(sha1, count, 8); 132 - 133 - for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { 134 - digest[i] = (uint8_t)((sha1->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); 135 - } 136 - 137 - memset(sha1, 0, sizeof(*sha1)); 138 - }
-25
wsockd/sha1.h
··· 1 - /* 2 - * Based on the SHA-1 C implementation by Steve Reid <steve@edmweb.com> 3 - * 100% Public Domain 4 - */ 5 - 6 - #ifndef SHA1_H 7 - #define SHA1_H 8 - 9 - #include <stddef.h> 10 - #include <stdint.h> 11 - 12 - #define SHA1_BLOCK_LENGTH 64 13 - #define SHA1_DIGEST_LENGTH 20 14 - 15 - typedef struct { 16 - uint32_t state[5]; 17 - uint64_t count; 18 - uint8_t buffer[SHA1_BLOCK_LENGTH]; 19 - } SHA1; 20 - 21 - void sha1_init(SHA1 *sha1); 22 - void sha1_update(SHA1 *sha1, const uint8_t *data, size_t length); 23 - void sha1_final(SHA1 *sha1, uint8_t digest[SHA1_DIGEST_LENGTH]); 24 - 25 - #endif // SHA1_H
-1003
wsockd/wsockd.c
··· 1 - /* 2 - * wsockd.c: solanum websockets helper 3 - * Copyright (C) 2007 Aaron Sethman <androsyn@ratbox.org> 4 - * Copyright (C) 2007 ircd-ratbox development team 5 - * Copyright (C) 2016 Ariadne Conill <ariadne@dereferenced.org> 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License as published by 9 - * the Free Software Foundation; either version 2 of the License, or 10 - * (at your option) any later version. 11 - * 12 - * This program is distributed in the hope that it will be useful, 13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 - * GNU General Public License for more details. 16 - * 17 - * You should have received a copy of the GNU General Public License 18 - * along with this program; if not, write to the Free Software 19 - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 20 - * USA 21 - */ 22 - 23 - #include "stdinc.h" 24 - #include "sha1.h" 25 - 26 - #define MAXPASSFD 4 27 - #ifndef READBUF_SIZE 28 - #define READBUF_SIZE 16384 29 - #endif 30 - 31 - #define WEBSOCKET_SERVER_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 32 - #define WEBSOCKET_ANSWER_STRING_1 "HTTP/1.1 101 Switching Protocols\r\nAccess-Control-Allow-Origin: *\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " 33 - #define WEBSOCKET_ANSWER_STRING_2 "\r\n\r\n" 34 - 35 - static void setup_signals(void); 36 - static pid_t ppid; 37 - 38 - static inline uint32_t 39 - buf_to_uint32(uint8_t *buf) 40 - { 41 - uint32_t x; 42 - memcpy(&x, buf, sizeof(x)); 43 - return x; 44 - } 45 - 46 - static inline void 47 - uint32_to_buf(uint8_t *buf, uint32_t x) 48 - { 49 - memcpy(buf, &x, sizeof(x)); 50 - return; 51 - } 52 - 53 - typedef struct _mod_ctl_buf 54 - { 55 - rb_dlink_node node; 56 - uint8_t *buf; 57 - size_t buflen; 58 - rb_fde_t *F[MAXPASSFD]; 59 - int nfds; 60 - } mod_ctl_buf_t; 61 - 62 - typedef struct _mod_ctl 63 - { 64 - rb_dlink_node node; 65 - int cli_count; 66 - rb_fde_t *F; 67 - rb_fde_t *F_pipe; 68 - rb_dlink_list readq; 69 - rb_dlink_list writeq; 70 - } mod_ctl_t; 71 - 72 - static mod_ctl_t *mod_ctl; 73 - 74 - typedef struct _conn 75 - { 76 - rb_dlink_node node; 77 - mod_ctl_t *ctl; 78 - 79 - rawbuf_head_t *modbuf_out; 80 - rawbuf_head_t *modbuf_in; 81 - 82 - buf_head_t plainbuf_out; 83 - buf_head_t plainbuf_in; 84 - 85 - uint32_t id; 86 - 87 - rb_fde_t *mod_fd; 88 - rb_fde_t *plain_fd; 89 - uint64_t mod_out; 90 - uint64_t mod_in; 91 - uint64_t plain_in; 92 - uint64_t plain_out; 93 - uint8_t flags; 94 - 95 - char client_key[37]; /* maximum 36 bytes + nul */ 96 - } conn_t; 97 - 98 - #define WEBSOCKET_OPCODE_TEXT_FRAME 1 99 - 100 - #define WEBSOCKET_MASK_LENGTH 4 101 - 102 - #define WEBSOCKET_MAX_UNEXTENDED_PAYLOAD_DATA_LENGTH 125 103 - 104 - typedef struct { 105 - uint8_t opcode_rsv_fin; // opcode: 4, rsv1: 1, rsv2: 1, rsv3: 1, fin: 1 106 - uint8_t payload_length_mask; // payload_length: 7, mask: 1 107 - } ws_frame_hdr_t; 108 - 109 - #define WEBSOCKET_FRAME_HDR_INIT ((ws_frame_hdr_t) { 0, 0 }) 110 - 111 - typedef struct { 112 - ws_frame_hdr_t header; 113 - uint8_t payload_data[WEBSOCKET_MAX_UNEXTENDED_PAYLOAD_DATA_LENGTH]; 114 - } ws_frame_payload_t; 115 - 116 - typedef struct { 117 - ws_frame_hdr_t header; 118 - } ws_frame_t; 119 - 120 - typedef struct { 121 - ws_frame_hdr_t header; 122 - uint16_t payload_length_extended; 123 - } ws_frame_ext_t; 124 - 125 - #define WEBSOCKET_FRAME_EXT_INIT ((ws_frame_ext_t) { WEBSOCKET_FRAME_HDR_INIT, 0 }) 126 - 127 - typedef struct { 128 - ws_frame_hdr_t header; 129 - uint64_t payload_length_extended; 130 - } ws_frame_ext2_t; 131 - 132 - static inline void 133 - ws_frame_set_opcode(ws_frame_hdr_t *header, int opcode) 134 - { 135 - header->opcode_rsv_fin &= ~0xF; 136 - header->opcode_rsv_fin |= opcode & 0xF; 137 - } 138 - 139 - static inline void 140 - ws_frame_set_fin(ws_frame_hdr_t *header, int fin) 141 - { 142 - header->opcode_rsv_fin &= ~(0x1 << 7); 143 - header->opcode_rsv_fin |= (fin << 7) & (0x1 << 7); 144 - } 145 - 146 - static void close_conn(conn_t * conn, int wait_plain, const char *fmt, ...); 147 - static void conn_mod_read_cb(rb_fde_t *fd, void *data); 148 - static void conn_plain_read_cb(rb_fde_t *fd, void *data); 149 - static void conn_plain_process_recvq(conn_t *conn); 150 - 151 - #define FLAG_CORK 0x01 152 - #define FLAG_DEAD 0x02 153 - #define FLAG_WSOCK 0x04 154 - #define FLAG_KEYED 0x08 155 - 156 - #define IsCork(x) ((x)->flags & FLAG_CORK) 157 - #define IsDead(x) ((x)->flags & FLAG_DEAD) 158 - #define IsKeyed(x) ((x)->flags & FLAG_KEYED) 159 - 160 - #define SetCork(x) ((x)->flags |= FLAG_CORK) 161 - #define SetDead(x) ((x)->flags |= FLAG_DEAD) 162 - #define SetWS(x) ((x)->flags |= FLAG_WSOCK) 163 - #define SetKeyed(x) ((x)->flags |= FLAG_KEYED) 164 - 165 - #define ClearCork(x) ((x)->flags &= ~FLAG_CORK) 166 - 167 - #define NO_WAIT 0x0 168 - #define WAIT_PLAIN 0x1 169 - 170 - #define CONN_HASH_SIZE 2000 171 - #define connid_hash(x) (&connid_hash_table[(x % CONN_HASH_SIZE)]) 172 - 173 - static const char *remote_closed = "Remote host closed the connection"; 174 - 175 - static rb_dlink_list connid_hash_table[CONN_HASH_SIZE]; 176 - static rb_dlink_list dead_list; 177 - 178 - static void conn_plain_read_shutdown_cb(rb_fde_t *fd, void *data); 179 - 180 - static void 181 - dummy_handler(int sig) 182 - { 183 - return; 184 - } 185 - 186 - static void 187 - setup_signals() 188 - { 189 - struct sigaction act; 190 - 191 - act.sa_flags = 0; 192 - act.sa_handler = SIG_IGN; 193 - sigemptyset(&act.sa_mask); 194 - sigaddset(&act.sa_mask, SIGPIPE); 195 - sigaddset(&act.sa_mask, SIGALRM); 196 - #ifdef SIGTRAP 197 - sigaddset(&act.sa_mask, SIGTRAP); 198 - #endif 199 - 200 - #ifdef SIGWINCH 201 - sigaddset(&act.sa_mask, SIGWINCH); 202 - sigaction(SIGWINCH, &act, 0); 203 - #endif 204 - sigaction(SIGPIPE, &act, 0); 205 - #ifdef SIGTRAP 206 - sigaction(SIGTRAP, &act, 0); 207 - #endif 208 - 209 - act.sa_handler = dummy_handler; 210 - sigaction(SIGALRM, &act, 0); 211 - } 212 - 213 - static int 214 - maxconn(void) 215 - { 216 - struct rlimit limit; 217 - 218 - if(!getrlimit(RLIMIT_NOFILE, &limit)) 219 - { 220 - return limit.rlim_cur; 221 - } 222 - return MAXCONNECTIONS; 223 - } 224 - 225 - static void 226 - conn_add_id_hash(conn_t * conn, uint32_t id) 227 - { 228 - conn->id = id; 229 - rb_dlinkAdd(conn, &conn->node, connid_hash(id)); 230 - } 231 - 232 - static void 233 - free_conn(conn_t * conn) 234 - { 235 - rb_linebuf_donebuf(&conn->plainbuf_in); 236 - rb_linebuf_donebuf(&conn->plainbuf_out); 237 - 238 - rb_free_rawbuffer(conn->modbuf_in); 239 - rb_free_rawbuffer(conn->modbuf_out); 240 - 241 - rb_free(conn); 242 - } 243 - 244 - static void 245 - clean_dead_conns(void *unused) 246 - { 247 - conn_t *conn; 248 - rb_dlink_node *ptr, *next; 249 - 250 - RB_DLINK_FOREACH_SAFE(ptr, next, dead_list.head) 251 - { 252 - conn = ptr->data; 253 - free_conn(conn); 254 - } 255 - 256 - dead_list.tail = dead_list.head = NULL; 257 - } 258 - 259 - static void 260 - conn_plain_write_sendq(rb_fde_t *fd, void *data) 261 - { 262 - conn_t *conn = data; 263 - int retlen; 264 - 265 - if(IsDead(conn)) 266 - return; 267 - 268 - while((retlen = rb_linebuf_flush(fd, &conn->plainbuf_out)) > 0) 269 - conn->plain_out += retlen; 270 - 271 - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) 272 - { 273 - close_conn(data, NO_WAIT, NULL); 274 - return; 275 - } 276 - 277 - if(rb_linebuf_alloclen(&conn->plainbuf_out) > 0) 278 - rb_setselect(conn->plain_fd, RB_SELECT_WRITE, conn_plain_write_sendq, conn); 279 - else 280 - rb_setselect(conn->plain_fd, RB_SELECT_WRITE, NULL, NULL); 281 - } 282 - 283 - static void 284 - conn_mod_write_sendq(rb_fde_t *fd, void *data) 285 - { 286 - conn_t *conn = data; 287 - const char *err; 288 - int retlen; 289 - 290 - if(IsDead(conn)) 291 - return; 292 - 293 - while((retlen = rb_rawbuf_flush(conn->modbuf_out, fd)) > 0) 294 - conn->mod_out += retlen; 295 - 296 - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) 297 - { 298 - if(retlen == 0) 299 - close_conn(conn, WAIT_PLAIN, "%s", remote_closed); 300 - err = strerror(errno); 301 - close_conn(conn, WAIT_PLAIN, "Write error: %s", err); 302 - return; 303 - } 304 - 305 - if(rb_rawbuf_length(conn->modbuf_out) > 0) 306 - rb_setselect(conn->mod_fd, RB_SELECT_WRITE, conn_mod_write_sendq, conn); 307 - else 308 - rb_setselect(conn->mod_fd, RB_SELECT_WRITE, NULL, NULL); 309 - 310 - if(IsCork(conn) && rb_rawbuf_length(conn->modbuf_out) == 0) 311 - { 312 - ClearCork(conn); 313 - conn_plain_read_cb(conn->plain_fd, conn); 314 - } 315 - } 316 - 317 - static void 318 - conn_mod_write(conn_t * conn, void *data, size_t len) 319 - { 320 - if(IsDead(conn)) /* no point in queueing to a dead man */ 321 - return; 322 - rb_rawbuf_append(conn->modbuf_out, data, len); 323 - } 324 - 325 - static void 326 - conn_mod_write_short_frame(conn_t * conn, void *data, int len) 327 - { 328 - ws_frame_hdr_t hdr = WEBSOCKET_FRAME_HDR_INIT; 329 - 330 - ws_frame_set_opcode(&hdr, WEBSOCKET_OPCODE_TEXT_FRAME); 331 - ws_frame_set_fin(&hdr, 1); 332 - hdr.payload_length_mask = (len + 2) & 0x7f; 333 - 334 - conn_mod_write(conn, &hdr, sizeof(hdr)); 335 - conn_mod_write(conn, data, len); 336 - conn_mod_write(conn, "\r\n", 2); 337 - } 338 - 339 - static void 340 - conn_mod_write_long_frame(conn_t * conn, void *data, int len) 341 - { 342 - ws_frame_ext_t hdr = WEBSOCKET_FRAME_EXT_INIT; 343 - 344 - ws_frame_set_opcode(&hdr.header, WEBSOCKET_OPCODE_TEXT_FRAME); 345 - ws_frame_set_fin(&hdr.header, 1); 346 - hdr.header.payload_length_mask = 126; 347 - hdr.payload_length_extended = htons(len + 2); 348 - 349 - conn_mod_write(conn, &hdr, sizeof(hdr)); 350 - conn_mod_write(conn, data, len); 351 - conn_mod_write(conn, "\r\n", 2); 352 - } 353 - 354 - static void 355 - conn_mod_write_frame(conn_t *conn, void *data, int len) 356 - { 357 - if(IsDead(conn)) /* no point in queueing to a dead man */ 358 - return; 359 - 360 - if (len < 123) 361 - { 362 - conn_mod_write_short_frame(conn, data, len); 363 - return; 364 - } 365 - 366 - conn_mod_write_long_frame(conn, data, len); 367 - } 368 - 369 - static void 370 - mod_write_ctl(rb_fde_t *F, void *data) 371 - { 372 - mod_ctl_t *ctl = data; 373 - mod_ctl_buf_t *ctl_buf; 374 - rb_dlink_node *ptr, *next; 375 - int retlen, x; 376 - 377 - RB_DLINK_FOREACH_SAFE(ptr, next, ctl->writeq.head) 378 - { 379 - ctl_buf = ptr->data; 380 - retlen = rb_send_fd_buf(ctl->F, ctl_buf->F, ctl_buf->nfds, ctl_buf->buf, 381 - ctl_buf->buflen, ppid); 382 - if(retlen > 0) 383 - { 384 - rb_dlinkDelete(ptr, &ctl->writeq); 385 - for(x = 0; x < ctl_buf->nfds; x++) 386 - rb_close(ctl_buf->F[x]); 387 - rb_free(ctl_buf->buf); 388 - rb_free(ctl_buf); 389 - 390 - } 391 - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) 392 - exit(0); 393 - 394 - } 395 - if(rb_dlink_list_length(&ctl->writeq) > 0) 396 - rb_setselect(ctl->F, RB_SELECT_WRITE, mod_write_ctl, ctl); 397 - } 398 - 399 - static void 400 - mod_cmd_write_queue(mod_ctl_t * ctl, const void *data, size_t len) 401 - { 402 - mod_ctl_buf_t *ctl_buf; 403 - ctl_buf = rb_malloc(sizeof(mod_ctl_buf_t)); 404 - ctl_buf->buf = rb_malloc(len); 405 - ctl_buf->buflen = len; 406 - memcpy(ctl_buf->buf, data, len); 407 - ctl_buf->nfds = 0; 408 - rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->writeq); 409 - mod_write_ctl(ctl->F, ctl); 410 - } 411 - 412 - static void 413 - close_conn(conn_t * conn, int wait_plain, const char *fmt, ...) 414 - { 415 - va_list ap; 416 - char reason[128]; /* must always be under 250 bytes */ 417 - uint8_t buf[256]; 418 - int len; 419 - if(IsDead(conn)) 420 - return; 421 - 422 - if (IsKeyed(conn)) 423 - conn_plain_process_recvq(conn); 424 - 425 - rb_rawbuf_flush(conn->modbuf_out, conn->mod_fd); 426 - rb_linebuf_flush(conn->plain_fd, &conn->plainbuf_out); 427 - rb_close(conn->mod_fd); 428 - SetDead(conn); 429 - 430 - rb_dlinkDelete(&conn->node, connid_hash(conn->id)); 431 - 432 - if(!wait_plain || fmt == NULL) 433 - { 434 - rb_close(conn->plain_fd); 435 - rb_dlinkAdd(conn, &conn->node, &dead_list); 436 - return; 437 - } 438 - 439 - rb_setselect(conn->plain_fd, RB_SELECT_READ, conn_plain_read_shutdown_cb, conn); 440 - rb_setselect(conn->plain_fd, RB_SELECT_WRITE, NULL, NULL); 441 - 442 - va_start(ap, fmt); 443 - vsnprintf(reason, sizeof(reason), fmt, ap); 444 - va_end(ap); 445 - 446 - buf[0] = 'D'; 447 - uint32_to_buf(&buf[1], conn->id); 448 - rb_strlcpy((char *) &buf[5], reason, sizeof(buf) - 5); 449 - len = (strlen(reason) + 1) + 5; 450 - mod_cmd_write_queue(conn->ctl, buf, len); 451 - } 452 - 453 - static conn_t * 454 - make_conn(mod_ctl_t * ctl, rb_fde_t *mod_fd, rb_fde_t *plain_fd) 455 - { 456 - conn_t *conn = rb_malloc(sizeof(conn_t)); 457 - conn->ctl = ctl; 458 - conn->mod_fd = mod_fd; 459 - conn->plain_fd = plain_fd; 460 - conn->id = -1; 461 - rb_set_nb(mod_fd); 462 - rb_set_nb(plain_fd); 463 - 464 - rb_linebuf_newbuf(&conn->plainbuf_in); 465 - rb_linebuf_newbuf(&conn->plainbuf_out); 466 - 467 - conn->modbuf_in = rb_new_rawbuffer(); 468 - conn->modbuf_out = rb_new_rawbuffer(); 469 - 470 - return conn; 471 - } 472 - 473 - static void 474 - cleanup_bad_message(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb) 475 - { 476 - int i; 477 - 478 - /* XXX should log this somehow */ 479 - for (i = 0; i < ctlb->nfds; i++) 480 - rb_close(ctlb->F[i]); 481 - } 482 - 483 - static void 484 - ws_frame_unmask(char *msg, int length, uint8_t maskval[WEBSOCKET_MASK_LENGTH]) 485 - { 486 - int i; 487 - 488 - for (i = 0; i < length; i++) 489 - msg[i] = msg[i] ^ maskval[i % 4]; 490 - } 491 - 492 - static void 493 - conn_mod_process_frame(conn_t *conn, ws_frame_hdr_t *hdr, int masked) 494 - { 495 - char msg[WEBSOCKET_MAX_UNEXTENDED_PAYLOAD_DATA_LENGTH]; 496 - uint8_t maskval[WEBSOCKET_MASK_LENGTH]; 497 - int dolen; 498 - 499 - /* if we're masked, we get to collect the masking key for this frame */ 500 - if (masked) 501 - { 502 - dolen = rb_rawbuf_get(conn->modbuf_in, maskval, sizeof(maskval)); 503 - if (!dolen) 504 - { 505 - close_conn(conn, WAIT_PLAIN, "websocket error: fault unpacking unmask key"); 506 - return; 507 - } 508 - } 509 - 510 - dolen = rb_rawbuf_get(conn->modbuf_in, msg, hdr->payload_length_mask); 511 - if (!dolen) 512 - { 513 - close_conn(conn, WAIT_PLAIN, "websocket error: fault unpacking message"); 514 - return; 515 - } 516 - 517 - if (masked) 518 - ws_frame_unmask(msg, dolen, maskval); 519 - 520 - rb_linebuf_parse(&conn->plainbuf_out, msg, dolen, 1); 521 - } 522 - 523 - static void 524 - conn_mod_process_large(conn_t *conn, ws_frame_hdr_t *hdr, int masked) 525 - { 526 - char msg[READBUF_SIZE]; 527 - uint16_t msglen; 528 - uint8_t maskval[WEBSOCKET_MASK_LENGTH]; 529 - int dolen; 530 - 531 - memset(msg, 0, sizeof msg); 532 - 533 - dolen = rb_rawbuf_get(conn->modbuf_in, &msglen, sizeof(msglen)); 534 - if (!dolen) 535 - { 536 - close_conn(conn, WAIT_PLAIN, "websocket error: fault unpacking message size"); 537 - return; 538 - } 539 - 540 - msglen = ntohs(msglen); 541 - 542 - if (masked) 543 - { 544 - dolen = rb_rawbuf_get(conn->modbuf_in, maskval, sizeof(maskval)); 545 - if (!dolen) 546 - { 547 - close_conn(conn, WAIT_PLAIN, "websocket error: fault unpacking unmask key"); 548 - return; 549 - } 550 - } 551 - 552 - dolen = rb_rawbuf_get(conn->modbuf_in, msg, msglen); 553 - if (!dolen) 554 - { 555 - close_conn(conn, WAIT_PLAIN, "websocket error: fault unpacking message"); 556 - return; 557 - } 558 - 559 - if (masked) 560 - ws_frame_unmask(msg, dolen, maskval); 561 - 562 - rb_linebuf_parse(&conn->plainbuf_out, msg, dolen, 1); 563 - } 564 - 565 - static void 566 - conn_mod_process_huge(conn_t *conn, ws_frame_hdr_t *hdr, int masked) 567 - { 568 - /* XXX implement me */ 569 - } 570 - 571 - static void 572 - conn_mod_process(conn_t *conn) 573 - { 574 - ws_frame_hdr_t hdr; 575 - 576 - while (1) 577 - { 578 - int masked; 579 - int dolen = rb_rawbuf_get(conn->modbuf_in, &hdr, sizeof(hdr)); 580 - if (dolen != sizeof(hdr)) 581 - break; 582 - 583 - masked = (hdr.payload_length_mask >> 7) == 1; 584 - 585 - hdr.payload_length_mask &= 0x7f; 586 - switch (hdr.payload_length_mask) 587 - { 588 - case 126: 589 - conn_mod_process_large(conn, &hdr, masked); 590 - break; 591 - case 127: 592 - conn_mod_process_huge(conn, &hdr, masked); 593 - break; 594 - default: 595 - conn_mod_process_frame(conn, &hdr, masked); 596 - break; 597 - } 598 - } 599 - 600 - conn_plain_write_sendq(conn->plain_fd, conn); 601 - } 602 - 603 - static void 604 - conn_mod_handshake_process(conn_t *conn) 605 - { 606 - char inbuf[READBUF_SIZE]; 607 - 608 - memset(inbuf, 0, sizeof inbuf); 609 - 610 - while (1) 611 - { 612 - char *p = NULL; 613 - 614 - int dolen = rb_rawbuf_get(conn->modbuf_in, inbuf, sizeof inbuf); 615 - if (!dolen) 616 - break; 617 - 618 - if ((p = rb_strcasestr(inbuf, "Sec-WebSocket-Key:")) != NULL) 619 - { 620 - char *start, *end; 621 - 622 - start = p + strlen("Sec-WebSocket-Key:"); 623 - 624 - for (; start < (inbuf + READBUF_SIZE) && *start; start++) 625 - { 626 - if (*start != ' ' && *start != '\t') 627 - break; 628 - } 629 - 630 - for (end = start; end < (inbuf + READBUF_SIZE) && *end; end++) 631 - { 632 - if (*end == '\r' || *end == '\n') 633 - { 634 - *end = '\0'; 635 - break; 636 - } 637 - } 638 - 639 - rb_strlcpy(conn->client_key, start, sizeof(conn->client_key)); 640 - SetKeyed(conn); 641 - } 642 - } 643 - 644 - if (IsKeyed(conn)) 645 - { 646 - SHA1 sha1; 647 - uint8_t digest[SHA1_DIGEST_LENGTH]; 648 - char *resp; 649 - 650 - sha1_init(&sha1); 651 - sha1_update(&sha1, (uint8_t *) conn->client_key, strlen(conn->client_key)); 652 - sha1_update(&sha1, (uint8_t *) WEBSOCKET_SERVER_KEY, strlen(WEBSOCKET_SERVER_KEY)); 653 - sha1_final(&sha1, digest); 654 - 655 - resp = (char *) rb_base64_encode(digest, SHA1_DIGEST_LENGTH); 656 - 657 - conn_mod_write(conn, WEBSOCKET_ANSWER_STRING_1, strlen(WEBSOCKET_ANSWER_STRING_1)); 658 - conn_mod_write(conn, resp, strlen(resp)); 659 - conn_mod_write(conn, WEBSOCKET_ANSWER_STRING_2, strlen(WEBSOCKET_ANSWER_STRING_2)); 660 - 661 - rb_free(resp); 662 - } 663 - 664 - conn_mod_write_sendq(conn->mod_fd, conn); 665 - } 666 - 667 - static void 668 - conn_mod_read_cb(rb_fde_t *fd, void *data) 669 - { 670 - char inbuf[READBUF_SIZE]; 671 - 672 - memset(inbuf, 0, sizeof inbuf); 673 - 674 - conn_t *conn = data; 675 - int length = 0; 676 - if (conn == NULL) 677 - return; 678 - 679 - if (IsDead(conn)) 680 - return; 681 - 682 - while (1) 683 - { 684 - if (IsDead(conn)) 685 - return; 686 - 687 - length = rb_read(fd, inbuf, sizeof(inbuf)); 688 - 689 - if (length < 0) 690 - { 691 - if (rb_ignore_errno(errno)) 692 - { 693 - rb_setselect(fd, RB_SELECT_READ, conn_mod_read_cb, conn); 694 - conn_plain_write_sendq(conn->plain_fd, conn); 695 - } 696 - else 697 - close_conn(conn, NO_WAIT, "Connection closed"); 698 - 699 - return; 700 - } 701 - else if (length == 0) 702 - { 703 - close_conn(conn, NO_WAIT, "Connection closed"); 704 - return; 705 - } 706 - 707 - rb_rawbuf_append(conn->modbuf_in, inbuf, length); 708 - if (!IsKeyed(conn)) 709 - conn_mod_handshake_process(conn); 710 - else 711 - conn_mod_process(conn); 712 - 713 - if ((size_t) length < sizeof(inbuf)) 714 - { 715 - rb_setselect(fd, RB_SELECT_READ, conn_mod_read_cb, conn); 716 - return; 717 - } 718 - } 719 - } 720 - 721 - static bool 722 - plain_check_cork(conn_t * conn) 723 - { 724 - if(rb_rawbuf_length(conn->modbuf_out) >= 4096) 725 - { 726 - /* if we have over 4k pending outbound, don't read until 727 - * we've cleared the queue */ 728 - SetCork(conn); 729 - rb_setselect(conn->plain_fd, RB_SELECT_READ, NULL, NULL); 730 - /* try to write */ 731 - if (IsKeyed(conn)) 732 - conn_mod_write_sendq(conn->mod_fd, conn); 733 - return true; 734 - } 735 - 736 - return false; 737 - } 738 - 739 - static void 740 - conn_plain_process_recvq(conn_t *conn) 741 - { 742 - char inbuf[READBUF_SIZE]; 743 - 744 - memset(inbuf, 0, sizeof inbuf); 745 - 746 - while (1) 747 - { 748 - int dolen = rb_linebuf_get(&conn->plainbuf_in, inbuf, sizeof inbuf, LINEBUF_COMPLETE, LINEBUF_PARSED); 749 - if (!dolen) 750 - break; 751 - 752 - conn_mod_write_frame(conn, inbuf, dolen); 753 - } 754 - 755 - if (IsKeyed(conn)) 756 - conn_mod_write_sendq(conn->mod_fd, conn); 757 - } 758 - 759 - static void 760 - conn_plain_read_cb(rb_fde_t *fd, void *data) 761 - { 762 - char inbuf[READBUF_SIZE]; 763 - 764 - memset(inbuf, 0, sizeof inbuf); 765 - 766 - conn_t *conn = data; 767 - int length = 0; 768 - if(conn == NULL) 769 - return; 770 - 771 - if(IsDead(conn)) 772 - return; 773 - 774 - if(plain_check_cork(conn)) 775 - return; 776 - 777 - while(1) 778 - { 779 - if(IsDead(conn)) 780 - return; 781 - 782 - length = rb_read(conn->plain_fd, inbuf, sizeof(inbuf)); 783 - 784 - if(length == 0 || (length < 0 && !rb_ignore_errno(errno))) 785 - { 786 - close_conn(conn, NO_WAIT, NULL); 787 - return; 788 - } 789 - 790 - if(length < 0) 791 - { 792 - rb_setselect(conn->plain_fd, RB_SELECT_READ, conn_plain_read_cb, conn); 793 - if (IsKeyed(conn)) 794 - conn_plain_process_recvq(conn); 795 - return; 796 - } 797 - conn->plain_in += length; 798 - 799 - (void) rb_linebuf_parse(&conn->plainbuf_in, inbuf, length, 0); 800 - 801 - if(IsDead(conn)) 802 - return; 803 - if(plain_check_cork(conn)) 804 - return; 805 - } 806 - } 807 - 808 - static void 809 - conn_plain_read_shutdown_cb(rb_fde_t *fd, void *data) 810 - { 811 - char inbuf[READBUF_SIZE]; 812 - conn_t *conn = data; 813 - int length = 0; 814 - 815 - if(conn == NULL) 816 - return; 817 - 818 - while(1) 819 - { 820 - length = rb_read(conn->plain_fd, inbuf, sizeof(inbuf)); 821 - 822 - if(length == 0 || (length < 0 && !rb_ignore_errno(errno))) 823 - { 824 - rb_close(conn->plain_fd); 825 - rb_dlinkAdd(conn, &conn->node, &dead_list); 826 - return; 827 - } 828 - 829 - if(length < 0) 830 - { 831 - rb_setselect(conn->plain_fd, RB_SELECT_READ, conn_plain_read_shutdown_cb, conn); 832 - return; 833 - } 834 - } 835 - } 836 - 837 - static void 838 - wsock_process(mod_ctl_t * ctl, mod_ctl_buf_t * ctlb) 839 - { 840 - conn_t *conn; 841 - uint32_t id; 842 - 843 - conn = make_conn(ctl, ctlb->F[0], ctlb->F[1]); 844 - 845 - id = buf_to_uint32(&ctlb->buf[1]); 846 - conn_add_id_hash(conn, id); 847 - SetWS(conn); 848 - 849 - if(rb_get_type(conn->mod_fd) & RB_FD_UNKNOWN) 850 - rb_set_type(conn->mod_fd, RB_FD_SOCKET); 851 - 852 - if(rb_get_type(conn->plain_fd) == RB_FD_UNKNOWN) 853 - rb_set_type(conn->plain_fd, RB_FD_SOCKET); 854 - 855 - conn_mod_read_cb(conn->mod_fd, conn); 856 - conn_plain_read_cb(conn->plain_fd, conn); 857 - } 858 - 859 - static void 860 - mod_process_cmd_recv(mod_ctl_t * ctl) 861 - { 862 - rb_dlink_node *ptr, *next; 863 - mod_ctl_buf_t *ctl_buf; 864 - 865 - RB_DLINK_FOREACH_SAFE(ptr, next, ctl->readq.head) 866 - { 867 - ctl_buf = ptr->data; 868 - 869 - switch (*ctl_buf->buf) 870 - { 871 - case 'A': 872 - { 873 - if (ctl_buf->nfds != 2 || ctl_buf->buflen != 5) 874 - { 875 - cleanup_bad_message(ctl, ctl_buf); 876 - break; 877 - } 878 - wsock_process(ctl, ctl_buf); 879 - break; 880 - } 881 - default: 882 - break; 883 - /* Log unknown commands */ 884 - } 885 - rb_dlinkDelete(ptr, &ctl->readq); 886 - rb_free(ctl_buf->buf); 887 - rb_free(ctl_buf); 888 - } 889 - 890 - } 891 - 892 - static void 893 - mod_read_ctl(rb_fde_t *F, void *data) 894 - { 895 - mod_ctl_buf_t *ctl_buf; 896 - mod_ctl_t *ctl = data; 897 - int retlen; 898 - int i; 899 - 900 - do 901 - { 902 - ctl_buf = rb_malloc(sizeof(mod_ctl_buf_t)); 903 - ctl_buf->buf = rb_malloc(READBUF_SIZE); 904 - ctl_buf->buflen = READBUF_SIZE; 905 - retlen = rb_recv_fd_buf(ctl->F, ctl_buf->buf, ctl_buf->buflen, ctl_buf->F, 906 - MAXPASSFD); 907 - if(retlen <= 0) 908 - { 909 - rb_free(ctl_buf->buf); 910 - rb_free(ctl_buf); 911 - } 912 - else 913 - { 914 - ctl_buf->buflen = retlen; 915 - rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->readq); 916 - for (i = 0; i < MAXPASSFD && ctl_buf->F[i] != NULL; i++) 917 - ; 918 - ctl_buf->nfds = i; 919 - } 920 - } 921 - while(retlen > 0); 922 - 923 - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) 924 - exit(0); 925 - 926 - mod_process_cmd_recv(ctl); 927 - rb_setselect(ctl->F, RB_SELECT_READ, mod_read_ctl, ctl); 928 - } 929 - 930 - static void 931 - read_pipe_ctl(rb_fde_t *F, void *data) 932 - { 933 - char inbuf[READBUF_SIZE]; 934 - int retlen; 935 - while((retlen = rb_read(F, inbuf, sizeof(inbuf))) > 0) 936 - { 937 - ;; /* we don't do anything with the pipe really, just care if the other process dies.. */ 938 - } 939 - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) 940 - exit(0); 941 - rb_setselect(F, RB_SELECT_READ, read_pipe_ctl, NULL); 942 - } 943 - 944 - int 945 - main(int argc, char **argv) 946 - { 947 - const char *s_ctlfd, *s_pipe, *s_pid; 948 - int ctlfd, pipefd, maxfd, x; 949 - maxfd = maxconn(); 950 - 951 - s_ctlfd = getenv("CTL_FD"); 952 - s_pipe = getenv("CTL_PIPE"); 953 - s_pid = getenv("CTL_PPID"); 954 - 955 - if(s_ctlfd == NULL || s_pipe == NULL || s_pid == NULL) 956 - { 957 - fprintf(stderr, 958 - "This is the solanum wsockd for internal ircd use.\n"); 959 - fprintf(stderr, 960 - "You aren't supposed to run me directly. Exiting.\n"); 961 - exit(1); 962 - } 963 - 964 - ctlfd = atoi(s_ctlfd); 965 - pipefd = atoi(s_pipe); 966 - ppid = atoi(s_pid); 967 - 968 - for(x = 0; x < maxfd; x++) 969 - { 970 - if(x != ctlfd && x != pipefd && x > 2) 971 - close(x); 972 - } 973 - x = open("/dev/null", O_RDWR); 974 - 975 - if(x >= 0) 976 - { 977 - if(ctlfd != 0 && pipefd != 0) 978 - dup2(x, 0); 979 - if(ctlfd != 1 && pipefd != 1) 980 - dup2(x, 1); 981 - if(ctlfd != 2 && pipefd != 2) 982 - dup2(x, 2); 983 - if(x > 2) 984 - close(x); 985 - } 986 - 987 - setup_signals(); 988 - rb_lib_init(NULL, NULL, NULL, 0, maxfd, 1024, 4096); 989 - rb_linebuf_init(4096); 990 - rb_init_rawbuffers(4096); 991 - 992 - mod_ctl = rb_malloc(sizeof(mod_ctl_t)); 993 - mod_ctl->F = rb_open(ctlfd, RB_FD_SOCKET, "ircd control socket"); 994 - mod_ctl->F_pipe = rb_open(pipefd, RB_FD_PIPE, "ircd pipe"); 995 - rb_set_nb(mod_ctl->F); 996 - rb_set_nb(mod_ctl->F_pipe); 997 - rb_event_addish("clean_dead_conns", clean_dead_conns, NULL, 10); 998 - read_pipe_ctl(mod_ctl->F_pipe, NULL); 999 - mod_read_ctl(mod_ctl->F, mod_ctl); 1000 - 1001 - rb_lib_loop(0); 1002 - return 0; 1003 - }