1 /* $Id: session.c,v 1.7 2019/05/08 20:00:25 benno Exp $ */ 2 /* 3 * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include <sys/param.h> 18 19 #include <assert.h> 20 #include <stdint.h> 21 #include <stdlib.h> 22 #include <unistd.h> 23 24 #include "extern.h" 25 26 /* 27 * Accept how much we've read, written, and file-size, and print them in 28 * a human-readable fashion (with GB, MB, etc. prefixes). 29 * This only prints as the client. 30 */ 31 static void 32 stats_log(struct sess *sess, 33 uint64_t tread, uint64_t twrite, uint64_t tsize) 34 { 35 double tr, tw, ts; 36 const char *tru = "B", *twu = "B", *tsu = "B"; 37 int trsz = 0, twsz = 0, tssz = 0; 38 39 assert(verbose); 40 if (sess->opts->server) 41 return; 42 43 if (tread >= 1024 * 1024 * 1024) { 44 tr = tread / (1024.0 * 1024.0 * 1024.0); 45 tru = "GB"; 46 trsz = 3; 47 } else if (tread >= 1024 * 1024) { 48 tr = tread / (1024.0 * 1024.0); 49 tru = "MB"; 50 trsz = 2; 51 } else if (tread >= 1024) { 52 tr = tread / 1024.0; 53 tru = "KB"; 54 trsz = 1; 55 } else 56 tr = tread; 57 58 if (twrite >= 1024 * 1024 * 1024) { 59 tw = twrite / (1024.0 * 1024.0 * 1024.0); 60 twu = "GB"; 61 twsz = 3; 62 } else if (twrite >= 1024 * 1024) { 63 tw = twrite / (1024.0 * 1024.0); 64 twu = "MB"; 65 twsz = 2; 66 } else if (twrite >= 1024) { 67 tw = twrite / 1024.0; 68 twu = "KB"; 69 twsz = 1; 70 } else 71 tw = twrite; 72 73 if (tsize >= 1024 * 1024 * 1024) { 74 ts = tsize / (1024.0 * 1024.0 * 1024.0); 75 tsu = "GB"; 76 tssz = 3; 77 } else if (tsize >= 1024 * 1024) { 78 ts = tsize / (1024.0 * 1024.0); 79 tsu = "MB"; 80 tssz = 2; 81 } else if (tsize >= 1024) { 82 ts = tsize / 1024.0; 83 tsu = "KB"; 84 tssz = 1; 85 } else 86 ts = tsize; 87 88 LOG1("Transfer complete: " 89 "%.*lf %s sent, %.*lf %s read, %.*lf %s file size", 90 trsz, tr, tru, 91 twsz, tw, twu, 92 tssz, ts, tsu); 93 } 94 95 /* 96 * At the end of transmission, we write our statistics if we're the 97 * server, then log only if we're not the server. 98 * Either way, only do this if we're in verbose mode. 99 * Returns zero on failure, non-zero on success. 100 */ 101 int 102 sess_stats_send(struct sess *sess, int fd) 103 { 104 uint64_t tw, tr, ts; 105 106 if (verbose == 0) 107 return 1; 108 109 tw = sess->total_write; 110 tr = sess->total_read; 111 ts = sess->total_size; 112 113 if (sess->opts->server) { 114 if (!io_write_ulong(sess, fd, tr)) { 115 ERRX1("io_write_ulong"); 116 return 0; 117 } else if (!io_write_ulong(sess, fd, tw)) { 118 ERRX1("io_write_ulong"); 119 return 0; 120 } else if (!io_write_ulong(sess, fd, ts)) { 121 ERRX1("io_write_ulong"); 122 return 0; 123 } 124 } 125 126 stats_log(sess, tr, tw, ts); 127 return 1; 128 } 129 130 /* 131 * At the end of the transmission, we have some statistics to read. 132 * Only do this (1) if we're in verbose mode and (2) if we're the 133 * server. 134 * Then log the findings. 135 * Return zero on failure, non-zero on success. 136 */ 137 int 138 sess_stats_recv(struct sess *sess, int fd) 139 { 140 uint64_t tr, tw, ts; 141 142 if (sess->opts->server || verbose == 0) 143 return 1; 144 145 if (!io_read_ulong(sess, fd, &tw)) { 146 ERRX1("io_read_ulong"); 147 return 0; 148 } else if (!io_read_ulong(sess, fd, &tr)) { 149 ERRX1("io_read_ulong"); 150 return 0; 151 } else if (!io_read_ulong(sess, fd, &ts)) { 152 ERRX1("io_read_ulong"); 153 return 0; 154 } 155 156 stats_log(sess, tr, tw, ts); 157 return 1; 158 } 159