コード例 #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
func (c *UnsubscribeCommand) Handle(packet *core.Packet, service *core.Service) error {
	utils.Debug("UNSUBSCRIBE packet: ", packet)
	if service == nil {
		return errors.New("UNSUBSCRIBE error: There is no service for this serviceId connected.")
	}
	if len(packet.Content) <= 0 {
		return errors.New("UNSUBSCRIBE error: The packet data is too short.")
	}
	for i := 0; i < len(packet.Content); i++ {
		c.GetMaster().SubscriptionMap.RemoveSubscription(service, utils.ByteToUint8(packet.Content[i]))
	}
	return nil
}
コード例 #3
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))
}
コード例 #4
0
ファイル: ask_tunnel.go プロジェクト: Craftolution/CraftoCore
func (c *AskTunnelCommand) Handle(packet *core.Packet, service *core.Service) error {
	utils.Debug("ASK_TUNNEL packet: ", packet)
	if service == nil {
		return errors.New("ASK_TUNNEL error: There is no service for this serviceId connected.")
	}
	if len(packet.Content) <= 0 {
		return errors.New("ASK_TUNNEL error: The packet data is too small.")
	}
	answerPacket := core.ConstructPacket(packet.Sender, packet.ServiceId, packet.PacketType, packet.PacketId, []byte{})
	services := c.GetMaster().Services
	for i := 0; i < len(packet.Content); i++ {
		tunnelRequest := utils.ByteToUint8(packet.Content[i])
		for _, service := range services {
			if port, ok := service.TunnelPorts[packet.ServiceId]; ok && service.ServiceId == tunnelRequest {
				answerPacket.AppendContent(utils.UintToByte(uint(len(service.TunnelHost)+3), 2))
				answerPacket.AppendContent(utils.UintToByte(uint(service.ServiceId), 1))
				answerPacket.AppendContent(utils.UintToByte(port, 2))
				answerPacket.AppendContent([]byte(service.TunnelHost))
			}
		}
	}
	service.Write(answerPacket)
	return nil
}
コード例 #5
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...))
}
コード例 #6
0
func (r *PacketReader) Recover(conn *net.TCPConn) {
	recoverBuffer := make([]byte, 4096)
	recovered := false

LoopRecovering:
	for !recovered {
		if !r.master.IsValidConnection(conn) {
			break LoopRecovering
		}
		n, err := conn.Read(recoverBuffer)
		if err == nil && n < 8 {
			// to few bytes, next try
			continue
		}
		if err != nil {
			netOpError, ok := err.(*net.OpError)
			if err == io.EOF || err.Error()[0:11] == "WSARecv tcp" || (ok && netOpError.Err.Error() == "read: connection reset by peer") {
				utils.Debug("PacketReader: Recovering stopped (Client disconnected) on Connection", conn)
				r.master.SetValidConnection(conn, false)
				break LoopRecovering
			}
			if ok && netOpError.Err.Error() == "use of closed network connection" {
				utils.Debug("PacketReader: Recovering stopped (Lost Connection) on Connection", conn)
				r.master.SetValidConnection(conn, false)
				break LoopRecovering
			}

			_, err := conn.Write(r.recovering[conn])
			if err != nil {
				utils.Debug("PacketReader: Error sending recover message:", err)
				netOpError, ok := err.(*net.OpError)
				if err == io.EOF || err.Error()[0:11] == "WSARecv tcp" || (ok && (netOpError.Err.Error() == "use of closed network connection" || netOpError.Err.Error() == "read: connection reset by peer")) {
					r.master.SetValidConnection(conn, false)
				}
				// Break anyway, but keep the connection valid
				// if wrong
				break LoopRecovering
			}

			utils.Debug("PacketReader: Recovering not successful, continue.")
			continue
		}

		recoverBufferStr := []uint8{}
		for _, b := range recoverBuffer {
			recoverBufferStr = append(recoverBufferStr, utils.ByteToUint8(b))
		}
		recovered = true
		for i := 1; recovered && i <= 8; i++ {
			if r.recovering[conn][8-i] != recoverBuffer[n-i] {
				recovered = false
			}
		}
	}
	r.recovering[conn] = []byte{}
	if recovered && r.master.IsValidConnection(conn) {
		utils.Debug("PacketReader: Recovering successful on Connection", conn)
	} else {
		utils.Debug("PacketReader: Recovering failed on Connection", conn)
	}
}