]> Cypherpunks.ru repositories - nncp.git/blob - src/cypherpunks.ru/nncp/humanizer.go
68031d833a982174e463f3c33517f5013893c92b
[nncp.git] / src / cypherpunks.ru / nncp / humanizer.go
1 /*
2 NNCP -- Node to Node copy
3 Copyright (C) 2016-2019 Sergey Matveev <stargrave@stargrave.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package nncp
20
21 import (
22         "fmt"
23         "regexp"
24         "strconv"
25         "strings"
26         "time"
27
28         "github.com/dustin/go-humanize"
29 )
30
31 func (ctx *Ctx) Humanize(s string) string {
32         s = strings.TrimRight(s, "\n")
33         splitted := strings.SplitN(s, " ", 4)
34         if len(splitted) != 4 {
35                 return s
36         }
37         var level string
38         if splitted[0] == "E" {
39                 level = "ERROR "
40         }
41         when, err := time.Parse(time.RFC3339Nano, splitted[1])
42         if err != nil {
43                 return s
44         }
45         who := splitted[2][1:]
46         closingBracket := strings.LastIndex(splitted[3], "]")
47         if closingBracket == -1 {
48                 return s
49         }
50         rem := strings.Trim(splitted[3][closingBracket+1:], " ")
51         sds := make(map[string]string)
52
53         re := regexp.MustCompile(`\w+="[^"]+"`)
54         for _, pair := range re.FindAllString(splitted[3][:closingBracket+1], -1) {
55                 sep := strings.Index(pair, "=")
56                 sds[pair[:sep]] = pair[sep+2 : len(pair)-1]
57         }
58
59         nodeS := sds["node"]
60         node, err := ctx.FindNode(nodeS)
61         if err == nil {
62                 nodeS = node.Name
63         }
64         var size string
65         if sizeRaw, exists := sds["size"]; exists {
66                 sp, err := strconv.ParseUint(sizeRaw, 10, 64)
67                 if err != nil {
68                         return s
69                 }
70                 size = humanize.IBytes(uint64(sp))
71         }
72
73         var msg string
74         switch who {
75         case "tx":
76                 switch sds["type"] {
77                 case "file":
78                         msg = fmt.Sprintf(
79                                 "File %s (%s) transfer to %s:%s: %s",
80                                 sds["src"], size, nodeS, sds["dst"], rem,
81                         )
82                 case "freq":
83                         msg = fmt.Sprintf(
84                                 "File request from %s:%s to %s: %s",
85                                 nodeS, sds["src"], sds["dst"], rem,
86                         )
87                 case "exec":
88                         msg = fmt.Sprintf(
89                                 "Exec to %s@%s (%s): %s",
90                                 nodeS, sds["dst"], size, rem,
91                         )
92                 case "trns":
93                         msg = fmt.Sprintf(
94                                 "Transitional packet to %s (%s) (nice %s): %s",
95                                 nodeS, size, sds["nice"], rem,
96                         )
97                 default:
98                         return s
99                 }
100                 if err, exists := sds["err"]; exists {
101                         msg += ": " + err
102                 }
103         case "rx":
104                 switch sds["type"] {
105                 case "exec":
106                         msg = fmt.Sprintf(
107                                 "Got exec from %s to %s (%s)",
108                                 nodeS, sds["dst"], size,
109                         )
110                 case "file":
111                         msg = fmt.Sprintf("Got file %s (%s) from %s", sds["dst"], size, nodeS)
112                 case "freq":
113                         msg = fmt.Sprintf("Got file request %s to %s", sds["src"], nodeS)
114                 case "trns":
115                         nodeT := sds["dst"]
116                         node, err := ctx.FindNode(nodeT)
117                         if err == nil {
118                                 nodeT = node.Name
119                         }
120                         msg = fmt.Sprintf(
121                                 "Got transitional packet from %s to %s (%s)",
122                                 nodeS, nodeT, size,
123                         )
124                 default:
125                         return s
126                 }
127                 if err, exists := sds["err"]; exists {
128                         msg += ": " + err
129                 }
130         case "check":
131                 msg = fmt.Sprintf("Checking: %s/%s/%s", sds["node"], sds["xx"], sds["pkt"])
132                 if err, exists := sds["err"]; exists {
133                         msg += fmt.Sprintf(" %s", err)
134                 }
135         case "nncp-xfer":
136                 switch sds["xx"] {
137                 case "rx":
138                         msg = "Packet transfer, received from"
139                 case "tx":
140                         msg = "Packet transfer, sent to"
141                 default:
142                         return s
143                 }
144                 if nodeS != "" {
145                         msg += " node " + nodeS
146                 }
147                 if size != "" {
148                         msg += fmt.Sprintf(" (%s)", size)
149                 }
150                 if err, exists := sds["err"]; exists {
151                         msg += ": " + err
152                 } else {
153                         msg += " " + rem
154                 }
155         case "nncp-bundle":
156                 switch sds["xx"] {
157                 case "rx":
158                         msg = "Bundle transfer, received from"
159                 case "tx":
160                         msg = "Bundle transfer, sent to"
161                 default:
162                         return s
163                 }
164                 if nodeS != "" {
165                         msg += " node " + nodeS
166                 }
167                 msg += " " + sds["pkt"]
168                 if size != "" {
169                         msg += fmt.Sprintf(" (%s)", size)
170                 }
171                 if err, exists := sds["err"]; exists {
172                         msg += ": " + err
173                 }
174         case "nncp-rm":
175                 msg += "removing " + sds["file"]
176         case "call-start":
177                 msg = fmt.Sprintf("Connected to %s", nodeS)
178         case "call-finish":
179                 rx, err := strconv.ParseUint(sds["rxbytes"], 10, 64)
180                 if err != nil {
181                         return s
182                 }
183                 rxs, err := strconv.ParseUint(sds["rxspeed"], 10, 64)
184                 if err != nil {
185                         return s
186                 }
187                 tx, err := strconv.ParseUint(sds["txbytes"], 10, 64)
188                 if err != nil {
189                         return s
190                 }
191                 txs, err := strconv.ParseUint(sds["txspeed"], 10, 64)
192                 if err != nil {
193                         return s
194                 }
195                 msg = fmt.Sprintf(
196                         "Finished call with %s: %s received (%s/sec), %s transferred (%s/sec)",
197                         nodeS,
198                         humanize.IBytes(uint64(rx)), humanize.IBytes(uint64(rxs)),
199                         humanize.IBytes(uint64(tx)), humanize.IBytes(uint64(txs)),
200                 )
201         case "sp-info":
202                 nice, err := NicenessParse(sds["nice"])
203                 if err != nil {
204                         return s
205                 }
206                 msg = fmt.Sprintf(
207                         "Packet %s (%s) (nice %s)",
208                         sds["hash"],
209                         size,
210                         NicenessFmt(nice),
211                 )
212                 offsetParsed, err := strconv.ParseUint(sds["offset"], 10, 64)
213                 if err != nil {
214                         return s
215                 }
216                 sizeParsed, err := strconv.ParseUint(sds["size"], 10, 64)
217                 if err != nil {
218                         return s
219                 }
220                 msg += fmt.Sprintf(": %d%%", 100*offsetParsed/sizeParsed)
221                 if len(rem) > 0 {
222                         msg += ": " + rem
223                 }
224         case "sp-infos":
225                 switch sds["xx"] {
226                 case "rx":
227                         msg = fmt.Sprintf("%s has got for us: ", nodeS)
228                 case "tx":
229                         msg = fmt.Sprintf("We have got for %s: ", nodeS)
230                 default:
231                         return s
232                 }
233                 msg += fmt.Sprintf("%s packets, %s", sds["pkts"], size)
234         case "sp-process":
235                 msg = fmt.Sprintf("%s has %s (%s): %s", nodeS, sds["hash"], size, rem)
236         case "sp-file":
237                 switch sds["xx"] {
238                 case "rx":
239                         msg = "Got packet "
240                 case "tx":
241                         msg = "Sent packet "
242                 default:
243                         return s
244                 }
245                 fullsize, err := strconv.ParseUint(sds["fullsize"], 10, 64)
246                 if err != nil {
247                         return s
248                 }
249                 sizeParsed, err := strconv.ParseUint(sds["size"], 10, 64)
250                 if err != nil {
251                         return s
252                 }
253                 msg += fmt.Sprintf(
254                         "%s %d%% (%s / %s)",
255                         sds["hash"],
256                         100*sizeParsed/fullsize,
257                         humanize.IBytes(uint64(sizeParsed)),
258                         humanize.IBytes(uint64(fullsize)),
259                 )
260         case "sp-done":
261                 switch sds["xx"] {
262                 case "rx":
263                         msg = fmt.Sprintf("Packet %s is retreived (%s)", sds["hash"], size)
264                 case "tx":
265                         msg = fmt.Sprintf("Packet %s is sent", sds["hash"])
266                 default:
267                         return s
268                 }
269         case "nncp-reass":
270                 chunkNum, exists := sds["chunk"]
271                 if exists {
272                         msg = fmt.Sprintf(
273                                 "Reassembling chunked file \"%s\" (chunk %s): %s",
274                                 sds["path"],
275                                 chunkNum,
276                                 rem,
277                         )
278                 } else {
279                         msg = fmt.Sprintf(
280                                 "Reassembling chunked file \"%s\": %s",
281                                 sds["path"],
282                                 rem,
283                         )
284                 }
285                 if err, exists := sds["err"]; exists {
286                         msg += ": " + err
287                 }
288         case "lockdir":
289                 msg = fmt.Sprintf("Acquire lock for %s: %s", sds["path"], sds["err"])
290         default:
291                 return s
292         }
293         return fmt.Sprintf("%s %s%s", when.Format(time.RFC3339), level, msg)
294 }