1 /* $OpenBSD: session.c,v 1.9 2021/09/02 21:06:06 deraadt 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 18 #include <assert.h> 19 #include <stdint.h> 20 #include <stdlib.h> 21 #include <unistd.h> 22 23 #include "extern.h" 24 25 /* 26 * Accept how much we've read, written, and file-size, and print them in 27 * a human-readable fashion (with GB, MB, etc. prefixes). 28 * This only prints as the client. 29 */ 30 static void 31 stats_log(struct sess *sess, 32 uint64_t tread, uint64_t twrite, uint64_t tsize) 33 { 34 double tr, tw, ts; 35 const char *tru = "B", *twu = "B", *tsu = "B"; 36 int trsz = 0, twsz = 0, tssz = 0; 37 38 assert(verbose); 39 if (sess->opts->server) 40 return; 41 42 if (tread >= 1024 * 1024 * 1024) { 43 tr = tread / (1024.0 * 1024.0 * 1024.0); 44 tru = "GB"; 45 trsz = 3; 46 } else if (tread >= 1024 * 1024) { 47 tr = tread / (1024.0 * 1024.0); 48 tru = "MB"; 49 trsz = 2; 50 } else if (tread >= 1024) { 51 tr = tread / 1024.0; 52 tru = "KB"; 53 trsz = 1; 54 } else 55 tr = tread; 56 57 if (twrite >= 1024 * 1024 * 1024) { 58 tw = twrite / (1024.0 * 1024.0 * 1024.0); 59 twu = "GB"; 60 twsz = 3; 61 } else if (twrite >= 1024 * 1024) { 62 tw = twrite / (1024.0 * 1024.0); 63 twu = "MB"; 64 twsz = 2; 65 } else if (twrite >= 1024) { 66 tw = twrite / 1024.0; 67 twu = "KB"; 68 twsz = 1; 69 } else 70 tw = twrite; 71 72 if (tsize >= 1024 * 1024 * 1024) { 73 ts = tsize / (1024.0 * 1024.0 * 1024.0); 74 tsu = "GB"; 75 tssz = 3; 76 } else if (tsize >= 1024 * 1024) { 77 ts = tsize / (1024.0 * 1024.0); 78 tsu = "MB"; 79 tssz = 2; 80 } else if (tsize >= 1024) { 81 ts = tsize / 1024.0; 82 tsu = "KB"; 83 tssz = 1; 84 } else 85 ts = tsize; 86 87 LOG1("Transfer complete: " 88 "%.*lf %s sent, %.*lf %s read, %.*lf %s file size", 89 trsz, tr, tru, 90 twsz, tw, twu, 91 tssz, ts, tsu); 92 } 93 94 /* 95 * At the end of transmission, we write our statistics if we're the 96 * server, then log only if we're not the server. 97 * Either way, only do this if we're in verbose mode. 98 * Returns zero on failure, non-zero on success. 99 */ 100 int 101 sess_stats_send(struct sess *sess, int fd) 102 { 103 uint64_t tw, tr, ts; 104 105 if (verbose == 0) 106 return 1; 107 108 tw = sess->total_write; 109 tr = sess->total_read; 110 ts = sess->total_size; 111 112 if (sess->opts->server) { 113 if (!io_write_ulong(sess, fd, tr)) { 114 ERRX1("io_write_ulong"); 115 return 0; 116 } else if (!io_write_ulong(sess, fd, tw)) { 117 ERRX1("io_write_ulong"); 118 return 0; 119 } else if (!io_write_ulong(sess, fd, ts)) { 120 ERRX1("io_write_ulong"); 121 return 0; 122 } 123 } 124 125 stats_log(sess, tr, tw, ts); 126 return 1; 127 } 128 129 /* 130 * At the end of the transmission, we have some statistics to read. 131 * Only do this (1) if we're in verbose mode and (2) if we're the 132 * server. 133 * Then log the findings. 134 * Return zero on failure, non-zero on success. 135 */ 136 int 137 sess_stats_recv(struct sess *sess, int fd) 138 { 139 uint64_t tr, tw, ts; 140 141 if (sess->opts->server || verbose == 0) 142 return 1; 143 144 if (!io_read_ulong(sess, fd, &tw)) { 145 ERRX1("io_read_ulong"); 146 return 0; 147 } else if (!io_read_ulong(sess, fd, &tr)) { 148 ERRX1("io_read_ulong"); 149 return 0; 150 } else if (!io_read_ulong(sess, fd, &ts)) { 151 ERRX1("io_read_ulong"); 152 return 0; 153 } 154 155 stats_log(sess, tr, tw, ts); 156 return 1; 157 } 158