Skip to content
Snippets Groups Projects
Commit f4989482 authored by Lukas Braun's avatar Lukas Braun
Browse files

test prep: pass reader/writer to handle_conn instead of conn

Because we don't want to keep the connection open while delaying for a
failed login, return the lock from handle_conn if the unlock should be
delayed. serve then closes the connection and sleeps before calling
Unlock().
parent 6b5db999
Branches
Tags
No related merge requests found
......@@ -225,21 +225,12 @@ retry:
}
}
func close(conn net.Conn, remote net.Addr) {
debugf("[%v] closing", remote)
conn.Close() // XXX: check err?
}
func handle_conn(db *sql.DB, conn net.Conn) {
remote := conn.RemoteAddr()
reader := bufio.NewReader(conn)
writer := bufio.NewWriter(conn)
func handle_conn(db *sql.DB, remote string, reader *bufio.Reader,
writer *bufio.Writer) (delay *sync.Mutex) {
debugf("[%v] reading name", remote)
name, err := get_line(reader)
if err != nil {
log.Printf("[%v] %v", remote, err)
close(conn, remote)
return
}
debugf("[%v] name: %v", remote, name)
......@@ -248,7 +239,6 @@ func handle_conn(db *sql.DB, conn net.Conn) {
offer, err := get_line(reader)
if err != nil {
log.Printf("[%v] %v", remote, err)
close(conn, remote)
return
}
......@@ -256,7 +246,6 @@ func handle_conn(db *sql.DB, conn net.Conn) {
result := "FAIL"
match, err := check_offer(db, remote, name, offer)
if err == sql.ErrNoRows {
close(conn, remote)
return
} else if err != nil {
log.Panic(err)
......@@ -271,43 +260,41 @@ func handle_conn(db *sql.DB, conn net.Conn) {
// zeroed mutex if we used a concurrent map without a temporary variable
// and further memory barriers)
faildelay.RLock()
delay, exists := faildelay.userlocks[name]
userlock, exists := faildelay.userlocks[name]
faildelay.RUnlock()
if !exists {
debugf("[%v] not yet in faildelay.userlocks", remote)
faildelay.Lock()
delay, exists = faildelay.userlocks[name]
userlock, exists = faildelay.userlocks[name]
if !exists {
delay = new(sync.Mutex)
faildelay.userlocks[name] = delay
userlock = new(sync.Mutex)
faildelay.userlocks[name] = userlock
}
faildelay.Unlock()
}
delay.Lock()
userlock.Lock()
debugf("[%v] have lock", remote)
if !match {
// invalid offer, unlocked in serve after delaying further attempts
delay = userlock
} else {
defer userlock.Unlock()
}
_, err = fmt.Fprintln(writer, result)
if err != nil {
log.Printf("[%v] %v", remote, err)
goto out
return
}
err = writer.Flush()
if err != nil {
log.Printf("[%v] %v", remote, err)
goto out
}
out:
close(conn, remote)
if !match {
debugf("[%v] delaying for %v", remote, cfg.Faildelay.Duration)
time.Sleep(cfg.Faildelay.Duration)
return
}
debugf("[%v] unlock", remote)
delay.Unlock()
return
}
......@@ -339,7 +326,22 @@ func serve(db *sql.DB) {
log.Printf("new connection: %v\n", conn.RemoteAddr())
// XXX: recover from database failure
go handle_conn(db, conn)
go func(conn net.Conn) {
remote := conn.RemoteAddr().String()
reader := bufio.NewReader(conn)
writer := bufio.NewWriter(conn)
delay := handle_conn(db, remote, reader, writer)
debugf("[%v] closing", remote)
conn.Close() // XXX: check err?
if delay != nil {
debugf("[%v] delaying for %v", remote, cfg.Faildelay.Duration)
time.Sleep(cfg.Faildelay.Duration)
debugf("[%v] unlock", remote)
delay.Unlock()
}
}(conn)
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment