/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ /* * * This file implements the socket polling functions that * allow us to quickly determine if there is anything for * netlib to do at any instance in time. These functions * previously resided in the FE's but now have been consolidated * in the backend as part of the NSPR20 transition, since we * are no longer using winsock async socket notification. * * Designed and implemented by Lou Montulli '98 */ #include "mkutils.h" #include "mkselect.h" #include "nslocks.h" typedef enum { ConnectSelect, ReadSelect } SelectType; /* define this to use FE timers for the call_netlib_all_the_time * function. Otherwise we will use NET_PollSockets to perform the * same functionality */ #ifdef XP_WIN #undef USE_TIMERS_FOR_CALL_ALL_THE_TIME #else #define USE_TIMERS_FOR_CALL_ALL_THE_TIME #endif #define MAX_SIMULTANIOUS_SOCKETS 100 /* should never have more than MAX sockets */ PRPollDesc poll_desc_array[MAX_SIMULTANIOUS_SOCKETS]; unsigned int fd_set_size = 0; PRIVATE int net_calling_all_the_time_count=0; PRIVATE XP_Bool net_slow_timer_on=FALSE; #if defined(NO_NETWORK_POLLING) #include "private/primpl.h" #if defined(XP_PC) #include "md/_win95.h" extern HWND gDNSWindow; extern UINT gMSGAsyncSelect; /* * Helper routine which extracts the OS specific socket from the PRFileDesc * structure... */ PRInt32 net_GetOSFDFromFileDesc(PRFileDesc* fd) { PRInt32 osfd = 0; PRFileDesc *bottom; bottom = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); /* what to do about that? */ if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) { osfd = bottom->secret->md.osfd; } return osfd; } #else /* ! XP_PC */ PRInt32 net_GetOSFDFromFileDesc(PRFileDesc* fd) { PR_ASSERT(0); /* write me */ return 0; } #endif /* ! XP_PC */ /* * Helper routine which maps the OS specific socket back to its associated * PRFileDesc structure... */ PRFileDesc* net_GetFileDescFromOSFD(PRInt32 osfd) { int i; PRFileDesc* fd = NULL; /* * Make sure this function is called inside of the LIBNET lock since * it modifies global data structures... */ PR_ASSERT(LIBNET_IS_LOCKED()); for (i=0; i fd_set_size) { LIBNET_UNLOCK(); return FALSE; } itmp = PR_Poll(poll_desc_array, fd_set_size, interval); if(itmp < 1) { LIBNET_UNLOCK(); return TRUE; /* potential for doing stuff in the future. */ } /* for now call on all active sockets. */ /* if this is too much call only one, but reorder the list each time. */ for(itmp=0; itmp < fd_set_size; itmp++) { if(poll_desc_array[itmp].out_flags) NET_ProcessNet(poll_desc_array[itmp].fd, NET_SOCKET_FD); } LIBNET_UNLOCK(); return TRUE; } void net_process_net_timer_callback(void *closure) { PR_ASSERT(net_calling_all_the_time_count >= 0); if (net_calling_all_the_time_count == 0) return; if (NET_ProcessNet(NULL, NET_EVERYTIME_TYPE) == 0) net_calling_all_the_time_count = 0; else FE_SetTimeout(net_process_net_timer_callback, NULL, 1); } MODULE_PRIVATE void NET_SetCallNetlibAllTheTime(MWContext *context, char *caller) { PR_ASSERT(net_calling_all_the_time_count >= 0); #ifdef USE_TIMERS_FOR_CALL_ALL_THE_TIME if (net_calling_all_the_time_count == 0) FE_SetTimeout(net_process_net_timer_callback, NULL, 1); #endif /* USE_TIMERS_FOR_CALL_ALL_THE_TIME */ net_calling_all_the_time_count++; #if defined(NO_NETWORK_POLLING) /* * Force the netlib thread to drop out of its wait state (ie. select). * This is necessary, since this function can be called on multiple * threads... */ net_ForceSelect(); #endif /* NO_NETWORK_POLLING */ } #define SLOW_NETLIB_TIMER_INTERVAL_MILLISECONDS 10 void net_process_slow_net_timer_callback(void *closure) { if(!NET_ProcessNet(NULL, NET_EVERYTIME_TYPE)) net_slow_timer_on = FALSE; /* dont reset the timer */ else if (net_slow_timer_on) FE_SetTimeout(net_process_slow_net_timer_callback, NULL, SLOW_NETLIB_TIMER_INTERVAL_MILLISECONDS); } /* this function turns on and off a reasonably slow timer that will * push the netlib along even when it doesn't get any onIdle time. * this is unfortunately necessary on windows because when a modal * dialog is up it won't call the OnIdle loop which is currently the * source of our events. */ MODULE_PRIVATE void NET_SetNetlibSlowKickTimer(PRBool set) { if(net_slow_timer_on == set) return; /* do nothing */ net_slow_timer_on = set; /* call immediately */ if(net_slow_timer_on) FE_SetTimeout(net_process_slow_net_timer_callback, NULL, SLOW_NETLIB_TIMER_INTERVAL_MILLISECONDS); } MODULE_PRIVATE void NET_ClearCallNetlibAllTheTime(MWContext *context, char *caller) { PR_ASSERT(net_calling_all_the_time_count > 0); net_calling_all_the_time_count--; } MODULE_PRIVATE PRBool NET_IsCallNetlibAllTheTimeSet(MWContext *context, char *caller) { if(caller == NULL) { if(net_calling_all_the_time_count > 0) return PR_TRUE; } else { /* not implemented */ PR_ASSERT(0); } return PR_FALSE; } MODULE_PRIVATE void NET_ClearDNSSelect(MWContext *context, PRFileDesc *file_desc) { #if defined(XP_WIN) || (defined(XP_UNIX) && defined(UNIX_ASYNC_DNS)) || (defined(XP_OS2) && !defined(XP_OS2_DOUGSOCK)) /* FE_AbortDNSLookup(file_desc); */ #endif /* XP_WIN || (XP_UNIX && UNIX_ASYNC_DNS) || (defined(XP_OS2) && !defined(XP_OS2_DOUGSOCK) */ } MODULE_PRIVATE void NET_SetFileReadSelect(MWContext *context, int file_desc) { /* need to conver this over to NSPR PRFileDesc's before it will work */ /* FE_SetFileReadSelect(context, file_desc); */ } MODULE_PRIVATE void NET_ClearFileReadSelect(MWContext *context, int file_desc) { /* need to conver this over to NSPR PRFileDesc's before it will work */ /* FE_ClearReadSelect(context, file_desc); */ } MODULE_PRIVATE void NET_SetReadSelect(MWContext *context, PRFileDesc *file_desc) { NET_SetReadPoll(file_desc); } MODULE_PRIVATE void NET_ClearReadSelect(MWContext *context, PRFileDesc *file_desc) { NET_ClearReadPoll(file_desc); } MODULE_PRIVATE void NET_SetConnectSelect(MWContext *context, PRFileDesc *file_desc) { NET_SetConnectPoll(file_desc); } MODULE_PRIVATE void NET_ClearConnectSelect(MWContext *context, PRFileDesc *file_desc) { NET_ClearConnectPoll(file_desc); }