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 }