Goroutine to service a client connection
(conn net.Conn)
| 55 | |
| 56 | // Goroutine to service a client connection |
| 57 | func ServiceConnection(conn net.Conn) { |
| 58 | |
| 59 | // Save off address |
| 60 | addr := conn.RemoteAddr().String() |
| 61 | |
| 62 | // Attach a Reader object to the connection, so we can read from it easily |
| 63 | in := bufio.NewReader(conn) |
| 64 | |
| 65 | // In our trivial protocol, the first line contains the client identity |
| 66 | // on a line by itself |
| 67 | intro, err := in.ReadString('\n') |
| 68 | if err != nil { |
| 69 | log.Printf("[%s] Aborting connection before we ever received client identity", addr) |
| 70 | conn.Close() |
| 71 | } |
| 72 | identity := strings.TrimSpace(intro) |
| 73 | |
| 74 | // Amnnnnnd that's it. No authentication. |
| 75 | |
| 76 | // Locate existing connection, if any. |
| 77 | existingConn := g_mapClientConnections[identity] |
| 78 | |
| 79 | // Add us to map or replace existing entry |
| 80 | g_mapClientConnections[identity] = conn |
| 81 | |
| 82 | // Now handle existing entry |
| 83 | if existingConn != nil { |
| 84 | log.Printf("[%s@%s] Closing connection to make room for new connection from '%s'", identity, existingConn.RemoteAddr().String(), addr) |
| 85 | existingConn.Close() |
| 86 | } |
| 87 | log.Printf("[%s@%s] Added connection", identity, addr) |
| 88 | |
| 89 | // Keep reading until connection is closed |
| 90 | for { |
| 91 | line, err := in.ReadString('\n') |
| 92 | if err != nil { |
| 93 | conn.Close() |
| 94 | |
| 95 | // Are we stil in the map? |
| 96 | if g_mapClientConnections[identity] == conn { |
| 97 | log.Printf("[%s@%s] Connecton closed. %s", identity, addr, err) |
| 98 | delete(g_mapClientConnections, identity) |
| 99 | } else { |
| 100 | // Assume it's because we got replaced by another connection. |
| 101 | // The other connection already logged, so don't do anything here |
| 102 | } |
| 103 | break |
| 104 | } |
| 105 | |
| 106 | // Our protocol is just [destination peer identity] [payload] |
| 107 | // And everything is in text. |
| 108 | dest_and_msg := strings.SplitN(line, " ", 2) |
| 109 | if len(dest_and_msg) != 2 { |
| 110 | log.Printf("[%s@%s] Ignoring weird input '%s' (maybe truncated?)", identity, addr, line) |
| 111 | continue |
| 112 | } |
| 113 | dest_identity := strings.TrimSpace(dest_and_msg[0]) |
| 114 | payload := dest_and_msg[1] |