diff options
author | Sina Ghaderi <32870524+Sina-Ghaderi@users.noreply.github.com> | 2021-03-19 08:06:20 +0330 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-19 08:06:20 +0330 |
commit | b8bb371ca118aa63785adffd98bb24cc1113f1c5 (patch) | |
tree | 00bab7b7194f92bee0e831958e34c099efbf80ff /vendor/syscon | |
parent | e16ec4f65419aefa0bb401d6af2e30be0d6bfa25 (diff) |
pushing to git services
Diffstat (limited to 'vendor/syscon')
-rw-r--r-- | vendor/syscon/syscon.go | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/vendor/syscon/syscon.go b/vendor/syscon/syscon.go new file mode 100644 index 0000000..50254e0 --- /dev/null +++ b/vendor/syscon/syscon.go @@ -0,0 +1,203 @@ +package syscon + +import ( + "bufio" + "bytes" + "config" + "datax" + "errors" + "fmt" + "net" + "os" + "path/filepath" + "regexp" + "strconv" + "strings" + "syslog" + "time" +) + +func StartNewService(conf *config.Config) { + if err := datax.SQLInit(conf); err != nil { + panic(syslog.BigError{Why: err, Cod: 1}) + } + defer datax.DBClose() + lisfunc, isthere := networkListenType[conf.GetConf("listener_type", 0)] + if !isthere { + panic(syslog.BigError{Why: errors.New("invalid listener_type in config file, should be either inet or unix"), Cod: 1}) + } + l := lisfunc(conf) + defer l.Close() + syslog.InformGreen("connection to sql server established") + syn := regexp.MustCompile(`(^sasl_username=.*[^\s].*)$`) + + for { + conn, err := l.Accept() + if err != nil { + syslog.InformError(err) + continue + } + + go handlePostfixConn(conn, syn) + } + +} + +func handlePostfixConn(conn net.Conn, syn *regexp.Regexp) { + defer conn.Close() + scanner := bufio.NewScanner(conn) + for scanner.Scan() { + if find := syn.MatchString(scanner.Text()); find { + pureName := strings.ReplaceAll(scanner.Text(), "sasl_username=", "") + userAcc, err := datax.GetUserFromDatabase(&pureName) + if err != nil { + syslog.InformError(err) + _, err := conn.Write([]byte("action=REJECT fixrate error: internal server error <1>, contact administrator\n\n")) + if err != nil { + syslog.InformError(err) + return + } + continue + } + + if userAcc.LastReset.Add(time.Duration(userAcc.Reset) * time.Second).Before(time.Now()) { + if err := userAcc.UpdateUserLastReset(time.Now()); err != nil { + syslog.InformError(err) + _, err := conn.Write([]byte("action=REJECT fixrate error: internal server error <2>, contact administrator\n\n")) + if err != nil { + syslog.InformError(err) + return + } + continue + } + + if err := userAcc.UpdateUserCounter(0); err != nil { + syslog.InformError(err) + _, err := conn.Write([]byte("action=REJECT fixrate error: internal server error <3>, contact administrator\n\n")) + if err != nil { + syslog.InformError(err) + return + } + continue + } + userAcc.Counter = 0 + } + if userAcc.Limit <= userAcc.Counter { + diff := userAcc.LastReset.Add(time.Duration(userAcc.Reset) * time.Second).Sub(time.Now()) + _, err := conn.Write([]byte(fmt.Sprintf("action=REJECT fixrate: sending limit exceeded, you can't send anything until next %v\n\n", diff.Round(time.Second)))) + if err != nil { + syslog.InformError(err) + return + } + continue + } + if err := userAcc.UpdateUserCounter(userAcc.Counter + 1); err != nil { + syslog.InformError(err) + _, err := conn.Write([]byte("action=REJECT fixrate error: internal server error <4>, contact administrator\n\n")) + if err != nil { + syslog.InformError(err) + return + } + continue + } + if _, err := conn.Write([]byte("action=OK\n\n")); err != nil { + syslog.InformError(err) + return + } + } + } + if err := scanner.Err(); err != nil { + panic(syslog.BigError{Why: err, Cod: 1}) + } +} + +func checkUinixSocket(socketAddr string) (string, bool) { + unix, err := os.Open("/proc/net/unix") + if err != nil { + panic(syslog.BigError{Why: err, Cod: 1}) + } + defer unix.Close() + u := bufio.NewScanner(unix) + for u.Scan() { + if bytes.Contains(u.Bytes(), []byte(socketAddr)) { + pid := findPid(strings.Fields(u.Text())[6]) + return pid, true + } + } + if err := u.Err(); err != nil { + panic(syslog.BigError{Why: err, Cod: 1}) + } + return "", false +} + +var networkListenType = map[string]func(conf *config.Config) net.Listener{ + "unix": func(conf *config.Config) net.Listener { + socketAddr := conf.GetConf("socket_path", 0) + if pid, exists := checkUinixSocket(socketAddr); exists { + panic(syslog.BigError{Why: fmt.Errorf("unix socket %v is held by another process (pid: %v), is another fixrate daemon runing?", socketAddr, pid), Cod: 1}) + } + if err := os.RemoveAll(socketAddr); err != nil { + panic(syslog.BigError{Why: err, Cod: 1}) + } + SockPerm, err := strconv.Atoi(conf.GetConf("socket_perm", 0)) + if err != nil { + panic(syslog.BigError{Why: errors.New("socket_path should hold an integer"), Cod: 1}) + } + l, err := net.Listen("unix", socketAddr) + if err != nil { + panic(syslog.BigError{Why: err, Cod: 1}) + } + + mod := os.FileMode(SockPerm) + if err = os.Chmod(socketAddr, mod); err != nil { + l.Close() + panic(syslog.BigError{Why: err, Cod: 1}) + } + syslog.InformGreen("start listening on unix socket", socketAddr) + return l + }, + "inet": func(conf *config.Config) net.Listener { + listenAddr := conf.GetConf("listen_addr", 0) + l, err := net.Listen("tcp", listenAddr) + if err != nil { + panic(syslog.BigError{Why: err, Cod: 1}) + } + syslog.InformGreen("start listening on tcp address", listenAddr) + return l + }, +} + +func findPid(inode string) string { + type sysInodes struct { + path string + link string + } + var pid string + fd, err := filepath.Glob("/proc/[0-9]*/fd/[0-9]*") + if err != nil { + return pid + } + + inodes := make([]sysInodes, len(fd)) + mx := make(chan sysInodes, len(fd)) + + go func(fd *[]string, outchan chan<- sysInodes) { + for _, item := range *fd { + link, _ := os.Readlink(item) + outchan <- sysInodes{item, link} + } + }(&fd, mx) + + for range fd { + inodes = append(inodes, <-mx) + } + + re := regexp.MustCompile(inode) + for _, item := range inodes { + out := re.FindString(item.link) + if len(out) != 0 { + pid = strings.Split(item.path, "/")[2] + } + } + return pid +} |