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) } } } }
/* 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) } }
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)), } }
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 } } }
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)), } }
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 }
// 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 }
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") }
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 } } }
func (pconn *persistentConn) setControlConn(conn net.Conn) { pconn.controlConn = conn pconn.reader = textproto.NewReader(bufio.NewReader(conn)) pconn.writer = textproto.NewWriter(bufio.NewWriter(conn)) }