Changeset 9b9e13bd4b3785fb55a4554ca02ceae0e7f34fd7

Show
Ignore:
Timestamp:
10/06/11 16:19:04 (8 months ago)
Author:
Neutron Soutmun <neo.neutron@…>
Children:
823108d8770786f2ef1ae5aae248241916093346
Parents:
6ff4a7845cd86f6a6af7c80845bf3f5ae04e9cfc
git-committer:
Neutron Soutmun <neo.neutron@…> (10/06/11 16:19:04)
Message:

squid-auth-helper multi-threaded support

  • tools/squid-auth-helper.c:
    • Support the concurrency > 1 in squid config setting. Could reduce the children to get more memory back as it is not necessary to spawn children much to serve the same scale now.
    • Create up to 8 threads to serve the requests.
Files:
1 modified

Legend:

Unmodified
Added
Removed
  • tools/squid-auth-helper.c

    r3a492ca r9b9e13b  
    1515#include <arpa/inet.h> 
    1616#include <xmlrpc.h> 
     17#include <semaphore.h> 
     18#include <pthread.h> 
    1719 
    1820struct vserver_info 
     
    2325}; 
    2426 
     27struct helper_opts 
     28{ 
     29  gchar   ch_tag[16]; 
     30  gchar   ip[40]; 
     31}; 
     32 
     33typedef struct helper_opts HelperOpts; 
     34 
    2535GList *vservers = 0; 
     36 
     37pthread_mutex_t helper_mtx = PTHREAD_MUTEX_INITIALIZER; 
     38sem_t           helper_sem; 
    2639 
    2740enum lcfg_status 
     
    101114} 
    102115 
     116static void * 
     117service (void *args) 
     118{ 
     119  HelperOpts *opts = (HelperOpts *) args; 
     120  GList   *vs; 
     121  struct in_addr ip_addr; 
     122  guint32  src_ip; 
     123  guint    vserver_id; 
     124  gchar    query[32]; 
     125  gchar   *reply; 
     126  GNetXmlRpcClient *client; 
     127  gint port = 8123; 
     128 
     129  if (inet_aton (opts->ip, &ip_addr) == 0) 
     130    { 
     131      /* ERR: Invalid source IP address */ 
     132      pthread_mutex_lock (&helper_mtx); 
     133      printf ("%sOK user=%s\n", opts->ch_tag, opts->ip); 
     134      fflush (stdout); 
     135      pthread_mutex_unlock (&helper_mtx); 
     136      goto out; 
     137    } 
     138  src_ip = ntohl (ip_addr.s_addr); 
     139 
     140  vserver_id = ~0; 
     141  for (vs = vservers; vs; vs = vs->next) 
     142    { 
     143      struct vserver_info *info = (struct vserver_info *) vs->data; 
     144      if ((src_ip & (~0 << (32 - info->mask))) == info->net_ip) 
     145        { 
     146          vserver_id = info->id; 
     147          break; 
     148        } 
     149    } 
     150 
     151  if (vserver_id == ~0) 
     152    { 
     153      /* ERR: vserver_id not found */ 
     154      pthread_mutex_lock (&helper_mtx); 
     155      printf ("%sOK user=%s\n", opts->ch_tag, opts->ip); 
     156      fflush (stdout); 
     157      pthread_mutex_unlock (&helper_mtx); 
     158      goto out; 
     159    } 
     160 
     161  /* query RahuNAS daemon for user name via xmlrpc */ 
     162  client = gnet_xmlrpc_client_new ("localhost", "/RPC2", port); 
     163  if (!client) 
     164    { 
     165      /* ERR: Failed to connect to localhost XMLRPC */ 
     166      pthread_mutex_lock (&helper_mtx); 
     167      printf ("%sOK user=%s\n", opts->ch_tag, opts->ip); 
     168      fflush (stdout); 
     169      pthread_mutex_unlock (&helper_mtx); 
     170      goto out; 
     171    } 
     172 
     173  snprintf (query, sizeof query, "%s|%d", opts->ip, vserver_id); 
     174  if (gnet_xmlrpc_client_call (client, 
     175                   "getsessioninfo", 
     176                   query, 
     177                   /* output  */ 
     178                   &reply) == 0) 
     179    { 
     180      gchar *tok; 
     181      /* reply format: id|user|sess-id|sess-start|mac|sess-timeout */ 
     182      tok = strtok (reply, "|"); /* id */ 
     183      tok = strtok (NULL, "|"); /* user */ 
     184      pthread_mutex_lock (&helper_mtx); 
     185      printf ("%sOK user=%s\n", opts->ch_tag, tok); 
     186      fflush (stdout); 
     187      pthread_mutex_unlock (&helper_mtx); 
     188      g_free (reply); 
     189    } 
     190  else 
     191    { 
     192      /* ERR: Error calling 'getsessioninfo' XMLRPC */ 
     193      pthread_mutex_lock (&helper_mtx); 
     194      printf ("%sOK user=%s\n", opts->ch_tag, opts->ip); 
     195      fflush (stdout); 
     196      pthread_mutex_unlock (&helper_mtx); 
     197    } 
     198 
     199  gnet_xmlrpc_client_delete (client); 
     200 
     201out: 
     202  sem_post (&helper_sem); 
     203  pthread_exit (NULL); 
     204} 
     205 
    103206int 
    104207main(int argc, char *argv[]) 
    105208{ 
     209  GList *vs; 
    106210  gchar line[1024]; 
    107   GList *vs; 
     211  int   max_concurrent = 8; 
     212  HelperOpts rr_opts[8]; 
     213  int   rr_idx = 0; 
    108214 
    109215  gnet_init (); 
     
    112218  ftw ("/etc/rahunas/rahunas.d", ftw_read_vserver, 20); 
    113219 
     220  /* Init semaphore */ 
     221  sem_init (&helper_sem, 0, max_concurrent); 
     222 
     223  /* Init helper options */ 
     224  memset (&rr_opts, '\0', sizeof (rr_opts)); 
     225 
    114226  /* read input from squid */ 
    115   while (fgets (line, sizeof line, stdin)) 
    116     { 
    117       int      len; 
    118       struct in_addr ip_addr; 
    119       guint32  src_ip; 
    120       guint    vserver_id; 
    121       gchar    query[32]; 
    122       gchar   *reply; 
    123       GNetXmlRpcClient *client; 
    124       gint port = 8123; 
    125  
     227  while (fgets (line, sizeof (line), stdin)) 
     228    { 
     229      pthread_t p; 
     230      int       len; 
     231      gchar    *sep = NULL; 
     232 
     233      line[sizeof (line) - 1] = '\0'; 
    126234      len = strlen (line); 
    127       if (line[len] == '\n') 
    128         line[len--] = '\0'; 
    129  
    130       if (inet_aton (line, &ip_addr) == 0) 
    131         { 
    132           /* ERR: Invalid source IP address */ 
    133           printf ("OK user=%s\n", line); 
     235      if (line[len - 1] == '\n') 
     236        line[--len] = '\0'; 
     237 
     238      sep = strchr (line, ' '); 
     239      if (sep) 
     240        { 
     241          *sep = '\0'; 
     242          strncpy (&rr_opts[rr_idx].ch_tag, line, 
     243                     sizeof (rr_opts[rr_idx].ch_tag) - 2); 
     244          strcat (&rr_opts[rr_idx].ch_tag, " "); 
     245 
     246          /* Strip white-space */ 
     247          sep++; 
     248          while (*sep == ' ' && (sep - line) < sizeof (line)) 
     249            sep++; 
     250 
     251          if ((sep - line) < sizeof (line)) 
     252            { 
     253              strncpy (&rr_opts[rr_idx].ip, sep, 
     254                         sizeof (rr_opts[rr_idx].ip) - 1); 
     255            } 
     256          else 
     257            { 
     258              rr_opts[rr_idx].ip[0] = '\0'; 
     259            } 
     260        } 
     261      else 
     262        { 
     263          rr_opts[rr_idx].ch_tag[0] = '\0'; 
     264          strncpy (&rr_opts[rr_idx].ip, line, sizeof (rr_opts[rr_idx].ip) - 1); 
     265        } 
     266 
     267      sem_wait (&helper_sem); 
     268 
     269      if (pthread_create (&p, NULL, (void *(*)(void *))service, 
     270            (void *)&rr_opts[rr_idx]) != 0) 
     271        { 
     272          pthread_mutex_lock (&helper_mtx); 
     273          printf ("%sOK user=%s\n", rr_opts[rr_idx].ch_tag, rr_opts[rr_idx].ip); 
    134274          fflush (stdout); 
    135           continue; 
    136         } 
    137       src_ip = ntohl (ip_addr.s_addr); 
    138  
    139       vserver_id = ~0; 
    140       for (vs = vservers; vs; vs = vs->next) 
    141         { 
    142           struct vserver_info *info = (struct vserver_info *) vs->data; 
    143           if ((src_ip & (~0 << (32 - info->mask))) == info->net_ip) 
    144             { 
    145               vserver_id = info->id; 
    146               break; 
    147             } 
    148         } 
    149  
    150       if (vserver_id == ~0) 
    151         { 
    152           /* ERR: vserver_id not found */ 
    153           printf ("OK user=%s\n", line); 
    154           fflush (stdout); 
    155           continue; 
    156         } 
    157  
    158       /* query RahuNAS daemon for user name via xmlrpc */ 
    159       client = gnet_xmlrpc_client_new ("localhost", "/RPC2", port); 
    160       if (!client) 
    161         { 
    162           /* ERR: Failed to connect to localhost XMLRPC */ 
    163           printf ("OK user=%s\n", line); 
    164           fflush (stdout); 
    165           continue; 
    166         } 
    167    
    168       snprintf (query, sizeof query, "%s|%d", line, vserver_id); 
    169       if (gnet_xmlrpc_client_call (client, 
    170                                    "getsessioninfo", 
    171                                    query, 
    172                                    /* output  */ 
    173                                    &reply) == 0) 
    174         { 
    175           gchar *tok; 
    176           /* reply format: id|user|sess-id|sess-start|mac|sess-timeout */ 
    177           tok = strtok (reply, "|"); /* id */ 
    178           tok = strtok (NULL, "|"); /* user */ 
    179           printf ("OK user=%s\n", tok); 
    180           fflush (stdout); 
    181           g_free (reply); 
     275          pthread_mutex_unlock (&helper_mtx); 
    182276        } 
    183277      else 
    184278        { 
    185           /* ERR: Error calling 'getsessioninfo' XMLRPC */ 
    186           printf ("OK user=%s\n", line); 
    187           fflush (stdout); 
    188         } 
    189  
    190       gnet_xmlrpc_client_delete (client); 
     279          pthread_detach (p); 
     280        } 
     281 
     282      rr_idx++; 
     283      rr_idx = rr_idx < max_concurrent ? rr_idx : 0; 
    191284    } 
    192285