~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Frontier Kernel
Frontier/Common/source/WinSockNetEvents.c

Version: ~ [ 10.0 ] ~

** Warning: Cannot open xref database.

1 2 /* $Id: WinSockNetEvents.c,v 1.4 2005/01/11 22:48:04 andreradke Exp $ */ 3 4 /****************************************************************************** 5 6 UserLand Frontier(tm) -- High performance Web content management, 7 object database, system-level and Internet scripting environment, 8 including source code editing and debugging. 9 10 Copyright (C) 1992-2004 UserLand Software, Inc. 11 12 This program is free software; you can redistribute it and/or modify 13 it under the terms of the GNU General Public License as published by 14 the Free Software Foundation; either version 2 of the License, or 15 (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 26 ******************************************************************************/ 27 28 /************************************************************************* 29 30 This file contains the Frontier NetEvents interface for the Windows 31 version. It uses the WinSock 1.1 specification. Extensions should be 32 added for the 2.0 specification at a later date. The primary advantage 33 of the 2.x specification is that more then just the TCP/IP protocol is 34 supported. In fact many protocols are supported including the Apple 35 Share protocol. 36 37 38 Created 7/20/97 Robert Bierman 39 40 General Note: All addresses are in HOST format. We convert to network 41 format internally. 42 43 **************************************************************************/ 44 45 46 #include "frontier.h" 47 #include "standard.h" 48 49 50 #ifdef NeverDefine_For_Reference 51 For reference I am listing the error codes from the windows winsock.h file here 52 53 /* 54 * All Windows Sockets error constants are biased by WSABASEERR from 55 * the "normal" 56 */ 57 #define WSABASEERR 10000 58 /* 59 * Windows Sockets definitions of regular Microsoft C error constants 60 */ 61 #define WSAEINTR (WSABASEERR+4) 62 #define WSAEBADF (WSABASEERR+9) 63 #define WSAEACCES (WSABASEERR+13) 64 #define WSAEFAULT (WSABASEERR+14) 65 #define WSAEINVAL (WSABASEERR+22) 66 #define WSAEMFILE (WSABASEERR+24) 67 68 /* 69 * Windows Sockets definitions of regular Berkeley error constants 70 */ 71 #define WSAEWOULDBLOCK (WSABASEERR+35) 72 #define WSAEINPROGRESS (WSABASEERR+36) 73 #define WSAEALREADY (WSABASEERR+37) 74 #define WSAENOTSOCK (WSABASEERR+38) 75 #define WSAEDESTADDRREQ (WSABASEERR+39) 76 #define WSAEMSGSIZE (WSABASEERR+40) 77 #define WSAEPROTOTYPE (WSABASEERR+41) 78 #define WSAENOPROTOOPT (WSABASEERR+42) 79 #define WSAEPROTONOSUPPORT (WSABASEERR+43) 80 #define WSAESOCKTNOSUPPORT (WSABASEERR+44) 81 #define WSAEOPNOTSUPP (WSABASEERR+45) 82 #define WSAEPFNOSUPPORT (WSABASEERR+46) 83 #define WSAEAFNOSUPPORT (WSABASEERR+47) 84 #define WSAEADDRINUSE (WSABASEERR+48) 85 #define WSAEADDRNOTAVAIL (WSABASEERR+49) 86 #define WSAENETDOWN (WSABASEERR+50) 87 #define WSAENETUNREACH (WSABASEERR+51) 88 #define WSAENETRESET (WSABASEERR+52) 89 #define WSAECONNABORTED (WSABASEERR+53) 90 #define WSAECONNRESET (WSABASEERR+54) 91 #define WSAENOBUFS (WSABASEERR+55) 92 #define WSAEISCONN (WSABASEERR+56) 93 #define WSAENOTCONN (WSABASEERR+57) 94 #define WSAESHUTDOWN (WSABASEERR+58) 95 #define WSAETOOMANYREFS (WSABASEERR+59) 96 #define WSAETIMEDOUT (WSABASEERR+60) 97 #define WSAECONNREFUSED (WSABASEERR+61) 98 #define WSAELOOP (WSABASEERR+62) 99 #define WSAENAMETOOLONG (WSABASEERR+63) 100 #define WSAEHOSTDOWN (WSABASEERR+64) 101 #define WSAEHOSTUNREACH (WSABASEERR+65) 102 #define WSAENOTEMPTY (WSABASEERR+66) 103 #define WSAEPROCLIM (WSABASEERR+67) 104 #define WSAEUSERS (WSABASEERR+68) 105 #define WSAEDQUOT (WSABASEERR+69) 106 #define WSAESTALE (WSABASEERR+70) 107 #define WSAEREMOTE (WSABASEERR+71) 108 109 #define WSAEDISCON (WSABASEERR+101) 110 111 /* 112 * Extended Windows Sockets error constant definitions 113 */ 114 #define WSASYSNOTREADY (WSABASEERR+91) 115 #define WSAVERNOTSUPPORTED (WSABASEERR+92) 116 #define WSANOTINITIALISED (WSABASEERR+93) 117 118 /* 119 * Error return codes from gethostbyname() and gethostbyaddr() 120 * (when using the resolver). Note that these errors are 121 * retrieved via WSAGetLastError() and must therefore follow 122 * the rules for avoiding clashes with error numbers from 123 * specific implementations or language run-time systems. 124 * For this reason the codes are based at WSABASEERR+1001. 125 * Note also that [WSA]NO_ADDRESS is defined only for 126 * compatibility purposes. 127 */ 128 129 #define h_errno WSAGetLastError() 130 131 /* Authoritative Answer: Host not found */ 132 #define WSAHOST_NOT_FOUND (WSABASEERR+1001) 133 #define HOST_NOT_FOUND WSAHOST_NOT_FOUND 134 135 /* Non-Authoritative: Host not found, or SERVERFAIL */ 136 #define WSATRY_AGAIN (WSABASEERR+1002) 137 #define TRY_AGAIN WSATRY_AGAIN 138 139 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ 140 #define WSANO_RECOVERY (WSABASEERR+1003) 141 #define NO_RECOVERY WSANO_RECOVERY 142 143 /* Valid name, no data record of requested type */ 144 #define WSANO_DATA (WSABASEERR+1004) 145 #define NO_DATA WSANO_DATA 146 147 /* no address, look for MX record */ 148 #define WSANO_ADDRESS WSANO_DATA 149 #define NO_ADDRESS WSANO_ADDRESS 150 151 #endif 152 //This ends the Reference Section 153 154 155 static unsigned char * tcperrorstrings [80] = { 156 "", 157 "\x1b" "Host not found. (DNS error)", /* 1 */ 158 "\x37" "Non-authoritative host not found. (Temporary DNS error)", /* 2 */ 159 "\x22" "Non-recoverable error. (DNS error)", /* 3 */ 160 "\x39" "Valid name, no data record of requested type. (DNS error)", /* 4 */ 161 "\x12" "Input/output error", /* 5 */ 162 "\x15" "Device not configured", /* 6 */ 163 "\x16" "Argument list too long", /* 7 */ 164 "\x11" "Exec format error", /* 8 */ 165 "\x13" "Bad file descriptor", /* 9 */ 166 "\x12" "No child processes", /* 10 */ 167 "\x19" "Resource deadlock avoided", /* 11 */ 168 "\x16" "Cannot allocate memory", /* 12 */ 169 "\x11" "Permission denied", /* 13 */ 170 "\x0b" "Bad address", /* 14 */ 171 "\x15" "Block device required", /* 15 */ 172 "\x0b" "Device busy", /* 16 */ 173 "\x0b" "File exists", /* 17 */ 174 "\x11" "Cross-device link", /* 18 */ 175 "\x21" "Operation not supported by device", /* 19 */ 176 "\x0f" "Not a directory", /* 20 */ 177 "\x0e" "Is a directory", /* 21 */ 178 "\x10" "Invalid argument", /* 22 */ 179 "\x1d" "Too many open files in system", /* 23 */ 180 "\x15" "Too many open sockets", /* 24 */ 181 "\x1e" "Inappropriate ioctl for device", /* 25 */ 182 "\x0e" "Text file busy", /* 26 */ 183 "\x0e" "File too large", /* 27 */ 184 "\x17" "No space left on device", /* 28 */ 185 "\x0d" "Illegal seek", /* 29 */ 186 "\x15" "Read-only file system", /* 30 */ 187 "\x0e" "Too many links", /* 31 */ 188 "\x0b" "Broken pipe", /* 32 */ 189 "", 190 "", 191 192 /* non-blocking and interrupt i/o */ 193 "\x20" "Resource temporarily unavailable", /* 35 */ 194 195 /* ipc/network software -- argument errors */ 196 "\x23" "A blocking operation is in progress", /* 36 */ 197 "\x20" "Operation is already in progress", /* 37 */ 198 199 /* ipc/network software -- argument errors */ 200 "\x20" "Socket operation on a non-socket", /* 38 */ 201 "\x1f" "Destination address is required", /* 39 */ 202 "\x10" "Message too long", /* 40 */ 203 "\x1e" "Protocol wrong type for socket", /* 41 */ 204 "\x16" "Protocol not available", /* 42 */ 205 "\x16" "Protocol not supported", /* 43 */ 206 "\x19" "Socket type not supported", /* 44 */ 207 "\x21" "Operation not supported on socket", /* 45 */ 208 "\x1d" "Protocol family not supported", /* 46 */ 209 "\x2f" "Address family not supported by protocol family", /* 47 */ 210 "\x16" "Address already in use", /* 48 */ 211 "\x1e" "Can't assign requested address", /* 49 */ 212 213 /* ipc/network software -- operational errors */ 214 "\x0f" "Network is down", /* 50 */ 215 "\x16" "Network is unreachable", /* 51 */ 216 "\x23" "Network dropped connection on reset", /* 52 */ 217 "\x20" "Software caused connection abort", /* 53 */ 218 "\x18" "Connection reset by peer", /* 54 */ 219 "\x19" "No buffer space available", /* 55 */ 220 "\x1b" "Socket is already connected", /* 56 */ 221 "\x17" "Socket is not connected", /* 57 */ 222 "\x20" "Can't send after socket shutdown", /* 58 */ 223 "\x21" "Too many references: can't splice", /* 59 */ 224 "\x14" "Connection timed out", /* 60 */ 225 "\x12" "Connection refused", /* 61 */ 226 227 "\x21" "Too many levels of symbolic links", /* 62 */ 228 "\x12" "File name too long", /* 63 */ 229 230 "\x0c" "Host is down", /* 64 */ 231 "\x10" "No route to host", /* 65 */ 232 "\x13" "Directory not empty", /* 66 */ 233 "\x12" "Too many processes", /* 67 */ 234 "\x0e" "Too many users", /* 68 */ 235 "\x13" "Disc quota exceeded", /* 69 */ 236 237 /* Network File System */ 238 "\x15" "Stale NFS file handle", /* 70 */ 239 "\x21" "Too many levels of remote in path", /* 71 */ 240 "\x11" "RPC struct is bad", /* 72 */ 241 "\x11" "RPC version wrong", /* 73 */ 242 "\x13" "RPC prog. not avail", /* 74 */ 243 "\x15" "Program version wrong", /* 75 */ 244 "\x19" "Bad procedure for program", /* 76 */ 245 "\x12" "No locks available", /* 77 */ 246 "\x18" "Function not implemented", /* 78 */ 247 "\x21" "Inappropriate file type or format", /* 79 */ 248 }; //tcperrorstrings 249 250 251 #define ACCEPT_CONN_WITHOUT_GLOBALS 1 252 253 #ifdef WIN95VERSION 254 #define ACCEPT_IN_SEPARATE_THREAD 1 255 #endif 256 257 #ifdef MACVERSION 258 #ifdef FRONTIER_GUSI_2 259 #include <compat.h> 260 #include <fcntl.h> 261 #include <inttypes.h> 262 #include <netdb.h> 263 #include <netinet/in.h> 264 #include <arpa/inet.h> 265 #include <sys/ioctl.h> 266 #include <sys/socket.h> 267 #include <sys/stat.h> 268 #include <sys/time.h> 269 #include <sys/types.h> 270 #include <sys/un.h> 271 #include <unistd.h> 272 #include <utime.h> 273 274 #include <pthread.h> 275 276 #define GUSI_SpinHook 'spin' 277 278 typedef void (*GUSIHook)(void); 279 280 void GUSISetHook (OSType code, GUSIHook hook); 281 282 #define ACCEPT_IN_SEPARATE_THREAD 1 283 284 #else 285 286 #include <GUSI.h> 287 288 #undef ACCEPT_IN_SEPARATE_THREAD 289 290 #endif 291 292 #include <sys/errno.h> 293 #include "mac.h" 294 #endif 295 296 #include "error.h" 297 #include "file.h" 298 #include "kb.h" 299 #include "ops.h" 300 #include "memory.h" 301 #include "threads.h" 302 #include "strings.h" 303 #include "lang.h" 304 #include "langinternal.h" 305 #include "process.h" 306 #include "processinternal.h" 307 #include "shell.h" 308 #include "shellhooks.h" 309 #ifdef WIN95VERSION 310 #include "FrontierWinMain.h" 311 #endif 312 313 #include "winsocknetevents.h" 314 315 316 #define NO_HOST_SERVICES NULL 317 318 #ifdef WIN95VERSION 319 #define WSAGetHostError() WSAGetLastError() 320 321 typedef struct hostData { 322 323 void * dummy; // strucure not needed under Windows 324 } hostData; 325 326 #define usleep(A) Sleep(A) 327 328 //#if 0 329 typedef int (WINAPI * tyTransmitFile) (SOCKET, HANDLE, DWORD, DWORD, LPOVERLAPPED, LPTRANSMIT_FILE_BUFFERS, DWORD); 330 static tyTransmitFile adrTransmitFile = nil; 331 //#endif 332 #endif 333 334 #ifdef MACVERSION 335 336 #ifdef FRONTIER_GUSI_2 337 typedef struct hostData { 338 339 void * dummy; // strucure not needed under Windows 340 } hostData; 341 #endif 342 343 extern int h_errno; 344 345 extern long sHostID = 0; //cached value in GUSINetDB.cp 346 347 #define WSAEWOULDBLOCK EAGAIN 348 #define WSAENOTCONN ENOTCONN 349 #define WSAETIMEDOUT ETIMEDOUT 350 #define WSAECONNABORTED ECONNABORTED 351 #define WSAENOTSOCK ENOTSOCK 352 #define WSAEMFILE EMFILE 353 #define WSAGetLastError() (errno == EINTR? userCanceledErr : errno) 354 #define WSAGetHostError() h_errno 355 356 #define wsprintf sprintf 357 358 #define INVALID_SOCKET (SOCKET)(~0) 359 #define SOCKET_ERROR (-1) 360 361 #define SD_READ 0 362 #define SD_SEND 1 363 #define SD_BOTH 2 364 365 #define closesocket(foo) close(foo) 366 #define ioctlsocket(d,request,argp) ioctl(d,request,argp) 367 typedef int SOCKET; 368 369 /* Microsoft Windows Extended data types */ 370 #define FAR 371 372 typedef struct sockaddr SOCKADDR; 373 typedef struct sockaddr *PSOCKADDR; 374 typedef struct sockaddr FAR *LPSOCKADDR; 375 376 typedef struct sockaddr_in SOCKADDR_IN; 377 typedef struct sockaddr_in *PSOCKADDR_IN; 378 typedef struct sockaddr_in FAR *LPSOCKADDR_IN; 379 380 typedef struct linger LINGER; 381 typedef struct linger *PLINGER; 382 typedef struct linger FAR *LPLINGER; 383 384 typedef struct in_addr IN_ADDR; 385 typedef struct in_addr *PIN_ADDR; 386 typedef struct in_addr FAR *LPIN_ADDR; 387 #endif 388 389 #define SOCKTYPE_INVALID -1 390 #define SOCKTYPE_UNKNOWN 0 391 #define SOCKTYPE_OPEN 1 392 #define SOCKTYPE_DATA 2 393 #define SOCKTYPE_LISTENING 3 394 #define SOCKTYPE_CLOSED 4 395 #define SOCKTYPE_LISTENSTOPPED 5 396 #define SOCKTYPE_INACTIVE 6 397 398 #define FRONTIER_MAX_STREAM 256 399 #define INTNETERROR_INVALIDSTREAM -1 400 401 typedef short tysocktypeid; 402 403 typedef struct tysockRecord { 404 SOCKET sockID; 405 tysocktypeid typeID; 406 long refcon; 407 bigstring callback; 408 long maxdepth; 409 long listenReference; 410 long currentListenDepth; 411 boolean flNotification; 412 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 413 Handle hcallbacktree; 414 #endif 415 #ifdef ACCEPT_IN_SEPARATE_THREAD 416 long idthread; 417 hdldatabaserecord hdatabase; 418 #endif 419 } sockRecord; 420 421 422 static short frontierWinSockCount = 0; 423 static boolean frontierWinSockLoaded = false; 424 static sockRecord sockstack[FRONTIER_MAX_STREAM]; 425 426 427 #ifdef MACVERSION 428 static short sockListenCount = 0; 429 static short sockListenList[FRONTIER_MAX_STREAM]; 430 #endif 431 432 433 #ifdef WIN95VERSION 434 435 static CRITICAL_SECTION sockstacksection; 436 437 static boolean sockstacksectioninitialized = false; 438 439 static void _entercriticalsockstacksection (void) { 440 441 if (!sockstacksectioninitialized) { 442 443 InitializeCriticalSection (&sockstacksection); 444 445 sockstacksectioninitialized = true; 446 } 447 448 EnterCriticalSection (&sockstacksection); 449 } 450 451 static void _leavecriticalsockstacksection (void) { 452 453 LeaveCriticalSection (&sockstacksection); 454 } 455 456 #else 457 458 #define _entercriticalsockstacksection() 459 460 #define _leavecriticalsockstacksection() 461 462 #endif 463 464 465 static char * TCPGETTYPE (tysocktypeid typeID) { 466 switch (typeID) { 467 case SOCKTYPE_INVALID: 468 return ("INVALID"); 469 470 case SOCKTYPE_UNKNOWN: 471 return ("UNKNOWN"); 472 473 case SOCKTYPE_OPEN: 474 return ("OPEN"); 475 476 case SOCKTYPE_DATA: 477 return ("DATA"); 478 479 case SOCKTYPE_LISTENING: 480 return ("LISTENING"); 481 482 case SOCKTYPE_CLOSED: 483 return ("CLOSED"); 484 485 case SOCKTYPE_LISTENSTOPPED: 486 return ("LISTEN-STOPPED"); 487 488 case SOCKTYPE_INACTIVE: 489 return ("INACTIVE"); 490 491 default: 492 break; 493 } 494 495 return ("BAD Type value"); 496 } /*TCPGETTYPE*/ 497 498 499 500 #define STR_P_ERROR_CLOSED_PREMATURELY "\x45" "Can't read stream because the TCP connection was closed unexpectedly." 501 502 /* 503 To disable the tcp tracker, don't define TCPTRACKER. 504 505 To enable tcp tracker ouput in the about window, define TCPTRACKER == 1. 506 507 To enable tcp tracker error ouput to a file, define TCPTRACKER == 2. 508 509 To enable full tcp tracker output to a file, define TCPTRACKER == 3. 510 */ 511 512 513 //#undef TCPTRACKER 514 #define TCPTRACKER 1 515 //#define TCPTRACKER 2 516 //#define TCPTRACKER 3 517 518 #if (TCPTRACKER == 3) 519 #pragma message ("*********************** TCPTRACKER is ON: Full output to tcpfile.txt ***********************") 520 521 static boolean fllogger = true; 522 523 #ifdef WIN95VERSION 524 extern DWORD ixthreadglobalsgrabcount; // Tls index of counter for nest globals grabbing 525 #endif 526 527 static FILE * tcpfile = NULL; 528 static char TCPmsg[400]; 529 530 #define TCPprintf(msg) msg 531 #define TCPERRORprintf(msg) msg 532 533 static void TCPWRITEMSG () { 534 unsigned long ticks = gettickcount (); 535 static unsigned long lastticks = 0; 536 #ifdef WIN95VERSION 537 DWORD idthread; 538 static DWORD idlastthread = 0; 539 long grabcount = (long) TlsGetValue (ixthreadglobalsgrabcount); 540 #endif 541 #ifdef MACVERSION 542 long idthread = (long) (**getcurrentthread ()).idthread; 543 static long idlastthread = 0; 544 #endif 545 546 if (fllogger) { 547 #ifdef WIN95VERSION 548 idthread = GetCurrentThreadId(); 549 #endif 550 551 if (tcpfile == NULL) { 552 tcpfile = fopen ("tcpfile.txt", "w+"); 553 } 554 555 if (idthread != idlastthread) { 556 fprintf (tcpfile, "\n"); 557 idlastthread = idthread; 558 } 559 560 #ifdef WIN95VERSION 561 fprintf (tcpfile, "%08X (%04ld) | %04X (%02ld) | %s", (unsigned long) ticks, (ticks - lastticks), idthread, grabcount, TCPmsg); 562 #endif 563 564 #ifdef MACVERSION 565 fprintf (tcpfile, "%08X (%04ld) | %04X | %s", (unsigned long) ticks, (ticks - lastticks), idthread, TCPmsg); 566 #endif 567 568 lastticks = ticks; 569 570 fflush (tcpfile); 571 } 572 } /*TCPWRITEMSG*/ 573 574 #define TCPERRORWRITEMSG TCPWRITEMSG 575 576 void TCPTRACKERIN (char * functionName, int linenumber, unsigned long streamID) { 577 if (fllogger) { 578 if ((streamID < 1) || (streamID >= FRONTIER_MAX_STREAM)) { 579 wsprintf (TCPmsg, "Entering %s at line %d, Stream = %ld - INVALID STREAM.\n", functionName, linenumber, streamID); 580 TCPWRITEMSG (); 581 return; 582 } 583 584 #ifdef WIN95VERSION 585 wsprintf (TCPmsg, "Entering %s at line %d, Stream = %ld, Socket = %ld, Type is %s, Max Depth is %d, Current Depth is %d, Notification is %s, Listen Ref is %08lX, Refcon = %08lX.\n", 586 functionName, linenumber, streamID, sockstack[streamID].sockID, TCPGETTYPE (sockstack[streamID].typeID), sockstack[streamID].maxdepth, 587 sockstack[streamID].currentListenDepth, sockstack[streamID].flNotification ? "ON" : "OFF", 588 sockstack[streamID].listenReference, sockstack[streamID].refcon); 589 #else 590 wsprintf (TCPmsg, "Entering %s at line %d, Stream = %ld, Socket = %ld, Type is %s, Max Depth is %d, Current Depth is %d, Listen Ref is %08lX, Refcon = %08lX.\n", 591 functionName, linenumber, streamID, sockstack[streamID].sockID, TCPGETTYPE (sockstack[streamID].typeID), sockstack[streamID].maxdepth, 592 sockstack[streamID].currentListenDepth, sockstack[streamID].listenReference, sockstack[streamID].refcon); 593 #endif 594 595 TCPWRITEMSG (); 596 } 597 } /*TCPTRACKERIN*/ 598 599 600 void TCPTRACKEROUT (char * functionName, int linenumber, unsigned long streamID) { 601 if (fllogger) { 602 if ((streamID < 1) || (streamID >= FRONTIER_MAX_STREAM)) { 603 wsprintf (TCPmsg, "Exiting %s at line %d, Stream = %08lX - INVALID STREAM.\n", functionName, linenumber, streamID); 604 TCPWRITEMSG (); 605 return; 606 } 607 608 #ifdef WIN95VERSION 609 wsprintf (TCPmsg, "Exiting %s at line %d, Stream = %ld, Socket = %ld, Type is %s, Max Depth is %d, Current Depth is %d, Notification is %s, Listen Ref is %08lX, Refcon = %08lX.\n", 610 functionName, linenumber, streamID, sockstack[streamID].sockID, TCPGETTYPE (sockstack[streamID].typeID), sockstack[streamID].maxdepth, 611 sockstack[streamID].currentListenDepth, sockstack[streamID].flNotification ? "ON" : "OFF", 612 sockstack[streamID].listenReference, sockstack[streamID].refcon); 613 #else 614 wsprintf (TCPmsg, "Exiting %s at line %d, Stream = %ld, Socket = %ld, Type is %s, Max Depth is %d, Current Depth is %d, Listen Ref is %08lX, Refcon = %08lX.\n", 615 functionName, linenumber, streamID, sockstack[streamID].sockID, TCPGETTYPE (sockstack[streamID].typeID), sockstack[streamID].maxdepth, 616 sockstack[streamID].currentListenDepth, sockstack[streamID].listenReference, sockstack[streamID].refcon); 617 #endif 618 619 TCPWRITEMSG (); 620 } 621 } /*TCPTRACKEROUT*/ 622 623 static void TCPTRACKERCLOSE () { 624 if (fllogger) { 625 if (tcpfile != NULL) 626 fclose (tcpfile); 627 } 628 } 629 630 631 #elif (TCPTRACKER == 2) 632 #pragma message ("*********************** TCPTRACKER is ON: Error output to tcpfile.txt **********************") 633 634 static boolean fllogger = true; 635 636 #ifdef WIN95VERSION 637 extern DWORD ixthreadglobalsgrabcount; // Tls index of counter for nest globals grabbing 638 #endif 639 640 static FILE * tcpfile = NULL; 641 static char TCPmsg[400]; 642 643 #define TCPprintf(msg) 644 #define TCPWRITEMSG() 645 #define TCPTRACKERIN(functionName, linenumber, streamID) 646 #define TCPTRACKEROUT(functionName, linenumber, streamID) 647 648 #define TCPERRORprintf(msg) msg 649 650 static void TCPERRORWRITEMSG () { 651 unsigned long ticks = gettickcount (); 652 static unsigned long lastticks = 0; 653 #ifdef WIN95VERSION 654 DWORD idthread; 655 static DWORD idlastthread = 0; 656 long grabcount = (long) TlsGetValue (ixthreadglobalsgrabcount); 657 #endif 658 #ifdef MACVERSION 659 long idthread = (long) (**getcurrentthread ()).idthread; 660 static long idlastthread = 0; 661 #endif 662 663 if (fllogger) { 664 #ifdef WIN95VERSION 665 idthread = GetCurrentThreadId(); 666 #endif 667 668 if (tcpfile == NULL) { 669 tcpfile = fopen ("tcpfile.txt", "w+"); 670 } 671 672 if (idthread != idlastthread) { 673 fprintf (tcpfile, "\n"); 674 idlastthread = idthread; 675 } 676 677 #ifdef WIN95VERSION 678 fprintf (tcpfile, "%08X (%04ld) | %04X (%02ld) | %s", (unsigned long) ticks, (ticks - lastticks), idthread, grabcount, TCPmsg); 679 #endif 680 681 #ifdef MACVERSION 682 fprintf (tcpfile, "%08X (%04ld) | %04X | %s", (unsigned long) ticks, (ticks - lastticks), idthread, TCPmsg); 683 #endif 684 685 lastticks = ticks; 686 687 fflush (tcpfile); 688 } 689 } /*TCPWRITEMSG*/ 690 691 692 static void TCPTRACKERCLOSE () { 693 if (fllogger) { 694 if (tcpfile != NULL) 695 fclose (tcpfile); 696 } 697 } 698 699 #elif (TCPTRACKER == 1) 700 #pragma message ("*********************** TCPTRACKER is ON: Full output to About window **********************") 701 702 #include "about.h" 703 #define fllogger (aboutstatsshowing()) 704 #define TCPprintf(msg) msg 705 #define TCPERRORprintf(msg) msg 706 707 static char TCPmsg[400]; 708 709 static void TCPWRITEMSG () { 710 711 if (fllogger) { 712 713 convertcstring (TCPmsg); 714 715 aboutsetmiscstring (TCPmsg); 716 } 717 } /*TCPWRITEMSG*/ 718 719 #define TCPERRORWRITEMSG TCPWRITEMSG 720 721 static void TCPTRACKERIN (char * functionName, int linenumber, unsigned long streamID) { 722 if (fllogger) { 723 if ((streamID < 1) || (streamID >= FRONTIER_MAX_STREAM)) { 724 wsprintf (TCPmsg, "Entering %s at line %d, Stream = %ld - INVALID STREAM.\n", functionName, linenumber, streamID); 725 TCPWRITEMSG (); 726 return; 727 } 728 729 wsprintf (TCPmsg, "Entering %s at line %d, Stream = %ld, Socket = %ld, Type is %s, Max Depth is %d, Current Depth is %d, Listen Ref is %08lX, Refcon = %08lX.\n", 730 functionName, linenumber, streamID, sockstack[streamID].sockID, TCPGETTYPE (sockstack[streamID].typeID), sockstack[streamID].maxdepth, 731 sockstack[streamID].currentListenDepth, sockstack[streamID].listenReference, sockstack[streamID].refcon); 732 733 TCPWRITEMSG (); 734 } 735 } /*TCPTRACKERIN*/ 736 737 738 static void TCPTRACKEROUT (char * functionName, int linenumber, unsigned long streamID) { 739 if (fllogger) { 740 if ((streamID < 1) || (streamID >= FRONTIER_MAX_STREAM)) { 741 wsprintf (TCPmsg, "Exiting %s at line %d, Stream = %08lX - INVALID STREAM.\n", functionName, linenumber, streamID); 742 TCPWRITEMSG (); 743 return; 744 } 745 746 wsprintf (TCPmsg, "Exiting %s at line %d, Stream = %ld, Socket = %ld, Type is %s, Max Depth is %d, Current Depth is %d, Listen Ref is %08lX, Refcon = %08lX.\n", 747 functionName, linenumber, streamID, sockstack[streamID].sockID, TCPGETTYPE (sockstack[streamID].typeID), sockstack[streamID].maxdepth, 748 sockstack[streamID].currentListenDepth, sockstack[streamID].listenReference, sockstack[streamID].refcon); 749 750 TCPWRITEMSG (); 751 } 752 } /*TCPTRACKEROUT*/ 753 754 #define TCPTRACKERCLOSE() 755 756 #else 757 758 #define TCPprintf(msg) 759 #define TCPERRORprintf(msg) 760 #define TCPWRITEMSG() 761 #define TCPERRORWRITEMSG() 762 #define TCPTRACKERIN(functionName, linenumber, streamID) 763 #define TCPTRACKEROUT(functionName, linenumber, streamID) 764 #define TCPTRACKERCLOSE() 765 766 #endif 767 768 769 static boolean getsockrecord (SOCKET sock, long *stream) { 770 long i; 771 772 for (i = 1; i < FRONTIER_MAX_STREAM; i++) { 773 if (sockstack[i].sockID == sock) { 774 *stream = i; 775 return (true); 776 } 777 } 778 779 *stream = -1; 780 781 return (false); 782 } /*getsockrecord*/ 783 784 785 static void initsockrecord (long i) { 786 787 /* 788 5.0.2b21 dmb: share repeated code 789 */ 790 791 sockstack[i].sockID = INVALID_SOCKET; 792 sockstack[i].typeID = SOCKTYPE_UNKNOWN; 793 sockstack[i].maxdepth = 0; 794 sockstack[i].listenReference = 0; 795 sockstack[i].currentListenDepth = 0; 796 sockstack[i].refcon = 0; 797 copystring (emptystring, sockstack[i].callback); 798 sockstack[i].flNotification = false; 799 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 800 sockstack[i].hcallbacktree = nil; 801 #endif 802 #ifdef ACCEPT_IN_SEPARATE_THREAD 803 sockstack[i].idthread = nil; 804 sockstack[i].hdatabase = nil; 805 #endif 806 } /*initsockrecord*/ 807 808 809 static boolean addsockrecord (long *stream) { 810 811 /* 812 5.1.5 dmb: reuse closed sockets before inactive ones. 813 814 6.2a12 AR: This is the bottleneck for grabbing a new or used socket record. 815 On Win32, protect the socket stack by declaring a critical section. 816 */ 817 818 long i; 819 820 _entercriticalsockstacksection(); 821 822 for (i = 1; i < FRONTIER_MAX_STREAM; i++) { 823 if (sockstack[i].typeID == SOCKTYPE_INVALID) { 824 initsockrecord (i); 825 *stream = i; 826 _leavecriticalsockstacksection(); 827 return (true); 828 } 829 } 830 831 /* If none are inactive, reuse those that are closed */ 832 833 for (i = 1; i < FRONTIER_MAX_STREAM; i++) { 834 if (sockstack[i].typeID == SOCKTYPE_CLOSED) { 835 initsockrecord (i); 836 *stream = i; 837 _leavecriticalsockstacksection(); 838 return (true); 839 } 840 } 841 842 /* If we used up all the stack, reuse those that are inactive */ 843 844 for (i = 1; i < FRONTIER_MAX_STREAM; i++) { 845 if (sockstack[i].typeID == SOCKTYPE_INACTIVE) { 846 initsockrecord (i); 847 *stream = i; 848 _leavecriticalsockstacksection(); 849 return (true); 850 } 851 } 852 853 _leavecriticalsockstacksection(); 854 855 *stream = -1; 856 857 return (false); 858 } /*addsockrecord*/ 859 860 861 static void clearsockstack () { 862 long i; 863 864 _entercriticalsockstacksection(); 865 866 for (i = 0; i < FRONTIER_MAX_STREAM; i++) { 867 sockstack[i].sockID = INVALID_SOCKET; 868 sockstack[i].typeID = SOCKTYPE_INVALID; 869 } 870 871 _leavecriticalsockstacksection(); 872 873 #ifdef MACVERSION 874 sockListenCount = 0; 875 #endif 876 } /*clearsockstack*/ 877 878 879 static void gettcperrorstring (int errcode, bigstring bs) { 880 881 int ixtcperr = errcode; 882 883 #ifdef WIN95VERSION 884 if (errcode >= WSAHOST_NOT_FOUND && errcode <= WSANO_DATA) 885 ixtcperr -= 1000; 886 887 ixtcperr -= WSABASEERR; 888 #endif 889 890 if (ixtcperr > 0 && ixtcperr < 80) { 891 892 copystring (tcperrorstrings [ixtcperr], bs); //handles nil source 893 894 if (!isemptystring (bs)) { 895 896 pushchar ('.', bs); 897 898 return; 899 } 900 } 901 902 #ifdef MACVERSION 903 getsystemerrorstring (errcode, bs); 904 #endif 905 906 #ifdef WIN95VERSION 907 getwinerrormessage (errcode, bs); 908 909 firstword (bs, '.', bs); //skip the cr 910 #endif 911 912 } /*gettcperrorstring*/ 913 914 915 static void plainneterror (bigstring bs) { 916 917 /* 918 6.1b15 AR 919 */ 920 921 bigstring errbs; 922 923 copystring (bs, errbs); 924 925 nullterminate (errbs); 926 927 TCPERRORprintf (wsprintf(TCPmsg, "NET ERROR - %s.\n", stringbaseaddress(errbs))); 928 TCPERRORWRITEMSG (); 929 930 langerrormessage (bs); 931 } /*neterror*/ 932 933 934 static void neterror (char * cannot, long errcode) { 935 936 bigstring bs; 937 bigstring errbs; 938 char prestring[256]; 939 940 wsprintf (prestring, "Can't %s because TCP/IP error code %ld", cannot, (long)errcode); 941 copyctopstring (prestring, errbs); 942 943 gettcperrorstring (errcode, bs); 944 945 //if (equaltextidentifiers (stringbaseaddress(bs), "No information available for error number", (short)strlen("No information available for error number")) != true) { 946 if (!isemptystring (bs)) { 947 948 pushstring ("\x03" " - ", errbs); 949 950 pushstring (bs, errbs); 951 } 952 else { 953 pushchar ('.', errbs); 954 } 955 956 nullterminate (errbs); 957 958 TCPERRORprintf (wsprintf(TCPmsg, "NET ERROR - %s.\n", stringbaseaddress(errbs))); 959 TCPERRORWRITEMSG (); 960 961 langerrormessage (errbs); 962 } /*neterror*/ 963 964 965 static void intneterror (long errcode) { 966 bigstring bs; 967 968 if (errcode == INTNETERROR_INVALIDSTREAM) 969 copyctopstring ("Invalid stream", bs); 970 else 971 copyctopstring ("Unknown stream error", bs); 972 973 langerrormessage (bs); 974 } /*intneterror*/ 975 976 977 #ifdef MACVERSION 978 979 #ifdef FRONTIER_GUSI_2 980 981 static void fwsGUSI2Spin (boolean flresting) { 982 short mask = osMask|activMask|mDownMask|keyDownMask; 983 984 if (inmainthread ()) { 985 986 if (flresting) { 987 EventRecord ev; 988 989 if (WaitNextEvent (mask, &ev, 1L, nil)) 990 shellprocessevent (&ev); 991 } 992 else 993 shellyield (false); 994 } 995 else { 996 /* if (flresting) { 997 998 boolean fl; 999 hdlthreadglobals hthread = getcurrentthreadglobals (); 1000 ThreadID idthread = (ThreadID) (**hthread).idthread; 1001 const long sleepTime = 6L; 1002 //hdlthreadqueue hq; 1003 1004 //if (!newclearhandle (sizeof (tythreadqueuerecord), (Handle *) &hq)) 1005 // return (memFullErr); 1006 1007 //(**hq).idthread = idthread; 1008 1009 TCPprintf (wsprintf(TCPmsg, "Going to sleep for %d ticks.\n", sleepTime)); 1010 TCPWRITEMSG(); 1011 1012 //listlink ((hdllinkedlist) gusisleepqueue, (hdllinkedlist) hq); 1013 1014 fl = processsleep (hthread, sleepTime); 1015 1016 if (!fl) { 1017 1018 //if (listunlink ((hdllinkedlist) gusisleepqueue, (hdllinkedlist) hq)) 1019 //disposehandle ((Handle) hq); 1020 1021 fl = langbackgroundtask (true); 1022 } 1023 1024 TCPprintf (wsprintf(TCPmsg, "Awake! at line %d.\n", __LINE__)); 1025 TCPWRITEMSG(); 1026 1027 // gusiwakethread = 0; 1028 } 1029 else */ 1030 langbackgroundtask (true); 1031 } 1032 }/*fwsGUSI2Spin*/ 1033 1034 #else 1035 1036 #if __powerc 1037 void RotateCursor (short); 1038 void RotateCursor (short i) {} // for GUSI 1039 #else 1040 void ROTATECURSOR (short); 1041 void ROTATECURSOR (short i) {} // for GUSI 1042 #endif 1043 1044 typedef struct tythreadqueuerecord { 1045 1046 struct tythreadqueuerecord **hnext; 1047 1048 ThreadID idthread; 1049 } tythreadqueuerecord, *ptrthreadqueue, **hdlthreadqueue; 1050 1051 1052 static hdlthreadqueue gusisleepqueue = nil; 1053 static hdlthreadqueue gusiwakequeue = nil; 1054 1055 1056 static int fwsGUSISpin (spin_msg msg, long arg) { 1057 1058 long sleepTime = 6; // 1/10 of a second by default 1059 boolean flresting = true; 1060 short mask = osMask|activMask|mDownMask|keyDownMask; //|highLevelEventMask|updateMask 1061 extern int GUSI_error (int); 1062 boolean fl = true; 1063 1064 if (languserescaped (false)) 1065 return GUSI_error (-128); 1066 1067 /* 1068 switch (msg) { 1069 case SP_SLEEP: 1070 case SP_SELECT: 1071 if (arg >= sleepTime) // Only sleep if patience guaranteed 1072 break; 1073 // Otherwise, fall through 1074 case SP_AUTO_SPIN: 1075 sleepTime = 0; 1076 flresting = false; 1077 break; 1078 //case SP_STREAM_WRITE: 1079 // if (arg >= sleepTime) 1080 // sleepTime = 120; 1081 // break; 1082 case SP_MISC: 1083 sleepTime = 0; 1084 break; 1085 1086 default: 1087 break; 1088 } 1089 */ 1090 1091 switch (msg) { 1092 1093 case SP_AUTO_SPIN: 1094 return noErr; 1095 1096 case SP_MISC: 1097 if (arg < 0) { 1098 sleepTime = 0; 1099 flresting = false; 1100 } 1101 else 1102 sleepTime = 6; 1103 1104 break; 1105 1106 case SP_NAME: 1107 case SP_ADDR: 1108 case SP_STREAM_READ: 1109 case SP_STREAM_WRITE: 1110 if (arg < 0) 1111 sleepTime = 0; 1112 else 1113 sleepTime = 120; 1114 break; 1115 1116 default: 1117 flresting = false; 1118 } 1119 1120 if (inmainthread ()) { 1121 1122 if (flresting) { 1123 EventRecord ev; 1124 1125 if (WaitNextEvent (mask, &ev, sleepTime, nil)) 1126 shellprocessevent (&ev); 1127 } 1128 // else 1129 // fl = shellyield (false); 1130 } 1131 1132 else { 1133 if (flresting) { 1134 1135 hdlthreadglobals hthread = getcurrentthreadglobals (); 1136 ThreadID idthread = (ThreadID) (**hthread).idthread; 1137 hdlthreadqueue hq; 1138 1139 if (!newclearhandle (sizeof (tythreadqueuerecord), (Handle *) &hq)) 1140 return (memFullErr); 1141 1142 (**hq).idthread = idthread; 1143 1144 TCPprintf (wsprintf(TCPmsg, "Going to sleep for %d ticks.\n", sleepTime)); 1145 TCPWRITEMSG(); 1146 1147 listlink ((hdllinkedlist) gusisleepqueue, (hdllinkedlist) hq); 1148 1149 fl = processsleep (hthread, sleepTime); 1150 1151 if (!fl) { 1152 1153 if (listunlink ((hdllinkedlist) gusisleepqueue, (hdllinkedlist) hq)) 1154 disposehandle ((Handle) hq); 1155 1156 fl = langbackgroundtask (true); 1157 } 1158 1159 TCPprintf (wsprintf(TCPmsg, "Awake! at line %d.\n", __LINE__)); 1160 TCPWRITEMSG(); 1161 1162 // gusiwakethread = 0; 1163 } 1164 else 1165 fl = langbackgroundtask (true); 1166 } 1167 1168 if (fl) 1169 return noErr; 1170 else 1171 return -128; 1172 } /*fwsGUSISpin*/ 1173 1174 1175 //#define GUSISLEEPQUEUESIZE 128 1176 //static ThreadID gusisleepqueue [GUSISLEEPQUEUESIZE]; 1177 1178 //static long ixlastcompleted = -1; 1179 //static long ixlastwoken = -1; 1180 1181 static void wakecompletedthreads (void) { 1182 1183 /* 1184 walk through the circular gusisleepqueue and wake any newly-completed threads 1185 */ 1186 1187 /* 1188 for ( ; ixlastwoken != ixlastcompleted; ixlastwoken = (ixlastwoken + 1) % GUSISLEEPQUEUESIZE) { 1189 1190 ThreadID id = gusisleepqueue [ixlastwoken]; 1191 */ 1192 hdlthreadqueue hq, hnext; 1193 1194 for (hq = (**gusiwakequeue).hnext; hq != nil; hq = hnext) { 1195 1196 ThreadID id = (**hq).idthread; 1197 hdlthreadglobals hg = getprocessthread (id); 1198 1199 hnext = (**hq).hnext; 1200 1201 listunlink ((hdllinkedlist) gusiwakequeue, (hdllinkedlist) hq); 1202 1203 disposehandle ((Handle) hq); 1204 1205 if (hg && processwake (hg)) { 1206 TCPprintf (wsprintf(TCPmsg, "Waking thread at line %d. Thread ID: %04X.\n", __LINE__, id)); 1207 TCPWRITEMSG(); 1208 } 1209 else { 1210 TCPERRORprintf (wsprintf(TCPmsg, "Error waking thread at line %d. Thread ID: %04X.\n", __LINE__, id)); 1211 TCPERRORWRITEMSG(); 1212 } 1213 } 1214 } /*wakecompletedthreads*/ 1215 1216 1217 static OSErr fwsGUSIWakeThread (ThreadID idthread) { 1218 1219 /* 1220 gusisleepqueue [ixlastcompleted] = idthread; 1221 1222 ixlastcompleted = (ixlastcompleted + 1) % GUSISLEEPQUEUESIZE; 1223 */ 1224 1225 /* 1226 5.1.5b10 dmb: can't do much in a completion routine. just move thread 1227 from sleepqueue to wakequeue. 1228 */ 1229 1230 hdlthreadqueue hq; 1231 1232 for (hq = (**gusisleepqueue).hnext; hq != nil; hq = (**hq).hnext) { 1233 1234 if ((**hq).idthread == idthread) { 1235 1236 listunlink ((hdllinkedlist) gusisleepqueue, (hdllinkedlist) hq); 1237 1238 listlink ((hdllinkedlist) gusiwakequeue, (hdllinkedlist) hq); 1239 1240 break; 1241 } 1242 } 1243 1244 return (noErr); 1245 } /*fwsGUSIWakeThread*/ 1246 1247 1248 static boolean fwsGUSIWakeupHook (hdlprocessthread hthread) { 1249 1250 /* 1251 if this thread is in our sleep queue, wake it up and return false 1252 1253 just to be extra careful, handle the case where the thread is already 1254 in the wake queue 1255 */ 1256 1257 hdlthreadqueue hq; 1258 ThreadID idthread = (ThreadID) (**hthread).idthread; 1259 1260 for (hq = (**gusisleepqueue).hnext; hq != nil; hq = (**hq).hnext) { 1261 1262 if ((**hq).idthread == idthread) { //move it to wake queue 1263 1264 listunlink ((hdllinkedlist) gusisleepqueue, (hdllinkedlist) hq); 1265 1266 listlink ((hdllinkedlist) gusiwakequeue, (hdllinkedlist) hq); 1267 1268 break; 1269 } 1270 } 1271 1272 for (hq = (**gusiwakequeue).hnext; hq != nil; hq = (**hq).hnext) { 1273 1274 if ((**hq).idthread == idthread) { //found it in wake queue, wake it 1275 1276 listunlink ((hdllinkedlist) gusiwakequeue, (hdllinkedlist) hq); 1277 1278 disposehandle ((Handle) hq); 1279 1280 if (processwake (hthread)) { 1281 TCPprintf (wsprintf(TCPmsg, "Hook: waking thread at line %d. Thread ID: %04X.\n", __LINE__, idthread)); 1282 TCPWRITEMSG(); 1283 } 1284 else { 1285 TCPERRORprintf (wsprintf(TCPmsg, "Hook: error waking thread at line %d. Thread ID: %04X.\n", __LINE__, idthread)); 1286 TCPERRORWRITEMSG(); 1287 } 1288 1289 return (false); //hooked 1290 } 1291 } 1292 1293 return (true); //not hooked 1294 } /*fwsGUSIWakeupHook*/ 1295 1296 1297 #endif 1298 #endif 1299 1300 1301 #ifdef PIKE 1302 1303 /*extern const*/ /*long maxconnections = 5;*/ 1304 1305 long maxconnections = longinfinity; /*7.1b5 PBS: no more connection limit*/ 1306 1307 #else 1308 1309 /*extern const*/ long maxconnections = longinfinity; /*7.0b37 PBS: reported in system.environment table in Frontier*/ 1310 /*7.1b2 RAB: made global variables*/ 1311 1312 #endif 1313 1314 /*7.0b37 PBS: Count connections in both Radio and Frontier.*/ 1315 1316 extern long ctconnections = 0; 1317 1318 1319 static boolean incrementconnectioncounter (void) { 1320 1321 if (ctconnections >= maxconnections) 1322 return (false); 1323 1324 ctconnections++; 1325 1326 return (true); 1327 } /*incrementconnectioncounter*/ 1328 1329 static void decrementconnectioncounter (void) { 1330 1331 ctconnections--; 1332 1333 assert (ctconnections >= 0); 1334 1335 } /*decrementconnectioncounter*/ 1336 1337 1338 long fwsNetEventGetConnectionCount (void) { 1339 1340 /*7.0b37 PBS: return current count of TCP connections. 1341 Used by tcp.countConnections verb. 1342 */ 1343 1344 return (ctconnections); 1345 } /*fwsNetEventGetConnectionCount*/ 1346 1347 1348 static boolean fwsNetEventLaunch (struct hostData *data) { 1349 1350 /* 1351 Initialize the NetEvents system 1352 1353 5.0.2b5 dmb: added hostData parameter and GUSI support to handle threading 1354 */ 1355 1356 #ifdef WIN95VERSION 1357 WSADATA wsaData; 1358 WORD VersionRequested; 1359 #endif 1360 1361 if (! frontierWinSockLoaded) { 1362 1363 #ifdef WIN95VERSION 1364 //#if 0 1365 HMODULE hmodule; 1366 //#endif 1367 1368 #if (TCPTRACKER >= 2) //if reporting to file 1369 long l; 1370 if (getProfileLong ("\x0a" "TCPTracker", &l)) { 1371 fllogger = (boolean) l; 1372 } 1373 else { 1374 setProfileLong ("\x0a" "TCPTracker", fllogger); /*this just sets the value in the registry*/ 1375 } 1376 #endif 1377 1378 VersionRequested = MAKEWORD(WINSOCK_VERSION_MAJOR, WINSOCK_VERSION_MINOR); 1379 1380 if (WSAStartup (VersionRequested, &wsaData) == SOCKET_ERROR) { 1381 neterror("start WinSock", WSAGetLastError ()); 1382 WSACleanup(); 1383 return (false); 1384 } 1385 1386 if ((LOBYTE(wsaData.wVersion) != WINSOCK_VERSION_MAJOR) || (HIBYTE(wsaData.wVersion) != WINSOCK_VERSION_MINOR)) { 1387 /* Tell the user that we couldn't find a useable WinSock DLL. */ 1388 WSACleanup( ); 1389 return(false); 1390 } 1391 1392 /* 1393 The TransmitFile function is only available on Windows NT. 1394 */ 1395 1396 //#if 0 1397 1398 hmodule = GetModuleHandle ("wsock32.dll"); 1399 1400 if (hmodule != nil) 1401 adrTransmitFile = (tyTransmitFile) GetProcAddress (hmodule, "TransmitFile"); 1402 1403 //#endif 1404 1405 #endif 1406 1407 #ifdef MACVERSION 1408 #ifdef FRONTIER_GUSI_2 1409 //GUSISetHook (GUSI_SpinHook, (GUSIHook) fwsGUSI2Spin); 1410 #else 1411 GUSISetup (GUSIwithInternetSockets); 1412 1413 GUSISetHook (GUSI_SpinHook, (GUSIHook) fwsGUSISpin); 1414 1415 GUSISetHook (GUSI_WakeThreadHook, (GUSIHook) fwsGUSIWakeThread); 1416 1417 if (!newclearhandle (sizeof (tythreadqueuerecord), (Handle *) &gusisleepqueue)) 1418 return (false); 1419 1420 if (!newclearhandle (sizeof (tythreadqueuerecord), (Handle *) &gusiwakequeue)) 1421 return (false); 1422 1423 shellpushwakeuphook (&fwsGUSIWakeupHook); 1424 #endif 1425 1426 #endif 1427 1428 clearsockstack(); 1429 } 1430 1431 #ifdef MACVERSION 1432 #ifndef FRONTIER_GUSI_2 1433 sethostdata (data); 1434 #endif 1435 #endif 1436 1437 ++frontierWinSockCount; 1438 frontierWinSockLoaded = true; 1439 1440 return (true); 1441 } /*fwsNetEventLaunch*/ 1442 1443 1444 /* 1445 boolean fwsNetEventIsRunning (void) { 1446 1447 /* Indicate if we are between a fwsNetEventLaunch and a fwsNetEventQuit * / 1448 1449 return (frontierWinSockLoaded); 1450 } /*fwsNetEventIsRunning*/ 1451 1452 1453 #ifdef MACVERSION 1454 1455 boolean fwsNetEventQuit (void) { 1456 1457 /* 1458 5.0.2b10: this function is being reborn to close all listeners on the Mac 1459 */ 1460 1461 // for (i = 0; i < sockListenCount; i++) { 1462 // listenstream = sockListenList[i]; 1463 1464 while (sockListenCount > 0) 1465 fwsNetEventCloseListen (sockListenList [0]); 1466 1467 return (true); 1468 } /*fwsNetEventQuit*/ 1469 1470 #endif 1471 1472 1473 boolean fwsNetEventShutDown (void) { 1474 1475 /* 1476 shut down the NetEvents system 1477 This is for Frontier Internal use ONLY 1478 */ 1479 1480 frontierWinSockCount = 0; 1481 1482 TCPTRACKERCLOSE(); 1483 1484 if (frontierWinSockLoaded) { 1485 #ifdef WIN95VERSION 1486 WSACleanup(); 1487 #endif 1488 1489 return (true); 1490 } 1491 1492 return (false); 1493 } /*fwsNetEventShutDown*/ 1494 1495 1496 boolean fwsNetEventAddressDecode (unsigned long addr, bigstring IPaddr) { 1497 1498 /* Convert an address (4 byte) into a dotted IP address */ 1499 1500 char * sysstring; 1501 struct in_addr in; 1502 struct hostData hostdata; 1503 1504 if (!fwsNetEventLaunch (&hostdata)) 1505 return (false); 1506 1507 in.s_addr = htonl(addr); 1508 1509 sysstring = inet_ntoa (in); 1510 1511 setstringlength (IPaddr,0); 1512 1513 if (sysstring == NULL) { 1514 1515 langlongparamerror (cantdecodeaddress, addr); 1516 1517 return (false); 1518 } 1519 1520 copyctopstring (sysstring, IPaddr); 1521 1522 return (true); 1523 } /*fwsNetEventAddressDecode*/ 1524 1525 1526 boolean fwsNetEventAddressEncode (bigstring IPaddr, unsigned long * addr) { 1527 1528 /* Convert a dotted IP address into an address (4 byte) */ 1529 1530 unsigned long netaddr; 1531 char sysstring[256]; 1532 #ifdef MACVERSION 1533 #ifndef FRONTIER_GUSI_2 1534 struct in_addr foo; 1535 #endif 1536 #endif 1537 struct hostData hostdata; 1538 1539 if (!fwsNetEventLaunch (&hostdata)) 1540 return (false); 1541 1542 copyptocstring (IPaddr, sysstring); 1543 1544 #ifdef MACVERSION 1545 #ifdef FRONTIER_GUSI_2 1546 netaddr = inet_addr (sysstring); 1547 #else 1548 foo = inet_addr (sysstring); 1549 netaddr = foo.s_addr; 1550 #endif 1551 #endif 1552 1553 #ifdef WIN95VERSION 1554 netaddr = inet_addr (sysstring); 1555 #endif 1556 1557 if (netaddr == INADDR_NONE) { 1558 1559 langparamerror (cantencodeaddress, IPaddr); 1560 1561 return (false); 1562 } 1563 1564 *addr = ntohl (netaddr); 1565 1566 return (true); 1567 } /*fwsNetEventAddressEncode*/ 1568 1569 1570 boolean fwsNetEventAddressToName (unsigned long addr, bigstring domainName) { 1571 1572 /* 1573 Convert an address (4 byte) into a domain name 1574 1575 5.1.5 dmb: release thread globals! 1576 */ 1577 1578 struct hostent * h; 1579 unsigned long netaddr; 1580 struct hostData hostdata; 1581 long errcode; 1582 1583 1584 if (!fwsNetEventLaunch (&hostdata)) 1585 return (false); 1586 1587 TCPprintf (wsprintf(TCPmsg, "Entering fwsNetEventAddressToName at line %d. Address: %ld.\n", __LINE__, addr)); 1588 TCPWRITEMSG(); 1589 1590 releasethreadglobalsnopriority(); 1591 1592 netaddr = htonl(addr); 1593 1594 h = gethostbyaddr ((char *) &netaddr, 4, PF_INET); 1595 1596 errcode = WSAGetHostError (); 1597 1598 grabthreadglobalsnopriority(); 1599 1600 if (h == NULL) { 1601 neterror("convert address", errcode); 1602 return (false); 1603 } 1604 1605 copyctopstring (h->h_name, domainName); 1606 1607 TCPprintf (wsprintf(TCPmsg, "Leaving fwsNetEventAddressToName at line %d. Domain name: %s.\n", __LINE__, h->h_name)); 1608 TCPWRITEMSG(); 1609 1610 return (true); 1611 } /*fwsNetEventAddressToName*/ 1612 1613 1614 boolean fwsNetEventNameToAddress (bigstring domainName, unsigned long * addr) { 1615 1616 /* 1617 Convert a domain name into an address (4 byte) 1618 1619 5.1.5 dmb: release thread globals! 1620 */ 1621 1622 struct hostent * h; 1623 char sysstring[256]; 1624 struct hostData hostdata; 1625 long errcode; 1626 1627 if (!fwsNetEventLaunch (&hostdata)) 1628 return (false); 1629 1630 copyptocstring (domainName, sysstring); 1631 1632 TCPprintf (wsprintf(TCPmsg, "Entering fwsNetEventNameToAddress at line %d. Domain name: %s.\n", __LINE__, sysstring)); 1633 TCPWRITEMSG(); 1634 1635 releasethreadglobalsnopriority(); 1636 1637 h = gethostbyname (sysstring); 1638 1639 errcode = WSAGetHostError (); 1640 1641 grabthreadglobalsnopriority(); 1642 1643 if (h == NULL) { 1644 neterror("convert name", errcode); 1645 return (false); 1646 } 1647 1648 *addr = ntohl (*((long *)h->h_addr_list[0])); 1649 1650 TCPprintf (wsprintf(TCPmsg, "Leaving fwsNetEventNameToAddress at line %d. Address: %ld.\n", __LINE__, addr)); 1651 TCPWRITEMSG(); 1652 1653 return (true); 1654 } /*fwsNetEventNameToAddress*/ 1655 1656 1657 boolean fwsNetEventMyAddress (unsigned long * addr) { 1658 1659 /* Get the hosts address */ 1660 1661 struct hostData hostdata; 1662 1663 #ifdef MACVERSION 1664 1665 if (!fwsNetEventLaunch (&hostdata)) 1666 return (false); 1667 1668 sHostID = 0; //clear cached value 1669 1670 *addr = (unsigned long) gethostid (); 1671 1672 return (true); 1673 #else 1674 struct hostent * h; 1675 char sysstring[256]; 1676 long errcode; 1677 1678 1679 if (!fwsNetEventLaunch (&hostdata)) 1680 return (false); 1681 1682 if (gethostname (sysstring, 255) == SOCKET_ERROR) { 1683 neterror("get local address", WSAGetHostError ()); 1684 return (false); 1685 } 1686 1687 releasethreadglobalsnopriority (); 1688 1689 h = gethostbyname (sysstring); 1690 1691 errcode = WSAGetHostError (); 1692 1693 grabthreadglobalsnopriority (); 1694 1695 if (h == NULL) { 1696 neterror("get local address name", errcode); 1697 return (false); 1698 } 1699 1700 *addr = ntohl (*((long *)h->h_addr_list[0])); 1701 1702 return (true); 1703 #endif 1704 } /*fwsNetEventMyAddress*/ 1705 1706 1707 1708 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 1709 1710 static boolean fwsgetcallbackcodetree (bigstring bs, Handle *htree) { 1711 1712 Handle htext; 1713 boolean fl; 1714 unsigned long savelines; 1715 unsigned short savechars; 1716 hdltreenode hmodule = nil; 1717 1718 if (!newtexthandle (bs, &htext)) 1719 return (false); 1720 1721 savelines = ctscanlines; 1722 1723 savechars = ctscanchars; 1724 1725 fl = langcompiletext (htext, false, &hmodule); /*always disposes htext*/ 1726 1727 ctscanlines = savelines; 1728 1729 ctscanchars = savechars; 1730 1731 if (!fl) 1732 return (false); 1733 1734 fl = langpacktree ((**hmodule).param1, htree); /*make a copy of the sub-tree*/ 1735 1736 langdisposetree (hmodule); 1737 1738 return (fl); 1739 } /*fwsgetcallbackcodetree*/ 1740 1741 1742 static boolean fwsnewprocess (hdltreenode hcode, bigstring bsname, hdlprocessrecord *hprocess) { 1743 1744 register hdlprocessrecord hp; 1745 hdlerrorstack herrorstack; 1746 hdltablestack htablestack; 1747 tyerrorrecord item; 1748 1749 if (!newclearhandle (sizeof (typrocessrecord), (Handle *) hprocess)) 1750 return (false); 1751 1752 hp = *hprocess; /*copy into register*/ 1753 1754 if (!newclearhandle (sizeof (tyerrorstack), (Handle *) &herrorstack)) { 1755 1756 disposehandle ((Handle) hp); 1757 1758 return (false); 1759 } 1760 1761 if (!newclearhandle (sizeof (tytablestack), (Handle *) &htablestack)) { 1762 1763 disposehandle ((Handle) hp); 1764 1765 disposehandle ((Handle) herrorstack); 1766 1767 return (false); 1768 } 1769 1770 (**hp).hcode = hcode; 1771 1772 (**hp).floneshot = true; 1773 1774 (**hp).errormessagecallback = &langerrordialog; 1775 1776 (**hp).debugerrormessagecallback = (langerrormessagecallback) &truenoop; 1777 1778 (**hp).htablestack = htablestack; 1779 1780 (**hp).herrorstack = herrorstack; 1781 1782 (**hp).processstartedroutine = (langvoidcallback) &truenoop; 1783 1784 (**hp).processkilledroutine = (langvoidcallback) &truenoop; 1785 1786 item.errorcallback = nil; 1787 1788 item.errorline = 0; 1789 1790 item.errorchar = 0; 1791 1792 item.errorrefcon = 0; 1793 1794 #ifdef flnewfeatures 1795 item.profilebase = 0; 1796 #endif 1797 1798 (**herrorstack).stack [(**herrorstack).toperror++] = item; 1799 1800 copystring (bsname, (**hp).bsname); 1801 1802 return (true); 1803 } /*newprocess*/ 1804 1805 1806 static boolean fwsruncallback (long listenstream, long acceptstream, long refcon) { 1807 1808 hdltreenode hcallbackaddress; 1809 hdltreenode hfunctioncall; 1810 hdltreenode hcode; 1811 hdltreenode hparam1; 1812 hdltreenode hparam2; 1813 tyvaluerecord val; 1814 hdlprocessrecord hprocess; 1815 Handle h; 1816 1817 //build code tree 1818 1819 if (!copyhandle (sockstack[listenstream].hcallbacktree, &h)) 1820 return (false); 1821 1822 if (!langunpacktree (h, &hcallbackaddress)) 1823 return (false); 1824 1825 setlongvalue (acceptstream, &val); 1826 1827 if (!newconstnode (val, &hparam1)) { 1828 langdisposetree (hcallbackaddress); 1829 return (false); 1830 } 1831 1832 setlongvalue (refcon, &val); 1833 1834 if (!newconstnode (val, &hparam2)) { 1835 langdisposetree (hcallbackaddress); 1836 langdisposetree (hparam1); 1837 return (false); 1838 } 1839 1840 pushlastlink (hparam2, hparam1); 1841 1842 if (!pushbinaryoperation (functionop, hcallbackaddress, hparam1, &hfunctioncall)) 1843 return (false); 1844 1845 if (!pushbinaryoperation (moduleop, hfunctioncall, nil, &hcode)) 1846 return (false); 1847 1848 //create new process 1849 1850 if (!fwsnewprocess (hcode, sockstack[listenstream].callback, &hprocess)) { 1851 langdisposetree (hcode); 1852 return (false); 1853 } 1854 1855 //add new process 1856 1857 return (addprocess (hprocess)); 1858 }/*fwsruncallback*/ 1859 1860 #endif 1861 1862 1863 static void parsecallbackstring (long stream, long p1, long p2, bigstring bs) { 1864 1865 /* 1866 5.1.5 dmb: common code for all callbacks 1867 */ 1868 1869 copystring (sockstack[stream].callback, bs); 1870 pushchar ('(', bs); 1871 pushlong (p1, bs); 1872 pushchar (',', bs); 1873 pushlong (p2, bs); 1874 pushchar (')', bs); 1875 1876 nullterminate(bs); //for debug display 1877 } /*parsecallbackstring*/ 1878 1879 1880 static boolean fwsrunstring (bigstring bs) { 1881 1882 /* 1883 5.1.5 dmb: make sure we have thread globals for the compiler and processlist, 1884 then run the string as a new process. 1885 1886 note: we might special case each call and build a code tree by hand, so we 1887 don't need globals. I'm not sure if adding a new process really needs globals. 1888 */ 1889 1890 boolean fl; 1891 1892 grabthreadglobalsnopriority (); 1893 1894 fl = processrunstringnoerrorclear (bs); 1895 1896 releasethreadglobalsnopriority (); 1897 1898 return (fl); 1899 } /*fwsrunstring*/ 1900 1901 1902 static boolean restartAccepter (SOCKET s, short listenstream) { 1903 boolean fl = true; 1904 1905 #ifdef WIN95VERSION 1906 long err; 1907 #ifndef ACCEPT_CONN_WITHOUT_GLOBALS 1908 bigstring bs; 1909 #endif 1910 unsigned long timewait; 1911 1912 TCPTRACKERIN ("restartAccepter", __LINE__, listenstream); 1913 1914 if (!sockstack[listenstream].flNotification 1915 && sockstack[listenstream].currentListenDepth < sockstack[listenstream].maxdepth) { 1916 1917 /*Turn it on again!*/ 1918 1919 if (WSAAsyncSelect (s, shellframewindow, wm_processAccept, FD_ACCEPT) != SOCKET_ERROR) 1920 { 1921 sockstack[listenstream].flNotification = true; 1922 fl = true; 1923 goto exit; 1924 } 1925 1926 /* Our interest in this has failed */ 1927 1928 err = WSAGetLastError(); 1929 1930 timewait = gettickcount() + (60L * 15L); /*max of 15 seconds*/ 1931 1932 while (timewait > gettickcount()) { 1933 if (err == WSAEINPROGRESS) { 1934 /* let's see if we can restart this ourselves */ 1935 TCPprintf (wsprintf(TCPmsg, "In restartAccepter at line %d. Attempting restart on listenstream: %d.\n", __LINE__, listenstream)); 1936 TCPWRITEMSG(); 1937 1938 //threadyield (true); 1939 1940 Sleep (100L); //100 milliseconds -- make sure we don't control the thread globals! 1941 1942 if (WSAAsyncSelect (s, shellframewindow, wm_processAccept, FD_ACCEPT) != SOCKET_ERROR) 1943 { 1944 sockstack[listenstream].flNotification = true; 1945 TCPprintf (wsprintf(TCPmsg, "In restartAccepter at line %d. Got listen restarted on listenstream: %d.\n", __LINE__, listenstream)); 1946 TCPWRITEMSG(); 1947 fl = true; 1948 goto exit; 1949 } 1950 1951 err = WSAGetLastError(); 1952 } 1953 else 1954 break; /*any other error we get out*/ 1955 } 1956 1957 sockstack[listenstream].typeID = SOCKTYPE_LISTENSTOPPED; 1958 #ifndef ACCEPT_IN_SEPARATE_THREAD 1959 sockstack[listenstream].hevent = nil; 1960 #endif 1961 1962 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 1963 TCPERRORprintf (wsprintf(TCPmsg, "In restartAccepter at line %d. Error setting future accepts %s (%ld, %ld).\n", __LINE__, stringbaseaddress (sockstack[listenstream].callback), err * -1L, listenstream * -1L)); 1964 TCPWRITEMSG(); 1965 1966 fl = fwsruncallback (listenstream, err * -1L, listenstream * -1L); 1967 #else 1968 parsecallbackstring (listenstream, err * -1L, listenstream * -1L, bs); 1969 1970 TCPERRORprintf (wsprintf(TCPmsg, "In restartAccepter at line %d. Error setting future accepts %s.\n", __LINE__, stringbaseaddress(bs))); 1971 TCPERRORWRITEMSG(); 1972 1973 fl = fwsrunstring (bs); 1974 #endif 1975 } 1976 1977 exit: 1978 1979 TCPTRACKEROUT ("restartAccepter", __LINE__, listenstream); 1980 1981 #endif 1982 return (fl); 1983 } /*restartAccepter*/ 1984 1985 1986 static boolean checkAccepter (unsigned long stream) { 1987 1988 if (sockstack[stream].listenReference != 0) { 1989 1990 long listenstream = sockstack[stream].listenReference; 1991 1992 --sockstack[listenstream].currentListenDepth; 1993 1994 #ifdef WIN95VERSION 1995 #ifndef ACCEPT_IN_SEPARATE_THREAD 1996 { 1997 boolean fl; 1998 1999 releasethreadglobalsnopriority (); 2000 2001 fl = restartAccepter (sockstack[listenstream].sockID, listenstream); 2002 2003 grabthreadglobalsnopriority (); 2004 2005 return (fl); 2006 } 2007 #endif 2008 #endif 2009 } 2010 2011 return (true); 2012 } /*checkAccepter*/ 2013 2014 2015 #ifdef ACCEPT_IN_SEPARATE_THREAD 2016 2017 static boolean fwsacceptsocket (long listenstream) { 2018 2019 /* 2020 Process an accept pending message on a socket 2021 */ 2022 2023 int sasize; 2024 struct sockaddr_in sa; 2025 SOCKET acceptsock; 2026 long err; 2027 boolean fl = false; 2028 long newstream; 2029 long dummy = 0; /*need a pointer to nil for ioctlsocket call*/ 2030 2031 TCPTRACKERIN ("fwsacceptsocket", __LINE__, listenstream); 2032 2033 /*Accept connection*/ 2034 2035 sasize = sizeof(sa); 2036 2037 acceptsock = accept (sockstack[listenstream].sockID, (struct sockaddr *)&sa, &sasize); 2038 2039 if (acceptsock != INVALID_SOCKET) { 2040 2041 #ifdef PIKE 2042 if (incrementconnectioncounter ()) { 2043 #endif 2044 2045 /*Increment listen depth*/ 2046 2047 ++sockstack[listenstream].currentListenDepth; 2048 2049 /*get socket record for accepted socket*/ 2050 2051 if (!addsockrecord (&newstream)) { 2052 2053 struct linger l; 2054 2055 l.l_onoff = 1; 2056 l.l_linger = 0; 2057 2058 TCPERRORprintf (wsprintf(TCPmsg, "In fwsacceptsocket at line %d. Error addding new socket record %s (%ld, %ld).\n", __LINE__, stringbaseaddress (sockstack[listenstream].callback), WSAEMFILE * -1L, sockstack[listenstream].refcon)); 2059 TCPERRORWRITEMSG(); 2060 2061 setsockopt (acceptsock, SOL_SOCKET, SO_LINGER, (char *) &l, sizeof(l)); /*abort*/ 2062 2063 fl = closesocket (acceptsock); 2064 2065 #ifdef PIKE 2066 decrementconnectioncounter (); 2067 #endif 2068 2069 goto exit; 2070 } 2071 2072 /*Add Socket to list*/ 2073 sockstack[newstream].sockID = acceptsock; 2074 sockstack[newstream].typeID = SOCKTYPE_OPEN; 2075 sockstack[newstream].listenReference = listenstream; 2076 sockstack[newstream].refcon = 0; 2077 2078 /*Pass "stream" and "refcon" to callback*/ 2079 2080 TCPprintf (wsprintf(TCPmsg, "In fwsacceptsocket at line %d. Accepted new socket %ld: %s (%ld, %ld).\n", __LINE__, acceptsock, stringbaseaddress (sockstack[listenstream].callback), newstream, sockstack[listenstream].refcon)); 2081 TCPWRITEMSG(); 2082 2083 fl = fwsruncallback (listenstream, newstream, sockstack[listenstream].refcon); 2084 2085 #ifdef PIKE 2086 } 2087 else { 2088 2089 struct linger l; 2090 2091 l.l_onoff = 1; 2092 l.l_linger = 0; 2093 2094 TCPERRORprintf (wsprintf(TCPmsg, "In fwsacceptsocket at line %d. Exceeded number of maximum connections: %ld of %ld.\n", __LINE__, ctconnections, maxconnections)); 2095 TCPERRORWRITEMSG(); 2096 2097 setsockopt (acceptsock, SOL_SOCKET, SO_LINGER, (char *) &l, sizeof(l)); 2098 2099 fl = closesocket (acceptsock); 2100 } 2101 #endif 2102 2103 } 2104 else 2105 { 2106 /*if an error - pass this on to callback*/ 2107 err = WSAGetLastError(); 2108 2109 TCPERRORprintf (wsprintf(TCPmsg, "In fwsacceptsocket at line %d. Error processing accept message %s (%ld, %ld).\n", __LINE__, stringbaseaddress (sockstack[listenstream].callback), err * -1L, sockstack[listenstream].refcon)); 2110 TCPWRITEMSG(); 2111 2112 fl = fwsruncallback (listenstream, err * -1L, sockstack[listenstream].refcon); 2113 2114 } 2115 2116 exit: 2117 2118 TCPprintf (wsprintf(TCPmsg, "Exiting fwsacceptsocket at line %d. Return value is %s.\n", __LINE__, fl?"True":"False")); 2119 TCPWRITEMSG(); 2120 2121 return (fl); 2122 } /*fwsacceptsocket*/ 2123 2124 2125 static void *fwsacceptingthreadmain (long *param) { 2126 2127 /* 2128 6.2a12 AR: we sit in a loop waiting for new connections. 2129 2130 7.1b29 PBS: fix CPU usage 100% bug on Win98/ME by yielding in this loop. 2131 2132 9.1b3 AR: Increased select timeout from 10 microseconds to 1 second. 2133 When select times out, it returns zero and all we do is check whether 2134 we need to break out of the while loop, so a higher timeout value is 2135 not a problem. This also makes the 7.1b29 bug fix redundant. 2136 2137 Further, we only need to check the current listen depth if we just 2138 accepted another connection. 2139 2140 Also, it's good practice to initialize the timeval struct through 2141 every iteration of the loop. 2142 */ 2143 2144 long listenstream = (long) param; 2145 register sockRecord* sockrecptr = &sockstack[listenstream]; 2146 register SOCKET sock = sockrecptr->sockID; 2147 Handle hcallback = sockrecptr->hcallbacktree; /*keep a copy in our stack so we can safely dispose it*/ 2148 long maxdepth = sockrecptr->maxdepth; 2149 fd_set readset; 2150 struct timeval tv; 2151 int res; 2152 2153 TCPTRACKERIN ("fwsacceptingthreadmain", __LINE__, listenstream); 2154 2155 attachtomainthread (sockrecptr->idthread); /*6.2b7 AR*/ 2156 2157 while (sockrecptr->typeID == SOCKTYPE_LISTENING) { 2158 2159 FD_ZERO (&readset); 2160 2161 FD_SET (sock, &readset); 2162 2163 tv.tv_sec = 1L; /* 1 second */ 2164 tv.tv_usec = 0L; /* 0 micro-seconds */ 2165 2166 res = select (sock+1, &readset, NULL, NULL, &tv); 2167 2168 TCPprintf (wsprintf(TCPmsg, "In fwsacceptingthreadmain at line %d. Select returned %ld.\n", __LINE__, (long) res)); 2169 TCPWRITEMSG(); 2170 2171 if (sockrecptr->typeID != SOCKTYPE_LISTENING || flshellclosingall) { 2172 break; 2173 } 2174 2175 if (res == 1) { 2176 2177 (void) fwsacceptsocket (listenstream); 2178 2179 while (sockrecptr->currentListenDepth >= maxdepth) { 2180 usleep (10L); /* sleep for 10 milli-seconds */ 2181 } 2182 } 2183 2184 /* 2185 #ifdef PIKE 2186 usleep (10L); /+7.1b29 PBS: fix CPU usage 100% bug on Win98/ME by yielding in this loop.+/ 2187 #endif 2188 */ 2189 }/*while*/ 2190 2191 disposehandle (hcallback); 2192 2193 if (sockrecptr->typeID == SOCKTYPE_LISTENSTOPPED) { 2194 /*we have been asked by fwsNetEventCloseListen to take responsibility of cleaning up*/ 2195 sockrecptr->sockID = INVALID_SOCKET; 2196 sockrecptr->typeID = SOCKTYPE_CLOSED; 2197 } 2198 2199 TCPTRACKEROUT ("fwsacceptingthreadmain", __LINE__, listenstream); 2200 2201 return (nil); 2202 }/*fwsacceptingthreadmain*/ 2203 2204 2205 static boolean fwslaunchacceptingthread (long stream) { 2206 2207 #ifdef WIN95VERSION 2208 2209 HANDLE hthread; 2210 2211 /*create listening thread*/ 2212 2213 hthread = CreateThread (nil, nil, (LPTHREAD_START_ROUTINE) &fwsacceptingthreadmain, (LPVOID) stream, CREATE_SUSPENDED, &sockstack[stream].idthread); 2214 2215 if (hthread == NULL) { 2216 2217 neterror("create listen thread", GetLastError ()); 2218 2219 return (false); 2220 } 2221 2222 ResumeThread (hthread); /*let the new thread fly*/ 2223 2224 #else 2225 2226 pthread_t idthread; 2227 pthread_attr_t attr; 2228 2229 pthread_attr_init (&attr); 2230 2231 pthread_create ((pthread_t *) &sockstack[stream].idthread, &attr, fwsacceptingthreadmain, (void *)stream); 2232 2233 pthread_attr_destroy (&attr); 2234 2235 #endif 2236 2237 return (true); 2238 }/*fwslaunchacceptingthread*/ 2239 2240 #endif 2241 2242 void fwsNetEventShutdownDependentListeners (long hdatabase) { 2243 2244 #ifdef ACCEPT_IN_SEPARATE_THREAD 2245 long i; 2246 2247 for (i = 1; i < FRONTIER_MAX_STREAM; i++) 2248 if (sockstack[i].typeID == SOCKTYPE_LISTENING) 2249 if (sockstack[i].hdatabase == (hdldatabaserecord) hdatabase) 2250 sockstack[i].typeID = SOCKTYPE_LISTENSTOPPED; /*make sure the separate thread terminates before the database goes away*/ 2251 #endif 2252 }/*fwsNetEventShutdownDependentListeners*/ 2253 2254 2255 /* Abort a stream and delete associated data */ 2256 boolean fwsNetEventAbortStream (unsigned long stream) { 2257 2258 /* 2259 5.1.5 dmb: release thread globals while we close; don't reset 2260 socket typeID until close is complete 2261 2262 6.2a9 AR: Don't reset socket typeID and sockID until close is complete 2263 so addsockrecord doesn't get to hand it out before we're done. 2264 This bug probably sneaked back in during the 6.1 development cycle. 2265 */ 2266 2267 SOCKET sock; 2268 int res, errcode; 2269 struct linger l; 2270 // struct hostData hostdata; 2271 2272 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 2273 return (false); 2274 2275 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 2276 intneterror (INTNETERROR_INVALIDSTREAM); 2277 return (false); 2278 } 2279 2280 TCPTRACKERIN ("fwsNetEventAbortStream", __LINE__, stream); 2281 2282 sock = sockstack[stream].sockID; 2283 2284 l.l_onoff = 1; 2285 l.l_linger = 0; 2286 2287 releasethreadglobalsnopriority(); 2288 2289 setsockopt (sock, SOL_SOCKET, SO_LINGER, (char *) &l, sizeof(l)); 2290 2291 res = closesocket(sock); 2292 2293 errcode = WSAGetLastError (); 2294 2295 grabthreadglobalsnopriority(); 2296 2297 #ifdef PIKE 2298 decrementconnectioncounter(); 2299 #endif 2300 2301 checkAccepter (stream); 2302 2303 sockstack[stream].sockID = INVALID_SOCKET; 2304 sockstack[stream].typeID = SOCKTYPE_CLOSED; 2305 2306 if (res == SOCKET_ERROR) { 2307 neterror("abort stream", errcode); 2308 return (false); 2309 } 2310 2311 TCPTRACKEROUT ("fwsNetEventAbortStream", __LINE__, stream); 2312 2313 return (true); 2314 } /*fwsNetEventAbortStream*/ 2315 2316 2317 boolean fwsNetEventCloseStream (unsigned long stream) { 2318 2319 /* 2320 Close a stream and delete associated data 2321 2322 do we want or should the user control the SO_LINGER flag for a 2323 graceful verses hard socket closure. for now it is the user. 2324 2325 6.2a9 AR: Don't reset socket typeID and sockID until close is complete 2326 so addsockrecord doesn't get to hand it out before we're done. 2327 This bug probably sneaked back in during the 6.1 development cycle. 2328 */ 2329 2330 SOCKET sock; 2331 long err; 2332 2333 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 2334 return (false); 2335 2336 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 2337 intneterror (INTNETERROR_INVALIDSTREAM); 2338 return (false); 2339 } 2340 2341 TCPTRACKERIN ("fwsNetEventCloseStream", __LINE__, stream); 2342 2343 sock = sockstack[stream].sockID; 2344 2345 #ifdef PIKE 2346 decrementconnectioncounter(); 2347 #endif 2348 2349 releasethreadglobalsnopriority(); 2350 2351 if (shutdown (sock, SD_SEND) == SOCKET_ERROR) { 2352 2353 err = WSAGetLastError (); 2354 2355 goto error; 2356 } 2357 2358 if (closesocket(sock) == SOCKET_ERROR) { 2359 2360 err = WSAGetLastError (); 2361 2362 goto error; 2363 } 2364 2365 grabthreadglobalsnopriority(); 2366 2367 checkAccepter (stream); 2368 2369 sockstack[stream].sockID = INVALID_SOCKET; 2370 sockstack[stream].typeID = SOCKTYPE_CLOSED; 2371 2372 TCPprintf (wsprintf(TCPmsg, "Leaving closeStream at line %d. Thread duration: %ld ticks.\n", __LINE__, gettickcount()-(**getcurrentthreadglobals()).timestarted)); 2373 TCPWRITEMSG(); 2374 2375 return (true); 2376 2377 error: 2378 2379 grabthreadglobalsnopriority (); 2380 2381 sockstack[stream].sockID = INVALID_SOCKET; 2382 sockstack[stream].typeID = SOCKTYPE_CLOSED; 2383 2384 neterror ("close stream", err); 2385 2386 return (false); 2387 } /*fwsNetEventCloseStream*/ 2388 2389 2390 boolean fwsNetEventCloseListen (unsigned long stream) { 2391 2392 /* 2393 Close a listen and delete associated data 2394 2395 do we want or should the user control the SO_LINGER flag for a 2396 graceful verses hard socket closure. for now it is the user. 2397 2398 5.1.5b7 dmb: set linger timeout to zero for Mac (now implemented in GUSI) 2399 2400 6.2a9 AR: Don't reset socket typeID and sockID until close is complete 2401 so addsockrecord doesn't get to hand it out before we're done. 2402 */ 2403 2404 SOCKET sock; 2405 int res, errcode; 2406 #ifdef MACVERSION 2407 int i,j; 2408 struct linger l; 2409 #endif 2410 // struct hostData hostdata; 2411 2412 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 2413 return (false); 2414 2415 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 2416 intneterror (INTNETERROR_INVALIDSTREAM); 2417 return (false); 2418 } 2419 2420 sock = sockstack[stream].sockID; 2421 2422 /* No more messages */ 2423 #ifndef ACCEPT_IN_SEPARATE_THREAD 2424 sockstack[stream].maxdepth = -100; /*never restart select call*/ 2425 #endif 2426 2427 TCPTRACKERIN ("fwsNetEventCloseListen", __LINE__, stream); 2428 2429 releasethreadglobalsnopriority(); 2430 2431 #ifdef WIN95VERSION 2432 #ifndef ACCEPT_IN_SEPARATE_THREAD 2433 WSAAsyncSelect (sock, shellframewindow, 0, 0); 2434 #endif 2435 #endif 2436 2437 #ifdef MACVERSION 2438 for (i = 0; i < sockListenCount; i++) { 2439 if (sockListenList [i] == stream) { 2440 if (i == (sockListenCount - 1)) { 2441 //easy case - end of list to remove 2442 --sockListenCount; 2443 } 2444 else { 2445 //Move remaining down in the list 2446 for (j = i; j < sockListenCount - 1; j++) 2447 sockListenList[j] = sockListenList[j+1]; 2448 2449 --sockListenCount; 2450 } 2451 2452 break; //It can only be in the list once. 2453 } 2454 } 2455 2456 l.l_onoff = 1; 2457 l.l_linger = 0; 2458 2459 setsockopt (sock, SOL_SOCKET, SO_LINGER, (char *) &l, sizeof(l)); 2460 2461 #endif 2462 2463 res = closesocket(sock); 2464 2465 errcode = WSAGetLastError (); 2466 2467 grabthreadglobalsnopriority(); 2468 2469 #ifdef ACCEPT_IN_SEPARATE_THREAD 2470 sockstack[stream].typeID = SOCKTYPE_LISTENSTOPPED; 2471 #else 2472 sockstack[stream].sockID = INVALID_SOCKET; 2473 sockstack[stream].typeID = SOCKTYPE_CLOSED; 2474 #endif 2475 2476 if (res == SOCKET_ERROR) { 2477 neterror("close listen", errcode); 2478 return (false); 2479 } 2480 2481 TCPTRACKEROUT ("fwsNetEventCloseListen", __LINE__, stream); 2482 2483 return (true); 2484 } /*fwsNetEventCloseListen*/ 2485 2486 2487 static short is_ipaddress (char *name) { 2488 2489 short ctfields = 1; 2490 short fieldlen = 0; 2491 char *p = name; 2492 2493 for (p = name; *p; ++p) { 2494 2495 if (*p == '.') { 2496 2497 if (fieldlen == 0) //leading dot, or consequtive dots 2498 return (false); 2499 2500 ++ctfields; 2501 2502 fieldlen = 0; 2503 } 2504 else { 2505 if (!isdigit (*p)) 2506 return (false); 2507 2508 if (++fieldlen > 3) // four consecutive digits 2509 return (false); 2510 } 2511 } 2512 2513 return (ctfields == 4); 2514 } /*is_ipaddress*/ 2515 2516 2517 static boolean fwsOpenStream (struct sockaddr_in *sa, unsigned long * stream) { 2518 2519 /* 2520 5.0.2b4 dmb: the common code between openAddrStream and openNameStream, so we 2521 don't have to convert one to the other to open a stream of either type 2522 2523 6.1d13 AR: Release thread globals. 2524 2525 6.2b1 AR: For Pike, decrement connection counter if connection attempt fails. 2526 */ 2527 2528 SOCKET sock; 2529 int errcode; 2530 long streamref; 2531 2532 if (!addsockrecord (&streamref)) { 2533 neterror ("open stream", WSAEMFILE); /*Too many open sockets*/ 2534 return (false); 2535 } 2536 2537 #ifdef PIKE 2538 if (!incrementconnectioncounter ()) { 2539 2540 plainneterror ("\x54" "Can't open stream because no more than five TCP connections may be open at any time."); 2541 2542 return (false); 2543 } 2544 #endif 2545 2546 releasethreadglobalsnopriority (); 2547 2548 sock = socket(PF_INET, SOCK_STREAM, 0); 2549 2550 if (sock == INVALID_SOCKET) { 2551 errcode = WSAGetLastError (); 2552 goto exit; 2553 } 2554 2555 if (connect (sock, (struct sockaddr *) sa, sizeof(*sa)) == SOCKET_ERROR) { 2556 errcode = WSAGetLastError (); 2557 closesocket (sock); 2558 goto exit; 2559 } 2560 2561 sockstack[streamref].typeID = SOCKTYPE_OPEN; 2562 2563 sockstack[streamref].sockID = sock; 2564 2565 *stream = streamref; 2566 2567 grabthreadglobalsnopriority (); 2568 2569 return (true); 2570 2571 exit: 2572 2573 sockstack[streamref].typeID = SOCKTYPE_INVALID; 2574 2575 grabthreadglobalsnopriority (); 2576 2577 neterror ("open stream", errcode); 2578 2579 #ifdef PIKE 2580 decrementconnectioncounter (); 2581 #endif 2582 2583 return (false); 2584 } /*fwsOpenStream*/ 2585 2586 2587 boolean fwsNetEventOpenAddrStream (unsigned long addr, unsigned long port, unsigned long * stream) { 2588 2589 /* 2590 Open a stream and create associated data 2591 2592 5.1.6 dmb: don't use a hostent; construct the sockaddr from the address, avoiding DNS 2593 */ 2594 2595 unsigned long netaddr; 2596 struct hostData hostdata; 2597 struct sockaddr_in sa; 2598 2599 if (!fwsNetEventLaunch (&hostdata)) 2600 return (false); 2601 2602 TCPprintf (wsprintf(TCPmsg, "Entering fwsNetEventOpenAddrStream at line %d. Address: %ld.\n", __LINE__, addr)); 2603 TCPWRITEMSG(); 2604 2605 netaddr = htonl(addr); 2606 2607 #ifdef MACVERSION 2608 sHostID = 0; //clear cached value 2609 #endif 2610 2611 memset (&sa, 0, sizeof(sa)); 2612 2613 memcpy (&(sa.sin_addr), &netaddr, sizeof (netaddr)); 2614 2615 sa.sin_family = AF_INET; 2616 2617 sa.sin_port = htons ((unsigned short) port); 2618 2619 return (fwsOpenStream (&sa, stream)); 2620 } /*fwsNetEventOpenAddrStream*/ 2621 2622 2623 boolean fwsNetEventOpenNameStream (bigstring name, unsigned long port, unsigned long * stream) { 2624 2625 /* 2626 Open a stream and create associated data 2627 2628 5.1.6 dmb: if passed an IP address, encode address and use that instead (avoid dns) 2629 */ 2630 2631 char sysstring[256]; 2632 struct hostent * hp; 2633 struct hostData hostdata; 2634 unsigned long addr; 2635 struct sockaddr_in sa; 2636 long errcode; 2637 2638 if (!fwsNetEventLaunch (&hostdata)) 2639 return (false); 2640 2641 copyptocstring (name, sysstring); 2642 2643 #ifdef MACVERSION 2644 sHostID = 0; //clear cached value 2645 #endif 2646 2647 TCPprintf (wsprintf(TCPmsg, "Entering fwsNetEventOpenNameStream at line %d. Domain name: %s.\n", __LINE__, sysstring)); 2648 TCPWRITEMSG(); 2649 2650 if (is_ipaddress (sysstring)) { 2651 2652 if (!fwsNetEventAddressEncode (name, &addr)) 2653 return (false); 2654 2655 return (fwsNetEventOpenAddrStream (addr, port, stream)); 2656 } 2657 2658 releasethreadglobalsnopriority (); 2659 2660 hp = gethostbyname (sysstring); 2661 2662 errcode = WSAGetHostError (); 2663 2664 grabthreadglobalsnopriority (); 2665 2666 if (hp == NULL) { 2667 neterror("open named stream", errcode); 2668 return (false); 2669 } 2670 2671 memset (&sa, 0, sizeof(sa)); 2672 2673 memcpy (&(sa.sin_addr), hp->h_addr_list[0], hp->h_length); 2674 2675 sa.sin_family = hp->h_addrtype; 2676 2677 sa.sin_port = htons ((unsigned short) port); 2678 2679 return (fwsOpenStream (&sa, stream)); 2680 } /*fwsNetEventOpenNameStream*/ 2681 2682 2683 boolean fwsNetEventReadStream (unsigned long stream, unsigned long * bytesToRead, char * buffer) { 2684 2685 /* Read from a stream */ 2686 2687 SOCKET sock; 2688 int res, errcode; 2689 // struct hostData hostdata; 2690 2691 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 2692 return (false); 2693 2694 TCPTRACKERIN ("fwsNetEventReadStream", __LINE__, stream); 2695 2696 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 2697 intneterror (INTNETERROR_INVALIDSTREAM); 2698 return (false); 2699 } 2700 2701 sock = sockstack[stream].sockID; 2702 2703 releasethreadglobalsnopriority(); 2704 2705 res = recv (sock, buffer, *bytesToRead, 0); 2706 2707 errcode = WSAGetLastError (); 2708 2709 grabthreadglobalsnopriority(); 2710 2711 if (res == SOCKET_ERROR) { 2712 neterror("read stream", errcode); 2713 return (false); 2714 } 2715 2716 TCPprintf (if (*bytesToRead > 0) {bigstring bs; texttostring(buffer, *bytesToRead, bs); firstword (bs, '\r', bs); convertpstring (bs); wsprintf (TCPmsg, "In ReadStream, read: %s\n", bs); TCPWRITEMSG ();}) 2717 TCPprintf (wsprintf(TCPmsg, "Exiting fwsNetEventReadStream at line %d. Bytes requested = %ld, read = %ld.\n", __LINE__, *bytesToRead, (unsigned long) res)); 2718 TCPWRITEMSG (); 2719 2720 // if (res == (int) bytesToRead) 2721 // return (true); 2722 // 2723 // return (false); 2724 2725 *bytesToRead = res; 2726 2727 return (true); 2728 } /*fwsNetEventReadStream*/ 2729 2730 2731 boolean fwsNetEventWriteStream (unsigned long stream, unsigned long bytesToWrite, char * buffer) { 2732 2733 /* 2734 Write to a Stream 2735 2736 5.0.2b3 dmb: if we write fewer bytes than requested, we need to retry, generate error 2737 */ 2738 2739 SOCKET sock; 2740 int res, errcode; 2741 // int len = sizeof (res); 2742 2743 // struct hostData hostdata; 2744 2745 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 2746 return (false); 2747 2748 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 2749 intneterror (INTNETERROR_INVALIDSTREAM); 2750 return (false); 2751 } 2752 2753 TCPTRACKERIN ("fwsNetEventWriteStream", __LINE__, stream); 2754 2755 sock = sockstack[stream].sockID; 2756 2757 //if (getsockopt (sock, SOL_SOCKET, SO_SNDBUF, &res, &len) != 0) 2758 // ; 2759 2760 releasethreadglobalsnopriority(); 2761 2762 res = send (sock, buffer, bytesToWrite, 0); 2763 2764 errcode = WSAGetLastError (); 2765 2766 grabthreadglobalsnopriority(); 2767 2768 if (res == SOCKET_ERROR) { 2769 neterror("write stream", errcode); 2770 return (false); 2771 } 2772 2773 if (res < (int) bytesToWrite) { 2774 neterror("write stream", WSAEWOULDBLOCK); 2775 return (false); 2776 } 2777 2778 TCPprintf (wsprintf(TCPmsg, "Exiting fwsNetEventWriteStream at line %d. Bytes requested = %ld, written = %ld.\n", __LINE__, bytesToWrite, (unsigned long) res)); 2779 TCPWRITEMSG (); 2780 2781 return (true); 2782 } /*fwsNetEventWriteStream*/ 2783 2784 2785 #ifdef MACVERSION 2786 /* 2787 static unsigned long selects = 0; 2788 static unsigned long accepts = 0; 2789 static unsigned long selecting = 0; 2790 static unsigned long accepting = 0; 2791 static unsigned long avgselect = 0; 2792 static unsigned long avgaccept = 0; 2793 */ 2794 static unsigned long maxlistendepth = 0; 2795 2796 #ifdef FRONTIER_GUSI_2 2797 2798 boolean fwsNetEventCheckAndAcceptSocket () { return (true); } 2799 2800 #else 2801 2802 boolean fwsNetEventCheckAndAcceptSocket () { 2803 int i; 2804 int res; 2805 SOCKET sock; 2806 fd_set readset; 2807 struct timeval tv; 2808 int sasize; 2809 struct sockaddr_in sa; 2810 SOCKET acceptsock; 2811 long listenstream, newstream; 2812 long err; 2813 boolean fl = true; 2814 #ifndef ACCEPT_CONN_WITHOUT_GLOBALS 2815 bigstring bs; 2816 #endif 2817 2818 if (!frontierWinSockLoaded) 2819 return (false); 2820 2821 #ifndef FRONTIER_GUSI_2 2822 wakecompletedthreads (); 2823 #endif 2824 2825 // unsigned long ticks; 2826 2827 //We could set all the sockets at one time, but I think that is harder to manage. 2828 //Let's just loop through each listen socket and see if it is ready. 2829 2830 for (i = 0; i < sockListenCount; i++) { 2831 listenstream = sockListenList[i]; 2832 2833 if (sockstack[listenstream].currentListenDepth <= (sockstack[listenstream].maxdepth)) { 2834 sock = sockstack[listenstream].sockID; 2835 2836 tv.tv_sec = 0; 2837 tv.tv_usec = 0; 2838 2839 FD_ZERO (&readset); 2840 2841 FD_SET(sock, &readset); 2842 2843 /* now check for data */ 2844 2845 // ticks = gettickcount (); 2846 2847 res = select (sock+1, &readset, NULL, NULL, &tv); 2848 2849 // selecting += gettickcount () - ticks; 2850 // avgselect = selecting / ++selects; 2851 2852 if (res == 1) { /* we have a live one...*/ 2853 2854 /*Grab socket record for child socket*/ 2855 2856 if (!addsockrecord (&newstream)) { 2857 /* if an error - pass this on to callback */ 2858 long err = WSAEMFILE; 2859 2860 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 2861 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventCheckAndAcceptSocket at line %d. Error %ld addding new socket record %s (%ld, %ld).\n", __LINE__, stringbaseaddress (sockstack[listenstream].callback), err * -1L, sockstack[listenstream].refcon)); 2862 TCPWRITEMSG(); 2863 2864 fl = fwsruncallback (listenstream, err * -1L, sockstack[listenstream].refcon); 2865 #else 2866 parsecallbackstring (listenstream, err * -1L, sockstack[listenstream].refcon, bs);; 2867 2868 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventCheckAndAcceptSocket at line %d. Error addding new socket record %s.\n", __LINE__, stringbaseaddress(bs))); 2869 TCPERRORWRITEMSG(); 2870 2871 fl = fwsrunstring (bs); 2872 #endif 2873 2874 continue; 2875 } 2876 2877 /*Accept connection*/ 2878 2879 sasize = sizeof(sa); 2880 2881 // ticks = gettickcount (); 2882 2883 acceptsock = accept (sock, (struct sockaddr *)&sa, &sasize); 2884 2885 // accepting += gettickcount () - ticks; 2886 // avgaccept = accepting / ++accepts; 2887 2888 if (acceptsock != INVALID_SOCKET) { 2889 #ifdef PIKE 2890 if (incrementconnectioncounter ()) { 2891 #endif 2892 /*sucessful connection - assign this */ 2893 ++sockstack[listenstream].currentListenDepth; 2894 2895 maxlistendepth = max (maxlistendepth, sockstack[listenstream].currentListenDepth); 2896 2897 /*Add Socket to list*/ 2898 sockstack[newstream].refcon = 0; 2899 sockstack[newstream].sockID = acceptsock; 2900 sockstack[newstream].typeID = SOCKTYPE_OPEN; 2901 sockstack[newstream].listenReference = listenstream; 2902 2903 /*Pass "stream" and "refcon" to callback*/ 2904 2905 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 2906 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventCheckAndAcceptSocket at line %d. Accepted new socket %ld, callback %s (%ld, %ld).\n", __LINE__, acceptsock, stringbaseaddress (sockstack[listenstream].callback), newstream, sockstack[listenstream].refcon)); 2907 TCPWRITEMSG(); 2908 2909 fl = fwsruncallback (listenstream, newstream, sockstack[listenstream].refcon); 2910 #else 2911 parsecallbackstring (listenstream, newstream, sockstack[listenstream].refcon, bs); 2912 2913 TCPprintf (sprintf(TCPmsg, "In fwsNetEventCheckAndAcceptSocket at line %d. Accepted new socket %ld, stream %ld callback message %s.\n", __LINE__, (unsigned long) acceptsock, (unsigned long) newstream, stringbaseaddress(bs))); 2914 TCPWRITEMSG(); 2915 2916 fl = fwsrunstring (bs); 2917 #endif 2918 2919 --i; // back up so we'll check this socket again 2920 #ifdef PIKE 2921 } 2922 else { 2923 2924 struct linger l; 2925 2926 l.l_onoff = 1; 2927 l.l_linger = 0; 2928 2929 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventCheckAndAcceptSocket at line %d. Exceeded number of maximum connections: %ld of %ld.\n", __LINE__, ctconnections, maxconnections)); 2930 TCPERRORWRITEMSG(); 2931 2932 setsockopt (acceptsock, SOL_SOCKET, SO_LINGER, (char *) &l, sizeof(l)); 2933 2934 fl = closesocket (acceptsock); 2935 2936 sockstack[newstream].typeID = SOCKTYPE_INVALID; 2937 } 2938 #endif 2939 } 2940 else 2941 { 2942 /* if an error - pass this on to callback */ 2943 err = WSAGetLastError(); 2944 2945 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 2946 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventCheckAndAcceptSocket at line %d. Error processing accept message %s (%ld, %ld).\n", __LINE__, stringbaseaddress (sockstack[listenstream].callback), err * -1L, sockstack[listenstream].refcon)); 2947 TCPWRITEMSG(); 2948 2949 fl = fwsruncallback (listenstream, err * -1L, sockstack[listenstream].refcon); 2950 #else 2951 parsecallbackstring (listenstream, err * -1L, sockstack[listenstream].refcon, bs); 2952 2953 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventCheckAndAcceptSocket at line %d. Error processing accept message %s.\n", __LINE__, stringbaseaddress(bs))); 2954 TCPERRORWRITEMSG(); 2955 2956 fl = fwsrunstring (bs); 2957 #endif 2958 2959 if (err == ENOTCONN) { 2960 2961 // 6.0b2 dmb: this code isn't right. the listens keep succeeding, 2962 // chewing up resources until they're gone; accepts still fail 2963 /* 2964 if (listen (sock, 5) == SOCKET_ERROR) { 2965 2966 neterror("setup listen stream", WSAGetLastError ()); 2967 2968 fwsNetEventCloseListen (listenstream); 2969 //closesocket (sock); 2970 } 2971 */ 2972 } 2973 sockstack[newstream].typeID = SOCKTYPE_INVALID; 2974 } 2975 } 2976 else if (res == SOCKET_ERROR) { 2977 //The select on that socket had an error - What to do?? 2978 } 2979 } 2980 } 2981 2982 return (fl); 2983 } /*fwsNetEventCheckAndAcceptSocket*/ 2984 #endif 2985 #endif 2986 2987 #ifdef WIN95VERSION 2988 boolean fwsNetEventAcceptSocket (WPARAM wParam, LPARAM lParam) { 2989 2990 /* 2991 Process an accept pending message on a socket 2992 2993 5.1.2 dmb: release thread globals on all errors 2994 */ 2995 2996 #ifdef ACCEPT_IN_SEPARATE_THREAD 2997 2998 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. THIS FUNCTION IS NOT SUPPOSED TO BE CALLED!\n", __LINE__)); 2999 TCPWRITEMSG(); 3000 3001 return (false); 3002 3003 #else 3004 3005 int sasize; 3006 struct sockaddr_in sa; 3007 SOCKET s, acceptsock; 3008 long err; 3009 boolean fl = false; 3010 long listenstream, newstream; 3011 long dummy = 0; /*need a pointer to nil for ioctlsocket call*/ 3012 #ifndef ACCEPT_CONN_WITHOUT_GLOBALS 3013 bigstring bs; 3014 #endif 3015 3016 s = (SOCKET) wParam; 3017 3018 /*get listen stream*/ 3019 if (!getsockrecord (s, &listenstream)) 3020 goto exit; 3021 3022 TCPTRACKERIN ("fwsNetEventAcceptSocket", __LINE__, listenstream); 3023 3024 if (listenstream < 0) 3025 goto exit; 3026 3027 if (sockstack[listenstream].typeID != SOCKTYPE_LISTENING) { 3028 /*something has happened to close this listen*/ 3029 goto exit; 3030 } 3031 3032 /*Check for error*/ 3033 3034 err = WSAGETSELECTERROR(lParam); 3035 3036 if (err != 0) { 3037 /* if an error - pass this on to callback */ 3038 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 3039 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. Error in accept message %s (%ld, %ld).\n", __LINE__, stringbaseaddress (sockstack[listenstream].callback), err * -1L, sockstack[listenstream].refcon)); 3040 TCPWRITEMSG(); 3041 3042 fl = fwsruncallback (listenstream, err * -1L, sockstack[listenstream].refcon); 3043 #else 3044 parsecallbackstring (listenstream, err * -1L, sockstack[listenstream].refcon, bs); 3045 3046 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. Error in accept message %s.\n", __LINE__, stringbaseaddress(bs))); 3047 TCPERRORWRITEMSG(); 3048 3049 fl = fwsrunstring (bs); 3050 #endif 3051 3052 goto exit; 3053 } 3054 3055 /*get socket record for accepted socket*/ 3056 3057 if (!addsockrecord (&newstream)) { 3058 /* if an error - pass this on to callback */ 3059 long err = WSAEMFILE; 3060 3061 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 3062 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. Error addding new socket record %s (%ld, %ld).\n", __LINE__, stringbaseaddress (sockstack[listenstream].callback), err * -1L, sockstack[listenstream].refcon)); 3063 TCPWRITEMSG(); 3064 3065 fl = fwsruncallback (listenstream, err * -1L, sockstack[listenstream].refcon); 3066 #else 3067 parsecallbackstring (listenstream, err * -1L, sockstack[listenstream].refcon, bs); 3068 3069 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. Error addding new socket record %s.\n", __LINE__, stringbaseaddress(bs))); 3070 TCPERRORWRITEMSG(); 3071 3072 fl = fwsrunstring (bs); 3073 #endif 3074 3075 goto exit; 3076 } 3077 3078 /*We do not want any more connection messages - at least if we've reached maximum listen depth*/ 3079 3080 if (!(sockstack[listenstream].currentListenDepth + 1 < sockstack[listenstream].maxdepth)) { 3081 3082 sockstack[listenstream].flNotification = false; 3083 3084 WSAAsyncSelect(s, shellframewindow, 0, 0); 3085 } 3086 3087 /*Accept connection*/ 3088 3089 sasize = sizeof(sa); 3090 3091 acceptsock = accept (s, (struct sockaddr *)&sa, &sasize); 3092 3093 if (acceptsock != INVALID_SOCKET) { 3094 3095 #ifdef PIKE 3096 if (incrementconnectioncounter ()) { 3097 #endif 3098 /*Switch child socket to blocking mode*/ 3099 if (WSAAsyncSelect(acceptsock, shellframewindow, 0, 0) == SOCKET_ERROR) { 3100 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. WSAAsyncSelect call failed: %ld.\n", __LINE__, WSAGetLastError ())); 3101 TCPERRORWRITEMSG(); 3102 } 3103 3104 if (ioctlsocket (acceptsock, FIONBIO, &dummy) == SOCKET_ERROR) { 3105 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. ioctlsocket call failed: %ld.\n", __LINE__, WSAGetLastError ())); 3106 TCPERRORWRITEMSG(); 3107 } 3108 3109 /*Increment listen depth*/ 3110 ++sockstack[listenstream].currentListenDepth; 3111 3112 /*Add Socket to list*/ 3113 sockstack[newstream].sockID = acceptsock; 3114 sockstack[newstream].typeID = SOCKTYPE_OPEN; 3115 sockstack[newstream].listenReference = listenstream; 3116 sockstack[newstream].refcon = 0; 3117 3118 /*Pass "stream" and "refcon" to callback*/ 3119 3120 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 3121 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. Accepted new socket %ld: %s (%ld, %ld).\n", __LINE__, acceptsock, stringbaseaddress (sockstack[listenstream].callback), newstream, sockstack[listenstream].refcon)); 3122 TCPWRITEMSG(); 3123 3124 fl = fwsruncallback (listenstream, newstream, sockstack[listenstream].refcon); 3125 #else 3126 parsecallbackstring (listenstream, newstream, sockstack[listenstream].refcon, bs); 3127 3128 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. Accepted new socket %ld, stream %ld callback message %s.\n", __LINE__, (unsigned long) acceptsock, (unsigned long) newstream, stringbaseaddress(bs))); 3129 TCPWRITEMSG(); 3130 3131 fl = fwsrunstring (bs); 3132 #endif 3133 3134 #ifdef PIKE 3135 } 3136 else { 3137 3138 struct linger l; 3139 3140 l.l_onoff = 1; 3141 l.l_linger = 0; 3142 3143 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. Exceeded number of maximum connections: %ld of %ld.\n", __LINE__, ctconnections, maxconnections)); 3144 TCPERRORWRITEMSG(); 3145 3146 setsockopt (acceptsock, SOL_SOCKET, SO_LINGER, (char *) &l, sizeof(l)); 3147 3148 fl = closesocket (acceptsock); 3149 3150 sockstack[newstream].typeID = SOCKTYPE_INVALID; 3151 } 3152 #endif 3153 3154 } 3155 else 3156 { 3157 /*if an error - pass this on to callback*/ 3158 err = WSAGetLastError(); 3159 3160 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 3161 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. Error processing accept message %s (%ld, %ld).\n", __LINE__, stringbaseaddress (sockstack[listenstream].callback), err * -1L, sockstack[listenstream].refcon)); 3162 TCPWRITEMSG(); 3163 3164 fl = fwsruncallback (listenstream, err * -1L, sockstack[listenstream].refcon); 3165 #else 3166 parsecallbackstring (listenstream, err * -1L, sockstack[listenstream].refcon, bs); 3167 3168 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventAcceptSocket at line %d. Error processing accept message %s.\n", __LINE__, stringbaseaddress(bs))); 3169 TCPERRORWRITEMSG(); 3170 3171 fl = fwsrunstring (bs); 3172 #endif 3173 3174 sockstack[newstream].typeID = SOCKTYPE_INVALID; 3175 } 3176 3177 restartAccepter (s, listenstream); 3178 3179 TCPprintf (wsprintf(TCPmsg, "Exiting fwsNetEventAcceptSocket at line %d. Return value is %s.\n", __LINE__, fl?"True":"False")); 3180 TCPWRITEMSG(); 3181 3182 exit: 3183 3184 return (fl); 3185 #endif 3186 } /*fwsNetEventAcceptSocket*/ 3187 #endif 3188 3189 3190 boolean fwsNetEventListenStream (unsigned long port, long depth, bigstring callback, unsigned long refcon, unsigned long * stream, unsigned long ipaddr, long hdatabase) { 3191 3192 /* Set up a listner on a port */ 3193 3194 SOCKET sock; 3195 SOCKADDR_IN addr; 3196 int errcode; 3197 long streamref; 3198 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 3199 Handle hcallbacktree = nil; 3200 #endif 3201 3202 nullterminate (callback); 3203 TCPprintf(wsprintf(TCPmsg, "Entering fwsNetEventListenStream at line %d. Port = %ld, Depth = %ld, Refcon = %ld, Callback = %s.\n", __LINE__, port, depth, refcon, stringbaseaddress(callback))); 3204 TCPWRITEMSG (); 3205 3206 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 3207 return (false); 3208 3209 if (!addsockrecord (&streamref)) { 3210 neterror ("initialize listen stream", WSAEMFILE); /*Too many open sockets*/ 3211 return (false); 3212 } 3213 3214 #ifdef ACCEPT_CONN_WITHOUT_GLOBALS 3215 if (!fwsgetcallbackcodetree (callback, &hcallbacktree)) 3216 return (false); 3217 #endif 3218 3219 releasethreadglobalsnopriority(); 3220 3221 sock = socket(PF_INET, SOCK_STREAM, 0); 3222 3223 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventListenStream at line %d. socket call result is sock = %ld.\n", __LINE__, (long)sock)); 3224 TCPWRITEMSG (); 3225 3226 if (sock == INVALID_SOCKET) { 3227 errcode = WSAGetLastError (); 3228 grabthreadglobalsnopriority(); 3229 neterror("create listen stream", errcode); 3230 sockstack[streamref].typeID = SOCKTYPE_INACTIVE; 3231 disposehandle (hcallbacktree); 3232 return (false); 3233 } 3234 3235 addr.sin_family = AF_INET; 3236 addr.sin_addr.s_addr = htonl(ipaddr); 3237 addr.sin_port = htons((unsigned short) port); 3238 3239 if (bind(sock, (LPSOCKADDR)&addr, sizeof (addr)) == SOCKET_ERROR) { 3240 errcode = WSAGetLastError (); 3241 grabthreadglobalsnopriority(); 3242 neterror("bind listen stream", errcode); 3243 closesocket (sock); 3244 sockstack[streamref].typeID = SOCKTYPE_INACTIVE; 3245 disposehandle (hcallbacktree); 3246 return (false); 3247 } 3248 3249 if (listen (sock, SOMAXCONN) == SOCKET_ERROR) { 3250 errcode = WSAGetLastError (); 3251 grabthreadglobalsnopriority(); 3252 neterror("setup listen stream", errcode); 3253 closesocket (sock); 3254 sockstack[streamref].typeID = SOCKTYPE_INACTIVE; 3255 disposehandle (hcallbacktree); 3256 return (false); 3257 } 3258 3259 grabthreadglobalsnopriority(); 3260 3261 sockstack[streamref].refcon = refcon; 3262 3263 sockstack[streamref].sockID = sock; 3264 3265 sockstack[streamref].typeID = SOCKTYPE_LISTENING; 3266 3267 copystring (callback, sockstack[streamref].callback); 3268 3269 sockstack[streamref].maxdepth = depth; 3270 3271 sockstack[streamref].listenReference = 0; //6.2a14 AR: was refcon, but probably doesn't make a difference (yet!) 3272 3273 sockstack[streamref].currentListenDepth = 0; 3274 3275 sockstack[streamref].hcallbacktree = hcallbacktree; 3276 3277 3278 *stream = streamref; 3279 3280 #ifdef MACVERSION 3281 sockListenList[sockListenCount++] = *stream; 3282 #endif 3283 3284 #ifdef ACCEPT_IN_SEPARATE_THREAD 3285 sockstack[streamref].hdatabase = (hdldatabaserecord) hdatabase; /*hdldatabaserecord of the db that contains the daemon script*/ 3286 3287 if (!fwslaunchacceptingthread (streamref)) { 3288 closesocket (sock); 3289 sockstack[streamref].typeID = SOCKTYPE_INACTIVE; 3290 disposehandle (hcallbacktree); 3291 return (false); 3292 } 3293 #else 3294 #ifdef WIN95VERSION 3295 releasethreadglobalsnopriority(); 3296 3297 if (WSAAsyncSelect (sock, shellframewindow, wm_processAccept, FD_ACCEPT) == SOCKET_ERROR) { 3298 /* Our interest in this has failed */ 3299 errcode = WSAGetLastError (); 3300 grabthreadglobalsnopriority(); 3301 neterror("setup listen stream", errcode); 3302 closesocket (sock); 3303 sockstack[streamref].typeID = SOCKTYPE_INACTIVE; 3304 disposehandle (hcallbacktree); 3305 return (false); 3306 } 3307 3308 sockstack[stream].flNotification = true; 3309 3310 grabthreadglobalsnopriority(); 3311 #endif 3312 #endif 3313 3314 TCPTRACKEROUT ("fwsNetEventListenStream", __LINE__, *stream); 3315 return (true); 3316 3317 } /*fwsNetEventListenStream*/ 3318 3319 3320 boolean fwsNetEventStatusStream (unsigned long stream, bigstring status, unsigned long * bytesPending) { 3321 3322 /* get the status of a stream */ 3323 3324 int res; 3325 SOCKET sock; 3326 fd_set readset; 3327 struct timeval tv; 3328 // struct hostData hostdata; 3329 3330 //#if (TCPTRACKER == 1) 3331 if (!inmainthread()) 3332 TCPTRACKERIN ("fwsNetEventStatusStream", __LINE__, stream); 3333 //#endif 3334 3335 *bytesPending = 0; 3336 3337 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 3338 return (false); 3339 3340 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 3341 intneterror (INTNETERROR_INVALIDSTREAM); 3342 return (false); 3343 } 3344 3345 sock = sockstack[stream].sockID; 3346 3347 switch (sockstack[stream].typeID) { 3348 case SOCKTYPE_INVALID: 3349 intneterror(INTNETERROR_INVALIDSTREAM); 3350 copyctopstring ("INACTIVE", status); 3351 return (false); 3352 3353 case SOCKTYPE_UNKNOWN: 3354 copyctopstring ("UNKNOWN", status); 3355 break; 3356 3357 case SOCKTYPE_OPEN: 3358 copyctopstring ("OPEN", status); 3359 3360 tv.tv_sec = 0; 3361 tv.tv_usec = 0; 3362 3363 FD_ZERO (&readset); 3364 3365 FD_SET(sock, &readset); 3366 3367 /* now check for data */ 3368 3369 res = select (sock+1, &readset, NULL, NULL, &tv); 3370 3371 if (res == SOCKET_ERROR) { 3372 neterror("check status on stream", WSAGetLastError ()); 3373 copyctopstring ("INACTIVE", status); 3374 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3375 return (false); 3376 } 3377 3378 if (res == 1) { /*this means that the socket we sent has data */ 3379 res = ioctlsocket (sock, FIONREAD, bytesPending); 3380 3381 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventStatusStream at line %d, ioctlsocket returned %ld with the number of bytes pending as %ld.\n", __LINE__, res, *bytesPending)); 3382 TCPWRITEMSG (); 3383 3384 if (res == SOCKET_ERROR) { 3385 neterror("check status on stream", WSAGetLastError ()); 3386 copyctopstring ("INACTIVE", status); 3387 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3388 return (false); 3389 } 3390 3391 if (*bytesPending == 0) 3392 { 3393 copyctopstring ("INACTIVE", status); 3394 3395 /* this condition means that the virtual socket has been closed */ 3396 3397 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3398 } 3399 else 3400 copyctopstring ("DATA", status); 3401 } 3402 3403 break; 3404 3405 case SOCKTYPE_LISTENING: 3406 copyctopstring ("LISTENING", status); 3407 break; 3408 3409 case SOCKTYPE_CLOSED: 3410 copyctopstring ("CLOSED", status); 3411 break; 3412 3413 case SOCKTYPE_LISTENSTOPPED: 3414 copyctopstring ("STOPPED", status); 3415 break; 3416 3417 case SOCKTYPE_INACTIVE: 3418 copyctopstring ("INACTIVE", status); 3419 break; 3420 3421 default: 3422 copyctopstring ("UNKNOWN", status); 3423 break; 3424 } 3425 3426 nullterminate (status); 3427 3428 //#if (TCPTRACKER == 1) 3429 if (!inmainthread()) { 3430 TCPprintf (wsprintf(TCPmsg, "Exiting fwsNetEventStatusStream at line %d, result is %s with bytes pending %ld.\n", __LINE__, stringbaseaddress(status), *bytesPending)); 3431 TCPWRITEMSG (); 3432 } 3433 //#endif 3434 3435 return (true); 3436 } /*fwsNetEventStatusStream*/ 3437 3438 3439 boolean fwsNetEventGetPeerAddress (unsigned long stream, unsigned long * peeraddress, unsigned long * peerport) { 3440 SOCKADDR_IN sockAddr; 3441 SOCKET sock; 3442 int nSockAddrLen; 3443 int res; 3444 3445 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 3446 intneterror (INTNETERROR_INVALIDSTREAM); 3447 return (false); 3448 } 3449 3450 TCPTRACKERIN ("fwsNetEventGetPeerAddress", __LINE__, stream); 3451 3452 sock = sockstack[stream].sockID; 3453 3454 memset(&sockAddr, 0, sizeof(sockAddr)); 3455 3456 nSockAddrLen = sizeof(sockAddr); 3457 3458 res = getpeername(sock, (SOCKADDR*)&sockAddr, &nSockAddrLen); 3459 3460 if (res == SOCKET_ERROR) { 3461 neterror("get peer address", WSAGetLastError()); 3462 return (false); 3463 } 3464 3465 *peerport = (unsigned long) ntohs(sockAddr.sin_port); 3466 *peeraddress = ntohl(sockAddr.sin_addr.s_addr); 3467 3468 TCPTRACKEROUT ("fwsNetEventGetPeerAddress", __LINE__, stream); 3469 3470 return (true); 3471 } /*fwsNetEventGetPeerAddress*/ 3472 3473 3474 boolean fwsNetEventReadStreamUntil (unsigned long stream, Handle hbuffer, Handle hpattern, unsigned long timeoutsecs) { 3475 3476 /* 3477 6.1d1 AR: Read from a stream appending to hbuffer until hpattern is found. 3478 3479 6.1d13 AR: Only grab globals when growing the handle (for proper out of memory errors). 3480 3481 6.1b9 AR: Check the whole buffer for the pattern -- not only the part we read. 3482 */ 3483 3484 SOCKET sock; 3485 fd_set readset; 3486 struct timeval tv; 3487 int res, errcode; 3488 long ix = gethandlesize (hbuffer); 3489 long ixstart = ix; 3490 unsigned long bytes; 3491 3492 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 3493 return (false); 3494 3495 TCPTRACKERIN ("fwsNetEventReadStreamUntil", __LINE__, stream); 3496 3497 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 3498 intneterror (INTNETERROR_INVALIDSTREAM); 3499 return (false); 3500 } 3501 3502 sock = sockstack[stream].sockID; 3503 3504 if (sock == INVALID_SOCKET) { 3505 neterror ("read stream", WSAENOTSOCK); 3506 return (false); 3507 } 3508 3509 releasethreadglobalsnopriority(); 3510 3511 tv.tv_sec = timeoutsecs; 3512 tv.tv_usec = 0; 3513 3514 FD_ZERO (&readset); 3515 3516 FD_SET (sock, &readset); /*as long as we're dealing with a single socket, 3517 doing this just once should be totally safe.*/ 3518 3519 while (searchhandle (hbuffer, hpattern, 0, ix) == -1L) { 3520 3521 res = select (sock+1, &readset, NULL, NULL, &tv); 3522 3523 switch (res) { 3524 3525 case 1: /*this means that the socket has data */ 3526 res = ioctlsocket (sock, FIONREAD, &bytes); 3527 3528 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventReadStreamUntil at line %d, ioctlsocket returned %ld with the number of bytes pending as %ld.\n", __LINE__, res, bytes)); 3529 TCPWRITEMSG (); 3530 3531 if (res == SOCKET_ERROR) { 3532 errcode = WSAGetLastError (); 3533 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3534 goto exit; 3535 } 3536 3537 if (bytes == 0) { /*closed prematurely*/ 3538 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3539 goto error_closedprematurely; 3540 } 3541 3542 grabthreadglobalsnopriority(); /*we need the globals because sethandlesize might throw an error*/ 3543 3544 if (!sethandlesize (hbuffer, ix + bytes)) 3545 return (false); /*we have the thread globals, so we can return immediately*/ 3546 3547 releasethreadglobalsnopriority(); 3548 3549 lockhandle (hbuffer); 3550 3551 res = recv (sock, &((*hbuffer) [ix]), bytes, 0); 3552 3553 unlockhandle (hbuffer); 3554 3555 if (res == SOCKET_ERROR) { 3556 errcode = WSAGetLastError (); 3557 goto exit; 3558 } 3559 3560 ix += res; 3561 3562 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventReadStreamUntil at line %d, requested reading %ld bytes, read %ld bytes.\n", __LINE__, bytes, res)); 3563 TCPWRITEMSG (); 3564 3565 break; 3566 3567 case 0: /*select timed out*/ 3568 errcode = WSAETIMEDOUT; 3569 goto exit; 3570 3571 case SOCKET_ERROR: 3572 errcode = WSAGetLastError (); 3573 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3574 goto exit; 3575 3576 default: 3577 errcode = -1; /* should never happen*/ 3578 goto exit; 3579 } 3580 } 3581 3582 grabthreadglobalsnopriority(); 3583 3584 if (!sethandlesize (hbuffer, ix)) 3585 return (false); 3586 3587 TCPprintf (wsprintf(TCPmsg, "Exiting fwsNetEventReadStreamUntil at line %d. Total bytes read = %ld.\n", __LINE__, ix - ixstart)); 3588 TCPWRITEMSG (); 3589 3590 return (true); 3591 3592 exit: 3593 grabthreadglobalsnopriority(); 3594 3595 if (!sethandlesize (hbuffer, ix)) 3596 return (false); 3597 3598 neterror ("read stream", errcode); 3599 3600 return (false); 3601 3602 error_closedprematurely: 3603 grabthreadglobalsnopriority(); 3604 3605 if (!sethandlesize (hbuffer, ix)) 3606 return (false); 3607 3608 plainneterror (STR_P_ERROR_CLOSED_PREMATURELY); 3609 3610 return (false); 3611 } /*fwsNetEventReadStreamUntil*/ 3612 3613 3614 3615 boolean fwsNetEventReadStreamUntilClosed (unsigned long stream, Handle hbuffer, unsigned long timeoutsecs) { 3616 3617 /* 3618 6.1b15 AR: Branched from fwsNetEventReadStreamUntil. Don't look for a pattern, just read until closed. 3619 */ 3620 3621 SOCKET sock; 3622 fd_set readset; 3623 struct timeval tv; 3624 int res, errcode; 3625 long ix = gethandlesize (hbuffer); 3626 long ixstart = ix; 3627 unsigned long bytes; 3628 3629 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 3630 return (false); 3631 3632 TCPTRACKERIN ("fwsNetEventReadStreamUntil", __LINE__, stream); 3633 3634 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 3635 intneterror (INTNETERROR_INVALIDSTREAM); 3636 return (false); 3637 } 3638 3639 sock = sockstack[stream].sockID; 3640 3641 if (sock == INVALID_SOCKET) { 3642 neterror ("read stream", WSAENOTSOCK); 3643 return (false); 3644 } 3645 3646 releasethreadglobalsnopriority(); 3647 3648 tv.tv_sec = timeoutsecs; 3649 tv.tv_usec = 0; 3650 3651 FD_ZERO (&readset); 3652 3653 FD_SET (sock, &readset); /*as long as we're dealing with a single socket, 3654 doing this just once should be totally safe.*/ 3655 3656 while (true) { 3657 3658 res = select (sock+1, &readset, NULL, NULL, &tv); 3659 3660 switch (res) { 3661 3662 case 1: /*this means that the socket has data */ 3663 res = ioctlsocket (sock, FIONREAD, &bytes); 3664 3665 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventReadStreamUntilClosed at line %d, ioctlsocket returned %ld with the number of bytes pending as %ld.\n", __LINE__, res, bytes)); 3666 TCPWRITEMSG (); 3667 3668 if (res == SOCKET_ERROR) { 3669 errcode = WSAGetLastError (); 3670 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3671 goto exit; 3672 } 3673 3674 if (bytes == 0) { /*we're done*/ 3675 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3676 goto done; 3677 } 3678 3679 grabthreadglobalsnopriority(); /*we need the globals because sethandlesize might throw an error*/ 3680 3681 if (!sethandlesize (hbuffer, ix + bytes)) 3682 return (false); /*we have the thread globals, so we can return immediately*/ 3683 3684 releasethreadglobalsnopriority(); 3685 3686 lockhandle (hbuffer); 3687 3688 res = recv (sock, &((*hbuffer) [ix]), bytes, 0); 3689 3690 unlockhandle (hbuffer); 3691 3692 if (res == SOCKET_ERROR) { 3693 errcode = WSAGetLastError (); 3694 goto exit; 3695 } 3696 3697 ix += res; 3698 3699 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventReadStreamUntilClosed at line %d, requested reading %ld bytes, read %ld bytes.\n", __LINE__, bytes, res)); 3700 TCPWRITEMSG (); 3701 3702 break; 3703 3704 case 0: /*select timed out*/ 3705 errcode = WSAETIMEDOUT; 3706 goto exit; 3707 3708 case SOCKET_ERROR: 3709 errcode = WSAGetLastError (); 3710 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3711 goto exit; 3712 3713 default: 3714 errcode = -1; /* should never happen*/ 3715 goto exit; 3716 } 3717 } 3718 3719 done: 3720 grabthreadglobalsnopriority(); 3721 3722 if (!sethandlesize (hbuffer, ix)) 3723 return (false); 3724 3725 TCPprintf (wsprintf(TCPmsg, "Exiting fwsNetEventReadStreamUntilClosed at line %d. Total bytes read = %ld.\n", __LINE__, ix - ixstart)); 3726 TCPWRITEMSG (); 3727 3728 return (true); 3729 3730 exit: 3731 grabthreadglobalsnopriority(); 3732 3733 if (!sethandlesize (hbuffer, ix)) 3734 return (false); 3735 3736 neterror ("read stream", errcode); 3737 3738 return (false); 3739 }/*fwsNetEventReadStreamUntilClosed*/ 3740 3741 3742 boolean fwsNetEventReadStreamBytes (unsigned long stream, Handle hbuffer, long ctbytes, unsigned long timeoutsecs) { 3743 3744 /* 3745 6.1d1 AR: Read the specified number of bytes from the stream appending to hbuffer. 3746 3747 6.1b9 AR: ctbytes applies to the whole buffer -- not only the part we read. 3748 */ 3749 3750 SOCKET sock; 3751 fd_set readset; 3752 struct timeval tv; 3753 int res; 3754 long lenbuffer = gethandlesize (hbuffer); 3755 long ix = lenbuffer; 3756 long bytes; 3757 long errcode; 3758 3759 if (ctbytes <= lenbuffer) /*6.1b8 AR: don't do anything*/ 3760 return (true); 3761 3762 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 3763 return (false); 3764 3765 TCPTRACKERIN ("fwsNetEventReadStreamBytes", __LINE__, stream); 3766 3767 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 3768 intneterror (INTNETERROR_INVALIDSTREAM); 3769 return (false); 3770 } 3771 3772 if (!sethandlesize (hbuffer, ctbytes)) //make enough room in one go 3773 return (false); 3774 3775 sock = sockstack[stream].sockID; 3776 3777 if (sock == INVALID_SOCKET) { 3778 neterror ("read stream", WSAENOTSOCK); 3779 return (false); 3780 } 3781 3782 releasethreadglobalsnopriority(); //from now on, don't touch lang globals before 3783 //having called grabthreadglobalsnopriority 3784 tv.tv_sec = timeoutsecs; 3785 tv.tv_usec = 0; 3786 3787 FD_ZERO (&readset); 3788 3789 FD_SET (sock, &readset); 3790 3791 lockhandle (hbuffer); 3792 3793 while (ix < ctbytes) { 3794 3795 res = select (sock+1, &readset, NULL, NULL, &tv); 3796 3797 switch (res) { 3798 3799 case 1: /*this means that the socket has data */ 3800 res = ioctlsocket (sock, FIONREAD, &bytes); 3801 3802 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventReadStreamBytes at line %d, ioctlsocket returned %ld with the number of bytes pending as %ld.\n", __LINE__, res, bytes)); 3803 TCPWRITEMSG (); 3804 3805 if (res == SOCKET_ERROR) { 3806 errcode = WSAGetLastError (); 3807 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3808 goto exit; 3809 } 3810 3811 if (bytes == 0) { /*closed prematurely*/ 3812 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3813 goto error_closedprematurely; 3814 } 3815 3816 if (bytes > (ctbytes - ix)) /* Don't read more than ctbytes */ 3817 bytes = ctbytes - ix; 3818 3819 res = recv (sock, &((*hbuffer) [ix]), bytes, 0); 3820 3821 if (res == SOCKET_ERROR) { /* might be WSAEMSGSIZE if we read less data than is available? */ 3822 errcode = WSAGetLastError (); 3823 goto exit; 3824 } 3825 3826 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventReadStreamBytes at line %d, requested reading %ld bytes, read %ld bytes.\n", __LINE__, bytes, res)); 3827 TCPWRITEMSG (); 3828 3829 ix += res; 3830 3831 break; 3832 3833 case 0: /*select timed out*/ 3834 errcode = WSAETIMEDOUT; 3835 goto exit; 3836 3837 case SOCKET_ERROR: 3838 errcode = WSAGetLastError (); 3839 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3840 goto exit; 3841 3842 default: 3843 errcode = -1; 3844 //assert (false); 3845 goto exit; 3846 } 3847 } 3848 3849 grabthreadglobalsnopriority(); 3850 3851 unlockhandle (hbuffer); 3852 3853 TCPprintf (wsprintf(TCPmsg, "Exiting fwsNetEventReadStreamBytes at line %d. Total bytes requested = %ld, bytes read = %ld.\n", __LINE__, ctbytes, ix)); 3854 TCPWRITEMSG (); 3855 3856 return (true); 3857 3858 exit: 3859 grabthreadglobalsnopriority(); 3860 3861 neterror("read stream", errcode); 3862 3863 unlockhandle (hbuffer); 3864 3865 sethandlesize (hbuffer, ix); /*shrinking, can't fail*/ 3866 3867 return (false); 3868 3869 error_closedprematurely: 3870 grabthreadglobalsnopriority(); 3871 3872 plainneterror (STR_P_ERROR_CLOSED_PREMATURELY); 3873 3874 unlockhandle (hbuffer); 3875 3876 sethandlesize (hbuffer, ix); /*shrinking, can't fail*/ 3877 3878 return (false); 3879 } /*fwsNetEventReadStreamBytes*/ 3880 3881 3882 boolean fwsNetEventWriteHandleToStream (unsigned long stream, Handle hbuffer, unsigned long chunksize, unsigned long timeoutsecs) { 3883 3884 /* Write to stream in chunks */ 3885 3886 SOCKET sock; 3887 fd_set writeset; 3888 struct timeval tv; 3889 int res; 3890 long ix = 0; 3891 unsigned long bytesremaining = gethandlesize (hbuffer); 3892 long bytestowrite; 3893 long errcode; 3894 3895 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 3896 return (false); 3897 3898 TCPTRACKERIN ("fwsNetEventWriteHandleToStream", __LINE__, stream); 3899 3900 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 3901 intneterror (INTNETERROR_INVALIDSTREAM); 3902 return (false); 3903 } 3904 3905 sock = sockstack[stream].sockID; 3906 3907 if (sock == INVALID_SOCKET) { 3908 neterror ("write stream", WSAENOTSOCK); 3909 return (false); 3910 } 3911 3912 tv.tv_sec = timeoutsecs; 3913 tv.tv_usec = 0; 3914 3915 FD_ZERO (&writeset); 3916 3917 FD_SET (sock, &writeset); 3918 3919 lockhandle (hbuffer); 3920 3921 releasethreadglobalsnopriority(); //from now on, don't touch lang globals before 3922 //having called grabthreadglobalsnopriority 3923 do { 3924 3925 res = select (sock+1, NULL, &writeset, NULL, &tv); 3926 3927 switch (res) { 3928 3929 case 1: /*this means that we can write to the socket */ 3930 bytestowrite = (bytesremaining < chunksize) ? bytesremaining : chunksize; 3931 3932 res = send (sock, &((*hbuffer) [ix]), bytestowrite, 0); 3933 3934 if (res == SOCKET_ERROR) { 3935 3936 errcode = WSAGetLastError (); 3937 3938 #ifdef WIN95VERSION 3939 if (errcode == WSAEWOULDBLOCK) { /*work around winsock bug on win95/win98*/ 3940 3941 unsigned long timewait = gettickcount() + (60L * 15L); /*max of 15 seconds*/ 3942 3943 while (timewait > gettickcount ()) { 3944 3945 Sleep (100L); /*wait six ticks (100 milliseconds) and try again*/ 3946 3947 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventWriteHandleToStream at line %d. Attempting to re-send on stream: %d.\n", __LINE__, stream)); 3948 TCPWRITEMSG(); 3949 3950 res = send (sock, &((*hbuffer) [ix]), bytestowrite, 0); 3951 3952 if (res == SOCKET_ERROR) { 3953 errcode = WSAGetLastError (); 3954 3955 if (errcode != WSAEWOULDBLOCK) { 3956 3957 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventWriteHandleToStream at line %d. Error re-sending on stream: %d.\n", __LINE__, stream)); 3958 TCPERRORWRITEMSG(); 3959 3960 goto exit; /*terminate attempts to send data and throw a script error*/ 3961 } 3962 } 3963 else 3964 goto continue_send; 3965 }/*while*/ 3966 } 3967 3968 TCPERRORprintf (wsprintf(TCPmsg, "In fwsNetEventWriteHandleToStream at line %d. Gave up re-sending on stream: %d.\n", __LINE__, stream)); 3969 TCPERRORWRITEMSG(); 3970 #endif 3971 3972 goto exit; /*unconditionally throw a script error*/ 3973 } 3974 3975 continue_send: 3976 3977 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventWriteHandleToStream at line %d, requested writing %ld bytes, wrote %ld bytes.\n", __LINE__, bytestowrite, res)); 3978 TCPWRITEMSG (); 3979 3980 bytesremaining -= res; 3981 3982 ix += res; 3983 3984 break; 3985 3986 case 0: /*select timed out*/ 3987 errcode = WSAETIMEDOUT; 3988 goto exit; 3989 3990 case SOCKET_ERROR: 3991 errcode = WSAGetLastError (); 3992 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 3993 goto exit; 3994 3995 default: /*should never happen*/ 3996 errcode = -1; 3997 //assert (false); 3998 goto exit; 3999 } 4000 } while (bytesremaining > 0); 4001 4002 grabthreadglobalsnopriority(); 4003 4004 unlockhandle (hbuffer); 4005 4006 TCPprintf (wsprintf(TCPmsg, "Exiting fwsNetEventWriteHandleToStream at line %d. Total bytes written = %ld.\n", __LINE__, ix)); 4007 TCPWRITEMSG (); 4008 4009 return (true); 4010 4011 exit: 4012 grabthreadglobalsnopriority(); 4013 4014 neterror("write stream", errcode); 4015 4016 unlockhandle (hbuffer); 4017 4018 return (false); 4019 } /*fwsNetEventWriteHandleToStream*/ 4020 4021 4022 //#if 0 4023 4024 static boolean fwstransmitfile (unsigned long stream, ptrfilespec fs) { 4025 4026 char *buffer; 4027 static const long kFileBufferSize = 32767L; 4028 boolean fl = false; 4029 hdlfilenum fnum; 4030 long ctread = 0; 4031 long ix = 0; 4032 4033 /* open file */ 4034 4035 if (!openfile (fs, &fnum, true)) 4036 return (false); 4037 4038 /* allocate buffer */ 4039 4040 buffer = malloc (kFileBufferSize); 4041 4042 if (buffer == nil) { 4043 memoryerror (); 4044 goto exit; 4045 } 4046 4047 while (true) { 4048 4049 /* read from file */ 4050 4051 if (!filesetposition (fnum, ix)) 4052 goto exit; 4053 4054 if (!filereaddata (fnum, kFileBufferSize, &ctread, buffer)) 4055 goto exit; 4056 4057 if (ctread == 0) { 4058 fl = true; 4059 goto exit; 4060 } 4061 4062 ix += ctread; 4063 4064 /* write to stream */ 4065 4066 if(!fwsNetEventWriteStream (stream, ctread, buffer)) 4067 goto exit; 4068 } 4069 4070 exit: 4071 /* free buffer */ 4072 4073 if (buffer != nil) 4074 free (buffer); 4075 4076 /* close file */ 4077 4078 fl = closefile (fnum); 4079 4080 return (fl); 4081 }/*fwstransmitfile*/ 4082 4083 4084 boolean fwsNetEventWriteFileToStream (unsigned long stream, Handle hprefix, Handle hsuffix, ptrfilespec fs) { 4085 4086 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 4087 return (false); 4088 4089 TCPTRACKERIN ("fwsNetEventWriteFileToStream", __LINE__, stream); 4090 4091 #ifdef WIN95VERSION 4092 4093 if (adrTransmitFile != nil) { 4094 4095 SOCKET sock; 4096 boolean fl; 4097 long errcode = 0; 4098 TRANSMIT_FILE_BUFFERS transmitbuffers; 4099 HANDLE hfile = INVALID_HANDLE_VALUE; 4100 char fn[300]; 4101 4102 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 4103 intneterror (INTNETERROR_INVALIDSTREAM); 4104 return (false); 4105 } 4106 4107 sock = sockstack[stream].sockID; 4108 4109 /* open file */ 4110 4111 copyptocstring (fsname (fs), fn); 4112 4113 hfile = CreateFile(fn, GENERIC_READ, FILE_SHARE_READ, 4114 NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); 4115 4116 if (hfile == INVALID_HANDLE_VALUE) { 4117 4118 oserror (GetLastError ()); 4119 4120 return (false); 4121 } 4122 4123 /* set up transmit buffers */ 4124 4125 if (hprefix != nil) { 4126 4127 lockhandle (hprefix); 4128 4129 transmitbuffers.HeadLength = gethandlesize (hprefix); 4130 4131 transmitbuffers.Head = (void *) *hprefix; 4132 } 4133 else { 4134 transmitbuffers.HeadLength = nil; 4135 4136 transmitbuffers.Head = nil; 4137 } 4138 4139 4140 if (hsuffix != nil) { 4141 4142 lockhandle (hsuffix); 4143 4144 transmitbuffers.TailLength = gethandlesize (hsuffix); 4145 4146 transmitbuffers.Tail = (void *) *hsuffix; 4147 } 4148 else { 4149 transmitbuffers.TailLength = nil; 4150 4151 transmitbuffers.Tail = nil; 4152 } 4153 4154 /* kernel call */ 4155 4156 releasethreadglobalsnopriority (); 4157 4158 fl = adrTransmitFile (sock, hfile, nil, nil, nil, &transmitbuffers, TF_WRITE_BEHIND); 4159 4160 if (!fl) 4161 errcode = GetLastError (); 4162 4163 grabthreadglobalsnopriority (); 4164 4165 /* clean up */ 4166 4167 if (hprefix != nil) 4168 unlockhandle (hprefix); 4169 4170 if (hsuffix != nil) 4171 unlockhandle (hsuffix); 4172 4173 if (!fl) { 4174 4175 neterror ("write file to stream", errcode); 4176 4177 return (false); 4178 } 4179 4180 TCPprintf (wsprintf(TCPmsg, "Exiting fwsNetEventWriteFileToStream at line %d.\n", __LINE__)); 4181 TCPWRITEMSG (); 4182 4183 return (true); 4184 } 4185 4186 #endif /*WIN95VERSION*/ 4187 4188 if (hprefix != nil) { 4189 boolean fl; 4190 4191 lockhandle (hprefix); 4192 4193 fl = fwsNetEventWriteStream (stream, gethandlesize (hprefix), *hprefix); 4194 4195 unlockhandle (hprefix); 4196 4197 if (!fl) 4198 return (false); 4199 } 4200 4201 if (!fwstransmitfile (stream, fs)) 4202 return (false); 4203 4204 if (hsuffix != nil) { 4205 boolean fl; 4206 4207 lockhandle (hsuffix); 4208 4209 fl = fwsNetEventWriteStream (stream, gethandlesize (hsuffix), *hsuffix); 4210 4211 unlockhandle (hsuffix); 4212 4213 if (!fl) 4214 return (false); 4215 } 4216 4217 TCPprintf (wsprintf(TCPmsg, "Exiting fwsNetEventWriteFileToStream at line %d.\n", __LINE__)); 4218 TCPWRITEMSG (); 4219 4220 return (true); 4221 } /*fwsNetEventWriteFileToStream*/ 4222 4223 //#endif 4224 4225 /* 4226 loop { //wait for data to read 4227 status = tcp.statusStream (stream, @bytespending); 4228 if (bytespending > 0) and (status == "DATA") { 4229 paramTable.request = paramTable.request + tcp.readStream (stream, bytespending); 4230 tcTimeout = clock.ticks () + 30}; //Now give only 1/2 second to get more data 4231 if status == "CLOSED" { 4232 break}; 4233 if status == "INACTIVE" { 4234 break}; 4235 if clock.ticks () > tcTimeout { 4236 break}; 4237 if status == "OPEN" { 4238 sys.systemTask (); //yield a little within this thread for the system 4239 thread.sleepfor (1)}}} //yield this thread for a second to allow normal Frontier processing 4240 */ 4241 4242 4243 boolean fwsNetEventInetdRead (unsigned long stream, Handle hbuffer, unsigned long timeoutsecs) { 4244 4245 /* 4246 6.1b2 AR: Wait timeoutsecs seconds for data to come in. After the first packed has been 4247 received, continue reading with a reduced timeout of 1 second. (For historical reasons.) 4248 */ 4249 4250 SOCKET sock; 4251 fd_set readset; 4252 struct timeval tv; 4253 int res, errcode; 4254 long ix = gethandlesize (hbuffer); 4255 long ixstart = ix; 4256 unsigned long bytes; 4257 4258 if (!fwsNetEventLaunch (NO_HOST_SERVICES)) 4259 return (false); 4260 4261 TCPTRACKERIN ("fwsNetEventInetdRead", __LINE__, stream); 4262 4263 if ((stream < 1) || (stream >= FRONTIER_MAX_STREAM)) { 4264 intneterror (INTNETERROR_INVALIDSTREAM); 4265 return (false); 4266 } 4267 4268 sock = sockstack[stream].sockID; 4269 4270 if (sock == INVALID_SOCKET) { 4271 neterror ("read stream", WSAENOTSOCK); 4272 return (false); 4273 } 4274 4275 releasethreadglobalsnopriority(); 4276 4277 tv.tv_sec = timeoutsecs; 4278 tv.tv_usec = 0; 4279 4280 FD_ZERO (&readset); 4281 4282 FD_SET (sock, &readset); /*as long as we're dealing with a single socket, 4283 doing this just once should be totally safe.*/ 4284 while (true) { 4285 4286 res = select (sock+1, &readset, NULL, NULL, &tv); 4287 4288 switch (res) { 4289 4290 case 1: /*this means that the socket has data */ 4291 res = ioctlsocket (sock, FIONREAD, &bytes); 4292 4293 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventInetdRead at line %d, ioctlsocket returned %ld with the number of bytes pending as %ld.\n", __LINE__, res, bytes)); 4294 TCPWRITEMSG (); 4295 4296 if (res == SOCKET_ERROR) { 4297 errcode = WSAGetLastError (); 4298 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 4299 goto exit; 4300 } 4301 4302 if (bytes == 0) { /*closed prematurely*/ 4303 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 4304 goto done; /*not an error in this case*/ 4305 } 4306 4307 grabthreadglobalsnopriority(); /*we need the globals because sethandlesize might throw an error*/ 4308 4309 if (!sethandlesize (hbuffer, ix + bytes)) 4310 return (false); /*we have the thread globals, so we can return immediately*/ 4311 4312 releasethreadglobalsnopriority(); 4313 4314 lockhandle (hbuffer); 4315 4316 res = recv (sock, &((*hbuffer) [ix]), bytes, 0); 4317 4318 unlockhandle (hbuffer); 4319 4320 if (res == SOCKET_ERROR) { 4321 errcode = WSAGetLastError (); 4322 goto exit; 4323 } 4324 4325 ix += res; 4326 4327 tv.tv_sec = 1; /*reduce timeout to one second after the first packet has been received*/ 4328 4329 TCPprintf (wsprintf(TCPmsg, "In fwsNetEventInetdRead at line %d, requested reading %ld bytes, read %ld bytes.\n", __LINE__, bytes, res)); 4330 TCPWRITEMSG (); 4331 4332 break; 4333 4334 case 0: /*select timed out*/ 4335 goto done; /*not an error in this case*/ 4336 4337 case SOCKET_ERROR: 4338 errcode = WSAGetLastError (); 4339 sockstack[stream].typeID = SOCKTYPE_INACTIVE; 4340 goto exit; 4341 4342 default: 4343 errcode = -1; /* should never happen*/ 4344 goto exit; 4345 } 4346 }/*while*/ 4347 4348 done: 4349 grabthreadglobalsnopriority(); 4350 4351 if (!sethandlesize (hbuffer, ix)) 4352 return (false); 4353 4354 TCPprintf (wsprintf(TCPmsg, "Exiting fwsNetEventInetdRead at line %d. Total bytes read = %ld.\n", __LINE__, ix - ixstart)); 4355 TCPWRITEMSG (); 4356 4357 return (true); 4358 4359 exit: 4360 grabthreadglobalsnopriority(); 4361 4362 neterror ("read stream", errcode); 4363 4364 return (false); 4365 } /*fwsNetEventInetdRead*/ 4366 4367 4368 boolean fwsNetEventGetStats (unsigned long stream, bigstring bs) { 4369 4370 unsigned long ctopen = 0; 4371 unsigned long ctdata = 0; 4372 unsigned long ctclosed = 0; 4373 unsigned long ctinactive = 0; 4374 unsigned long i; 4375 4376 setemptystring (bs); 4377 4378 for (i = 1; i <= FRONTIER_MAX_STREAM; i++) { 4379 4380 if (sockstack[i].listenReference == (long) stream) { 4381 4382 switch (sockstack[i].typeID) { 4383 4384 case SOCKTYPE_OPEN: 4385 ctopen++; 4386 break; 4387 4388 case SOCKTYPE_DATA: 4389 ctdata++; 4390 break; 4391 4392 case SOCKTYPE_CLOSED: 4393 ctclosed++; 4394 break; 4395 4396 case SOCKTYPE_INACTIVE: 4397 ctinactive++; 4398 break; 4399 }/*switch*/ 4400 } 4401 }/*for*/ 4402 4403 pushlong (ctopen, bs); 4404 4405 pushchar (',', bs); 4406 4407 pushlong (ctdata, bs); 4408 4409 pushchar (',', bs); 4410 4411 pushlong (ctclosed, bs); 4412 4413 pushchar (',', bs); 4414 4415 pushlong (ctinactive, bs); 4416 4417 return (true); 4418 }/*fwsNetEventGetStats*/ 4419 4420

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.