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 }
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)) }
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...)) }