crossroads

Git mirror of https://crossroads.e-tunity.com/
git clone git://git.finwo.net/app/crossroads
Log | Files | Refs

netcopy.c (3148B)


      1 /*************************************************************************
      2  * This file is part of Crosroads 1.23, a load balancer and fail over
      3  * utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
      4  * Visit http://crossroads.e-tunity.com for information.
      5  *************************************************************************/
      6 #include "crossroads.h"
      7 
      8 unsigned net_copy (int cl, int sr, unsigned max, unsigned char *buf) {
      9     fd_set readset, exset;
     10     struct timeval tv, *tvp, tv1, tv2;
     11     int nfd;
     12     unsigned nread, nwritten, totwritten;
     13     CopyDirection dir;
     14     double microsec;
     15 
     16     /* Prepare select() sets */
     17     FD_ZERO (&readset);
     18     FD_ZERO (&exset);
     19 
     20     FD_SET (cl, &readset);
     21     FD_SET (cl, &exset);
     22     FD_SET (sr, &readset);
     23     FD_SET (sr, &exset);
     24 
     25     /* Prepare timout state */
     26     if (activeservice->connectiontimeout) {
     27 	tv.tv_sec = activeservice->connectiontimeout;
     28 	tv.tv_usec = 0;
     29 	tvp = &tv;
     30     } else
     31 	tvp = 0;
     32 
     33     /* Wait for a socket to become readable */
     34     gettimeofday (&tv1, 0);
     35     nfd = select (FD_SETSIZE, &readset, 0, &exset, tvp);
     36     if (nfd < 1) {
     37 	decr_client_count();
     38 	log_activity_end();
     39 	mark_activity (0, 0, st_available);
     40 	error ("Service %s: network copy stopped after timeout",
     41 	       activeservice->name);
     42     }
     43 
     44     /* Check for exceptions. */
     45     if (FD_ISSET (cl, &exset)) {
     46 	decr_client_count();
     47 	log_activity_end();
     48 	error ("Service %s: client exception", activeservice->name);
     49     }
     50     if (FD_ISSET (sr, &exset)) {
     51 	decr_client_count();
     52 	log_activity_end();
     53 	mark_activity (0, 0, st_unavailable);
     54 	error ("Service %s: server exception", activeservice->name);
     55     }
     56 
     57     /* Do the read. */
     58     if (FD_ISSET (sr, &readset))
     59 	dir = dir_server_to_client;
     60     else
     61 	dir = dir_client_to_server;
     62 
     63     nread = read (dir == dir_client_to_server ? cl : sr, buf, max);
     64     if (nread < 1) {
     65 	decr_client_count();
     66 	log_activity_end();
     67 	if (nread < 0) {
     68 	    if (dir == dir_server_to_client)
     69 		mark_activity (0, 0, st_unavailable);
     70 	    error ("Service %s: read error when getting data from %s",
     71 		   activeservice->name,
     72 		   dir == dir_client_to_server ? "client" : "server");
     73 	} else {
     74 	    msg ("Service %s: %s signals end of data",
     75 		 activeservice->name,
     76 		 dir == dir_client_to_server ? "client" : "server");
     77 	    exit (0);
     78 	}
     79     }
     80 
     81     /* Update thruput / traffic logs. */
     82     trafficlog (buf, nread, dir);
     83     thruputlog (buf, nread, dir);
     84 
     85     /* Write to dest. */
     86     totwritten = 0;
     87     while (totwritten < nread) {
     88 	nwritten = write (dir == dir_client_to_server ? sr : cl,
     89 			  buf + totwritten,
     90 			  nread - totwritten);
     91 	if (nwritten < 1) {
     92 	    if (dir == dir_client_to_server)
     93 		mark_activity (0, 0, st_unavailable);
     94 	    decr_client_count();
     95 	    log_activity_end();
     96 	    error ("Service %s: write error when sending data to %s",
     97 		   dir == dir_client_to_server ? "server" : "client");
     98 	}
     99 	totwritten += nwritten;
    100     }
    101 
    102     gettimeofday (&tv2, 0);
    103     microsec = ( (tv2.tv_sec * 1000000 + tv2.tv_usec) -
    104                  (tv1.tv_sec * 1000000 + tv1.tv_usec) );
    105 
    106     mark_activity (totwritten, microsec / 1000000, st_intermediate);
    107 
    108     return (nread);
    109 }