func (c *NothingCommand) Handle(packet *core.Packet, service *core.Service) error { utils.Debug("NOTHING packet: ", packet) if service == nil { return errors.New("NOTHING error: There is no service for this serviceId connected.") } return nil }
func (r *PacketReader) SetRecovering(conn *net.TCPConn, recoverMessage *Packet) { if !r.master.IsValidConnection(conn) { utils.Debug("PacketReader: Can't send recover message, because the connection is not valid:", conn) return } _, err := conn.Write(recoverMessage.Prepare()) 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) } return } r.recovering[conn] = recoverMessage.Prepare() utils.Debug("PacketReader: Connection", conn, "must recover with this message:", recoverMessage) }
func HandleIndex(w http.ResponseWriter, r *http.Request) { utils.Debug(r, "Index") err := views.IndexTemplate.Execute(w, nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }
func (c *DisconnectCommand) Handle(packet *core.Packet, service *core.Service) error { utils.Debug("DISCONNECT packet: ", packet) if service == nil { return errors.New("DISCONNECT error: There is no service for this serviceId connected.") } if len(packet.Content) > 0 { return errors.New("DISCONNECT error: The packet data is too long.") } return c.GetMaster().DisconnectService(service) }
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 }
func (c *SyncTimeCommand) Handle(packet *core.Packet, service *core.Service) error { utils.Debug("SYNC_TIME packet: ", packet) if service == nil { return errors.New("SYNC_TIME error: There is no service for this serviceId connected.") } timeBytes, err := time.Now().MarshalText() if err != nil { return err } answerPacket := core.ConstructPacket(packet.Sender, packet.ServiceId, packet.PacketType, packet.PacketId, []byte{}) answerPacket.AppendContent(timeBytes) service.Write(answerPacket) return nil }
func (s *Service) Write(packet *Packet) { if !s.master.IsValidConnection(s.Connection) { return } if config.DEBUG { utils.Debug(s.Connection.LocalAddr(), "->", s.Connection.RemoteAddr(), "Len:", packet.ContentLength, "Packet:", packet) } else { utils.Print(s.Connection.LocalAddr(), "->", s.Connection.RemoteAddr(), "Len:", packet.ContentLength) } _, err := s.Connection.Write(packet.Prepare()) if err != nil { 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")) { s.master.RemoveValidConnection(s.Connection) } } }
func (master *Master) ConnectService(service *Service) error { if service == nil { return errors.New("The service can't be nil.") } serviceId := service.ServiceId if service2, found := master.ServiceById[serviceId]; found { if service2 == service { return errors.New("The service is connected already.") } else { return errors.New("Another service is connected as this serviceId already.") } } master.Services = append(master.Services, service) master.ServiceById[service.ServiceId] = service master.LastPacketId[service.ServiceId] = 0 utils.Debug("Master: Service connected:", service) return nil }
//example of using a model to save a User func HandleSaveUser(w http.ResponseWriter, r *http.Request) { company := r.FormValue("company") email := r.FormValue("email") admin := utils.GetCheckboxAsBool(r.FormValue("admin")) user := models.User{ Company: company, Email: email, Admin: admin, Enabled: true, Created: time.Now(), } err := models.SaveUser(appengine.NewContext(r), &user) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } else { utils.Debug(r, "Saved User "+company+", "+email+", Admin: "+strconv.FormatBool(admin)) } }
func (c *ListServicesCommand) Handle(packet *core.Packet, service *core.Service) error { utils.Debug("LIST_SERVICES packet: ", packet) if service == nil { return errors.New("LIST_SERVICES error: There is no service for this serviceId connected.") } if len(packet.Content) > 0 { return errors.New("LIST_SERVICES error: The packet data is too long.") } answerPacket := core.ConstructPacket(packet.Sender, packet.ServiceId, packet.PacketType, packet.PacketId, []byte{}) services := c.GetMaster().Services for _, service := range services { answerPacket.AppendContent(utils.UintToByte(uint(len(service.Name)+1), 2)) answerPacket.AppendContent(utils.UintToByte(uint(service.ServiceId), 1)) answerPacket.AppendContent([]byte(service.Name)) } service.Write(answerPacket) return 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 (master *Master) DisconnectService(service *Service) error { if service == nil { return errors.New("The service can't be nil.") } serviceId := service.ServiceId if service2, found := master.ServiceById[serviceId]; found { if service2 == service { for index, service3 := range master.Services { if service3 == service { master.Services = append(master.Services[:index], master.Services[index+1:]...) } } delete(master.ServiceById, serviceId) delete(master.LastPacketId, serviceId) // Unsubscribe all active subscriptions for i := 0; i < 256; i++ { master.SubscriptionMap.RemoveSubscription(service, uint8(i)) } utils.Debug("Master: Service disconnected:", service) return nil } } return errors.New("The service isn't connected.") }
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 }
func (master *Master) Listen() { utils.Debug("Master: Now listening for TCP connections.") running := true // fetch new tcp connections parallel go func() { LoopConnector: for running { select { case <-master.quit: running = false break LoopConnector default: conn, err := master.listener.AcceptTCP() if err != nil { if err == io.EOF || err.Error()[0:11] != "WSARecv tcp" { running = false break LoopConnector } netOpError, ok := err.(*net.OpError) if ok && (netOpError.Err.Error() == "use of closed network connection" || netOpError.Err.Error() == "read: connection reset by peer") { running = false break LoopConnector } utils.Debug("Master: Error accepting new TCP connection:", err) continue } master.newConnections <- conn } } utils.Debug("Master: LoopConnector stopped.") }() LoopWorker: for running { select { case <-master.quit: utils.Debug("Master: LoopWorker stopped.") break LoopWorker case conn := <-master.newConnections: master.AddValidConnection(conn) go master.packetReader.Listen(conn) case conn := <-master.deadConnections: master.RemoveValidConnection(conn) services := master.Services for _, service := range services { if service.Connection == conn { master.DisconnectService(service) } } case message := <-master.messages: if !message.IsData() { service := master.ServiceById[message.ServiceId] err := master.GetCommandInterpreter().Handle(message, service) if err != nil { utils.Debug("Master WARN: CommandInterpreter couldn't handle packet:", err) } } subscribers := master.SubscriptionMap.GetServicesForPacketType(message.PacketType) for _, service := range subscribers { service.Write(message) } } } utils.Print("Master stopped.") }
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...)) }
func (r *PacketReader) Listen(conn *net.TCPConn) { for _, connection := range r.connections { if connection == conn { utils.Debug("PacketReader: Already listening on Connection", conn, ". Skipped enabling another listener.") return } } r.connections = append(r.connections, conn) utils.Debug("PacketReader: Now listening on Connection:", conn) r.recovering[conn] = []byte{} defer conn.Close() LoopListen: for r.master.IsValidConnection(conn) { select { case <-r.quit: utils.Debug("PacketReader: LoopListen stopped. (Quit)", conn) break LoopListen default: if len(r.recovering[conn]) > 0 { r.Recover(conn) if !r.master.IsValidConnection(conn) { utils.Debug("PacketReader: LoopListen stopped. (Recovering failed)", conn) r.master.deadConnections <- conn break LoopListen } } else { packet, err := r.Read(conn) 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") { r.master.SetValidConnection(conn, false) r.master.deadConnections <- conn utils.Debug("PacketReader: LoopListen stopped. (Client disconnected)", conn) break LoopListen } if ok && netOpError.Err.Error() == "use of closed network connection" { r.master.SetValidConnection(conn, false) r.master.deadConnections <- conn utils.Debug("PacketReader: LoopListen stopped. (Lost Connection)", conn) break LoopListen } utils.Debug("PacketReader: Error reading a packet for Connection", conn, ":", err) continue } if config.DEBUG { utils.Debug(conn.RemoteAddr(), "->", conn.LocalAddr(), "Len:", packet.ContentLength, "Packet:", packet) } else { utils.Print(conn.RemoteAddr(), "->", conn.LocalAddr(), "Len:", packet.ContentLength) } r.master.NewMessage(packet) } } } for index, connection := range r.connections { if connection == conn { r.connections = append(r.connections[:index], r.connections[index+1:]...) break } } delete(r.recovering, conn) utils.Debug("PacketReader stopped listening on Connection:", conn) }
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) } }
func HandleAdmin(w http.ResponseWriter, r *http.Request) { utils.Debug(r, "Handle Admin") }