-
Notifications
You must be signed in to change notification settings - Fork 2
/
client.go
95 lines (80 loc) · 1.64 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Package ident implements an RFC 1413 client
package ident // import "honnef.co/go/ident"
import (
"bufio"
"fmt"
"net"
"strings"
)
type Response struct {
OS string
Charset string
Identifier string
}
type ResponseError struct {
Type string
}
func (e ResponseError) Error() string {
return fmt.Sprintf("Ident error: %s", e.Type)
}
type ProtocolError struct {
Line string
}
func (e ProtocolError) Error() string {
return fmt.Sprintf("Unexpected response from server: %s", e.Line)
}
func Query(ip string, portOnServer, portOnClient int) (Response, error) {
var (
conn net.Conn
err error
fields []string
r *bufio.Reader
resp string
)
conn, err = net.Dial("tcp", ip+":113")
if err != nil {
goto Error
}
_, err = conn.Write([]byte(fmt.Sprintf("%d, %d", portOnServer, portOnClient)))
if err != nil {
goto Error
}
r = bufio.NewReader(conn)
resp, err = r.ReadString('\n')
if err != nil {
goto Error
}
fields = strings.SplitN(strings.TrimSpace(resp), " : ", 4)
if len(fields) < 3 {
goto ProtocolError
}
switch fields[1] {
case "USERID":
if len(fields) != 4 {
goto ProtocolError
}
var os, charset string
osAndCharset := strings.SplitN(fields[2], ",", 2)
if len(osAndCharset) == 2 {
os = osAndCharset[0]
charset = osAndCharset[1]
} else {
os = osAndCharset[0]
charset = "US-ASCII"
}
return Response{
OS: os,
Charset: charset,
Identifier: fields[3],
}, nil
case "ERROR":
if len(fields) != 3 {
goto ProtocolError
}
return Response{}, ResponseError{fields[3]}
}
ProtocolError:
return Response{}, ProtocolError{resp}
Error:
return Response{}, err
}