Пример #1
0
func downstream() {
	// Downstream
	for {
		pkt, err := proto.ReadPacket(user.Conn)
		if err != nil {
			fmt.Fprintf(stderr, "Read packet error: %s\n", err.Error())
			user.Conn.Close()
			panic("Socket error!")
		}
		if !pkt.Validate(user.RPubKey) {
			fmt.Fprintf(stderr, "Invalid sign for packet!\n")
			user.Conn.Close()
			panic("Socket error!")
		}
		switch pkt.Frametype {
		case 4:
			if len(pkt.Payload) != 1 {
				fmt.Fprintf(stderr, "Invalid packet\n")
				user.Conn.Close()
				panic("Socket error!")
			}
			if pkt.Payload[0] != 0 {
				fmt.Fprintf(stderr, "Login failed, please try again.")
			}
		case 5:
			str, _, err := proto.ReadString(pkt.Payload)
			if err != nil {
				fmt.Fprintf(stderr, "Invalid packet\n")
				user.Conn.Close()
				panic("Socket error!")
			}
			fmt.Fprintf(stderr, "You are kicked by server: %s\n", str)
			os.Exit(0)
		case 6:
			fmt.Fprintf(stderr, "Room list: \n")
			b := pkt.Payload
			for len(b) >= 6 {
				uid := binary.BigEndian.Uint16(b)
				b = b[2:]
				ua := ""
				ub := ""
				ua, b, err = proto.ReadString(b)
				if err != nil {
					fmt.Fprintf(stderr, "Invalid packet\n")
					user.Conn.Close()
					panic("Socket error!")
				}
				ub, b, err = proto.ReadString(b)
				if err != nil {
					fmt.Fprintf(stderr, "Invalid packet\n")
					user.Conn.Close()
					panic("Socket error!")
				}
				if ua == "" {
					ua = "[Empty]"
				}
				if ub == "" {
					ub = "[Empty]"
				}
				fmt.Fprintf(stderr, "  Room #%d Black: %s White: %s\n", uid, ua, ub)
			}
		case 7:
			fmt.Fprintf(stderr, "User list: \n")
			b := pkt.Payload
			for len(b) >= 2 {
				ua := ""
				ua, b, err = proto.ReadString(b)
				if err != nil {
					fmt.Fprintf(stderr, "Invalid packet\n")
					user.Conn.Close()
					panic("Socket error!")
				}
				fmt.Fprintf(stderr, "  %s\n", ua)
			}
		case 8:
			if len(pkt.Payload) != 1 {
				fmt.Fprintf(stderr, "Invalid packet\n")
				user.Conn.Close()
				panic("Socket error!")
			}
			switch pkt.Payload[0] {
			case 0:
				fmt.Fprintf(stderr, "Join successfully!\n")
			case 1:
				fmt.Fprintf(stderr, "No such room!\n")
			case 2:
				fmt.Fprintf(stderr, "No vacancy in room!\n")
			case 3:
				fmt.Fprintf(stderr, "You are already in a game room!\n")
			}
		case 9:
			fmt.Fprintf(stderr, "You are now in the lobby.\n")
		case 12:
			b := pkt.Payload
			if len(pkt.Payload) <= 21 {
				fmt.Fprintf(stderr, "Invalid packet\n")
				user.Conn.Close()
				panic("Socket error!")
			}
			placed := binary.BigEndian.Uint64(b)
			color := binary.BigEndian.Uint64(b[8:])
			turn := uint8(b[16])
			b = b[17:]
			white, b, err := proto.ReadString(b)
			if err != nil {
				fmt.Fprintf(stderr, "Invalid packet\n")
				user.Conn.Close()
				panic("Socket error!")
			}
			black, b, err := proto.ReadString(b)
			if err != nil {
				fmt.Fprintf(stderr, "Invalid packet\n")
				user.Conn.Close()
				panic("Socket error!")
			}
			fmt.Fprintln(rl.Stdout())
			wc := 0
			bc := 0
			var buff [8]byte
			for i := 0; i <= 63; i++ {
				buff[i&7] = '.'
				if placed&(uint64(1)<<uint(i)) != 0 {
					if color&(uint64(1)<<uint(i)) == 0 {
						bc++
						buff[i&7] = 'b'
					} else {
						buff[i&7] = 'w'
						wc++
					}
				}
				if (i & 7) == 7 {
					fmt.Fprintln(rl.Stdout(), string(buff[:]))
				}
			}
			if white == "" {
				white = "[Empty]"
			}
			if black == "" {
				black = "[Empty]"
			}
			fmt.Fprintf(rl.Stdout(), "White: %s[%d], Black: %s[%d]\n", white, wc, black, bc)
			if turn == 0 {
				fmt.Fprintf(rl.Stdout(), "Game over! ")
				if wc == 0 && bc == 0 {

				} else if wc > bc {
					fmt.Fprintf(rl.Stdout(), "White wins!")
				} else if wc < bc {
					fmt.Fprintf(rl.Stdout(), "Black wins!")
				} else if wc == bc {
					fmt.Fprintf(rl.Stdout(), "Tie")
				}
			} else if turn == 1 {
				fmt.Fprintf(stderr, "Black's turn!\n")
			} else if turn == 2 {
				fmt.Fprintf(stderr, "White's turn!\n")
			}
			fmt.Fprintln(rl.Stdout())
		case 13:
			b := pkt.Payload
			who, b, err := proto.ReadString(b)
			if err != nil {
				fmt.Fprintf(stderr, "Invalid packet\n")
				user.Conn.Close()
				panic("Socket error!")
			}
			msg, b, err := proto.ReadString(b)
			if err != nil {
				fmt.Fprintf(stderr, "Invalid packet\n")
				user.Conn.Close()
				panic("Socket error!")
			}
			if who == "" {
				fmt.Fprintf(stderr, "[SYSTEM] ")
			} else {
				fmt.Fprintf(stderr, "%s: ", who)
			}
			fmt.Fprintln(stderr, msg)
		}
	}
}
Пример #2
0
func client(conn net.Conn, id int) {
	user := new(common.User)
	user.Conn = conn
	user.Pubkey = pubkey
	user.Privkey = privkey
	pkt, err := proto.ReadPacket(user.Conn)
	if err != nil {
		fmt.Fprintf(rl.Stderr(), "[Conn %d] Read packet error: %s\n", id, err.Error())
		user.Conn.Close()
		return
	}
	if pkt.Frametype != 0 || len(pkt.Payload) != 64 {
		fmt.Fprintf(rl.Stderr(), "[Conn %d] Unexpected packet type %d\n", id, pkt.Frametype)
		user.Conn.Close()
		return
	}
	user.RPubKey = new([ed25519.PublicKeySize]byte)
	copy(user.RPubKey[:], pkt.Payload[:32])
	if !pkt.Validate(user.RPubKey) {
		fmt.Fprintf(rl.Stderr(), "[Conn %d] Invalid sign for packet!\n", id)
		user.Conn.Close()
		return
	}
	// Client key & challenge
	payload := make([]byte, 96)
	copy(payload, pubkey[:])
	copy(payload[32:], pkt.Payload[32:])
	challenge := make([]byte, 32)
	_, err = rand.Read(challenge)
	if err != nil {
		fmt.Fprintf(rl.Stderr(), "[Conn %d] !!WARNING!!, random pool error: %s, using empty challenge string!\n", id, err.Error())
	}
	copy(payload[64:], challenge)
	pkt = proto.NewPacket(1, payload)
	pkt.Sign(privkey)
	_, err = user.Conn.Write(pkt.Bytes())
	if err != nil {
		fmt.Fprintf(rl.Stderr(), "[Conn %d] Write packet error: %s\n", id, err.Error())
		user.Conn.Close()
		return
	}
	// Server validation
	pkt, err = proto.ReadPacket(user.Conn)
	if err != nil {
		fmt.Fprintf(rl.Stderr(), "[Conn %d] Read packet error: %s\n", id, err.Error())
		user.Conn.Close()
		return
	}
	if !pkt.Validate(user.RPubKey) {
		fmt.Fprintf(rl.Stderr(), "[Conn %d] Invalid sign for packet!\n", id)
		user.Conn.Close()
		return
	}
	if pkt.Frametype != 2 || len(pkt.Payload) != 32 {
		fmt.Fprintf(rl.Stderr(), "[Conn %d] Unexpected packet type %d\n", id, pkt.Frametype)
		user.Conn.Close()
		return
	}
	if !bytes.Equal(pkt.Payload, challenge) {
		fmt.Fprintf(rl.Stderr(), "[Conn %d] Invalid challenge data!\n", id)
		user.Conn.Close()
		return
	}
	pkt = proto.NewPacket(3, []byte{})
	pkt.Sign(privkey)
	_, err = user.Conn.Write(pkt.Bytes())
	if err != nil {
		fmt.Fprintf(rl.Stderr(), "[Conn %d] Write packet error: %s\n", id, err.Error())
		user.Conn.Close()
		return
	}
	// Login
	for {
		pkt, err = proto.ReadPacket(user.Conn)
		if err != nil {
			fmt.Fprintf(rl.Stderr(), "[Conn %d] Read packet error: %s\n", id, err.Error())
			user.Conn.Close()
			return
		}
		if !pkt.Validate(user.RPubKey) {
			fmt.Fprintf(rl.Stderr(), "[Conn %d] Invalid sign for packet!\n", id)
			user.Conn.Close()
			return
		}
		if pkt.Frametype != 4 {
			fmt.Fprintf(rl.Stderr(), "[Conn %d] Unexpected packet type %d\n", id, pkt.Frametype)
			user.Conn.Close()
			return
		}
		username, _, err := proto.ReadString(pkt.Payload)
		if err != nil {
			fmt.Fprintf(rl.Stderr(), "[Conn %d] Unexpected packet type %d\n", id, pkt.Frametype)
			user.Conn.Close()
			return
		}
		if _, ok := users[username]; !ok {
			// Username ok
			fmt.Fprintf(rl.Stderr(), "[Conn %d] User %s logged in, from %s\n", id, username, user.Conn.RemoteAddr().String())
			pkt = proto.NewPacket(4, []byte{0})
			pkt.Sign(privkey)
			_, err = user.Conn.Write(pkt.Bytes())
			if err != nil {
				fmt.Fprintf(rl.Stderr(), "[Conn %d] Write packet error: %s\n", id, err.Error())
				user.Conn.Close()
				return
			}
			users[username] = user
			user.Name = username
			defer func(name string) { users[name].Kick(""); delete(users, name) }(username) // Delete on leave
			break
		}
		pkt = proto.NewPacket(4, []byte{1})
		pkt.Sign(privkey)
		_, err = user.Conn.Write(pkt.Bytes())
		if err != nil {
			fmt.Fprintf(rl.Stderr(), "[Conn %d] Write packet error: %s\n", id, err.Error())
			user.Conn.Close()
			return
		}
	}
	for !user.Kicked {
		pkt, err := proto.ReadPacket(user.Conn)
		if err != nil {
			fmt.Fprintf(rl.Stderr(), "[Conn %d] Read packet error: %s\n", id, err.Error())
			user.Conn.Close()
			return
		}
		if !pkt.Validate(user.RPubKey) {
			fmt.Fprintf(rl.Stderr(), "[Conn %d] Invalid sign for packet!\n", id)
			user.Conn.Close()
			return
		}
		buf := make([]byte, 16384)
		switch pkt.Frametype {
		case 5: // Quit packet
			reason, _, err := proto.ReadString(pkt.Payload)
			if err != nil {
				fmt.Fprintf(rl.Stderr(), "[Conn %d] Unexpected packet type %d\n", id, pkt.Frametype)
				user.Conn.Close()
				return
			}
			fmt.Fprintf(rl.Stderr(), "[Conn %d] Client Quit: %s\n", id, reason)
			user.Conn.Close()
			return
		case 6: // Roomlist request
			b := buf
			for rid, room := range games {
				if room == nil {
					continue
				}
				usera := ""
				if room.Black != nil {
					usera = room.Black.Name
				}
				userb := ""
				if room.White != nil {
					userb = room.White.Name
				}
				binary.BigEndian.PutUint16(b, rid)
				b = b[2:]
				b, _ = proto.WriteString(b, usera)
				b, _ = proto.WriteString(b, userb)
			}
			length := 16384 - len(b)
			b = buf[:length]
			pkt = proto.NewPacket(6, b)
			pkt.Sign(privkey)
			_, err = user.Conn.Write(pkt.Bytes())
			if err != nil {
				fmt.Fprintf(rl.Stderr(), "[Conn %d] Write packet error: %s\n", id, err.Error())
				user.Conn.Close()
				return
			}
		case 7: // Player list request
			b := buf
			for username := range users {
				b, _ = proto.WriteString(b, username)
			}
			length := 16384 - len(b)
			b = buf[:length]
			pkt = proto.NewPacket(7, b)
			pkt.Sign(privkey)
			_, err = user.Conn.Write(pkt.Bytes())
			if err != nil {
				fmt.Fprintf(rl.Stderr(), "[Conn %d] Write packet error: %s\n", id, err.Error())
				user.Conn.Close()
				return
			}
		case 8:
			if len(pkt.Payload) != 2 {
				fmt.Fprintf(rl.Stderr(), "[Conn %d] Unexpected packet type %d\n", id, pkt.Frametype)
				user.Conn.Close()
				return
			}
			jrid := binary.BigEndian.Uint16(pkt.Payload)
			room := games[jrid]
			result := user.Join(room)
			pkt = proto.NewPacket(8, []byte{result})
			pkt.Sign(privkey)
			_, err = user.Conn.Write(pkt.Bytes())
			if err != nil {
				fmt.Fprintf(rl.Stderr(), "[Conn %d] Write packet error: %s\n", id, err.Error())
				user.Conn.Close()
				return
			}
		case 9:
			user.Leave()
			pkt = proto.NewPacket(9, []byte{})
			pkt.Sign(privkey)
			_, err = user.Conn.Write(pkt.Bytes())
			if err != nil {
				fmt.Fprintf(rl.Stderr(), "[Conn %d] Write packet error: %s\n", id, err.Error())
				user.Conn.Close()
				return
			}
		case 10:
			user.Restart()
			if user.Game.Black != nil {
				user.Game.Black.SendMessage("", fmt.Sprintf("%s is now ready.", user.Name))
			}
			if user.Game.White != nil {
				user.Game.White.SendMessage("", fmt.Sprintf("%s is now ready.", user.Name))
			}
		case 11:
			if len(pkt.Payload) != 1 {
				fmt.Fprintf(rl.Stderr(), "[Conn %d] Unexpected packet type %d\n", id, pkt.Frametype)
				user.Conn.Close()
				return
			}
			xy := uint8(pkt.Payload[0])
			x := xy >> 4
			y := xy & 15
			if user.Game.Black == user {
				if !user.Game.Place(x, y, 1) {
					user.SendMessage("", "Invalid operation")
				}
			} else {
				if !user.Game.Place(x, y, 2) {
					user.SendMessage("", "Invalid operation")
				}
			}
		case 13:
			p := pkt.Payload
			dest, p, err := proto.ReadString(p)
			if err != nil {
				fmt.Fprintf(rl.Stderr(), "[Conn %d] Unexpected packet type %d\n", id, pkt.Frametype)
				user.Conn.Close()
				return
			}
			msg, p, err := proto.ReadString(p)
			if err != nil {
				fmt.Fprintf(rl.Stderr(), "[Conn %d] Unexpected packet type %d\n", id, pkt.Frametype)
				user.Conn.Close()
				return
			}
			if dest != "" {
				u, ok := users[dest]
				if !ok {
					user.SendMessage("", "No such user.")
				} else {
					go u.SendMessage(user.Name, msg)
				}
			}
		}
	}
}