tools.go_stun

Yohn Y. 2020-04-25 Parent:6455d3067db1 Child:12d8f041fbdf

3:102fbdab34d8 Go to Latest

tools.go_stun/main.go

+ Добавляем логирование в отдельной горутине, чтобы снизить влияние процесса логирования на время обработки запросов

History
1 package main
3 import (
4 "errors"
5 "fmt"
6 "log/syslog"
7 "net"
8 "os"
9 "strings"
10 "time"
11 )
13 const (
14 LOG_IDENT string = "net-a0fs-gostun"
15 )
17 const (
18 LOGP_INFO = iota
19 LOGP_WARN
20 LOGP_ERR
21 )
23 type logMessage struct {
24 prio uint
25 msg string
26 }
28 var log_chan = make(chan logMessage, 100)
30 func log_handler() {
31 var err error
33 log, err := syslog.New(syslog.LOG_USER, LOG_IDENT)
34 if err != nil {
35 panic(err)
36 }
38 for log_msg := range log_chan {
39 switch log_msg.prio {
40 case LOGP_INFO:
41 err = log.Info(log_msg.msg)
42 case LOGP_WARN:
43 err = log.Warning(log_msg.msg)
44 case LOGP_ERR:
45 err = log.Err(log_msg.msg)
46 default:
47 err = log.Err(fmt.Sprintf("Unknown type of log priority: %v", log_msg.prio))
48 }
50 if err != nil {
51 panic(err)
52 }
53 }
54 }
56 func log_info(msg string, vars ...interface{}) {
57 log_chan <- logMessage{
58 prio: LOGP_INFO,
59 msg: fmt.Sprintf(msg, vars...)}
60 }
62 func log_warn(msg string, vars ...interface{}) {
63 log_chan <- logMessage{
64 prio: LOGP_WARN,
65 msg: fmt.Sprintf(msg, vars...)}
66 }
68 func log_err(msg string, vars ...interface{}) {
69 log_chan <- logMessage{
70 prio: LOGP_ERR,
71 msg: fmt.Sprintf(msg, vars...)}
72 }
74 func getPort() (res string, err error) {
75 if len(os.Args) < 2 {
76 err = errors.New("No port specify")
77 } else {
78 res = fmt.Sprintf(":%s", os.Args[1])
79 }
80 return
81 }
83 func fail(code int, msg string) {
84 usage := "Usage: cmd port"
85 usage += "\n port: port number for listening clients"
87 fmt.Fprintln(os.Stderr, msg)
88 fmt.Fprintln(os.Stderr, usage)
89 os.Exit(code)
90 return
91 }
93 func handler(conn net.Conn) {
94 _s_tm := time.Now()
95 remoteAddr := conn.RemoteAddr().String()
97 defer func() {
98 var err error
99 _s_tmd := time.Now().Sub(_s_tm)
100 if r_err := recover(); r_err != nil {
101 log_err("Error on service for %s (service time: %v): %v", remoteAddr, _s_tmd, r_err)
102 } else {
103 err = conn.Close()
104 if err != nil {
105 log_err("Error on closing socket when service %s (service time: %v): %v",
106 remoteAddr, _s_tmd, err)
108 } else {
109 log_info("Ok service %s in %v", remoteAddr, _s_tmd)
112 }()
114 addr_spit := strings.Split(remoteAddr, ":")
115 addr_last := len(addr_spit) - 1
116 addr := strings.Join(addr_spit[:addr_last], ":")
118 var dns string
119 dns_names, err := net.LookupAddr(strings.Trim(addr, "[] "))
120 if err != nil {
121 log_warn("Fail to resolve dns name for %s: %v", remoteAddr, err)
122 } else {
123 for _, dns_name := range dns_names {
124 dns += "Name: " + dns_name + "\n"
127 addr = "IP: " + addr + "\n"
128 port := "Port: " + addr_spit[addr_last] + "\n"
130 if _, err := conn.Write([]byte(addr)); err != nil {
131 panic(err.Error())
133 if _, err := conn.Write([]byte(dns)); err != nil {
134 panic(err.Error())
136 if _, err := conn.Write([]byte(port)); err != nil {
137 panic(err.Error())
141 func main() {
142 port, err := getPort()
143 if err != nil {
144 fail(1, fmt.Sprint("Error in parsing port number: ", err))
147 go log_handler()
149 svc, err := net.Listen("tcp", port)
150 if err != nil {
151 fail(2, fmt.Sprint("Fail to open socket: ", err))
154 for {
155 conn, err := svc.Accept()
156 if err != nil {
157 fail(1, fmt.Sprint("Error accepting connections: ", err))
159 go handler(conn)