コード例 #1
0
ファイル: packet.go プロジェクト: Craftolution/CraftoCore
func NewPacket(conn *net.TCPConn, raw []byte) (*Packet, error) {
	if len(raw) < 8 {
		return nil, errors.New("The packet is too short. The header can't be completed.")
	}
	if len(raw) > config.MAX_PACKET_SIZE {
		return nil, errors.New("The packet exceeds the maximal packet size.")
	}
	contentLength := int(utils.ByteToUint(raw[0:3])) - 5
	if len(raw) != contentLength+8 {
		return nil, errors.New("The packet content size does not match the size value in the header: " + strconv.Itoa(len(raw)) + " != " + strconv.Itoa(int(contentLength)))
	}
	packet := new(Packet)
	packet.Sender = conn
	packet.ServiceId = utils.ByteToUint8(raw[3])
	packet.PacketType = utils.ByteToUint8(raw[4])
	packet.PacketId = utils.ByteToUint(raw[5:8])
	packet.ContentLength = uint(contentLength)
	if packet.ContentLength > 0 {
		packet.Content = raw[8:]
	} else {
		packet.Content = []byte{}
	}
	packet.Raw = raw
	packet.prepared = true
	return packet, nil
}
コード例 #2
0
ファイル: connect.go プロジェクト: Craftolution/CraftoCore
func (c *ConnectCommand) Handle(packet *core.Packet, service *core.Service) error {
	utils.Debug("CONNECT packet: ", packet)
	if service != nil {
		return errors.New("CONNECT error: There is already a service for this serviceId connected.")
	}
	rawData := packet.Content
	dataLength := len(rawData)
	if dataLength < 2 {
		return errors.New("CONNECT error: The packet data is too short.")
	}
	serviceName := ""
	tunnelHost := ""
	tunnelPorts := make(map[uint8]uint)
	lenServiceName := int(utils.ByteToUint8(rawData[0]))
	if dataLength < 2+lenServiceName {
		return errors.New("CONNECT error: The packet data is too short. (serviceName)")
	}
	lenTunnelHost := int(utils.ByteToUint8(rawData[lenServiceName+1]))
	if dataLength < 2+lenServiceName+lenTunnelHost {
		return errors.New("CONNECT error: The packet data is too short. (tunnelHost)")
	}
	lenTunnelPorts := dataLength - lenServiceName - lenTunnelHost - 2
	if lenTunnelPorts%3 != 0 {
		return errors.New("CONNECT error: The packet data length is not valid. (tunnelPorts)")
	}

	if lenServiceName > 0 {
		serviceName = string(rawData[1 : lenServiceName+1])
	}
	if lenTunnelHost > 0 {
		tunnelHost = string(rawData[lenServiceName+2 : lenServiceName+2+lenTunnelHost])
	}
	for i := 0; i*3 < lenTunnelPorts; i++ {
		pos := lenServiceName + lenTunnelHost + 2 + (i * 3)
		tunnelPorts[utils.ByteToUint8(rawData[pos])] = utils.ByteToUint(rawData[pos+1 : pos+3])
	}
	return c.GetMaster().ConnectService(core.NewService(c.GetMaster(), packet.ServiceId, serviceName, packet.Sender, tunnelHost, tunnelPorts))
}
コード例 #3
0
func (r *PacketReader) Read(conn *net.TCPConn) (*Packet, error) {
	headerBuffer := make([]byte, 8)
	n, err := conn.Read(headerBuffer)
	if err != nil {
		return nil, err
	}
	if n != 8 {
		return nil, errors.New("Packet header was " + strconv.Itoa(n) + " bytes.")
	}
	contentLength := int(utils.ByteToUint(headerBuffer[0:3])) - 5
	if contentLength < 0 {
		return nil, errors.New("Packet ContentLength is a negative number. ContentLength - 5 Header bytes: " + strconv.Itoa(contentLength))
	}
	serviceId := utils.ByteToUint8(headerBuffer[3])
	packetId := utils.ByteToUint(headerBuffer[5:8])
	service := r.master.ServiceById[serviceId]

	// Don't trust the packet serviceId, if the connection is already connected to the master,
	// instead use the connected serviceId information
	setServiceId := serviceId
	for sId, service := range r.master.ServiceById {
		if service.Connection == conn {
			setServiceId = sId
		}
	}
	if setServiceId != serviceId {
		utils.Debug("PacketReader: WARN: The serviceId of the connected service for this Connection (", conn, ") does not match the packet serviceId", serviceId, ". Overriding the packet serviceId for recover messages.")
	}

	recoverMessage := ConstructPacket(conn, setServiceId, PACKETTYPE_NOTHING, packetId, []byte{})
	if contentLength > config.MAX_PACKET_SIZE {
		r.SetRecovering(conn, recoverMessage)
		return nil, errors.New("Packet header indicates too long packet: " + strconv.Itoa(contentLength))
	}
	if service != nil && service.Connection != conn {
		r.SetRecovering(conn, recoverMessage)
		return nil, errors.New("packet sender connection is not origin service connection")
	}
	if lastId, found := r.master.LastPacketId[serviceId]; found {
		if packetId <= lastId {
			r.SetRecovering(conn, recoverMessage)
			return nil, errors.New("Packet header packetId is too small: " + strconv.Itoa(int(packetId)) + " <= " + strconv.Itoa(int(lastId)))
		}
	}
	r.master.LastPacketId[serviceId] = packetId

	if contentLength <= 0 {
		return NewPacket(conn, headerBuffer)
	}

	contentBuffer := make([]byte, contentLength)
	n, err = conn.Read(contentBuffer)
	if err != nil {
		if err != io.EOF && err.Error()[0:11] != "WSARecv tcp" {
			netOpError, ok := err.(*net.OpError)
			if !ok || (netOpError.Err.Error() != "use of closed network connection" && netOpError.Err.Error() != "read: connection reset by peer") {
				r.SetRecovering(conn, recoverMessage)
			}
		}
		return nil, err
	}
	if n != contentLength {
		r.SetRecovering(conn, recoverMessage)
		return nil, errors.New("Packet content does not fit into the defined content buffer size exactly: " + strconv.Itoa(n) + " != " + strconv.Itoa(contentLength))
	}
	return NewPacket(conn, append(headerBuffer, contentBuffer...))
}