Пример #1
0
func handleConnection(log *logrus.Entry, c net.Conn, timeout time.Duration) {
	var err error
	defer c.Close()
	writer := textproto.NewWriter(bufio.NewWriter(c))
	// This is annoying
	// if ApiWelcomeMessage != "" {
	// 	writer.PrintfLine(ApiWelcomeMessage)
	// }
	bufc := bufio.NewReaderSize(c, 10*1024*1024)
	for {
		var msg []byte
		select {
		case <-Done:
			return
		default:
			c.SetDeadline(time.Now().Add(timeout))
			msg, err = bufc.ReadBytes('\n')
			if err != nil {
				if err.Error() != "EOF" {
					log.WithError(err).Debug("Unable to read from connection")
					if ApiErrorHandlerFn != nil {
						ApiErrorHandlerFn(err, writer)
					}
				}
				return
			}
			log.WithField("size", len(msg)).Debug("Read on connection")
			for _, h := range ApiMessageHandlerFns {
				h(msg, writer)
			}
		}
	}
}
Пример #2
0
/*
CACHE <statusCode> <crc32>\r\n
Headers: Values\r\n
\r\n
<body>
*/
func (p *proxyWriter) cacheHeader() {
	if p.c.useStale&Supdating == 0 {
		p.lock()
	}
	hdr := p.rw.Header()
	p.f = p.createf()
	p.bw = bufio.NewWriter(p.f)
	tpw := textproto.NewWriter(p.bw)
	err := tpw.PrintfLine("CACHE %d %d", p.statusCode, p.st.crc)
	if err != nil {
		panic(err)
	}
	for k, v := range hdr {
		switch k {
		case "Cache-Control", "Expires":
			continue
		}
		for _, s := range v {
			err = tpw.PrintfLine("%s: %s", k, s)
			if err != nil {
				panic(err)
			}
		}
	}
	_, err = p.bw.WriteString("\r\n")
	if err != nil {
		panic(err)
	}
}
Пример #3
0
func newHandler(s *server, conn net.Conn) *handler {
	return &handler{
		server: s,
		conn:   conn,
		reader: textproto.NewReader(bufio.NewReader(conn)),
		writer: textproto.NewWriter(bufio.NewWriter(conn)),
	}
}
Пример #4
0
func (c *Conn) handleOutput() {
	var w = textproto.NewWriter(bufio.NewWriter(c.c))
	for {
		select {
		case out := <-c.Out:
			w.PrintfLine(out)
		case <-c.Err:
			return
		}
	}
}
Пример #5
0
func newSession(server *Server, handler SessionHandler, conn net.Conn, isTLS bool) *session {
	return &session{
		server:    server,
		sHandler:  handler,
		conn:      conn,
		gotHelo:   false,
		isTLS:     isTLS,
		keepGoing: true,
		reader:    textproto.NewReader(bufio.NewReader(conn)),
		writer:    textproto.NewWriter(bufio.NewWriter(conn)),
	}
}
Пример #6
0
func newIrcClient(conn net.Conn) *ircClient {
	c := &ircClient{
		conn,
		textproto.NewWriter(bufio.NewWriter(conn)),
		make(chan []string, 1024),
		make(chan string, 1),
		make(chan []string, 6),
	}

	go func() {
		var line string
		var fields []string
		var err error
		r := textproto.NewReader(bufio.NewReader(conn))
		for {
			if line, err = r.ReadLine(); err == nil {
				fields = strings.Fields(line)[1:]
				if len(fields) > 3 {
					switch fields[0] {

					case RPL_NAMREPLY:
						c.namesReplies <- fields[2:]

					case RPL_WHOISUSER, RPL_WHOISSERVER, RPL_WHOISOPERATOR, RPL_WHOISIDLE, RPL_ENDOFWHOIS, RPL_WHOISCHANNELS:
						c.whoisReplies <- fields

					case RPL_ENDOFNAMES:

					default:
						if Verbose {
							fmt.Fprintln(os.Stderr, "\t ", line)
						}
					}
				} else if len(fields) >= 2 && fields[0] == "PING" {
					c.w.PrintfLine("PONG %s", fields[1])
				} else {
					if Verbose {
						fmt.Fprintf(os.Stderr, "got some sort of short unhandled msg %q\n", line)
					}
				}
			} else {
				fmt.Fprintln(os.Stderr, err)
				conn.Close()
				break
			}
		}
	}()

	c.w.PrintfLine("NICK fc%x", rand.Int31())
	c.w.PrintfLine("USER %x 8 * :%x", rand.Int31(), rand.Int31())
	return c
}
Пример #7
0
// Dial connects to an IRC host.
func Dial(address string) (*Client, error) {
	conn, err := net.Dial("tcp", address)
	if err != nil {
		return nil, err
	}
	client := Client{
		conn:     conn,
		writer:   textproto.NewWriter(bufio.NewWriter(conn)),
		reader:   textproto.NewReader(bufio.NewReader(conn)),
		send:     make(chan *Msg, 5),
		recv:     make(chan *Msg, 5),
		handlers: make([]Handler, 0),
	}
	return &client, nil
}
Пример #8
0
func (self nntpFrontend) handle_connection(sock net.Conn) {
	log.Println("incoming nntp frontend connection", sock.RemoteAddr())
	// wrap the socket
	r := textproto.NewReader(bufio.NewReader(sock))
	w := textproto.NewWriter(bufio.NewWriter(sock))
	var line, newsgroup string
	// write out greeting
	err := w.PrintfLine("201 ayyy srndv2 nntp frontend here, posting disallowed")
	for {
		if err != nil {
			// abort it
			log.Println("error handling nntp frontend connection", err)
			break
		}
		line, err = r.ReadLine()
		lline := strings.ToLower(line)

		// we are in reader mode
		if lline == "quit" {
			break
		} else if strings.HasPrefix(lline, "newsgroups ") {
			// handle newsgroups command
			// TODO: don't ignore dates
			w.PrintfLine("231 list of newsgroups follows")
			groups := self.db.GetAllNewsgroups()
			dw := w.DotWriter()
			for _, group := range groups {
				last, first, err := self.db.GetLastAndFirstForGroup(group)
				if err == nil {
					io.WriteString(dw, fmt.Sprintf("%s %d %d y\r\n", group, last, first))
				} else {
					log.Println("cannot get last/first ids for group", group, err)
				}
			}
			dw.Close()
		} else if lline == "list" {
			w.PrintfLine("215 list of newsgroups follows")
			// handle list command
			groups := self.db.GetAllNewsgroups()
			dw := w.DotWriter()
			for _, group := range groups {
				last, first, err := self.db.GetLastAndFirstForGroup(group)
				if err == nil {
					io.WriteString(dw, fmt.Sprintf("%s %d %d y\r\n", group, last, first))
				} else {
					log.Println("cannot get last/first ids for group", group, err)
				}
			}
			dw.Close()
		} else if strings.HasPrefix(lline, "group ") {
			// handle group command
			newsgroup = lline[6:]
			if self.db.HasNewsgroup(newsgroup) {
				article_count := self.db.CountPostsInGroup(newsgroup, 0)
				last, first, err := self.db.GetLastAndFirstForGroup(newsgroup)
				if err == nil {
					w.PrintfLine("211 %d %d %d %s", article_count, first, last, newsgroup)
				} else {
					w.PrintfLine("500 internal error, %s", err.Error())
				}
			} else {
				w.PrintfLine("411 no such news group")
				newsgroup = ""
			}
		} else if lline == "list overview.fmt" {
			// handle overview listing
			if newsgroup == "" {
				// no newsgroup
				w.PrintfLine("412 No newsgorup selected")
			} else {
				// assume we got the newsgroup set
				dw := w.DotWriter()
				// write out format
				// TODO: hard coded
				io.WriteString(dw, "215 Order of fields in overview database.\r\n")
				io.WriteString(dw, "Subject:\r\nFrom:\r\nDate:\r\nMessage-ID:\r\nRefernces:\r\n")
				dw.Close()
			}
		} else if strings.HasPrefix(lline, "xover ") {
			if newsgroup == "" {
				w.PrintfLine("412 No newsgroup selected")
			} else {
				// handle xover command
				// every article
				models, err := self.db.GetPostsInGroup(newsgroup)
				if err == nil {
					w.PrintfLine("224 Overview information follows")

					dw := w.DotWriter()
					for idx, model := range models {
						io.WriteString(dw, fmt.Sprintf("%.6d\t%s\t\"%s\" <%s@%s>\t%s\t%s\t%s\r\n", idx+1, model.Subject(), model.Name(), model.Name(), model.Frontend(), model.Date(), model.MessageID(), model.Reference()))
					}
					dw.Close()
				} else {
					w.PrintfLine("500 error, %s", err.Error())
				}
			}
		} else if strings.HasPrefix(lline, "article ") {
			if newsgroup == "" {
				w.PrintfLine("412 No Newsgroup Selected")
			} else {
				article := line[8:]
				var msgid string
				var article_no int64
				if ValidMessageID(article) {
					article_no = 0 // eh
				} else {
					article_no, err = strconv.ParseInt(article, 10, 32)
					if err == nil {
						msgid, err = self.db.GetMessageIDForNNTPID(newsgroup, article_no)
					}
				}
				if err == nil {
					w.PrintfLine("220 %d %s", article_no, msgid)
					fname := self.store.GetFilename(msgid)
					f, err := os.Open(fname)
					if err == nil {
						dw := w.DotWriter()
						_, err = io.Copy(dw, f)
						dw.Close()
						f.Close()
					}
				} else {
					w.PrintfLine("500 error, %s", err.Error())
				}
			}
		} else if lline == "mode reader" {
			w.PrintfLine("201 posting disallowed")
		} else if strings.HasPrefix(lline, "mode ") {
			// handle other mode
			w.PrintfLine("%d mode not implemented", 501)
		} else if lline == "capabilities" {
			// send capabilities
			dw := w.DotWriter()
			io.WriteString(dw, "101 yeh we can do stuff\r\n")
			io.WriteString(dw, "VERSION 2\r\n")
			io.WriteString(dw, "IMPLEMENTATION srndv2 nntp frontend\r\n")
			io.WriteString(dw, "READER\r\n")
			dw.Close()
		} else {
			// idk what command this is, log it and report error
			log.Println("invalid line from nntp frontend connection:", line)
			w.PrintfLine("500 idk what that means")
		}
	}
	sock.Close()
	log.Println("nntp frontend connection closed")
}
Пример #9
0
func handleConnection(c *net.TCPConn) {
	defer c.Close()
	defer log.WithField("client", c.RemoteAddr()).Debug("Disconnected")
	// var timeout = 60 * time.Second
	var lastMsg []byte
	var bufc = bufio.NewReader(c)
	for {
		var msg []byte
		var err error
		select {
		default:
			writer := textproto.NewWriter(bufio.NewWriter(c))
			// c.SetDeadline(time.Now().Add(timeout))
			msg, err = bufc.ReadBytes('\n')
			if err != nil {
				switch err.(type) {
				case net.Error:
					if err.(net.Error).Timeout() {
						log.Warn("Connection timed out")
					}
				default:
					if err != io.EOF {
						log.WithField("error", err).Error("Reading bytes")
					}
				}
				return
			}
			if bytes.Compare(bytes.TrimSpace(msg), []byte(`!!`)) == 0 {
				log.WithField("msg", bytes.NewBuffer(lastMsg).String()).Info("Writing last message")
				c.Write(lastMsg)
				if err != nil {
					log.WithField("err", err).Error("Unable to write last message")
				}
				msg = lastMsg
			}
			switch {
			case bytes.HasPrefix(msg, []byte(`publish `)):
				matches := publishCmd.FindSubmatch(msg)
				if len(matches) != 3 {
					err = errors.New(`Unrecognized pattern for command "publish"`)
				} else {
					//					var event map[string]interface{}
					//					err := json.Unmarshal(matches[2], &event)
					//					if err != nil {
					//						log.WithFields(log.Fields{"err": err, "msg": string(matches[2])}).Error("Bad json")
					//						break
					//					}
					err = nc.Publish(string(matches[1]), matches[2])
					if err != nil {
						log.WithField("err", err).Error("Publish failed")
						break
					}
					log.Debug("Message published")
				}
			case bytes.HasPrefix(msg, []byte(`#`)):
				// Comment line
				msg = lastMsg
			case len(bytes.TrimSpace(msg)) == 0:
				// Empty line
				msg = lastMsg
			default:
				err = errors.New("Unrecognized command")
			}
			if err != nil {
				log.Error(err)
				writer.PrintfLine(err.Error())
				writer.PrintfLine(apiHelp())
			}
			lastMsg = msg
		}
	}
}
Пример #10
0
func (pconn *persistentConn) setControlConn(conn net.Conn) {
	pconn.controlConn = conn
	pconn.reader = textproto.NewReader(bufio.NewReader(conn))
	pconn.writer = textproto.NewWriter(bufio.NewWriter(conn))
}