1
2 /*-
3 *
4 * New BSD License 2006
5 *
6 * Copyright (c) 2006, Jorgen Lundman
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met:
12 *
13 * 1 Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2 Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * 3 Neither the name of the stuff nor the names of its contributors
20 * may be used to endorse or promote products derived from this
21 * software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36
37 // $Id: io.c,v 1.107 2006/06/30 01:22:58 lundman Exp $
38 // Core input output functions, the main select() call and misc connectivity
39 // Jorgen Lundman November 5th, 1999
40
41
42 // Universal system headers
43
44 // To properly increase fd_set, we need to over-ride some things.
45 #ifdef FD_SETSIZE
46 #undef FD_SETSIZE
47 #endif
48
49 #define FD_SETSIZE 4096
50
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <sys/types.h>
54 #include <errno.h>
55 #include <string.h>
56 #if __STDC__ || defined(WIN32)
57 #include <stdarg.h>
58 #else
59 #include <varargs.h>
60 #endif
61 #include <signal.h>
62
63 // OS specific system headers
64 #ifdef WIN32
65 #define WINDOWS_LEAN_AND_MEAN
66 #include <winsock2.h>
67 #include <io.h>
68 #else
69 #include <sys/time.h> /* big sigh to linux */
70 #include <unistd.h>
71 #endif
72 #include <fcntl.h>
73
74
75
76
77
78 // Implementation specific headers
79
80 #include "connections.h"
81 #include "sockets.h"
82 #include "io.h"
83
84 #include "lion.h"
85 #include "pipe.h"
86 #include "lgroup.h"
87
88 #include "udp.h"
89
90 #ifdef WITH_SSL
91 #include "tls.h"
92 #endif
93
94
95 //#define DEBUG
96
97 __RCSID("$LiON: lundman/lion/io.c,v 1.107 2006/06/30 01:22:58 lundman Exp $");
98
99
100
101
102 #ifndef MIN
103 #define MIN(a,b) (((a)<(b))?(a):(b))
104 #endif
105
106 #ifndef EWOULDBLOCK
107 #define EWOULDBLOCK EAGAIN
108 #endif
109
110
111 //#define NO_STARVATION_FIX
112 //#define FAVOUR_UPLOAD // Used with starvation fix.
113
114 // Be aware that if you use SSL/TLS, and you disable the READITERATE feature
115 // you risk stalling connections. SSL reads in 16k chunks, but if buffersize
116 // in lion is smaller, we will get one chunk, then wait for more data (in
117 // select() which will never happen) so you will never get the last bit.
118 //#define NO_READITERATE
119 // This max should be defined to ensure buffersize * MAX > 16384.
120 // SSL/TLS uses 17k internally, we have to make sure we read at least that
121 // much. Which is 17408.
122 #define READITERATE_MAX 17408
123 //#define READITERATE_MAX 32768
124
125
126
127 // The fd set holders for select.
128 THREAD_SAFE static fd_set io_fdset_read;
129 THREAD_SAFE static fd_set io_fdset_write;
130
131 THREAD_SAFE static int io_num_fd_inuse = 0;
132
133 THREAD_SAFE static int io_max_connections_allowed = 256;
134
135
136 // Do we compress packets larger than this, or disable?
137 THREAD_SAFE static int io_compress_level = 0;
138
139
140 // The time struct for select's timeout
141 THREAD_SAFE static struct timeval timeout;
142
143
144 // Current time, set once every loop, since time() is quite expensive
145 THREAD_SAFE time_t lion_global_time = 0;
146
147
148 // Force next loop to be poll (no timeout) and enter processing.
149 THREAD_SAFE int io_force_loop = 0;
150
151
152 THREAD_SAFE FILE *trace_file = NULL;
153
154
155
156
157
lion_compress_level(int level)158 void lion_compress_level(int level)
159 {
160
161 io_compress_level = level;
162
163 }
164
165
166
167
168 //
169 // The core, main loop, select calls etc. This function only returns
170 // when the program should exit/abort.
171 //
172 // IN: int utimeout, int timeout - both 0 == poll only, no block
173 // OUT: error, 0 for graceful exit.
174 //
lion_poll(int utimeout,int stimeout)175 int lion_poll(int utimeout, int stimeout)
176 {
177 THREAD_SAFE static int dsize = -1; // result from getdtablesize()
178 int nret; // return code from select()
179 int was_forced = 0;
180
181 // printf ("\n> ");fflush(stdout);
182
183 // Setup the timeval for timeout.
184 // This is tuneable, but 30secs is pretty good for timeouts.
185 timeout.tv_usec = utimeout;
186 timeout.tv_sec = stimeout;
187
188 if (io_force_loop) {
189 // printf("f! ");
190 timeout.tv_usec = 0;
191 timeout.tv_sec = 0;
192 io_force_loop = 0;
193 was_forced = 1;
194 }
195
196 // setup dsize, on Win32 it is ignored, on
197 // unix it retrieved from getdtablesize(), or
198 // OPEN_MAX, or use POSIX getrlimit(), or ....
199
200 // Compute the maximum allowed connections we will allow.
201 // Which is bigger? dsize or FD_MAXSET?
202 if (dsize == -1)
203 dsize = getdtablesize();
204
205
206 #ifdef NBBY
207 io_max_connections_allowed = MIN(dsize, FD_SETSIZE * NBBY);
208 #else
209 io_max_connections_allowed = MIN(dsize, FD_SETSIZE * 8);
210 #endif
211
212 // Trim off, say, 10 connections
213 io_max_connections_allowed -= 10; // Fudge numbers are cool
214
215
216 // Clear the fdset's
217 FD_ZERO( &io_fdset_read );
218 FD_ZERO( &io_fdset_write );
219
220
221 time(&lion_global_time);
222
223
224 // Add all fd's that are required
225
226 io_set_fdset( &io_fdset_read, &io_fdset_write );
227
228
229 // There is a bug in WIN32 that happens if you call select()
230 // with _no_ sockets at all (where it should sleep) it returns
231 // an serious error instead.
232 // If we are not to block, we can simply return here, otherwise
233 // call sleep manually.
234 //if (stimeout == 2) printf("cause\n");
235
236
237 #ifdef WIN32
238 if (!io_num_fd_inuse) {
239
240
241 if (was_forced) {
242 io_process_fdset( &io_fdset_read, &io_fdset_write );
243 }
244
245
246 // Not blocking? just return
247 if (!utimeout && !stimeout) return 0;
248
249 // Block for a bit
250 Sleep(utimeout + (stimeout * 1000));
251
252 return 1;
253
254 }
255 #endif
256
257
258 // Check if we should lower the timeout here due to timer-events.
259 // If a timer is due inside the timeout specified, we need to change it
260 // to a lower number.
261 timers_select(&timeout);
262
263
264 // Simply call select
265 // Can optimise here by passing the highest fd+1 instead of dsize
266 //
267 // printf ("s ");fflush(stdout);
268
269 nret = select( dsize, &io_fdset_read, &io_fdset_write, NULL, &timeout);
270
271 // Check any timer events before io? or after?
272 timers_process();
273
274
275 // printf ("a ");fflush(stdout);
276
277 switch ( nret ) {
278
279 case -1: // error
280 // The only annoying thing here is SunOS/HPUX and some Ultrix
281 // can (frequently) return EAGAIN so we ignore it, and restart,
282 // all other errors mean exit.
283
284 if (( errno == EAGAIN ) || ( errno == EINTR )) {
285 return 0;
286 }
287
288 perror("select: ");
289
290 return -1; // Signal we had a serious error.
291 break;
292
293 case 0: // timeout - perform various timeout checks.
294 //io_pushread();
295
296 // printf("T "); fflush(stdout);
297
298 time(&lion_global_time);
299
300 if (was_forced) {
301 io_process_fdset( &io_fdset_read, &io_fdset_write );
302 }
303
304
305 // Check for rate_out caps
306 io_process_rate();
307
308 return 1;
309 break;
310
311
312
313 default: // there was something happening on our sockets.
314 time(&lion_global_time);
315
316 io_process_fdset( &io_fdset_read, &io_fdset_write );
317
318
319 // Right, to attempt to avoid starvation of clients, since we would
320 // always parse the list in the same order, we "cycle" it here.
321 #ifndef NO_STARVATION_FIX
322
323 connections_cycle();
324
325 #endif
326
327 io_process_rate();
328
329 return 0;
330
331 } // switch
332
333 return 0; // avoid the warning
334
335 }
336
337
338
339
340 // INTERNAL
341 // Add all fd's to the fdset as appropriate
342 // Encapsulated these calls so that winsock wont have to be included
343 // everywhere they are used.
344 //
io_set_fdset(fd_set * fdset_read,fd_set * fdset_write)345 void io_set_fdset( fd_set *fdset_read, fd_set *fdset_write )
346 {
347
348 // These functions call io_set_fdsetread and io_set_fdsetwrite
349
350 io_num_fd_inuse = 0;
351
352 // Add all the sockets known to the system
353 connections_find(io_set_fdset_sub, NULL, NULL);
354
355
356
357 }
358
359
360 // 0 means DON'T add to fd_set, and deny traffic
361 // none-zero means still within limit.
362 // This is called often, could make it faster, maybe #define.
io_check_rate_in(connection_t * node)363 int io_check_rate_in(connection_t *node)
364 {
365 // We do this in order of efficiency
366 // First check connection rate...
367 if (node->rate_in) {
368
369 // No time has passed, say ok
370 // time is assigned as now-1, this can't happen
371 // if (node->time_start >= lion_global_time)
372 // return 1;
373
374 // No need for float maths, go for int approximation.
375 if (( node->bytes_in / (lion_global_time - node->time_start ) / 1024)
376 >= node->rate_in) {
377
378 return 0;
379 }
380 }
381
382
383 // Are we in a group?
384 if (node->group && !lgroup_check_rate_in(node, node->group)) {
385
386 // node->group_bytes_in = 0;
387 return 0;
388 }
389
390 // Check global cap, but only on sockets? or on all? wtf do we do here.
391 // Let's assume they mean just on network sockets.
392 if (!lgroup_check_rate_in(node, LGROUP_GLOBAL)) {
393
394 //node->group_bytes_in = 0;
395 return 0;
396 }
397
398
399 //node->group_bytes_in = 0;
400
401 return 1;
402
403 }
404
405
406
407 // 0 means post BUFFER_USED event, and request deny traffic
408 // none-zero means still within limit.
409 // This is called often, could make it faster, maybe #define.
io_check_rate_out(connection_t * node)410 int io_check_rate_out(connection_t *node)
411 {
412
413 // Rate disabled (why are we here), say ok.
414 if (node->rate_out) {
415
416 if (( node->bytes_out / (lion_global_time - node->time_start ) / 1024)
417 >= node->rate_out)
418 return 0;
419
420 }
421
422 // Are we in a group?
423 if (node->group && !lgroup_check_rate_out(node, node->group)) {
424
425 // node->group_bytes_out = 0;
426 return 0;
427 }
428
429 // Check global cap, but only on sockets? or on all? wtf do we do here.
430 // Let's assume they mean just on network sockets.
431
432 if (!lgroup_check_rate_out(node, LGROUP_GLOBAL)) {
433
434 //node->group_bytes_out = 0;
435 return 0;
436 }
437
438
439 //node->group_bytes_out = 0;
440
441 return 1;
442
443 }
444
445
io_set_fdset_sub(connection_t * node,void * arg1,void * arg2)446 int io_set_fdset_sub( connection_t *node, void *arg1, void *arg2)
447 {
448
449
450 // Perform the magic for sockets
451
452 if (node->type == LION_TYPE_SOCKET) {
453
454 switch ( node->status ) {
455
456 case ST_PENDING: // We are trying to connect(), add to both
457 case ST_LISTEN: // we've called accept(), add to both.
458 if (node->socket >= 0) {
459
460 // Allow them to "sleep" a listening socket.
461 if (!node->disable_read) {
462
463 // Do we seriously want to cap it during connection?
464 //if (io_check_rate_in(node))
465 io_set_fdsetread ( node->socket );
466
467 io_set_fdsetwrite( node->socket );
468
469 }
470
471 } else {
472 io_force_loop = 1;
473 }
474 break;
475
476 case ST_CONNECTED: // Connect, look for new input
477 if (!node->disable_read) {
478
479 // Check CPS
480 if (io_check_rate_in(node)) {
481 io_set_fdsetread ( node->socket );
482
483 #if 0
484 if (node->trace)
485 fprintf(trace_file, "%p: adding to fd_set (%d)\n",
486 node,
487 node->socket);
488 #endif
489
490 }
491 }
492 break;
493
494 case ST_BUFFERFULL:// We have data in send buffer, w8 until we can send it
495 if (!node->disable_read) {
496 if (io_check_rate_in(node))
497 io_set_fdsetread ( node->socket );
498 }
499 // printf("+ "); fflush(stdout);
500 io_set_fdsetwrite( node->socket );
501 break;
502
503 case ST_READBUFFERFULL:// Full on reading, don't try to read.
504 //io_set_fdsetread ( node->socket );
505 //io_set_fdsetwrite( node->socket );
506 break;
507
508 case ST_NONE: // Do nothing
509 case ST_WANTRETURN:
510 case ST_DISCONNECT:
511 case ST_RESUMEREAD:
512 default:
513 break;
514
515 }
516
517 // Check the extended user want modes
518 if (node->status != ST_DISCONNECT)
519 switch( node->want_mode ) {
520
521 case NET_WANT_READ:
522 #ifdef DEBUGVERBOSE
523 printf("Want read, setting %d %d\n",
524 node->socket, node->status);
525 #endif
526 io_set_fdsetread ( node->socket );
527 break;
528 case NET_WANT_WRITE:
529 io_set_fdsetwrite( node->socket );
530 break;
531 case NET_WANT_NONE:
532 case NET_WANT_CLOSE:
533 break;
534 }
535
536
537 return 1; // Keep iterating
538
539 } // SOCKET
540
541
542
543
544 if (node->type == LION_TYPE_FILE) {
545
546 switch ( node->status ) {
547
548 case ST_PENDING: // We are trying to connect(), add to both
549 case ST_LISTEN: // we've called accept(), add to both.
550 if (node->socket >= 0) {
551 if (io_check_rate_in(node))
552 io_set_fdsetread ( node->socket );
553 } else
554 io_force_loop = 1;
555 break;
556
557 case ST_CONNECTED: // Connect, look for new input
558 if (!node->disable_read) {
559 if (io_check_rate_in(node))
560 io_set_fdsetread ( node->socket );
561 }
562 break;
563
564 case ST_BUFFERFULL:// We have data in send buffer, w8 until we can send it
565 if (!node->disable_read) {
566 if (io_check_rate_in(node))
567 io_set_fdsetread ( node->socket );
568 }
569 io_set_fdsetwrite( node->socket );
570 break;
571
572 case ST_READBUFFERFULL:// Full on reading, don't try to read.
573 //io_set_fdsetread ( node->socket );
574 //io_set_fdsetwrite( node->socket );
575 break;
576
577 case ST_NONE: // Do nothing
578 case ST_WANTRETURN:
579 case ST_DISCONNECT:
580 case ST_RESUMEREAD:
581 default:
582 break;
583
584 }
585
586
587 return 1; // Keep iterating
588
589 } // FILE
590
591
592 #ifdef WIN32
593
594 if (node->type == LION_TYPE_PIPE_FILE) {
595
596 switch ( node->status ) {
597
598 case ST_PENDING: // We are trying to connect(), add to both
599 case ST_LISTEN: // we've called accept(), add to both.
600 io_force_loop = 1;
601 break;
602
603 case ST_CONNECTED: // Connect, look for new input
604 if (!node->disable_read) {
605
606 if (io_check_rate_in(node))
607 io_set_fdsetread ( node->socket );
608
609 }
610 break;
611
612 case ST_BUFFERFULL:// We have data in send buffer, w8 until we can send it
613 if (!node->disable_read) {
614 if (io_check_rate_in(node))
615 io_set_fdsetread ( node->socket );
616 }
617 io_set_fdsetwrite( node->socket );
618 break;
619
620 case ST_READBUFFERFULL:// Full on reading, don't try to read.
621 //io_set_fdsetread ( node->socket );
622 //io_set_fdsetwrite( node->socket );
623 break;
624
625 case ST_WANTRETURN: // This node wants return code
626 // If this node now has the returncode, force a loop so the
627 // event is sent!
628 if (node->return_code != -1)
629 io_force_loop = 1;
630 break;
631
632 case ST_NONE: // Do nothing
633 case ST_DISCONNECT:
634 case ST_RESUMEREAD:
635 default:
636 break;
637
638 }
639
640
641 return 1; // Keep iterating
642
643 } // PIPE
644
645 #endif
646
647
648
649
650
651 if (node->type == LION_TYPE_PIPE) {
652
653 switch ( node->status ) {
654
655 case ST_PENDING: // We are trying to connect(), add to both
656 case ST_LISTEN: // we've called accept(), add to both.
657 if (node->socket >= 0) {
658 if (io_check_rate_in(node))
659 io_set_fdsetread ( node->socket );
660 } else
661 io_force_loop = 1;
662 break;
663
664 case ST_CONNECTED: // Connect, look for new input
665 if (!node->disable_read) {
666 if (io_check_rate_in(node))
667 io_set_fdsetread ( node->socket );
668 }
669 break;
670
671 case ST_BUFFERFULL:// We have data in send buffer, w8 until we can send it
672 if (!node->disable_read) {
673 if (io_check_rate_in(node))
674 io_set_fdsetread ( node->socket );
675 }
676 io_set_fdsetwrite( node->socket );
677 break;
678
679 case ST_READBUFFERFULL:// Full on reading, don't try to read.
680 //io_set_fdsetread ( node->socket );
681 //io_set_fdsetwrite( node->socket );
682 break;
683
684 case ST_WANTRETURN: // This node wants return code
685 // If this node now has the returncode, force a loop so the
686 // event is sent!
687 if (node->return_code != -1)
688 io_force_loop = 1;
689 break;
690
691 case ST_NONE: // Do nothing
692 case ST_DISCONNECT:
693 case ST_RESUMEREAD:
694 default:
695 break;
696
697 }
698
699
700 return 1; // Keep iterating
701
702 } // PIPE
703
704
705
706
707 if (node->type == LION_TYPE_UDP) {
708
709 switch ( node->status ) {
710
711 case ST_PENDING:
712 io_force_loop = 1;
713 break;
714
715 case ST_CONNECTED: // Connect, look for new input
716 if (!node->disable_read) {
717
718 // Check CPS
719 if (io_check_rate_in(node))
720 io_set_fdsetread ( node->socket );
721
722 }
723 break;
724
725 case ST_BUFFERFULL:// We have data in send buffer, w8 until we can send it
726 if (!node->disable_read) {
727 if (io_check_rate_in(node))
728 io_set_fdsetread ( node->socket );
729 }
730 io_set_fdsetwrite( node->socket );
731 break;
732
733 case ST_READBUFFERFULL:// Full on reading, don't try to read.
734 //io_set_fdsetread ( node->socket );
735 //io_set_fdsetwrite( node->socket );
736 break;
737
738 case ST_NONE: // Do nothing
739 case ST_WANTRETURN:
740 case ST_DISCONNECT:
741 case ST_RESUMEREAD:
742 default:
743 break;
744
745 }
746
747
748 return 1; // Keep iterating
749
750 } // UDP
751
752
753
754
755
756
757 return 1; // Keep iterating
758
759 }
760
761
762
763 //
764 // Set a fd into the fdset_read
765 //
io_set_fdsetread(int fd)766 void io_set_fdsetread( int fd )
767 {
768
769 if (fd > io_num_fd_inuse)
770 io_num_fd_inuse = fd;
771
772 FD_SET( fd, &io_fdset_read );
773 }
774
775 //
776 // Set a fd into the fdset_read
777 //
io_set_fdsetwrite(int fd)778 void io_set_fdsetwrite( int fd )
779 {
780
781 if (fd > io_num_fd_inuse)
782 io_num_fd_inuse = fd;
783
784 FD_SET( fd, &io_fdset_write );
785 }
786
787
788
789
790 //
791 // Clear a fd into the fdset_read
792 //
io_clear_fdsetread(int fd)793 void io_clear_fdsetread( int fd )
794 {
795 FD_CLR( fd, &io_fdset_read );
796 }
797
798 //
799 // Set a fd into the fdset_read
800 //
io_clear_fdsetwrite(int fd)801 void io_clear_fdsetwrite( int fd )
802 {
803 FD_CLR( fd, &io_fdset_write );
804 }
805
806
807
808
809
810
811
812 //
813 // Check all fdset's for new data
814 //
io_process_fdset(fd_set * fdset_read,fd_set * fdset_write)815 void io_process_fdset( fd_set *fdset_read, fd_set *fdset_write )
816 {
817
818
819 connections_find(io_process_fdset_sub, NULL, NULL);
820
821 // We also need to loop this again, and if there are any
822 // node of type ST_DISCONNECT, we want to close them, and
823 // abort the iteration immediately (as it may be in invalid state)
824 // Since we change the linked list, we can only remove one node at a
825 // time (sub returns 0). But since this is ONLY called when select()
826 // says there was IO (not in TIMEOUT) we would only free ONE node here.
827 // So, now we iterate until all NODES are released.
828 while(connections_find(io_purge_sub, NULL, NULL)) {
829 #ifdef DEBUG
830 printf("PURGE..");
831 #endif
832 };
833
834 }
835
io_purge_sub(connection_t * node,void * arg1,void * arg2)836 int io_purge_sub( connection_t *node, void *arg1, void *arg2)
837 {
838
839 switch (node->status) {
840
841 case ST_DISCONNECT:
842 #ifdef DEBUG
843 printf("[io] disconnected %p - releasing...\n", node);
844 #endif
845 lion_disconnect( node );
846 connections_free(node);
847 return 0;
848
849 default:
850 if (node->want_mode == NET_WANT_CLOSE) {
851 lion_disconnect( node );
852 connections_free(node);
853 return 0;
854 }
855 }
856
857 if ((node->type == LION_TYPE_NONE)
858 #ifdef WIN32
859 && !node->start_address
860 #endif
861 ) {
862 #ifdef DEBUG
863 printf("[io] Found node type none %p - releasing...\n", node);
864 #endif
865 connections_free(node);
866 return 0;
867 }
868
869 return 1;
870 }
871
io_process_fdset_sub(connection_t * node,void * arg1,void * arg2)872 int io_process_fdset_sub( connection_t *node, void *arg1, void *arg2)
873 {
874
875 #ifdef DEBUG
876 //printf("check %d for want %d %p %d\n", node->socket, node->want_mode,
877 // node, node->status);
878 #endif
879
880
881 #if 0 // now in a rate_sub
882 // If we have sent a previous event for rate_out reasons, and
883 // we are no longer over the limit, send enabling event now
884 if (node->rate_out_capped && io_check_rate_out(node)) {
885
886 printf("[io] releasing out cap\n");
887 _lion_userinput( node, node->user_data,
888 LION_BUFFER_EMPTY,
889 0, NULL);
890
891 node->rate_out_capped = 0;
892 }
893 #endif
894
895
896 if (node->type == LION_TYPE_SOCKET) {
897
898
899 switch ( node->status ) {
900
901 case ST_LISTEN: // we've called accept(), check both
902 if (node->socket < 0) { // failed
903 _lion_userinput( node, node->user_data, LION_CONNECTION_LOST,
904 errno,
905 strerror(errno) ); // reason? FIXME
906
907 node->status = ST_DISCONNECT;
908 break;
909
910 }
911
912 if (io_isset_fdsetread( node->socket )) {
913
914 // New connection, signal the user.
915 _lion_userinput( node, node->user_data, LION_CONNECTION_NEW,
916 0, NULL );
917
918 break;
919
920 }
921
922
923
924 case ST_PENDING: // We are trying to connect(), check both
925
926 if (node->socket < 0) { // failed
927
928 _lion_userinput( node, node->user_data, LION_CONNECTION_LOST,
929 errno,
930 strerror(errno) ); // reason? FIXME
931
932 node->status = ST_DISCONNECT;
933 break;
934
935 }
936 // Basically here, if we find we can write to this socket,
937 // it means the connection established fine, and we can
938 // move to ST_CONNECTED state.
939 // If we get a read-trigger only, this means the connection failed
940
941
942 // Check for failure first. If we can read(), but not write().
943 if (io_isset_fdsetread( node->socket ) &&
944 !io_isset_fdsetwrite( node->socket )) {
945
946 // Blast, connection failed
947 // there is a ceaveat here, the only way to get
948 // errno to be set to the failure reason, is
949 // to actually call read(), which we know will fail
950 // but that sets the error code for us.
951
952 sockets_read( node->socket, node->buffer, 1 );
953 //perror("[Services]: services_process_fdset[ST_LISTEN]: connection failed");
954 // Call the above layer
955 _lion_userinput( node, node->user_data, LION_CONNECTION_LOST,
956 errno,
957 strerror(errno) ); // reason? FIXME
958
959 node->status = ST_DISCONNECT;
960 break;
961
962 } // if fdread
963
964
965 // Check for success, ie, we can write.
966 if (io_isset_fdsetwrite( node->socket )) {
967
968 // Sweet, connected.
969 node->status = ST_CONNECTED;
970
971 // Update time for rate
972 node->time_start = lion_global_time - 1;
973
974 #ifdef WITH_SSL
975 // We have to delay the connected event to user code
976 // as they may start to send things until SSL is happy
977 if (node->want_ssl == LION_SSL_CLIENT) {
978
979 // printf("connected and want_ssl is on, call auth\n");
980
981 if (tls_clauth( node ) != 1) { // Wank, failed.
982 // Tricky, do I issue connected_even to client
983 // followed by secure_fail, but they might send
984 // information before the 2nd signal. I could just
985 // close the socket and say it failed, but it is nice
986 // to give the option to the client. SO, we
987 // issue secure_failed first, even though, from the
988 // client's POV it socket "doesn't exist" and they can
989 // have the option to close it. If the socket
990 // still is open we also issue connected_event.
991 // printf("posting failure1\n");
992
993 _lion_userinput( node, node->user_data,
994 LION_CONNECTION_SECURE_FAILED,
995 0, NULL ); // FIXME, SSL_get_error
996
997 // If they asked to disconnect, we just stop here.
998 if (node->status == ST_DISCONNECT)
999 break;
1000
1001
1002 // Falls down to send connected...
1003
1004
1005 } else {
1006
1007 // Sweet, connected.
1008 // When connecting to localhost, the connection,
1009 // and challenge can be so fast, that its done in the
1010 // one call, and status is set to CONNECTED, only
1011 // to have us overwrite it here, and get stuck forever.
1012 // Bug fixed, 20050525
1013 // node->status = ST_SSL_NEG;
1014
1015 // Connection is in progress, so delay events
1016 break;
1017
1018 }
1019
1020
1021
1022 } else if (node->want_ssl == LION_SSL_SERVER) {
1023
1024
1025 // If we are in SERVER mode, we dont want to send the
1026 // connected event above, since we need to wait for
1027 // input, sense for SSL and so on.
1028 break;
1029
1030
1031 }
1032
1033
1034
1035
1036 #endif
1037
1038
1039 _lion_userinput( node, node->user_data,
1040 LION_CONNECTION_CONNECTED, 0, NULL );
1041
1042
1043 break;
1044
1045 }
1046
1047 break; // ST_PENDING & ST_LISTEN
1048
1049
1050
1051 case ST_READBUFFERFULL:// We have data in send buffer, w8 until we can send it
1052
1053 if (io_isset_fdsetwrite( node->socket )) {
1054
1055 // ahh there is room to transmit again, purge the buffer
1056 lion_output( node, NULL, 0);
1057
1058 }
1059 break;
1060
1061
1062 case ST_BUFFERFULL:// We have data in send buffer, w8 until we can send it
1063
1064 if (io_isset_fdsetwrite( node->socket )) {
1065
1066 //printf("res ");
1067
1068 // ahh there is room to transmit again, purge the buffer
1069 lion_output( node, NULL, 0);
1070
1071 // Detect sending failures.
1072 if (node->status == ST_DISCONNECT)
1073 break;
1074
1075 }
1076
1077 // Fall-through!!!
1078 case ST_CONNECTED: // Connect, look for new input
1079
1080 if (node->trace)
1081 fprintf(trace_file, "%p: fd_set (%d) r/w %d/%d\n",
1082 node,
1083 node->socket,
1084 io_isset_fdsetread( node->socket ),
1085 io_isset_fdsetwrite( node->socket ));
1086
1087
1088 if (io_isset_fdsetread( node->socket )) {
1089
1090 // printf("Read isset want %d\n", node->want_mode);
1091
1092 // Special case, if WANT_READ was set, we just call...
1093 if (node->want_mode == NET_WANT_READ) {
1094
1095 #ifdef WITH_SSL
1096 // if (node->status == ST_SSL_NEG)
1097 // tls_cont_auth(node);
1098 //else
1099 node->want_mode = NET_WANT_NONE;
1100 #endif
1101
1102
1103 } else {
1104
1105 #ifdef WITH_SSL
1106 // If we want SSL on incoming connections, lets
1107 // auto-sense if this input is SSL or not. That way
1108 // we don't swallow input incase it isnt.
1109 if ( node->want_ssl == LION_SSL_SERVER ) {
1110
1111 tls_peek(node);
1112 break;
1113
1114 }
1115 #endif
1116
1117
1118 // We have input, deal with it
1119 io_input( node );
1120
1121 }
1122
1123
1124 // Check if WANT_WRITE is set, and isset write
1125 } else if ((node->want_mode == NET_WANT_WRITE) &&
1126 (io_isset_fdsetwrite( node->socket ))) {
1127
1128 #ifdef WITH_SSL
1129 //if (node->status == ST_SSL_NEG)
1130 // tls_cont_auth(node);
1131 //else
1132 node->want_mode = NET_WANT_NONE;
1133 #endif
1134
1135 }
1136
1137
1138 // If we have sent a previous event for rate_out reasons, and
1139 // we are no longer over the limit, send enabling event now
1140
1141 break; // ST_CONNECTED
1142 break; // ST_BUFFERFULL
1143
1144
1145
1146 #ifdef WITH_SSL
1147 case ST_SSL_NEG:
1148 if (node->want_mode != NET_WANT_NONE) {
1149 if ((node->auth_type == LION_SSL_SERVER) &&
1150 (io_isset_fdsetread( node->socket )))
1151 tls_cont_auth(node);
1152 else if ((node->auth_type == LION_SSL_CLIENT) &&
1153 (io_isset_fdsetread( node->socket )))
1154 tls_cont_clauth(node);
1155 }
1156 break;
1157 #endif
1158
1159 case ST_RESUMEREAD:
1160 io_input( node );
1161 break;
1162
1163
1164 case ST_DISCONNECT: // Wanting disconnect
1165 case ST_WANTRETURN:
1166 case ST_NONE: // Do nothing
1167 default:
1168
1169 break;
1170
1171 }
1172
1173 return 1; // Keep iterating
1174
1175 } // SOCKET
1176
1177
1178
1179 // ******************************************************************
1180
1181
1182
1183
1184 if (node->type == LION_TYPE_FILE) {
1185
1186
1187 switch ( node->status ) {
1188
1189
1190 case ST_LISTEN: // there is no LISTEN state on files
1191 break;
1192
1193
1194
1195 case ST_PENDING: // file open, just say its good.
1196
1197 if (node->socket < 0) { // failed
1198
1199 _lion_userinput( node, node->user_data, LION_FILE_FAILED,
1200 errno,
1201 strerror(errno) ); // reason? FIXME
1202
1203 node->status = ST_DISCONNECT;
1204 break;
1205
1206 }
1207
1208 // We only get here if the file was opened successfully anyway
1209 // so we mark it good, and send the event. Note there is
1210 // a potential starvation here. Only opened a file, no sockets
1211 // have io and the file has nothing to read, the poll would
1212 // block until timeout.
1213
1214 node->status = ST_CONNECTED;
1215
1216 // Update time for rate
1217 node->time_start = lion_global_time - 1;
1218
1219 _lion_userinput( node, node->user_data, LION_FILE_OPEN,
1220 0, NULL );
1221
1222 break; // ST_PENDING
1223
1224
1225
1226 case ST_READBUFFERFULL:// We have data in send buffer, w8 until we can send it
1227
1228 if (io_isset_fdsetwrite( node->socket )) {
1229
1230 // ahh there is room to transmit again, purge the buffer
1231 lion_output( node, NULL, 0);
1232
1233 }
1234 break;
1235
1236
1237 case ST_BUFFERFULL:// We have data in send buffer, w8 until we can send it
1238 if (io_isset_fdsetwrite( node->socket )) {
1239
1240 // ahh there is room to transmit again, purge the buffer
1241 lion_output( node, NULL, 0);
1242
1243 }
1244
1245 // Fall-through!!!
1246 case ST_CONNECTED: // Connect, look for new input
1247
1248 if (io_isset_fdsetread( node->socket )) {
1249
1250 // We have input, deal with it
1251 io_input( node );
1252
1253 }
1254
1255 break; // ST_CONNECTED
1256 break; // ST_BUFFERFULL
1257
1258
1259 case ST_DISCONNECT: // Wanting disconnect
1260 case ST_WANTRETURN:
1261 case ST_NONE: // Do nothing
1262 case ST_RESUMEREAD:
1263 default:
1264
1265 break;
1266
1267 }
1268
1269
1270
1271
1272 return 1; // Keep iterating
1273 } // FILE
1274
1275
1276
1277
1278
1279
1280
1281
1282 #ifdef WIN32
1283
1284 // ******************************************************************
1285
1286
1287
1288
1289 if (node->type == LION_TYPE_PIPE_FILE) {
1290
1291
1292 switch ( node->status ) {
1293
1294
1295 case ST_LISTEN: // there is no LISTEN state on files
1296 break;
1297
1298
1299
1300 case ST_PENDING: // fork, fail, or success
1301
1302 if (node->socket < 0) { // failed
1303
1304 _lion_userinput( node, node->user_data, LION_FILE_FAILED,
1305 0, "file IO failed" ); // reason? FIXME
1306 node->status = ST_DISCONNECT;
1307 break;
1308
1309 }
1310
1311 //printf("io - pipe_file for conncted\n");
1312
1313 // Assume pipe was successful.
1314 node->status = ST_CONNECTED;
1315
1316 _lion_userinput( node, node->user_data, LION_FILE_OPEN,
1317 0, NULL );
1318 // We assume the user does all of the wanted lseek() etc in the event above.
1319 // So we release the mutex so the child runs
1320 #ifdef DEBUG
1321 printf("[io] Telling child %p to start\n", node);
1322 #endif
1323 ReleaseMutex( node->mutex );
1324 //CloseHandle( node->mutex );
1325 // Clear mutex here so that file really gets closed.
1326 node->mutex = NULL;
1327 break; // ST_PENDING
1328
1329
1330 case ST_READBUFFERFULL:// We have data in send buffer, w8 until we can send it
1331
1332 if (io_isset_fdsetwrite( node->socket )) {
1333
1334 // ahh there is room to transmit again, purge the buffer
1335 lion_output( node, NULL, 0);
1336
1337 }
1338 break;
1339
1340
1341 case ST_BUFFERFULL:// We have data in send buffer, w8 until we can send it
1342 if (io_isset_fdsetwrite( node->socket )) {
1343
1344 // ahh there is room to transmit again, purge the buffer
1345 lion_output( node, NULL, 0);
1346
1347 }
1348
1349 // Fall-through!!!
1350 case ST_CONNECTED: // Connect, look for new input
1351
1352 if (io_isset_fdsetread( node->socket )) {
1353
1354 // We have input, deal with it
1355 io_input( node );
1356
1357 }
1358
1359
1360 break; // ST_CONNECTED
1361
1362 case ST_WANTRETURN:
1363
1364 // Ok, if we have the return code now finally, issue the
1365 // event.
1366
1367 if (node->return_code != -1) {
1368
1369 _lion_userinput( node, node->user_data,
1370 LION_PIPE_EXIT,
1371 pipe_get_status(node),
1372 NULL);
1373
1374 // Note we set the status to disconnect here, AFTER the
1375 // event. Because the app can call to ask for another event
1376 // when the returncode is know, we over-rule this here. You
1377 // can only ask for it once, and it is known now anyway.
1378 node->status = ST_DISCONNECT;
1379
1380 }
1381
1382
1383 break;
1384
1385
1386 case ST_DISCONNECT: // Wanting disconnect
1387 case ST_NONE: // Do nothing
1388 case ST_RESUMEREAD:
1389 default:
1390
1391 break;
1392
1393 }
1394
1395
1396
1397
1398 return 1; // Keep iterating
1399 } // PIPE
1400
1401
1402
1403 #endif
1404
1405
1406
1407
1408
1409
1410
1411
1412 // ******************************************************************
1413
1414
1415
1416
1417
1418
1419
1420 if (node->type == LION_TYPE_PIPE) {
1421
1422
1423 switch ( node->status ) {
1424
1425
1426 case ST_LISTEN: // there is no LISTEN state on files
1427 break;
1428
1429
1430
1431 case ST_PENDING: // fork, fail, or success
1432 if (node->socket < 0) { // failed
1433
1434 if (node->error_code) {
1435 _lion_userinput( node, node->user_data, LION_PIPE_FAILED,
1436 node->error_code,
1437 strerror(node->error_code) );
1438 } else {
1439
1440 // Who closes the socket here? XXX
1441 _lion_userinput( node, node->user_data, LION_PIPE_FAILED,
1442 0, "fork failed" ); // reason? FIXME
1443 }
1444
1445 node->status = ST_DISCONNECT;
1446 break;
1447
1448 }
1449
1450 // Assume pipe was successful.
1451 node->status = ST_CONNECTED;
1452
1453 // Update time for rate
1454 node->time_start = lion_global_time - 1;
1455
1456 _lion_userinput( node, node->user_data, LION_PIPE_RUNNING,
1457 0, NULL );
1458
1459 #ifdef WIN32
1460 if ( node->mutex ) {
1461 #ifdef DEBUG
1462 printf("[io] tellchild %p to start..\n", node);
1463 #endif
1464 ReleaseMutex( node->mutex );
1465 //CloseHandle( node->mutex );
1466 //node->mutex = NULL;
1467 }
1468 #endif
1469
1470 if (node->outbuffer > 0) {
1471 printf("[io] Connected, with data, setting READBUFFERFULL\n");
1472 node->status = ST_READBUFFERFULL;
1473 }
1474
1475 break; // ST_PENDING
1476
1477
1478
1479 case ST_READBUFFERFULL:// We have data in send buffer, w8 until we can send it
1480
1481 if (io_isset_fdsetwrite( node->socket )) {
1482
1483 // ahh there is room to transmit again, purge the buffer
1484 lion_output( node, NULL, 0);
1485
1486 }
1487 break;
1488
1489
1490 case ST_BUFFERFULL:// We have data in send buffer, w8 until we can send it
1491 if (io_isset_fdsetwrite( node->socket )) {
1492
1493 // ahh there is room to transmit again, purge the buffer
1494 lion_output( node, NULL, 0);
1495
1496 }
1497
1498 // Fall-through!!!
1499 case ST_CONNECTED: // Connect, look for new input
1500
1501 if (io_isset_fdsetread( node->socket )) {
1502
1503 // We have input, deal with it
1504 io_input( node );
1505
1506 }
1507
1508 break; // ST_CONNECTED
1509
1510 case ST_WANTRETURN:
1511
1512 // Ok, if we have the return code now finally, issue the
1513 // event.
1514
1515 if (node->return_code != -1) {
1516
1517 _lion_userinput( node, node->user_data,
1518 LION_PIPE_EXIT,
1519 pipe_get_status(node),
1520 NULL);
1521
1522 // Note we set the status to disconnect here, AFTER the
1523 // event. Because the app can call to ask for another event
1524 // when the returncode is known, we over-rule this here. You
1525 // can only ask for it once, and it is known now anyway.
1526 node->status = ST_DISCONNECT;
1527
1528 }
1529
1530
1531 break;
1532
1533
1534 case ST_DISCONNECT: // Wanting disconnect
1535 case ST_RESUMEREAD:
1536 case ST_NONE: // Do nothing
1537 default:
1538
1539 break;
1540
1541 }
1542
1543
1544
1545
1546 return 1; // Keep iterating
1547 } // PIPE
1548
1549
1550
1551
1552
1553
1554
1555
1556 // ******************************************************************
1557
1558
1559
1560
1561
1562
1563
1564 if (node->type == LION_TYPE_UDP) {
1565
1566
1567 switch ( node->status ) {
1568
1569
1570 case ST_PENDING: // We are trying to connect(), check both
1571
1572 if (node->socket < 0) { // failed
1573
1574 _lion_userinput( node, node->user_data, LION_CONNECTION_LOST,
1575 errno,
1576 strerror(
1577 node->error_code ?
1578 node->error_code :
1579 errno) );
1580
1581 node->status = ST_DISCONNECT;
1582 break;
1583
1584 }
1585
1586 _lion_userinput( node, node->user_data, LION_CONNECTION_CONNECTED,
1587 0,
1588 NULL); // reason? FIXME
1589
1590 node->status = ST_CONNECTED;
1591 break;
1592
1593
1594 case ST_READBUFFERFULL:// We have data in send buffer, w8 until we can send it
1595
1596 if (io_isset_fdsetwrite( node->socket )) {
1597
1598 // Need to clear UDP so other nodes steal it.
1599 io_clear_fdsetread( node->socket );
1600
1601 // ahh there is room to transmit again, purge the buffer
1602 lion_output( node, NULL, 0);
1603
1604 }
1605 break;
1606
1607
1608 case ST_BUFFERFULL:// We have data in send buffer, w8 until we can send it
1609
1610 if (io_isset_fdsetwrite( node->socket )) {
1611
1612 io_clear_fdsetwrite( node->socket );
1613
1614 // ahh there is room to transmit again, purge the buffer
1615 lion_output( node, NULL, 0);
1616
1617 }
1618
1619 // Fall-through!!!
1620 case ST_CONNECTED: // Connect, look for new input
1621
1622 if (io_isset_fdsetread( node->socket )) {
1623
1624 io_clear_fdsetread( node->socket );
1625 // printf("Read isset want %d\n", node->want_mode);
1626
1627 // Special case, if WANT_READ was set, we just call...
1628 // We have input, deal with it
1629 io_input( node );
1630
1631 }
1632
1633
1634 break; // ST_CONNECTED
1635 break; // ST_BUFFERFULL
1636
1637
1638
1639 case ST_DISCONNECT: // Wanting disconnect
1640 case ST_WANTRETURN:
1641 case ST_RESUMEREAD:
1642 case ST_NONE: // Do nothing
1643 default:
1644
1645 break;
1646
1647 }
1648
1649 return 1; // Keep iterating
1650
1651 } // UDP
1652
1653
1654
1655
1656
1657
1658 return 1; // Keep iterating
1659 }
1660
1661
1662
1663 //
1664 // Check if a fd is set in read
1665 //
io_isset_fdsetread(int fd)1666 int io_isset_fdsetread( int fd )
1667 {
1668 return FD_ISSET( fd, &io_fdset_read );
1669 }
1670
1671 //
1672 // Check if a fd is set in write
1673 //
io_isset_fdsetwrite(int fd)1674 int io_isset_fdsetwrite( int fd )
1675 {
1676 return FD_ISSET( fd, &io_fdset_write );
1677 }
1678
1679
1680
1681
io_near_full(void)1682 int io_near_full( void )
1683 {
1684
1685 if (io_num_fd_inuse >= io_max_connections_allowed)
1686 return 0;
1687
1688 return 1;
1689
1690 }
1691
1692
1693
1694
1695
1696
1697
1698
io_process_rate_sub(connection_t * node,void * arg1,void * arg2)1699 int io_process_rate_sub( connection_t *node, void *arg1, void *arg2)
1700 {
1701
1702 if (!node->rate_out_capped)
1703 return 1;
1704
1705 //printf("[io]: testing cap on %p\n", node);
1706
1707
1708 switch( node->status ) {
1709
1710 case ST_PENDING:
1711 case ST_LISTEN:
1712 case ST_CONNECTED:
1713 case ST_BUFFERFULL:
1714
1715 // If we have sent a previous event for rate_out reasons, and
1716 // we are no longer over the limit, send enabling event now
1717 if (io_check_rate_out(node)) {
1718
1719 // printf("[io] releasing out cap 2\n");
1720 _lion_userinput( node, node->user_data,
1721 LION_BUFFER_EMPTY,
1722 0, NULL);
1723
1724 node->rate_out_capped = 0;
1725 }
1726
1727 break;
1728 default:
1729 //printf("[io]: not %d\n", node->status);
1730 break;
1731 }
1732
1733 return 1;
1734 }
1735
1736
1737
1738 //
1739 // If select() timedout, we need to also loop through and check for
1740 // rate_out that should now be enabled again. If the loop is ran when
1741 // select isn't idle, it is automatically cared for in process loop above.
1742 // We could always call this loop, but then we loop twice everytime.
1743 //
io_process_rate(void)1744 void io_process_rate( void )
1745 {
1746
1747
1748 connections_find(io_process_rate_sub, NULL, NULL);
1749
1750
1751 }
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761 //
1762 //
lion_connect(char * host,int port,unsigned long iface,int iport,int lion_flags,void * user_data)1763 connection_t *lion_connect(char *host, int port, unsigned long iface,
1764 int iport,
1765 int lion_flags, void *user_data)
1766 {
1767 connection_t *newd;
1768 unsigned long ip;
1769
1770 newd = connections_new();
1771
1772 newd->type = LION_TYPE_SOCKET;
1773 newd->user_data = user_data;
1774
1775 if (lion_flags & LION_FLAG_TRACE)
1776 lion_enable_trace(newd);
1777
1778 if (newd->trace)
1779 fprintf(trace_file, "%p: lion_connect\n", newd);
1780
1781 // This function blocks.
1782 ip = sockets_gethost(host);
1783
1784
1785 if (!ip || ((newd->socket = sockets_connect(ip, port, iface, iport)) <0)) {
1786
1787 // Signal above layer of failure
1788 if (lion_flags & LION_FLAG_FULFILL) {
1789
1790 newd->status = ST_PENDING;
1791 // and sockets is == -1 it will be failed in pending.
1792 io_force_loop = 1;
1793 return newd;
1794
1795 } else {
1796
1797 _lion_userinput( newd, newd->user_data, LION_CONNECTION_LOST,
1798 errno, strerror( errno ) );
1799
1800 connections_free(newd);
1801
1802 return NULL;
1803
1804 }
1805
1806 }
1807
1808 // Let the network layer we are pending a connection
1809 newd->status = ST_PENDING;
1810
1811 return newd;
1812
1813 }
1814
1815
lion_listen(int * port,unsigned long iface,int lion_flags,void * user_data)1816 connection_t *lion_listen(int *port, unsigned long iface, int lion_flags,
1817 void *user_data)
1818 {
1819 connection_t *newd;
1820
1821 newd = connections_new();
1822
1823 newd->type = LION_TYPE_SOCKET;
1824
1825 newd->user_data = user_data;
1826
1827 if (lion_flags & LION_FLAG_TRACE)
1828 lion_enable_trace(newd);
1829
1830 if (newd->trace)
1831 fprintf(trace_file, "%p: lion_listen\n", newd);
1832
1833 if (((newd->socket = sockets_make(port, iface,
1834 (lion_flags & LION_FLAG_EXCLUSIVE)
1835 )) < 0)) {
1836
1837 // Signal above layer of failure
1838 if (lion_flags & LION_FLAG_FULFILL) {
1839
1840 newd->status = ST_LISTEN;
1841 // and sockets is == -1 it will be failed in pending.
1842 io_force_loop = 1;
1843 return newd;
1844
1845 }
1846
1847 _lion_userinput( newd, newd->user_data, LION_CONNECTION_LOST,
1848 errno, strerror( errno ) );
1849
1850 connections_free(newd);
1851
1852 return NULL;
1853 }
1854
1855 // Let the network layer we are pending a connection
1856 newd->status = ST_LISTEN;
1857
1858 return newd;
1859
1860 }
1861
1862
lion_accept(connection_t * node,int close_old,int lion_flags,void * user_data,unsigned long * remhost,int * remport)1863 connection_t *lion_accept(connection_t *node, int close_old, int lion_flags,
1864 void *user_data,unsigned long *remhost, int *remport)
1865 {
1866 connection_t *newd;
1867
1868 newd = connections_new();
1869
1870 newd->type = LION_TYPE_SOCKET;
1871
1872 newd->user_data = user_data;
1873
1874 newd->socket = sockets_accept( node->socket, remhost, remport);
1875
1876
1877 if (close_old)
1878 node->status = ST_DISCONNECT;
1879
1880 if (lion_flags & LION_FLAG_TRACE)
1881 lion_enable_trace(newd);
1882
1883 if (newd->trace)
1884 fprintf(trace_file, "%p: lion_accept\n", newd);
1885
1886 if (newd->socket < 0) {
1887
1888 if (lion_flags & LION_FLAG_FULFILL) {
1889
1890 newd->status = ST_PENDING;
1891 // and sockets is == -1 it will be failed in pending.
1892 io_force_loop = 1;
1893 return newd;
1894 }
1895
1896 // Signal above layer of failure
1897 _lion_userinput( newd, newd->user_data, LION_CONNECTION_LOST,
1898 errno, strerror( errno ) );
1899
1900 connections_free(newd);
1901
1902 return NULL;
1903
1904 }
1905
1906
1907 newd->status = ST_PENDING;
1908
1909 return newd;
1910
1911 }
1912
1913
1914
1915
1916 //
1917 // close flushes any data in the output buffer before closing.
1918 // the app will receive BUFFER_EMPTY followed by _CLOSED
1919 //
lion_close(connection_t * node)1920 void lion_close(connection_t *node)
1921 {
1922 #ifdef WIN32
1923 int r = 0;
1924 #endif
1925 static connection_t *rentry = NULL;
1926
1927 if (!node)
1928 return;
1929
1930 if (node->trace)
1931 fprintf(trace_file, "%p: lion_close\n", node);
1932
1933 // If we are already in an event, delay this close.
1934 if (node->in_event) {
1935 node->want_mode = NET_WANT_CLOSE;
1936 return;
1937 }
1938
1939
1940 if (rentry == node) return;
1941
1942 rentry = node;
1943
1944
1945 // Check if there is data to flush
1946 // if there is, signal we are technically closed, then in
1947 // the write section we actually close it, and send the event.
1948 if ((node->status == ST_BUFFERFULL)
1949 #ifdef WIN32
1950 // In Windows, if we are writing a file, say in Write mode, and we've not released the mutex
1951 // then the data will never get written. Soft_close (next poll loop releases mutex).
1952 || (node->mutex)
1953 #endif
1954 ) {
1955
1956 #ifdef DEBUG
1957 printf("net_close(%p) with data, flushing...\n", node);
1958 #endif
1959
1960 // In Windows, a file is a pipe, so it is in PENDING. The when it gets
1961 // connected, we release Mutex, and set to CONNECTED. If the caller has lion_open()
1962 // lion_printf(), lion_close(). It would never enter CONNECTED, and mutex never released.
1963 if (node->status == ST_PENDING) {
1964 node->soft_closed = 1;
1965 return;
1966 }
1967
1968 node->status = ST_BUFFERFULL;
1969 node->soft_closed = 1;
1970
1971 if (node->trace)
1972 fprintf(trace_file, "%p: soft_close due to bufferdata\n", node);
1973
1974 return;
1975 }
1976
1977 #ifdef DEBUG
1978 printf("lion_close(%p) no data, closing.\n", node);
1979 #endif
1980
1981 node->soft_closed = 0;
1982
1983
1984 #ifdef WITH_SSL
1985 tls_close(node);
1986 #endif
1987
1988
1989 node->status = ST_DISCONNECT;
1990 node->want_mode = NET_WANT_NONE;
1991
1992 switch(node->type) {
1993
1994 case LION_TYPE_SOCKET:
1995 if (node->socket > 0)
1996 sockets_close( node->socket );
1997 node->socket = -1;
1998 _lion_userinput( node, node->user_data,
1999 LION_CONNECTION_CLOSED, 0, NULL);
2000 break;
2001 case LION_TYPE_FILE:
2002 if (node->socket > 0)
2003 close( node->socket );
2004 node->socket = -1;
2005 _lion_userinput( node, node->user_data,
2006 LION_FILE_CLOSED, 0, NULL);
2007 break;
2008 #ifdef WIN32
2009 case LION_TYPE_PIPE_FILE:
2010 if (node->socket > 0)
2011 sockets_close( node->socket );
2012 node->socket = -1;
2013
2014 // printf("lion_close\n");
2015
2016 GetExitCodeThread( node->thread, &r);
2017
2018 if (node->thread2 && !r) {
2019 GetExitCodeThread( node->thread2, &r);
2020 }
2021
2022 if (r) {
2023 _lion_userinput( node, node->user_data,
2024 LION_FILE_FAILED, r, "IO error");
2025 } else {
2026 _lion_userinput( node, node->user_data,
2027 LION_FILE_CLOSED, 0, NULL);
2028 }
2029
2030 if (node->thread) {
2031 CloseHandle( node->thread );
2032 node->thread = NULL;
2033 }
2034 if (node->thread2) {
2035 CloseHandle( node->thread2 );
2036 node->thread2 = NULL;
2037 }
2038
2039
2040 break;
2041 #endif
2042 case LION_TYPE_PIPE:
2043 if (node->socket > 0)
2044 sockets_close( node->socket );
2045 // close( node->socket );
2046 node->socket = -1;
2047 _lion_userinput( node, node->user_data,
2048 LION_PIPE_EXIT, 0, NULL);
2049 break;
2050 case LION_TYPE_UDP:
2051 // UDP we only close the actual UDP socket if we are the last one.
2052 if ((node->socket > 0) && !udp_find_others(node)) {
2053 #ifdef DEBUG
2054 printf("[io] udp, no others %d actually closing.\n", node->socket);
2055 #endif
2056 sockets_close( node->socket );
2057 node->socket = -1;
2058 }
2059 _lion_userinput( node, node->user_data,
2060 LION_CONNECTION_CLOSED, 0, NULL);
2061 break;
2062 default:
2063 break;
2064 }
2065
2066 node->type = LION_TYPE_NONE;
2067 rentry = NULL;
2068
2069 }
2070
2071
2072 //
2073 // net_disconnect does NOT flush output buffer, simply drops everything
2074 // and closes. Since we will generate an "event" to the user, and they may
2075 // call lion_disconnect() again, we need to make sure we don't loop forever.
2076 //
lion_disconnect(connection_t * node)2077 void lion_disconnect(connection_t *node)
2078 {
2079 #ifdef WIN32
2080 int r = 0;
2081 #endif
2082 static connection_t *rentry = NULL;
2083
2084 if (node->trace)
2085 fprintf(trace_file, "%p: lion_disconnect\n", node);
2086
2087 // If we are already in an event, delay this close.
2088 if (node->in_event) {
2089 node->want_mode = NET_WANT_CLOSE;
2090 return;
2091 }
2092
2093 if (rentry == node) return;
2094
2095 rentry = node;
2096
2097 #ifdef WITH_SSL
2098 tls_close(node);
2099 #endif
2100
2101 node->want_mode = NET_WANT_NONE;
2102
2103
2104 switch(node->type) {
2105
2106 case LION_TYPE_SOCKET:
2107 if (node->socket > 0)
2108 sockets_close( node->socket );
2109 node->socket = -1;
2110 if (node->status != ST_DISCONNECT)
2111 _lion_userinput( node, node->user_data,
2112 LION_CONNECTION_CLOSED, 0, NULL);
2113 break;
2114 case LION_TYPE_FILE:
2115 if (node->socket > 0)
2116 close( node->socket );
2117 node->socket = -1;
2118 if (node->status != ST_DISCONNECT)
2119 _lion_userinput( node, node->user_data,
2120 LION_FILE_CLOSED, 0, NULL);
2121 break;
2122 #ifdef WIN32
2123 case LION_TYPE_PIPE_FILE:
2124 if (node->socket > 0)
2125 sockets_close( node->socket );
2126 node->socket = -1;
2127 if (node->status != ST_DISCONNECT) {
2128
2129 // printf("lion?disconnect\n");
2130 GetExitCodeThread( node->thread, &r);
2131
2132 if (node->thread2 && !r)
2133 GetExitCodeThread( node->thread2, &r);
2134
2135 if (r) {
2136 _lion_userinput( node, node->user_data,
2137 LION_FILE_FAILED, r, "file IO error");
2138 } else {
2139 _lion_userinput( node, node->user_data,
2140 LION_FILE_CLOSED, 0, NULL);
2141 }
2142 }
2143
2144 if (node->thread) {
2145 CloseHandle( node->thread );
2146 node->thread = NULL;
2147 }
2148
2149 if (node->thread2) {
2150 CloseHandle( node->thread2 );
2151 node->thread2 = NULL;
2152 }
2153
2154
2155 break;
2156 #endif
2157 case LION_TYPE_PIPE:
2158 if (node->socket > 0)
2159 sockets_close( node->socket );
2160 // close( node->socket );
2161 node->socket = -1;
2162 if (node->status != ST_DISCONNECT)
2163 _lion_userinput( node, node->user_data,
2164 LION_PIPE_EXIT, 0, NULL);
2165 break;
2166 case LION_TYPE_UDP:
2167 // UDP we only close the actual UDP socket if we are the last one.
2168 if ((node->socket > 0) && !udp_find_others(node)) {
2169 #ifdef DEBUG
2170 printf("[io] udp, no others %d actually closing.\n", node->socket);
2171 #endif
2172 sockets_close( node->socket );
2173 node->socket = -1;
2174 }
2175 if (node->status != ST_DISCONNECT)
2176 _lion_userinput( node, node->user_data,
2177 LION_CONNECTION_CLOSED, 0, NULL);
2178 break;
2179 default:
2180 break;
2181 }
2182
2183
2184 node->status = ST_NONE;
2185 node->type = LION_TYPE_NONE;
2186
2187 rentry = NULL;
2188
2189 }
2190
2191
2192
2193
2194
io_release_all_sub(connection_t * node,void * arg1,void * arg2)2195 int io_release_all_sub( connection_t *node, void *arg1, void *arg2)
2196 {
2197 #ifdef DEBUG_VERBOSE
2198 printf("io_release_all_sub(): %p %p\n", node, arg2);
2199 #endif
2200
2201 if (arg2 && (arg2 == (void *) node)) // is it the node to skip?
2202 return 1; // iterate to the next one.
2203
2204 if (arg1) *((int *)arg1) = 1; // Found a node
2205
2206 // We don't want to generate any events here, so set each node's status
2207 // to disconnect
2208
2209 node->status = ST_DISCONNECT;
2210
2211 lion_disconnect( node ); // refering to node after this call is illegal.
2212 connections_free( node );
2213
2214 return 0; // Since we delete this node, STOP iterating!
2215
2216 }
2217
2218
2219
io_release_all(connection_t * except_for)2220 void io_release_all( connection_t *except_for )
2221 {
2222 int not_empty;
2223
2224
2225 // iterate everything, passing a long an int so we know if we found
2226 // anything, so we can know when to stop. Also pass the except_for node
2227 // if any, to skip releasing a certain node.
2228
2229 // Since we are removing nodes from the linked list we have to
2230 // stop iterating every time!
2231 do {
2232 not_empty = 0;
2233 connections_find(io_release_all_sub,
2234 (void *)¬_empty, (void *)except_for );
2235 } while( not_empty );
2236
2237
2238 }
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254 #include <string.h>
2255 #include "base64.h"
2256 #include "zlib.h"
2257
2258 #define NET_COMPRESS_MAGIC "@CP!" // 4 bytes only!
2259
2260
2261 //
2262 // Send a string to a service
2263 //
2264 #if __STDC__ || defined(WIN32)
lion_printf(connection_t * node,char const * fmt,...)2265 int lion_printf(connection_t *node, char const *fmt, ...)
2266 #else
2267 int lion_printf(node, fmt, va_alist)
2268 connection_t *node;
2269 char const *fmt;
2270 va_dcl
2271 #endif
2272 {
2273 va_list ap;
2274 THREAD_SAFE static char msg[STATIC_BUFFER_SIZE];
2275 int result;
2276
2277
2278 if (!node) return -1;
2279
2280
2281 #if __STDC__ || defined(WIN32)
2282 va_start(ap, fmt);
2283 #else
2284 va_start(ap);
2285 #endif
2286
2287 // Buffer overflow! No vsnprintf on many systems :(
2288 //result = vsprintf(msg, fmt, ap);
2289 result = vsnprintf(msg, sizeof(msg), fmt, ap);
2290 va_end(ap);
2291
2292
2293
2294 // printf("%08x : %s", node, msg);
2295
2296
2297
2298
2299 //result = net_output( node, msg, result);
2300 return lion_send( node, msg, result);
2301
2302 }
2303
2304
2305
2306
2307 //
2308 // Wrapper for net_output, this check for the need to compress
2309 //
lion_send(connection_t * node,char * buffer,unsigned int len)2310 int lion_send( connection_t *node, char *buffer, unsigned int len)
2311 {
2312 THREAD_SAFE static char msg[STATIC_BUFFER_SIZE];
2313 unsigned int new_len;
2314
2315 // Do we compress it? Is it large enough?
2316 if (io_compress_level && (len >= io_compress_level)) {
2317 z_stream state;
2318
2319 #ifdef DEBUG
2320 printf("Output is %u bytes.\n", len);
2321 #endif
2322
2323 memset(&state, 0, sizeof(state));
2324
2325
2326 //state.strm.next_in = NULL;
2327
2328 if (deflateInit2(&state, Z_BEST_COMPRESSION, 8,
2329 -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) == Z_OK) {
2330 // Z_BEST_COMPRESSION Z_DEFAULT_COMPRESSION
2331
2332 // deflateReset(&state.strm);
2333
2334 state.next_in = buffer;
2335 state.avail_in = len;
2336
2337 state.next_out = msg;
2338 state.avail_out = buffer_size;
2339
2340 if (deflate(&state, Z_PACKET_FLUSH ) != Z_OK)
2341 printf("Deflate not OK\n");
2342
2343 #ifdef DEBUG
2344 printf("Compressed size: %u bytes.\n",
2345 buffer_size - state.avail_out);
2346 #endif
2347
2348 deflateEnd(&state);
2349
2350
2351 new_len = buffer_size - state.avail_out;
2352
2353
2354
2355 // Check if the final compressed size, after base64 is larger
2356 if (BASE64_ENCODE_SIZE(new_len) > len) // Compression is pointless
2357 return lion_output( node, buffer, len);
2358
2359
2360 // base64 the result
2361 // we assume it fits in original buffer! FIXME!!
2362 strcpy(buffer, NET_COMPRESS_MAGIC);
2363 base64_encode( msg, new_len, &buffer[4] );
2364 strcat(buffer, "\r\n");
2365 new_len = strlen(buffer);
2366
2367
2368 #ifdef DEBUG
2369 printf("Base64 size: %u\n", new_len);
2370 #endif
2371
2372 return lion_output( node, buffer, new_len);
2373
2374 }
2375
2376
2377 }
2378
2379
2380
2381 return lion_output( node, buffer, len);
2382
2383 }
2384
2385
2386
io_passbinary(connection_t * node)2387 int io_passbinary(connection_t *node)
2388 {
2389
2390 if ((node->status == ST_DISCONNECT) || (node->socket == -1)) {
2391 #ifdef DEBUG
2392 printf("[io] passbinary with empty state: %p\n", node);
2393 #endif
2394 return 0;
2395 }
2396
2397
2398 // Send this data to user.
2399 if (node->type == LION_TYPE_UDP) {
2400
2401 udp_input(node, LION_BINARY, node->inbuffer, node->buffer);
2402
2403 } else {
2404
2405 _lion_userinput(node, node->user_data, LION_BINARY,
2406 node->inbuffer, node->buffer);
2407
2408 }
2409
2410 node->inbuffer = 0;
2411
2412 return 0;
2413
2414 }
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
io_read(connection_t * node,char * buffer,int size)2426 int io_read(connection_t *node, char *buffer, int size)
2427 {
2428 int result = 0;
2429
2430 errno = 0;
2431
2432 switch(node->type) {
2433
2434 case LION_TYPE_SOCKET:
2435 case LION_TYPE_PIPE: // getsocketpair
2436 #ifdef WITH_SSL
2437 if (node->use_ssl) {
2438 result = tls_read(node, buffer, size);
2439 } else {
2440 #endif
2441 result = sockets_read(node->socket, buffer, size);
2442 #ifdef WITH_SSL
2443 }
2444 #endif
2445 break;
2446
2447
2448
2449 #ifdef WIN32
2450 case LION_TYPE_PIPE_FILE:
2451 result = sockets_read(node->socket, buffer, size);
2452
2453 #ifdef WITH_SSL
2454 // Decrypt file?
2455 if (node->use_ssl && (result > 0)) {
2456
2457 BF_cfb64_encrypt(buffer,
2458 buffer,
2459 result,
2460 &node->bf_key,
2461 node->bf_ivec,
2462 &node->bf_num,
2463 BF_DECRYPT);
2464
2465 }
2466 #endif
2467 break;
2468 #endif // Win32
2469
2470
2471 case LION_TYPE_FILE:
2472 result = read(node->socket, buffer, size);
2473
2474 // Decrypt file?
2475 #ifdef WITH_SSL
2476 if (node->use_ssl && (result > 0)) {
2477
2478 BF_cfb64_encrypt(buffer,
2479 buffer,
2480 result,
2481 &node->bf_key,
2482 node->bf_ivec,
2483 &node->bf_num,
2484 BF_DECRYPT);
2485
2486 }
2487 #endif
2488 break;
2489
2490 case LION_TYPE_UDP:
2491 result = sockets_recvfrom(node->socket, buffer, size,
2492 &node->udp_host, &node->udp_port);
2493 default:
2494 break;
2495
2496 }
2497
2498
2499 // If we are a PIPE, and we have never read any input before
2500 // check if the input started with PIPE_MAGIC. If it does
2501 // fetch out the real error code so we can send FAILED to
2502 // the application.
2503 // if (node->type == LION_TYPE_PIPE)
2504 // printf(" >> %d %d\n", node->bytes_in, result);
2505
2506
2507
2508 if ((node->type == LION_TYPE_PIPE) &&
2509 #ifdef DEBUG // in debug we let it print some stuff
2510 (node->bytes_in < 99) &&
2511 #else
2512 (node->bytes_in == 0) &&
2513 #endif
2514 (result > strlen(PIPE_MAGIC)) &&
2515 !memcmp(buffer, PIPE_MAGIC, strlen(PIPE_MAGIC))) {
2516
2517 // We *know* that the int is followed by a non-digit (\n) so
2518 // we could just call atoi on it, but it could be a malicious
2519 // lion user could use that. So, lets force a null-term.
2520 buffer[result] = 0;
2521
2522 node->error_code = atoi( &buffer[ strlen(PIPE_MAGIC) ] );
2523 #ifdef DEBUG
2524 printf("[io_read] pipe errno hook: %d\n", node->error_code);
2525 #endif
2526
2527 }
2528
2529 //printf("r%d %d %d ", result, errno, WSAGetLastError()); fflush(stdout);
2530
2531
2532 return result;
2533
2534 }
2535
2536
2537
io_write(connection_t * node,char * buffer,int size)2538 int io_write(connection_t *node, char *buffer, int size)
2539 {
2540 int sent = 0;
2541
2542 errno = 0;
2543
2544 switch(node->type) {
2545
2546 case LION_TYPE_SOCKET:
2547 case LION_TYPE_PIPE:
2548
2549 #ifdef WITH_SSL
2550 if (node->use_ssl) {
2551 sent = tls_write( node, buffer, size);
2552
2553 if (sent == -2) {
2554
2555 sent = 0; // we need more? how do we signal this?
2556
2557 }
2558
2559 } else {
2560
2561 #endif
2562 sent = sockets_write( node->socket, buffer, size);
2563
2564 #ifdef WITH_SSL
2565 }
2566 #endif
2567 break;
2568
2569
2570 #ifdef WIN32
2571 case LION_TYPE_PIPE_FILE:
2572
2573 #ifdef WITH_SSL
2574 if (node->use_ssl && (size > 0)) {
2575
2576 BF_cfb64_encrypt(buffer,
2577 buffer,
2578 size,
2579 &node->bf_key,
2580 node->bf_ivec,
2581 &node->bf_num,
2582 BF_ENCRYPT);
2583
2584 }
2585 #endif
2586
2587 sent = sockets_write( node->socket, buffer, size);
2588 break;
2589 #endif // Win32
2590
2591
2592
2593 case LION_TYPE_FILE:
2594
2595 // Encrypt file?
2596 #ifdef WITH_SSL
2597 if (node->use_ssl && (size > 0)) {
2598
2599 BF_cfb64_encrypt(buffer,
2600 buffer,
2601 size,
2602 &node->bf_key,
2603 node->bf_ivec,
2604 &node->bf_num,
2605 BF_ENCRYPT);
2606
2607 }
2608 #endif
2609
2610 sent = write( node->socket, buffer, size);
2611
2612 #if 0 // simulate error
2613 if (node->bytes_out >10000) {
2614 sent = -1;
2615 errno = ENOSPC;
2616 }
2617 #endif
2618 break;
2619
2620 case LION_TYPE_UDP:
2621 // What do we do if host is NULL?
2622 sent = sockets_sendto( node->socket, buffer, size,
2623 node->host, node->port);
2624
2625 default:
2626 break;
2627
2628 }
2629
2630 if (sent > 0) {
2631 node->bytes_out += sent;
2632
2633 // node->group_bytes_out += sent;
2634 lgroup_add_out(node, sent);
2635 }
2636
2637
2638 // printf("w%d ", sent); fflush(stdout);
2639 if (node->trace)
2640 fprintf(trace_file, "%p: io_write(%d) => %d (0x%X)\n", node,
2641 node->outbuffer, sent, sent);
2642
2643
2644 return sent;
2645
2646 }
2647
2648
2649 //
2650 // There was a sign that there is new information on a socket
2651 // retrieve it and seperate it into string chunks to pass on.
2652 //
io_input(connection_t * node)2653 int io_input(connection_t *node)
2654 {
2655 int result = 0;
2656 char *line; // Pointer to the current start of a string.
2657 #ifndef NO_READITERATE
2658 int turns = 0;
2659 #endif
2660
2661 // printf("Input on node %p type %d socket %d ssl %d\n",
2662 // node, node->type, node->socket, node->use_ssl);
2663
2664
2665 // First, is this connection supposed to be binary?
2666 if (node->binary) {
2667
2668 #ifndef NO_READITERATE
2669
2670 do {
2671
2672 if (((turns++) * node->inbuffer_size) > READITERATE_MAX) break;
2673
2674
2675 if (node->status == ST_DISCONNECT) break;
2676
2677 #endif
2678 errno = 0;
2679
2680
2681 result = io_read(node,&node->buffer[node->inbuffer],
2682 node->inbuffer_size - node->inbuffer);
2683
2684 if (result == -2) //TLS needs more input
2685 return -2;
2686
2687 if ((result == -1) &&
2688 ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
2689 return -2;
2690
2691 #ifdef WIN32
2692 if ((result == -1) && (WSAGetLastError() == WSAEWOULDBLOCK))
2693 return 0;
2694 #endif
2695
2696 // printf(" io_input() %d -> %d\n", node->socket, result);
2697
2698
2699 if (result <= 0) {
2700
2701 //printf("Closed but inbuffer is %d\n", node->inbuffer);
2702
2703 node->status = ST_DISCONNECT;
2704
2705 // If we are a pipe, get the real return code, if known.
2706
2707 switch( node->type ) {
2708
2709 case LION_TYPE_SOCKET:
2710 case LION_TYPE_UDP:
2711 _lion_userinput( node, node->user_data,
2712 result < 0 ? LION_CONNECTION_LOST :
2713 LION_CONNECTION_CLOSED,
2714 errno, strerror( errno ) );
2715 return -1;
2716 case LION_TYPE_FILE:
2717 #ifdef WIN32
2718 case LION_TYPE_PIPE_FILE:
2719 #endif
2720 _lion_userinput( node, node->user_data,
2721 result < 0 ? LION_FILE_FAILED :
2722 LION_FILE_CLOSED,
2723 errno, strerror( errno ) );
2724
2725 // Special feature here, if we are reading a file, but
2726 // reach EOF, but expect it to grow (like tail -f) we
2727 // allow the application to disable read in the closed
2728 // event.
2729 if (node->disable_read) {
2730 node->status = ST_CONNECTED;
2731 return -2;
2732 }
2733
2734 return -1;
2735 case LION_TYPE_PIPE:
2736 #ifdef DEBUG
2737 printf("[1] ret %d\n", pipe_get_status(node));
2738 #endif
2739
2740 if (node->error_code) { // If we've set an error_code, it failed.
2741
2742 _lion_userinput( node, node->user_data,
2743 LION_PIPE_FAILED,
2744 node->error_code,
2745 strerror(node->error_code));
2746
2747 } else {
2748
2749 _lion_userinput( node, node->user_data,
2750 LION_PIPE_EXIT,
2751 pipe_get_status(node),
2752 NULL);
2753 }
2754
2755 return -1;
2756 default:
2757 return -1;
2758
2759 }
2760
2761
2762 }
2763
2764 node->inbuffer += result;
2765
2766 node->bytes_in += (bytes_t) result;
2767 //node->group_bytes_in += result;
2768
2769
2770 // capping code to know about it.
2771 lgroup_add_in(node, result);
2772
2773
2774 // Pass it to program and all that logic
2775 io_passbinary(node);
2776
2777
2778
2779 #ifndef NO_READITERATE
2780 // Capping may have kicked in here, so it is no
2781 // good to keep spinning if so.
2782 // We can not cap here in SSL mode! Have to go MIN 16k
2783 if (!io_check_rate_in( node )) {
2784 return 0;
2785 }
2786
2787
2788 } while (!node->disable_read && (result > 0));
2789 #endif
2790
2791
2792 return 0;
2793
2794
2795 } // END OF BINARY MODE
2796
2797
2798
2799
2800 // While we can get a line from the buffer parse it.
2801 // notice this can get seperated from here, so that we
2802 // simply call read() and fill the buffer here, and call
2803 // io_getline from elsewere. But not really required.
2804
2805 #ifndef NO_READITERATE
2806
2807 do {
2808
2809 if (((turns++) * node->inbuffer_size) > READITERATE_MAX) break;
2810
2811 if (node->status == ST_DISCONNECT) break;
2812
2813 #endif
2814
2815
2816 // Reset the current position counter here.
2817 line = NULL;
2818
2819 while((result = io_getline(node, &line)) > 0) {
2820
2821 if (node->trace) {
2822 int start, len;
2823
2824 start = line - node->buffer;
2825 len = strlen(line);
2826 fprintf(trace_file, "%p: io_getline: turn %d: parsed 0x%X-0x%X of buffer 0x%X. With 0x%X remaining.\n",
2827 node,
2828 #ifndef NO_READITERATE
2829 turns,
2830 #else
2831 0,
2832 #endif
2833 start,
2834 start + len,
2835 node->inbuffer,
2836 node->inbuffer - start - len
2837 );
2838
2839 if ((node->inbuffer - start - len) == 0x0A)
2840 printf("break\n");
2841
2842 }
2843
2844 // Pass the string on to next layer
2845 //services_command(node, line);
2846
2847 // Check if input is compressed
2848 if (!strncmp(NET_COMPRESS_MAGIC, line, 4)) {
2849 THREAD_SAFE static char decode[STATIC_BUFFER_SIZE];
2850 THREAD_SAFE static char large[STATIC_BUFFER_SIZE];
2851 int new_len;
2852 z_stream state;
2853
2854
2855 #ifdef DEBUG
2856 printf("Compressed input '%s'\n", line);
2857 #endif
2858
2859 // We need to base64_decode it, then inflate it.
2860 new_len = base64_decode(&line[4], decode, strlen( &line[4] ));
2861
2862 if (new_len > 0) {
2863
2864 // Call the inflator..
2865
2866 #ifdef DEBUG
2867 printf("Base64 length %d\n", new_len);
2868 #endif
2869 memset(&state, 0, sizeof(state));
2870
2871
2872 if (inflateInit2(&state, -MAX_WBITS) == Z_OK) {
2873
2874 #ifdef DEBUG
2875 printf("inflate ready\n");
2876 #endif
2877
2878 //if (inflateInit2(&state, Z_BEST_COMPRESSION, 8,
2879 // -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) == Z_OK) {
2880 // Z_BEST_COMPRESSION Z_DEFAULT_COMPRESSION
2881
2882 // deflateReset(&state.strm);
2883
2884 state.next_in = decode;
2885 state.avail_in = new_len;
2886
2887 state.next_out = large;
2888 state.avail_out = STATIC_BUFFER_SIZE;
2889
2890 if (inflate(&state, Z_PACKET_FLUSH ) != Z_OK)
2891 printf("Inflate not OK\n");
2892
2893 #ifdef DEBUG
2894 printf("Compressed size: %u bytes.\n",
2895 STATIC_BUFFER_SIZE - state.avail_out);
2896 #endif
2897
2898 inflateEnd(&state);
2899
2900 if (node->type == LION_TYPE_UDP) {
2901
2902 udp_input(node, LION_INPUT, strlen(large), large);
2903
2904 } else {
2905
2906 _lion_userinput( node, node->user_data,
2907 LION_INPUT, strlen(large), large);
2908
2909 }
2910
2911 continue; // Don't call userinput below again.
2912 } // inflateInit
2913
2914 } // new_len
2915
2916 } // Compress magic
2917
2918 if (node->type == LION_TYPE_UDP) {
2919
2920 udp_input(node, LION_INPUT, strlen(line), line);
2921
2922 } else {
2923
2924 _lion_userinput( node, node->user_data, LION_INPUT,
2925 strlen(line), line);
2926 }
2927
2928 } // while getline
2929
2930
2931 #ifndef NO_READITERATE
2932
2933 if (node->trace) {
2934 fprintf(trace_file, "%p: io_getline: turn %d: result %d.\n",
2935 node,
2936 turns,
2937 result);
2938 }
2939
2940
2941 if (result == -2) return 0; // Failure? More input?
2942 if (result < 0) return result; // Failure? More input?
2943
2944 // Capping may have kicked in here, so it is no
2945 // good to keep spinning if so.
2946 if (!io_check_rate_in( node )) {
2947 return 0;
2948 }
2949
2950
2951 if (node->want_mode != NET_WANT_NONE) break;
2952
2953
2954 // Keep calling read until we;
2955 // Hit READITERATE_MAX
2956 // Return -1 or -2 from io_getline
2957 // rate_in is triggered
2958 // state is DISCONNECT
2959 // or read is disabled
2960 } while (!node->disable_read);
2961
2962 #endif
2963
2964
2965
2966
2967 // We are done.
2968 // We return 0 when there are no more info to process
2969 // and -1 signifies the connection was lost.
2970
2971 return result;
2972 }
2973
2974
2975
2976 //
2977 // Reads a buffer full, parses it until it finds a complete string (\r\n)
2978 // then returns all full strings until there are no more. (Left overs are
2979 // saved for the next buffer read)
2980 //
io_getline(connection_t * node,char ** last)2981 int io_getline(connection_t *node, char **last)
2982 {
2983 int len; // return int of read().
2984 int left; // remaining items
2985 THREAD_SAFE static char *next = NULL; // strtok style PC holder.
2986 // While we are iterating getline to send lines of input to the user,
2987 // they might call disable_read, which we should honour.
2988 if (node->disable_read) {
2989
2990 if (node->inbuffer && *last) {
2991 *last = next;
2992 left = (node->inbuffer - (*last - node->buffer));
2993 if (left > 0) {
2994 // Copy remaining.
2995 memcpy(node->buffer, *last, left);
2996 node->inbuffer = left;
2997 next = NULL;
2998 }
2999 return 0;
3000 }
3001 return 0;
3002 }
3003
3004
3005 if (node->status == ST_RESUMEREAD) {
3006 node->status = ST_CONNECTED;
3007 *last = node->buffer;
3008 next = *last;
3009 }
3010
3011
3012 // If last is NULL, it's the first call to this function for this
3013 // current iteration, so first we call read() to receive more data.
3014 if (!*last) {
3015
3016
3017 // Set it to start of the buffer
3018 *last = node->buffer;
3019 next = *last;
3020
3021
3022 // Retrieve more data from the socket.
3023 // We write it after any data that may already be left in the buffer
3024 // from a previous read. Generally doesn't happen, but we need to
3025 // allocate for it. (Buffer over/under -run hacking etc)
3026
3027 // if ((len = sockets_read(node->socket, &node->buffer[node->inbuffer],
3028 // BUFFER_SIZE - node->inbuffer)) <= 0) {
3029
3030 // If we are using SSL and the socket is encrypted, call the appropriate
3031 // SSL functions to read DATA. This should probably be done in socket.c
3032 // but we dont pass the node, just the socket to that layer.
3033 len = io_read(node, &node->buffer[node->inbuffer],
3034 node->inbuffer_size - node->inbuffer);
3035
3036 if (node->trace)
3037 fprintf(trace_file, "%p: io_read(%d) => %d (0x%X) errno %d\n", node,
3038 node->inbuffer, len, len, errno);
3039
3040
3041 if (len == -2)
3042 return -2;
3043 // Did the read request succeed?
3044
3045
3046 // Check if it was a fake error, so that we don't accidentally
3047 // close the connection.
3048 // Was this a real error or what?
3049 if ((errno == EWOULDBLOCK) ||
3050 (errno == EAGAIN)
3051 #ifdef WIN32
3052 || (WSAGetLastError() == WSAEWOULDBLOCK)
3053 #endif
3054 )
3055 return -2; // Need more data.
3056
3057
3058
3059
3060 if (len <= 0) {
3061
3062 node->status = ST_DISCONNECT;
3063
3064 switch( node->type ) {
3065
3066 case LION_TYPE_SOCKET:
3067 case LION_TYPE_UDP:
3068 _lion_userinput( node, node->user_data,
3069 len < 0 ? LION_CONNECTION_LOST :
3070 LION_CONNECTION_CLOSED,
3071 errno, strerror( errno ) );
3072 return -1;
3073
3074 case LION_TYPE_FILE:
3075 #ifdef WIN32
3076 case LION_TYPE_PIPE_FILE:
3077 #endif
3078 _lion_userinput( node, node->user_data,
3079 len < 0 ? LION_FILE_FAILED :
3080 LION_FILE_CLOSED,
3081 errno, strerror( errno ) );
3082 return -1;
3083
3084 case LION_TYPE_PIPE:
3085 #ifdef DEBUG
3086 printf("[io] 2 read %d\n", len);
3087 #endif
3088
3089 if (node->error_code) { // If we've set an error_code, it failed.
3090
3091 _lion_userinput( node, node->user_data,
3092 LION_PIPE_FAILED,
3093 node->error_code,
3094 strerror(node->error_code));
3095
3096 } else {
3097
3098 _lion_userinput( node, node->user_data,
3099 LION_PIPE_EXIT,
3100 pipe_get_status(node),
3101 NULL);
3102 }
3103
3104 return -1;
3105
3106 default:
3107 return -1;
3108
3109 }
3110
3111
3112
3113 }
3114
3115
3116 // Move along the PC according to how much was read.
3117 node->inbuffer += len;
3118 node->bytes_in += (bytes_t) len;
3119 // node->group_bytes_in += len;
3120 lgroup_add_in(node, len);
3121
3122
3123 } else { // last == NULL
3124
3125 // last isn't NULL, so we are now still parsing buffer content, if any
3126
3127 *last = next;
3128
3129 }
3130
3131
3132 // Right we now have some data in the buffer, extract a string.
3133
3134 do {
3135
3136
3137 if ((int)(next - node->buffer) >= node->inbuffer) {
3138
3139
3140 // Compute what is remaining
3141 left = (node->inbuffer - (*last - node->buffer));
3142
3143
3144 // we only bother keeping the remaining if it is more than
3145 // 3, since 2 is just \r\n.
3146
3147 if (left > 0) {
3148
3149 // Copy remaining.
3150 memcpy(node->buffer, *last, left);
3151
3152 // Reset pointers and PC
3153 node->inbuffer = left;
3154 next = NULL;
3155
3156 if (node->trace)
3157 fprintf(trace_file, "%p: leaving incomplete input of 0x%X bytes until next read.\n",
3158 node,
3159 left);
3160
3161 }
3162
3163 // stop processing
3164 return 0;
3165
3166 }
3167
3168
3169
3170
3171 // Check if we've hit the end.
3172 if ((*next == '\n') || (*next == '\r')) { /* Got a line */
3173
3174 // yep, skip past all blank \r or \n.
3175
3176 // ass, this wipes out empty lines too.. we will only zap
3177 // the next char, if we found a \r and the next is a \n
3178 // bounds check, '\r' could be last char, which means +1
3179 // is beyond buffer.
3180
3181 if ((*next == '\r') &&
3182 (next < &node->buffer[ node->inbuffer_size - 1 ]) &&
3183 (next[1] == '\n'))
3184 *(next++) = (char) 0;
3185
3186 *(next++) = (char) 0;
3187
3188 //while((*next == '\n') || (*next == '\r'))
3189 // *(next++) = (char) 0;
3190
3191 // and replace them with \0. (Terminate string).
3192
3193 // If we've completely finished parsing the input
3194 // start again from the start. If not, "next" is ready for
3195 // next time around.
3196 if (node->inbuffer - ((int)(next - node->buffer)) <= 0) {
3197 node->inbuffer = 0;
3198 }
3199
3200 // Signal we have a valid string.
3201 return 1;
3202 }
3203
3204
3205 /* This next should never happen */
3206 /* But we check for it just incase. I've never seen it yet. */
3207
3208 // if ((next > node->buffer + BUFFER_SIZE)) {
3209 if ((next > node->buffer + node->inbuffer_size)) {
3210 fprintf(stderr,"Internal Error, most likely due to a bug\r\n");
3211 node->inbuffer = 0;
3212 return 0;
3213 }
3214
3215 // Advance to next char
3216 next++;
3217
3218 } while(1);
3219
3220 // NOT REACHED
3221 return 0; // avoid the warning
3222 }
3223
3224
3225
3226
3227 //
3228 // Send some information. If we can't send, or only part, store
3229 // it in the output buffer, and set our status to ST_BUFFERFULL.
3230 //
3231 // FIXME: Currently the logic is if you try to send more on a
3232 // handle in state ST_BUFFERFULL, it will attempt to call io_write again
3233 // this is uneccessary! We should only buffer in this situation.
3234 //
lion_output(connection_t * node,char * buffer,unsigned int len)3235 int lion_output( connection_t *node, char *buffer, unsigned int len)
3236 {
3237 int sent = 0;
3238 int send_buffer_empty = 0; // Set this if we should send event.
3239 unsigned long suggested_size = 0;
3240 char *tmp_ptr = NULL;
3241
3242
3243 if (!node) return -1;
3244
3245
3246 // assert's
3247 if ( node->status == ST_DISCONNECT) return -1;
3248
3249 // First we check if there is anything already in the buffer, if
3250 // so, we attempt to send that (first?)
3251
3252 if ( node->outbuffer ) {
3253
3254
3255
3256 // Ensure we don't try to write packets larger than THRESHHOLD
3257 // or they will be dropped.
3258
3259 // Check for SSL of course
3260 sent = io_write( node, node->obuffer, node->outbuffer);
3261
3262 // printf("io_write() tried to send %d but managed %d\n", node->outbuffer);
3263
3264 // did we manage to send it all?
3265 if (sent == node->outbuffer) {
3266
3267 if (node->status == ST_BUFFERFULL) {
3268 node->status = ST_CONNECTED;
3269 }
3270
3271 node->outbuffer = 0;
3272
3273
3274 // Check if we were soft_closed already, and the buffer is
3275 // now empty, we can close it for real.
3276 if (node->soft_closed) {
3277 //net_close(node);
3278
3279 node->status = ST_DISCONNECT;
3280
3281 switch (node->type ) {
3282
3283 case LION_TYPE_UDP:
3284 case LION_TYPE_SOCKET:
3285 _lion_userinput( node, node->user_data,
3286 LION_CONNECTION_CLOSED, 0, NULL);
3287 return 0;
3288 case LION_TYPE_FILE:
3289 #ifdef WIN32
3290 case LION_TYPE_PIPE_FILE:
3291 #endif
3292 _lion_userinput( node, node->user_data,
3293 LION_FILE_CLOSED, 0, NULL);
3294 return 0;
3295 case LION_TYPE_PIPE:
3296 _lion_userinput( node, node->user_data,
3297 LION_PIPE_EXIT, 0, NULL);
3298 return 0;
3299 default:
3300 return 0;
3301 }
3302
3303 }
3304
3305
3306
3307
3308 // Technically we could send buffer empty event here, but
3309 // it is possible that the data passed to us fill it again
3310 // so we delay it, until we are sure.
3311 send_buffer_empty = 1;
3312
3313
3314 } else { // rats, we still have data to buffer.
3315
3316 // Will the buffer be too full? If so what choice do we have but to
3317 // either discard the info, or drop the connection with buffer overrun?
3318
3319
3320 if (sent < 0) {
3321
3322 // Was this a real error or what?
3323 if ((errno == EWOULDBLOCK) ||
3324 (errno == EAGAIN)
3325 #ifdef WIN32
3326 || (WSAGetLastError() == WSAEWOULDBLOCK)
3327 #endif
3328 ) {
3329
3330 sent = 0;
3331
3332 } else {
3333
3334 #ifdef DEBUG
3335 printf("net_output(%p:%d) Failed! %d\n",
3336 node, node->socket,
3337 errno);
3338 #endif
3339
3340 switch ( node->type ) {
3341
3342 case LION_TYPE_SOCKET:
3343 case LION_TYPE_UDP:
3344 _lion_userinput( node, node->user_data,
3345 len < 0 ? LION_CONNECTION_LOST :
3346 LION_CONNECTION_CLOSED,
3347 errno, strerror( errno ) );
3348 break;
3349 case LION_TYPE_FILE:
3350 #ifdef WIN32
3351 case LION_TYPE_PIPE_FILE:
3352 #endif
3353 _lion_userinput( node, node->user_data,
3354 len < 0 ? LION_FILE_FAILED :
3355 LION_FILE_CLOSED,
3356 errno, strerror( errno ) );
3357 break;
3358 case LION_TYPE_PIPE:
3359 _lion_userinput( node, node->user_data,
3360 len < 0 ? LION_PIPE_FAILED :
3361 LION_PIPE_EXIT,
3362 errno, strerror( errno ) );
3363 break;
3364 }
3365
3366 node->status = ST_DISCONNECT;
3367 return -1;
3368
3369 }
3370
3371 } // if (sent < 0)
3372
3373
3374
3375
3376 //
3377 // BUG 2004/02/13
3378 //
3379 // IF we have newdata,
3380 // AND we had data in buffer,
3381 // AND we had a partial write on buffer data,
3382 // THEN we need to keep remaining, PLUS newdata and
3383 // return.
3384
3385 // So, add on the space needed with regards to "len" the newdata.
3386 while (node->outbuffer + (node->outbuffer - sent) + len >
3387 node->outbuffer_size) {
3388
3389
3390 // This assumes that "outbuffer_size * 2" is always >
3391 // than "len" can ever be. "len" SHOULD always be less
3392 // than the original buffer size. But we could change this in
3393 // future...
3394
3395
3396 // Grow buffer
3397 //node->obuffer =
3398 tmp_ptr =
3399 realloc(node->obuffer, node->outbuffer_size * 2);
3400
3401 // BUG 2004/01/22 - We over-write the original pointer, so
3402 // even though we disconnect the user, we never free() the
3403 // memory (yes, realloc fails, but it doesn't release the
3404 // old buffer!).
3405 // Fixed.
3406
3407 if (!tmp_ptr) {
3408
3409 // log_printf(LOG_DEBUG, "%08x - Attempted to grow output buffer 1 but failed!\n",
3410 // node->socket);
3411
3412 #ifdef DEBUG
3413 printf("%p:dumping connection due to realloc failure.\n",
3414 node);
3415 #endif
3416
3417 node->outbuffer = 0;
3418 node->outbuffer_size = 0;
3419 node->status = ST_DISCONNECT;
3420
3421 return -1;
3422
3423 }
3424
3425
3426 node->obuffer = tmp_ptr;
3427
3428 // We grew in size
3429 node->outbuffer_size *= 2;
3430
3431 #ifdef DEBUG
3432 printf("%08x: Grew output buffer 1 to %d\n",
3433 node->socket, node->outbuffer_size);
3434 #endif
3435
3436 } // while
3437
3438 // If something was sent, but not all, we need to store it.
3439 // copy the partial write.
3440 if (sent > 0) {
3441
3442 memcpy( node->obuffer,
3443 &node->obuffer[ sent ], node->outbuffer - sent );
3444
3445 node->outbuffer -= sent;
3446
3447 }
3448
3449 // Copy the new data
3450 if (len) {
3451
3452 // BUG 2005/01/19. We copied new data to the START of
3453 // output buff, when there might be data in there already
3454 //
3455 memcpy( &node->obuffer[node->outbuffer],
3456 buffer, len );
3457
3458 node->outbuffer += len;
3459
3460 #ifdef DEBUG
3461 //printf("[io] partial buffer write with new data? resending event\n");
3462 #endif
3463
3464 _lion_userinput( node, node->user_data,
3465 LION_BUFFER_USED,
3466 0, NULL);
3467 }
3468
3469
3470 // ZZZ!!!!
3471 node->status = ST_BUFFERFULL;
3472
3473 // We can NOT let it fall down here to try to send data, since
3474 // then new data goes before buffered.
3475 // technically, we should not be here if the app obeys the
3476 // buffering events. Send another?
3477
3478 return sent;
3479
3480 } // else (didnt send all)
3481
3482 } // if node->outbuffer
3483
3484
3485
3486
3487 // Check if we were passed new information to send
3488 if (!buffer || ( len == 0 )) {
3489
3490
3491 // Check for capping..
3492 if (!io_check_rate_out( node )) {
3493
3494 // Ok, this needs to be capped. So we send the "fake" event.
3495 if (!node->rate_out_capped) {
3496 //printf("[io] sending out cap\n");
3497 _lion_userinput( node, node->user_data,
3498 LION_BUFFER_USED,
3499 0, NULL);
3500 }
3501
3502 node->rate_out_capped = 1;
3503 send_buffer_empty = 0;
3504
3505 }
3506
3507
3508
3509 // Send buffer empty?
3510 if (send_buffer_empty) {
3511
3512 _lion_userinput( node, node->user_data,
3513 LION_BUFFER_EMPTY,
3514 0, NULL);
3515
3516 }
3517
3518 return sent;
3519 }
3520
3521
3522 // Attempt to send the new info, if we've already failed above
3523 // we don't attempt it again, just incase it would pass thru (and then
3524 // we'd get data out of order)
3525
3526 sent = 0;
3527 errno = 0;
3528
3529
3530 // If we try to send more than THRESHHOLD we will just trigger our own
3531 // code and drop it. So we send maximum upto THRESHHOLD
3532
3533 sent = io_write( node, buffer, len);
3534
3535 // printf("io_write(%p) send %d => %d '%s'\n", node,
3536 // len, sent, "data" /*buffer*/);
3537
3538
3539
3540 #ifdef WIN32
3541 if (WSAGetLastError() == WSAEWOULDBLOCK)
3542 sent = 0;
3543 #endif
3544
3545
3546 if ((sent < 0) && ((errno == EWOULDBLOCK) ||
3547 (errno == EAGAIN))) {
3548 sent = 0;
3549
3550 // fcntl(node->socket, F_SETFL, (fcntl(node->socket, F_GETFL) & ~O_NONBLOCK));
3551
3552
3553 }
3554
3555
3556
3557 if (sent < 0) {
3558 // Was this a real error or what?
3559
3560 switch ( node->type ) {
3561
3562 case LION_TYPE_UDP:
3563
3564 // These are not permanent failures
3565
3566 #ifdef WIN32
3567 switch(WSAGetLastError()) {
3568 case WSAEINPROGRESS:
3569 case WSAENOBUFS:
3570 case WSAEWOULDBLOCK:
3571 case WSAEHOSTUNREACH:
3572 case WSAETIMEDOUT:
3573 return -1;
3574 }
3575 #else
3576 switch(errno) {
3577 case EMSGSIZE:
3578 case EAGAIN:
3579 case ENOBUFS:
3580 case EHOSTUNREACH:
3581 return -1;
3582 }
3583 #endif
3584 /* FALL-THROUGH */
3585
3586 case LION_TYPE_SOCKET:
3587 _lion_userinput( node, node->user_data,
3588 LION_CONNECTION_LOST,
3589 errno, strerror( errno ) );
3590 break;
3591 case LION_TYPE_FILE:
3592 #ifdef WIN32
3593 case LION_TYPE_PIPE_FILE:
3594 #endif
3595 _lion_userinput( node, node->user_data,
3596 LION_FILE_FAILED,
3597 errno, strerror( errno ) );
3598 break;
3599 case LION_TYPE_PIPE:
3600 _lion_userinput( node, node->user_data,
3601 LION_PIPE_FAILED,
3602 errno, strerror( errno ) );
3603 break;
3604 }
3605
3606 node->status = ST_DISCONNECT;
3607
3608 return -1;
3609
3610 }
3611
3612 if ((unsigned int)sent == len) {
3613
3614 // We sent all that we wanted to send, so it's easy going.
3615 if (node->status == ST_BUFFERFULL)
3616 node->status = ST_CONNECTED;
3617
3618
3619
3620 if (!io_check_rate_out( node )) {
3621
3622 // Ok, this needs to be capped. So we send the "fake" event.
3623 if (!node->rate_out_capped) {
3624
3625 _lion_userinput( node, node->user_data,
3626 LION_BUFFER_USED,
3627 0, NULL);
3628 }
3629
3630 node->rate_out_capped = 1;
3631 send_buffer_empty = 0;
3632
3633 }
3634
3635
3636 return sent;
3637
3638 }
3639
3640
3641
3642 // Drat! We didn't send as much as we wanted to, buffer it.
3643 // Copy the remaining data to the output buffer, set the
3644 // counter and change our status.
3645
3646 // Check if we would over flow.
3647 if (node->outbuffer + ( len - sent ) > node->outbuffer_size) {
3648 // Grow buffer
3649
3650 // Bug 2005/07/15 (reported by mutex)
3651 // We need to grow the buffer, but we need to make sure we grow it
3652 // enough to actually fit the desired size, not just assume that
3653 // *2 is enough. Programmers do crazy things sometimes.
3654 suggested_size = node->outbuffer_size;
3655 do {
3656 suggested_size = suggested_size * 2;
3657 } while (suggested_size < (node->outbuffer + ( len - sent )));
3658
3659
3660 tmp_ptr = realloc(node->obuffer, suggested_size);
3661
3662 if (!tmp_ptr) {
3663
3664 #ifdef DEBUG
3665 printf("%p: dumping connection due to realloc failure.\n",
3666 node);
3667 #endif
3668
3669 node->outbuffer = 0;
3670 node->outbuffer_size = 0;
3671 node->status = ST_DISCONNECT;
3672
3673 return -1;
3674
3675 }
3676
3677
3678 node->obuffer = tmp_ptr;
3679
3680 // We grew in size
3681 node->outbuffer_size = suggested_size;
3682
3683 #ifdef DEBUG
3684 printf("%08x: Grew output buffer 2 to %d\n",
3685 node->socket, node->outbuffer_size);
3686 #endif
3687
3688
3689
3690 }
3691
3692 // obuffer 0x3c042000
3693 // outbuffer = 0
3694 // outbuffer_size 5600
3695 //
3696 memcpy( &node->obuffer[ node->outbuffer ],
3697 &buffer[ sent ], len - sent );
3698
3699
3700 // Adjust the size
3701 node->outbuffer += len - sent;
3702
3703 // ZZZ!!!!
3704 node->status = ST_BUFFERFULL;
3705 // printf("ST_BUFF "); fflush(stdout);
3706
3707
3708 // If the output buffer WAS empty, but now we had to fill it
3709 // we should send an event to the client that we are now forced to use it.
3710 // We do this here, after outbuffer update and status change incase the
3711 // user foolishly calls net_send() from the event(!)
3712 if (node->outbuffer == (len - sent) ) {
3713
3714 _lion_userinput( node, node->user_data,
3715 LION_BUFFER_USED,
3716 0, NULL);
3717
3718 send_buffer_empty = 0;
3719
3720 // We clear the capping code here, or it will send a BUFFER_EMPTY
3721 // event when the capping is lifted (but outbuffer is still full!)
3722 node->rate_out_capped = 0;
3723
3724 // Leave here so we dont send another buffer used in capping code.
3725 return sent;
3726 }
3727
3728
3729 // Check for capping..
3730 if (!io_check_rate_out( node )) {
3731
3732 // Ok, this needs to be capped. So we send the "fake" event.
3733 if (!node->rate_out_capped) {
3734 //printf("[io] sending out cap2\n");
3735 _lion_userinput( node, node->user_data,
3736 LION_BUFFER_USED,
3737 0, NULL);
3738 }
3739
3740 node->rate_out_capped = 1;
3741 send_buffer_empty = 0;
3742
3743 }
3744
3745
3746
3747
3748
3749 if (send_buffer_empty) {
3750
3751 _lion_userinput( node, node->user_data,
3752 LION_BUFFER_EMPTY,
3753 0, NULL);
3754
3755 }
3756
3757
3758
3759
3760 return sent;
3761 }
3762
3763
3764
3765 //
3766 //
3767 //
3768 //
3769 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3770 // ***************************************************************
3771 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3772 //
3773 //
3774 //
3775
3776
3777
3778
3779
3780
lion_find_iterate(connection_t * node,void * arg1,void * arg2)3781 int lion_find_iterate(connection_t *node, void *arg1, void *arg2)
3782 {
3783 THREAD_SAFE static int (*user_function)(void *, void *, void *) = NULL;
3784
3785 if (!node && arg1) {
3786 user_function = (int (*)(void *, void *, void *)) arg1;
3787 return 1;
3788 }
3789
3790 // Don't show nodes that have been disconnected to the users.
3791 if (user_function) {
3792 if (node->status != ST_DISCONNECT)
3793 return user_function( node, arg1, arg2 );
3794 else
3795 return 1;
3796 }
3797
3798 return 0;
3799
3800 }
3801
3802
3803
lion_find(int (* user_function)(connection_t *,void *,void *),void * arg1,void * arg2)3804 connection_t *lion_find( int (*user_function)(connection_t *, void *, void *),
3805 void *arg1, void *arg2)
3806 {
3807 static char twoth[] =
3808 "200-The code of Hubba.\r\n"
3809 " Far off, in a history shrouded by the mists of time, lived an\r\n"
3810 " ancient warrior race. Their code embodied the proud traditions\r\n"
3811 " of a noble people, and was known and respected by all. This code,\r\n"
3812 " which was strictly enforced, held the warriors to always live for\r\n"
3813 " the moment (which moment, it never said), to never flee a battle\r\n"
3814 " (slower than your pursuers) and, above all, to always drink of the\r\n"
3815 " magic potion, the liquid of life, the aqua vitae they called \"Cohk\".\r\n"
3816 " \r\n"
3817 " These people became extinct almost overnight, for reasons which\r\n"
3818 " baffle anthropologists to this day. Their code however, lives on;\r\n"
3819 " practised in secrecy by trained initiates and passed on by word\r\n"
3820 " of mouth to the new disciples. It is: The Way of the Hubba.\r\n";
3821
3822
3823 lion_find_iterate(NULL, user_function, NULL);
3824
3825 return connections_find(lion_find_iterate, arg1, arg2);
3826
3827 twoth[0] = twoth[0];
3828
3829 }
3830
3831