func (s *Server) serveConnection(conn net.Conn) { defer conn.Close() if s.ReadTimeout != 0 { conn.SetReadTimeout(s.ReadTimeout) } if s.WriteTimeout != 0 { conn.SetWriteTimeout(s.WriteTimeout) } br := bufio.NewReader(conn) for { t := &transaction{ server: s, conn: conn, br: br} if err := t.prepare(); err != nil { if err != os.EOF { log.Println("twister: prepare failed", err) } break } t.invokeHandler() if t.hijacked { return } if err := t.finish(); err != nil { log.Println("twister: finish failed", err) break } if t.closeAfterResponse { break } } }
// prepConn() takes a net.Conn and attaches a file descriptor release in its Close method func (p *Proxy) prepConn(c net.Conn) (net.Conn, os.Error) { c.(*net.TCPConn).SetKeepAlive(true) err := c.SetReadTimeout(p.config.Timeout) if err != nil { log.Printf("Error TCP set read timeout: %s\n", err) c.Close() p.fdl.Unlock() return c, err } err = c.SetWriteTimeout(p.config.Timeout) if err != nil { log.Printf("Error TCP set write timeout: %s\n", err) c.Close() p.fdl.Unlock() return c, err } return util.NewRunOnCloseConn(c, func() { p.fdl.Unlock() }), nil }
// Send a request on the connection and hope for a reply. // Up to cfg.attempts attempts. func exchange(cfg *dnsConfig, c net.Conn, name string) (*dnsMsg, os.Error) { if len(name) >= 256 { return nil, &DNSError{Error: "name too long", Name: name} } out := new(dnsMsg) out.id = uint16(rand.Int()) ^ uint16(time.Nanoseconds()) out.question = []dnsQuestion{ dnsQuestion{name, dnsTypeMX, dnsClassINET}, } out.recursion_desired = true msg, ok := out.Pack() if !ok { return nil, &DNSError{Error: "internal error - cannot pack message", Name: name} } for attempt := 0; attempt < cfg.attempts; attempt++ { n, err := c.Write(msg) if err != nil { return nil, err } c.SetReadTimeout(int64(cfg.timeout) * 1e9) // nanoseconds buf := make([]byte, 2000) // More than enough. n, err = c.Read(buf) if err != nil { if e, ok := err.(net.Error); ok && e.Timeout() { continue } return nil, err } buf = buf[0:n] in := new(dnsMsg) if !in.Unpack(buf) || in.id != out.id { continue } return in, nil } var server string if a := c.RemoteAddr(); a != nil { server = a.String() } return nil, &DNSError{Error: "no answer from server", Name: name, Server: server, IsTimeout: true} }
func connect(svc ServiceContext, cs chan<- Msg, conn net.Conn) { defer logAndClose(conn) // Read connect message conn.SetReadTimeout(1e9) // 1s msg := readMessageOrPanic(conn) if msg.Connect == nil { panic("Connect message not received!") } // Check protocol version if *msg.Connect.Version != ProtocolVersion { // TODO: Send a wrong protocol message, for now just close panic(fmt.Sprintf("Wrong protocol version %d, needed %d", *msg.Connect.Version, ProtocolVersion)) } // Send connect reply msg = makeConnect() sendMessageOrPanic(conn, msg) // Read login message msg = readMessageOrPanic(conn) if msg.Login == nil { panic("Login message not received!") } login := msg.Login logged_in, reason := startLogin(login) // Send login reply msg = makeLoginResult(logged_in, reason) sendMessageOrPanic(conn, msg) cl := newClient(svc, cs, conn, login) cs <- addClientMsg{cl} }
func (c *client) worker_loop(n net.Conn) { defer n.Close() for h, _ := range c.handlers { buf := make([]byte, 0) buf = append(buf, []byte(h)...) buf = append(buf, 0) _, e := n.Write(make_req(CAN_DO, []byte(h))) if e != nil { return } } n.SetReadTimeout(1e9 * 60) _, e := n.Write(make_req(GRAB_JOB, []byte{})) if e != nil { return } for { // worker asks for jobs periodically // server will only push a job to a sleeping worker cmd, cmd_len, to, e := read_header(n) if e != nil { return } if to { // timed out, ask for another job _, e := n.Write(make_req(GRAB_JOB, []byte{})) if e != nil { return } continue } if cmd == NO_JOB { // no jobs, go asleep _, e = n.Write(make_req(PRE_SLEEP, []byte{})) if e != nil { return } continue } databuf := make([]byte, cmd_len) _, e = io.ReadFull(n, databuf) if e != nil { return } switch cmd { case NOOP: // a wakeup call? case ECHO_RES: case ERROR: //a := bytes.SplitN ( databuf, []byte{0}, 2 ) case JOB_ASSIGN: done := false var buf []byte = nil for !done { buf, done, e = c.do_work(cmd, databuf) if e != nil { break } } if buf == nil { buf = []byte{1, 0} } _, e = n.Write(make_req(WORK_COMPLETE, buf)) if e != nil { return } } _, e = n.Write(make_req(GRAB_JOB, []byte{})) if e != nil { return } } }