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 *)&not_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