home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libnet / mkselect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  8.2 KB  |  321 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /*
  19.  *
  20.  * This file implements the socket polling functions that
  21.  * allow us to quickly determine if there is anything for
  22.  * netlib to do at any instance in time.  These functions
  23.  * previously resided in the FE's but now have been consolidated
  24.  * in the backend as part of the NSPR20 transition, since we
  25.  * are no longer using winsock async socket notification.
  26.  *
  27.  * Designed and implemented by Lou Montulli '98
  28.  */
  29.  
  30. #include "mkutils.h"
  31. #include "mkselect.h"
  32.  
  33. typedef enum {
  34.     ConnectSelect,
  35.     ReadSelect
  36. } SelectType;
  37.  
  38. /* define this to use FE timers for the call_netlib_all_the_time
  39.  * function.  Otherwise we will use NET_PollSockets to perform the
  40.  * same functionality
  41.  */
  42. #ifdef XP_WIN
  43. #undef USE_TIMERS_FOR_CALL_ALL_THE_TIME
  44. #else
  45. #define USE_TIMERS_FOR_CALL_ALL_THE_TIME
  46. #endif
  47.  
  48. #define MAX_SIMULTANIOUS_SOCKETS 100
  49. /* should never have more than MAX sockets */
  50. PRPollDesc poll_desc_array[MAX_SIMULTANIOUS_SOCKETS];
  51. unsigned int fd_set_size = 0;               
  52. PRIVATE int net_calling_all_the_time_count=0;
  53. PRIVATE XP_Bool net_slow_timer_on=FALSE;
  54.  
  55. /*  Add a select entry, no duplicates. */
  56. PRIVATE void 
  57. net_add_select(SelectType stType, PRFileDesc *prFD)
  58. {
  59.     unsigned int index = fd_set_size;
  60.     unsigned int count;
  61.  
  62. #define CONNECT_FLAGS PR_POLL_READ | PR_POLL_EXCEPT | PR_POLL_WRITE
  63. #define READ_FLAGS    PR_POLL_READ | PR_POLL_EXCEPT
  64.  
  65.     /*  Go through the list, make sure that there is not already an entry for fd. */
  66.     for(count=0; count < fd_set_size; count++)
  67.     {
  68.         if(poll_desc_array[count].fd == prFD)
  69.         {
  70.             /* found it */
  71.             /* verify that it has the same flags that we wan't,  
  72.              * otherwise add it again with different flags
  73.              */
  74.             if((stType == ConnectSelect && poll_desc_array[count].in_flags == CONNECT_FLAGS)
  75.                || (stType == ReadSelect && poll_desc_array[count].in_flags == READ_FLAGS))
  76.             {
  77.                 index = count;
  78.                 break;
  79.             }
  80.         }
  81.     }
  82.  
  83.     /* need to add a new one if we didnt' find the index */
  84.     if(index == fd_set_size)
  85.     {
  86.         poll_desc_array[fd_set_size].fd = prFD;
  87.         fd_set_size++;
  88.     }
  89.     
  90.     if(stType == ConnectSelect)
  91.         poll_desc_array[index].in_flags = CONNECT_FLAGS;
  92.     else if(stType == ReadSelect)
  93.         poll_desc_array[index].in_flags = READ_FLAGS;
  94.     else
  95.         XP_ASSERT(0);
  96. }
  97.  
  98. /*  Remove a select if it exists. */
  99. PRIVATE void 
  100. net_remove_select(SelectType stType, PRFileDesc *prFD)
  101. {
  102.     unsigned int count;
  103.  
  104.     /*  Go through the list */
  105.     for(count=0; count < fd_set_size; count++)
  106.     {
  107.         if(poll_desc_array[count].fd == prFD)
  108.         {
  109.             
  110.             if((stType == ConnectSelect && poll_desc_array[count].in_flags == CONNECT_FLAGS)
  111.                || (stType == ReadSelect && poll_desc_array[count].in_flags == READ_FLAGS))
  112.             {
  113.                 /* found it collapse the list */
  114.  
  115.                 fd_set_size--;
  116.                 if(count < fd_set_size)
  117.                     XP_MEMCPY(&poll_desc_array[count], &poll_desc_array[count+1], (fd_set_size - count) * sizeof(PRPollDesc));
  118.  
  119.                 return;
  120.             }
  121.         }
  122.     }
  123.  
  124.     /* didn't find it.  opps */
  125. }
  126.  
  127. MODULE_PRIVATE void 
  128. NET_SetReadPoll(PRFileDesc *fd) 
  129. {
  130.     net_add_select(ReadSelect, fd);
  131. }
  132.  
  133. MODULE_PRIVATE void 
  134. NET_ClearReadPoll(PRFileDesc *fd) 
  135. {
  136.     net_remove_select(ReadSelect, fd);
  137. }
  138.  
  139. MODULE_PRIVATE void 
  140. NET_SetConnectPoll(PRFileDesc *fd) 
  141. {
  142.     net_add_select(ConnectSelect, fd);
  143. }
  144.  
  145. MODULE_PRIVATE void 
  146. NET_ClearConnectPoll(PRFileDesc *fd) 
  147. {
  148.     net_remove_select(ConnectSelect, fd);
  149. }
  150.  
  151. /* call PR_Poll and call Netlib if necessary 
  152.  *
  153.  * return FALSE if nothing to do.
  154.  */
  155. PUBLIC XP_Bool 
  156. NET_PollSockets(void)
  157. {
  158.     static PRIntervalTime interval = 0;
  159.     register unsigned int itmp;
  160.  
  161.     if(net_calling_all_the_time_count)
  162.           NET_ProcessNet(NULL, NET_EVERYTIME_TYPE);
  163.         
  164.     if(!interval)
  165.         interval = PR_MillisecondsToInterval(1); 
  166.  
  167.     if(1 > fd_set_size)
  168.         return FALSE;
  169.  
  170.     itmp = PR_Poll(poll_desc_array, fd_set_size, interval);
  171.  
  172.     if(itmp < 1)
  173.         return TRUE; /* potential for doing stuff in the future. */
  174.  
  175.     /* for now call on all active sockets. */
  176.     /* if this is too much call only one, but reorder the list each time. */
  177.     for(itmp=0; itmp < fd_set_size; itmp++)
  178.     {
  179.         if(poll_desc_array[itmp].out_flags)
  180.             NET_ProcessNet(poll_desc_array[itmp].fd, NET_SOCKET_FD);
  181.     }
  182.  
  183.     return TRUE;
  184. }
  185.  
  186. void 
  187. net_process_net_timer_callback(void *closure)
  188. {
  189.     if(!NET_ProcessNet(NULL, NET_EVERYTIME_TYPE))
  190.         return;  /* dont reset the timer */
  191.  
  192.     if(net_calling_all_the_time_count)
  193.         FE_SetTimeout(net_process_net_timer_callback, NULL, 1);
  194. }
  195.  
  196. MODULE_PRIVATE void
  197. NET_SetCallNetlibAllTheTime(MWContext *context, char *caller)
  198. {
  199.     if(net_calling_all_the_time_count < 0)
  200.     {
  201.         XP_ASSERT(0);
  202.         net_calling_all_the_time_count = 0;
  203.     }
  204.  
  205. #ifdef USE_TIMERS_FOR_CALL_ALL_THE_TIME
  206.     FE_SetTimeout(net_process_net_timer_callback, NULL, 1);
  207. #endif /* USE_TIMERS_FOR_CALL_ALL_THE_TIME */
  208.     
  209.     net_calling_all_the_time_count++;
  210. }
  211.  
  212. #define SLOW_NETLIB_TIMER_INTERVAL_MILLISECONDS 10
  213. void 
  214. net_process_slow_net_timer_callback(void *closure)
  215. {
  216.     if(!NET_ProcessNet(NULL, NET_EVERYTIME_TYPE))
  217.         net_slow_timer_on = FALSE; /* dont reset the timer */
  218.     else if (net_slow_timer_on)
  219.         FE_SetTimeout(net_process_slow_net_timer_callback, 
  220.                 NULL,     
  221.                 SLOW_NETLIB_TIMER_INTERVAL_MILLISECONDS);
  222. }
  223.  
  224. /* this function turns on and off a reasonably slow timer that will
  225.  * push the netlib along even when it doesn't get any onIdle time.
  226.  * this is unfortunately necessary on windows because when a modal
  227.  * dialog is up it won't call the OnIdle loop which is currently the
  228.  * source of our events.
  229.  */
  230. MODULE_PRIVATE void
  231. NET_SetNetlibSlowKickTimer(XP_Bool set)
  232. {
  233.     if(net_slow_timer_on == set)
  234.         return; /* do nothing */
  235.  
  236.     net_slow_timer_on = set;
  237.  
  238.     /* call immediately */
  239.     if(net_slow_timer_on)
  240.         FE_SetTimeout(net_process_slow_net_timer_callback, 
  241.                 NULL,     
  242.                 SLOW_NETLIB_TIMER_INTERVAL_MILLISECONDS);
  243. }
  244.  
  245. MODULE_PRIVATE void
  246. NET_ClearCallNetlibAllTheTime(MWContext *context, char *caller)
  247. {
  248.     if(net_calling_all_the_time_count < 1)
  249.     {
  250.         XP_ASSERT(0);
  251.         net_calling_all_the_time_count = 1;
  252.     }
  253.  
  254.     net_calling_all_the_time_count--;
  255.  
  256. }
  257.  
  258. MODULE_PRIVATE XP_Bool
  259. NET_IsCallNetlibAllTheTimeSet(MWContext *context, char *caller)
  260. {
  261.     if(caller == NULL)
  262.     {
  263.         if(net_calling_all_the_time_count > 0)
  264.             return TRUE;
  265.     }
  266.     else
  267.     {
  268.         /* not implemented */
  269.         XP_ASSERT(0);
  270.     }
  271.  
  272.     return FALSE;
  273. }
  274.  
  275. MODULE_PRIVATE void
  276. NET_ClearDNSSelect(MWContext *context, PRFileDesc *file_desc)
  277. {
  278. #if defined(XP_WIN) || (defined(XP_UNIX) && defined(UNIX_ASYNC_DNS)) || (defined(XP_OS2) && !defined(XP_OS2_DOUGSOCK))
  279.       /* FE_AbortDNSLookup(file_desc);  */
  280. #endif /* XP_WIN || (XP_UNIX && UNIX_ASYNC_DNS) || (defined(XP_OS2) && !defined(XP_OS2_DOUGSOCK) */
  281.  
  282. }
  283.  
  284. MODULE_PRIVATE void
  285. NET_SetFileReadSelect(MWContext *context, int file_desc)
  286. {
  287.     /* need to conver this over to NSPR PRFileDesc's before it will work */
  288. /*    FE_SetFileReadSelect(context, file_desc);     */
  289. }
  290.  
  291. MODULE_PRIVATE void
  292. NET_ClearFileReadSelect(MWContext *context, int file_desc)
  293. {
  294.     /* need to conver this over to NSPR PRFileDesc's before it will work */
  295. /*    FE_ClearReadSelect(context, file_desc);         */
  296. }
  297.  
  298. MODULE_PRIVATE void
  299. NET_SetReadSelect(MWContext *context, PRFileDesc *file_desc)
  300. {
  301.     NET_SetReadPoll(file_desc);
  302. }
  303.  
  304. MODULE_PRIVATE void
  305. NET_ClearReadSelect(MWContext *context, PRFileDesc *file_desc)
  306. {
  307.     NET_ClearReadPoll(file_desc);
  308. }
  309.  
  310. MODULE_PRIVATE void
  311. NET_SetConnectSelect(MWContext *context, PRFileDesc *file_desc)
  312. {
  313.     NET_SetConnectPoll(file_desc);
  314. }
  315.  
  316. MODULE_PRIVATE void
  317. NET_ClearConnectSelect(MWContext *context, PRFileDesc *file_desc)
  318. {
  319.     NET_ClearConnectPoll(file_desc);
  320. }
  321.