Git Product home page Git Product logo

nex-protocols-go's Introduction

Rendez-vous servers with protocol support in Go

GoDoc

Usage note

This library is designed around, and customized for, Rock Band 3. While it may work with other Quazal Rendez-vous titles that aren't Rock Band 3, do not expect it to work correctly out of the box with anything but Rock Band 3. If you are looking for a more generic NEX/PRUDP protocol library, see the upstream version of this repository.

Install

go get github.com/ihatecompvir/nex-protocols-go

Example (Secure server)

func main() {
    nexServer := nex.NewServer()
    nexServer.SetPrudpVersion(0)
    nexServer.SetSignatureVersion(1)
    nexServer.SetKerberosKeySize(16)
    nexServer.SetAccessKey("ridfebb9")

    secureServer := nexproto.NewSecureProtocol(nexServer)
    friendsServer := nexproto.NewFriendsProtocol(nexServer)

    // Handle PRUDP CONNECT packet (not an RMC method)
    nexServer.On("Connect", func(packet *nex.PacketV0) {
        packet.GetSender().SetClientConnectionSignature(packet.GetConnectionSignature())

        payload := packet.GetPayload()
        stream := nex.NewStream(payload)

        ticketData := stream.ReadNEXBufferNext()
        requestData := stream.ReadNEXBufferNext()

        // TODO: use random key from auth server
        ticketDataEncryption := nex.NewKerberosEncryption([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
        decryptedTicketData := ticketDataEncryption.Decrypt(ticketData)
        ticketDataStream := nex.NewStream(decryptedTicketData)

        _ = ticketDataStream.ReadU64LENext(1)[0] // expiration time
        _ = ticketDataStream.ReadU32LENext(1)[0] // User PID
        sessionKey := ticketDataStream.ReadBytesNext(16)

        requestDataEncryption := nex.NewKerberosEncryption(sessionKey)
        decryptedRequestData := requestDataEncryption.Decrypt(requestData)
        requestDataStream := nex.NewStream(decryptedRequestData)

        _ = requestDataStream.ReadU32LENext(1)[0] // User PID
        _ = requestDataStream.ReadU32LENext(1)[0] //CID of secure server station url
        responseCheck := requestDataStream.ReadU32LENext(1)[0]

        responseValueStream := nex.NewStream(make([]byte, 4))
        responseValueBufferStream := nex.NewStream()
        responseValueBufferStream.Grow(8)

        responseValueStream.WriteU32LENext([]uint32{responseCheck + 1})
        responseValueBufferStream.WriteNEXBuffer(responseValueStream.Bytes())

        packet.GetSender().UpdateRC4Key(sessionKey)

        nexServer.AcknowledgePacket(packet, responseValueBufferStream.Bytes())
    })

    // Secure protocol handles

    // Handle Register RMC method
    secureServer.Register(func(client *nex.Client, callID uint32, stationUrls []*nex.StationURL) {
        localStation := stationUrls[0]

        address := client.GetAddress().IP.String()
        port := string(client.GetAddress().Port)

        localStation.SetAddress(&address)
        localStation.SetPort(&port)

        localStationURL := localStation.EncodeToString()

        rmcResponseStream := nex.NewStream()
        rmcResponseStream.Grow(int64(4 + 4 + 2 + len(localStationURL) + 1))

        rmcResponseStream.WriteU32LENext([]uint32{0x10001}) // Success
        rmcResponseStream.WriteU32LENext([]uint32{uint32(secureServer.ConnectionIDCounter.Increment())})
        rmcResponseStream.WriteNEXStringNext(localStationURL)

        rmcResponseBody := rmcResponseStream.Bytes()

        // Build response packet
        rmcResponse := nex.NewRMCResponse(nexproto.SecureProtocolID, callID)
        rmcResponse.SetSuccess(nexproto.SecureMethodRegisterEx, rmcResponseBody)

        rmcResponseBytes := rmcResponse.Bytes()

        responsePacket := nex.NewPacketV0(client, nil)

        responsePacket.SetVersion(0)
        responsePacket.SetSource(0xA1)
        responsePacket.SetDestination(0xAF)
        responsePacket.SetType(nex.DataPacket)
        responsePacket.SetPayload(rmcResponseBytes)

        responsePacket.AddFlag(nex.FlagNeedsAck)
        responsePacket.AddFlag(nex.FlagReliable)

        nexServer.Send(responsePacket)
    })

    // Handle RegisterEx RMC method
    secureServer.RegisterEx(func(client *nex.Client, callID uint32, stationUrls []*nex.StationURL, loginData nexproto.NintendoLoginData) {
        // TODO: Validate loginData
        secureServer.RegisterHandler(client, callID, stationUrls)
    })

    // Friends (WiiU) protocol handles

    friendsServer.CheckSettingStatus(func(client *nex.Client, callID uint32) {
        rmcResponseStream := nex.NewStream()
        rmcResponseStream.Grow(1)

        rmcResponseStream.WriteByteNext(0xFF)

        rmcResponseBody := rmcResponseStream.Bytes()

        // Build response packet
        rmcResponse := nex.NewRMCResponse(nexproto.FriendsProtocolID, callID)
        rmcResponse.SetSuccess(nexproto.FriendsMethodCheckSettingStatus, rmcResponseBody)

        rmcResponseBytes := rmcResponse.Bytes()

        responsePacket := nex.NewPacketV0(client, nil)

        responsePacket.SetVersion(0)
        responsePacket.SetSource(0xA1)
        responsePacket.SetDestination(0xAF)
        responsePacket.SetType(nex.DataPacket)
        responsePacket.SetPayload(rmcResponseBytes)

        responsePacket.AddFlag(nex.FlagNeedsAck)
        responsePacket.AddFlag(nex.FlagReliable)

        nexServer.Send(responsePacket)
    })

    friendsServer.UpdateAndGetAllInformation(func(client *nex.Client, callID uint32, nnaInfo *nexproto.NNAInfo, presence *nexproto.NintendoPresenceV2, birthday *nex.DateTime) {
        comment := "Pretendo Online"
        datetime := nex.NewDateTime(0)

        rmcResponseStream := nex.NewStream()
        rmcResponseStream.Grow(int64(
            3 + // PrincipalPreference
            1 + 2 + len(comment) + 1 + 8 + // Comment
            4 + // FriendInfo List length
            4 + // FriendRequest (Sent) List length
            4 + // FriendRequest (Received) List length
            4 + // BlacklistedPrincipal List length
            1 + // Unknown
            4 + // PersistentNotification List length
            1)) // Unknown

        // TODO: Make the following fields into structs and encode them

        //PrincipalPreference
        rmcResponseStream.WriteByteNext(0)
        rmcResponseStream.WriteByteNext(0)
        rmcResponseStream.WriteByteNext(0)
        //Comment
        rmcResponseStream.WriteByteNext(0)
        rmcResponseStream.WriteNEXStringNext(comment)
        rmcResponseStream.WriteU64LENext([]uint64{datetime.Now()})
        //List<FriendInfo>
        rmcResponseStream.WriteU32LENext([]uint32{0})
        //List<FriendRequest> (Sent)
        rmcResponseStream.WriteU32LENext([]uint32{0})
        //List<FriendRequest> (Received)
        rmcResponseStream.WriteU32LENext([]uint32{0})
        //List<BlacklistedPrincipal>
        rmcResponseStream.WriteU32LENext([]uint32{0})
        //Unknown
        rmcResponseStream.WriteByteNext(0)
        //List<PersistentNotification>
        rmcResponseStream.WriteU32LENext([]uint32{0})
        //Unknown
        rmcResponseStream.WriteByteNext(0)

        rmcResponseBody := rmcResponseStream.Bytes()

        // Build response packet
        rmcResponse := nex.NewRMCResponse(nexproto.FriendsProtocolID, callID)
        rmcResponse.SetSuccess(nexproto.FriendsMethodUpdateAndGetAllInformation, rmcResponseBody)

        rmcResponseBytes := rmcResponse.Bytes()

        responsePacket := nex.NewPacketV0(client, nil)

        responsePacket.SetVersion(0)
        responsePacket.SetSource(0xA1)
        responsePacket.SetDestination(0xAF)
        responsePacket.SetType(nex.DataPacket)
        responsePacket.SetPayload(rmcResponseBytes)

        responsePacket.AddFlag(nex.FlagNeedsAck)
        responsePacket.AddFlag(nex.FlagReliable)

        nexServer.Send(responsePacket)
    })

    nexServer.Listen("192.168.0.28:60001")
}

nex-protocols-go's People

Contributors

jonbarrow avatar ihatecompvir avatar shutterbug2000 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.