Updated NEX lib versions

This commit is contained in:
Jonathan Barrow
2023-04-08 14:05:02 -04:00
parent be21209d3c
commit 03c438080d
85 changed files with 1749 additions and 1450 deletions

View File

@@ -1,44 +0,0 @@
package main
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func addToBufferQueues(err error, client *nex.Client, callID uint32, params []*nexproto.BufferQueueParam, buffers [][]byte) {
pResults := make([]uint32, 0)
for i := 0; i < len(params); i++ {
buffer := buffers[i]
param := params[i]
insertBufferQueueData(param.DataID, param.Slot, buffer)
incrementCourseFailCount(param.DataID)
pResults = append(pResults, 0x690001)
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream.WriteListUInt32LE(pResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodAddToBufferQueues, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}

View File

@@ -1,37 +0,0 @@
package main
import (
"fmt"
"os"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func completeAttachFile(err error, client *nex.Client, callID uint32, dataStoreCompletePostParam *nexproto.DataStoreCompletePostParam) {
rmcResponseStream := nex.NewStreamOut(nexServer)
// TODO: complete this
rmcResponseStream.WriteString(fmt.Sprintf("http://%s.b-cdn.net/image/%d.jpg", os.Getenv("S3_BUCKET_NAME"), dataStoreCompletePostParam.DataID))
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodCompleteAttachFile, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}

View File

@@ -1,37 +0,0 @@
package main
import (
nex "github.com/PretendoNetwork/nex-go"
)
func connect(packet *nex.PacketV1) {
payload := packet.Payload()
stream := nex.NewStreamIn(payload, nexServer)
_, _ = stream.ReadBuffer()
checkData, _ := stream.ReadBuffer()
sessionKey := make([]byte, nexServer.KerberosKeySize())
kerberos := nex.NewKerberosEncryption(sessionKey)
checkDataDecrypted := kerberos.Decrypt(checkData)
checkDataStream := nex.NewStreamIn(checkDataDecrypted, nexServer)
userPID := checkDataStream.ReadUInt32LE() // User PID
packet.Sender().SetPID(userPID)
_ = checkDataStream.ReadUInt32LE() //CID of secure server station url
responseCheck := checkDataStream.ReadUInt32LE()
responseValueStream := nex.NewStreamOut(nexServer)
responseValueStream.WriteUInt32LE(responseCheck + 1)
responseValueBufferStream := nex.NewStreamOut(nexServer)
responseValueBufferStream.WriteBuffer(responseValueStream.Bytes())
nexServer.AcknowledgePacket(packet, responseValueBufferStream.Bytes())
packet.Sender().UpdateRC4Key(sessionKey)
packet.Sender().SetSessionKey(sessionKey)
}

View File

@@ -1,42 +0,0 @@
package main
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
// This is the same as DataStoreSMM::RecommendedCourseSearchObject
// Not sure why they used a different method here?
func ctrPickUpCourseSearchObject(err error, client *nex.Client, callID uint32, dataStoreSearchParam *nexproto.DataStoreSearchParam, extraData []string) {
pRankingResults := make([]*nexproto.DataStoreCustomRankingResult, 0)
courseMetadatas := getCourseMetadatasByLimit(100) // In PCAPs param.minimalRatingFrequency is 100 but is 0 here?
for _, courseMetadata := range courseMetadatas {
pRankingResults = append(pRankingResults, courseMetadataToDataStoreCustomRankingResult(courseMetadata))
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream.WriteListStructure(pRankingResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodCTRPickUpCourseSearchObject, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}

View File

@@ -1,466 +0,0 @@
package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"time"
"github.com/PretendoNetwork/nex-go"
"github.com/gocql/gocql"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var cluster *gocql.ClusterConfig
var cassandraClusterSession *gocql.Session
var mongoClient *mongo.Client
var mongoContext context.Context
var mongoDatabase *mongo.Database
var mongoCollection *mongo.Collection
func connectMongo() {
mongoClient, _ = mongo.NewClient(options.Client().ApplyURI(os.Getenv("MONGO_URI")))
mongoContext, _ = context.WithTimeout(context.Background(), 10*time.Second)
_ = mongoClient.Connect(mongoContext)
mongoDatabase = mongoClient.Database("pretendo")
mongoCollection = mongoDatabase.Collection("pnids")
}
func connectCassandra() {
// Connect to Cassandra
var err error
cluster = gocql.NewCluster("127.0.0.1")
cluster.Timeout = 30 * time.Second
createKeyspace("pretendo_smm")
cluster.Keyspace = "pretendo_smm"
cassandraClusterSession, err = cluster.CreateSession()
if err != nil {
panic(err)
}
// Create tables if missing
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.courses (
data_id bigint PRIMARY KEY,
playable boolean,
owner_pid int,
name text,
size int,
creation_date bigint,
update_date bigint,
world_record_first_pid int,
world_record_pid int,
world_record_creation_date bigint,
world_record_update_date bigint,
world_record int,
meta_binary blob,
flag int,
extra_data list<text>,
data_type smallint,
period smallint
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.courses")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.ratings (
data_id bigint PRIMARY KEY,
stars counter,
attempts counter,
failures counter,
completions counter
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.ratings")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.buffer_queues (
id uuid PRIMARY KEY,
data_id bigint,
slot int,
buffer blob
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.buffer_queues")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.generator_last_id (
node_id int PRIMARY KEY,
last_id int
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.generator_last_id")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.user_play_info (
pid int PRIMARY KEY,
starred_courses set<bigint>,
played_courses set<bigint>
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.user_play_info")
log.Fatal(err)
}
fmt.Println("Connected to Cassandra")
}
// Adapted from gocql common_test.go
func createKeyspace(keyspace string) {
flagRF := flag.Int("rf", 1, "replication factor for pretendo_smm keyspace")
c := *cluster
c.Keyspace = "system"
c.Timeout = 30 * time.Second
s, err := c.CreateSession()
if err != nil {
panic(err)
}
defer s.Close()
if err := s.Query(fmt.Sprintf(`CREATE KEYSPACE IF NOT EXISTS %s
WITH replication = {
'class' : 'SimpleStrategy',
'replication_factor' : %d
}`, keyspace, *flagRF)).Exec(); err != nil {
log.Fatal(err)
}
}
////////////////////////////////
// //
// Cassandra database methods //
// //
////////////////////////////////
func createDataStoreIDGeneratorRow(nodeID int) {
if err := cassandraClusterSession.Query(`INSERT INTO pretendo_smm.generator_last_id(node_id, last_id) VALUES (?, ?) IF NOT EXISTS`, nodeID, 0).Exec(); err != nil {
log.Fatal(err)
}
}
func getDataStoreIDGeneratorLastID(nodeID int) uint32 {
var lastID uint32
_ = cassandraClusterSession.Query(`SELECT last_id FROM pretendo_smm.generator_last_id WHERE node_id=?`, nodeID).Scan(&lastID)
return lastID
}
func setDataStoreIDGeneratorLastID(nodeID int, value uint32) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.generator_last_id SET last_id=? WHERE node_id=?`, value, nodeID).Exec(); err != nil {
log.Fatal(err)
}
}
func initializeCourseData(courseID uint64, ownerPID uint32, size uint32, name string, flag uint32, extraData []string, dataType uint16, period uint16) {
datetime := nex.NewDateTime(0)
now := datetime.Now()
if err := cassandraClusterSession.Query(`INSERT INTO pretendo_smm.courses(
data_id,
owner_pid,
size,
name,
flag,
extra_data,
playable,
creation_date,
update_date,
world_record_first_pid,
world_record_pid,
world_record_creation_date,
world_record_update_date,
world_record,
data_type,
period
)
VALUES (
?,
?,
?,
?,
?,
?,
false,
?,
?,
0,
0,
0,
0,
0,
?,
?
) IF NOT EXISTS`,
courseID, ownerPID, size, name, flag, extraData, now, now, dataType, period).Exec(); err != nil {
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET stars=stars+0, attempts=attempts+0, failures=failures+0, completions=completions+0 WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}
func updateCourseMetaBinary(courseID uint64, metaBinary []byte) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET meta_binary=? WHERE data_id=?`, metaBinary, courseID).Exec(); err != nil {
log.Fatal(err)
}
}
func setCoursePlayable(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET playable=true WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}
func getCourseMetadatasByLimit(limit uint32) []*CourseMetadata {
var sliceMap []map[string]interface{}
var err error
if sliceMap, err = cassandraClusterSession.Query(`SELECT data_id, owner_pid, size, name, meta_binary, flag, creation_date, update_date, data_type, period FROM pretendo_smm.courses LIMIT ?`, limit).Iter().SliceMap(); err != nil {
log.Fatal(err)
}
courseMetadatas := make([]*CourseMetadata, 0)
for _, course := range sliceMap {
dataID := uint64(course["data_id"].(int64))
var stars uint32
var attempts uint32
var failures uint32
var completions uint32
_ = cassandraClusterSession.Query(`SELECT stars, attempts, failures, completions FROM pretendo_smm.ratings WHERE data_id=?`, dataID).Scan(&stars, &attempts, &failures, &completions)
courseMetadata := &CourseMetadata{
DataID: dataID,
OwnerPID: uint32(course["owner_pid"].(int)),
Size: uint32(course["size"].(int)),
CreatedTime: nex.NewDateTime(uint64(course["creation_date"].(int64))),
UpdatedTime: nex.NewDateTime(uint64(course["update_date"].(int64))),
Name: course["name"].(string),
MetaBinary: course["meta_binary"].([]byte),
Stars: stars,
Attempts: attempts,
Failures: failures,
Completions: completions,
Flag: uint32(course["flag"].(int)),
DataType: uint16(course["data_type"].(int16)),
Period: uint16(course["period"].(int16)),
}
courseMetadatas = append(courseMetadatas, courseMetadata)
}
return courseMetadatas
}
func getCourseMetadataByDataID(dataID uint64) *CourseMetadata {
var ownerPID uint32
var size uint32
var name string
var metaBinary []byte
var flag uint32
var createdTime uint64
var updatedTime uint64
var dataType uint16
var period uint16
err := cassandraClusterSession.Query(`SELECT owner_pid, size, name, meta_binary, flag, creation_date, update_date, data_type, period FROM pretendo_smm.courses WHERE data_id=?`, dataID).Scan(&ownerPID, &size, &name, &metaBinary, &flag, &createdTime, &updatedTime, &dataType, &period)
if err != nil {
if err == gocql.ErrNotFound {
return nil
} else {
log.Fatal(err)
}
}
var stars uint32
var attempts uint32
var failures uint32
var completions uint32
_ = cassandraClusterSession.Query(`SELECT stars, attempts, failures, completions FROM pretendo_smm.ratings WHERE data_id=?`, dataID).Scan(&stars, &attempts, &failures, &completions)
courseMetadata := &CourseMetadata{
DataID: dataID,
OwnerPID: ownerPID,
Size: size,
CreatedTime: nex.NewDateTime(createdTime),
UpdatedTime: nex.NewDateTime(updatedTime),
Name: name,
MetaBinary: metaBinary,
Stars: stars,
Attempts: attempts,
Failures: failures,
Completions: completions,
Flag: flag,
DataType: dataType,
Period: period,
}
return courseMetadata
}
func getCourseMetadataByDataIDs(dataIDs []uint64) []*CourseMetadata {
// TODO: Do this in one query?
courseMetadatas := make([]*CourseMetadata, 0)
for _, dataID := range dataIDs {
courseMetadata := getCourseMetadataByDataID(dataID)
if courseMetadata != nil {
courseMetadatas = append(courseMetadatas, courseMetadata)
}
}
return courseMetadatas
}
func getCourseMetadatasByPID(pid uint32) []*CourseMetadata {
courseMetadatas := make([]*CourseMetadata, 0)
// TODO: Fix this query? Seems like a weird way of doing this...
var sliceMap []map[string]interface{}
var err error
if sliceMap, err = cassandraClusterSession.Query(`SELECT data_id FROM pretendo_smm.courses WHERE owner_pid=? ALLOW FILTERING`, pid).Iter().SliceMap(); err != nil {
log.Fatal(err)
}
for _, course := range sliceMap {
dataID := uint64(course["data_id"].(int64))
courseMetadatas = append(courseMetadatas, getCourseMetadataByDataID(dataID))
}
return courseMetadatas
}
func insertBufferQueueData(dataID uint64, slot uint32, buffer []byte) {
if err := cassandraClusterSession.Query(`INSERT INTO pretendo_smm.buffer_queues( id, data_id, slot, buffer ) VALUES ( now(), ?, ?, ? ) IF NOT EXISTS`, dataID, slot, buffer).Exec(); err != nil {
log.Fatal(err)
}
}
func getBufferQueueDeathData(dataID uint64) [][]byte {
pBufferQueue := make([][]byte, 0)
var sliceMap []map[string]interface{}
var err error
if sliceMap, err = cassandraClusterSession.Query(`SELECT buffer FROM pretendo_smm.buffer_queues WHERE data_id=? AND slot=3 ALLOW FILTERING`, dataID).Iter().SliceMap(); err != nil {
log.Fatal(err)
}
for _, bufferQueue := range sliceMap {
pBufferQueue = append(pBufferQueue, bufferQueue["buffer"].([]byte))
}
return pBufferQueue
}
func getCourseWorldRecord(dataID uint64) *CourseWorldRecord {
var worldRecordFirstPID uint32
var worldRecordPID uint32
var worldRecordCreatedTime uint64
var worldRecordUpdatedTime uint64
var worldRecord int32
_ = cassandraClusterSession.Query(`SELECT world_record_first_pid, world_record_pid, world_record_creation_date, world_record_update_date, world_record FROM pretendo_smm.courses WHERE data_id=?`, dataID).Scan(&worldRecordFirstPID, &worldRecordPID, &worldRecordCreatedTime, &worldRecordUpdatedTime, &worldRecord)
if worldRecordFirstPID == 0 {
return nil
}
return &CourseWorldRecord{
FirstPID: worldRecordFirstPID,
BestPID: worldRecordPID,
CreatedTime: nex.NewDateTime(worldRecordCreatedTime),
UpdatedTime: nex.NewDateTime(worldRecordUpdatedTime),
Score: worldRecord,
}
}
func updateCourseWorldRecord(courseID uint64, ownerPID uint32, score int32) {
datetime := nex.NewDateTime(0)
now := datetime.Now()
if getCourseWorldRecord(courseID) == nil {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET world_record_first_pid=?, world_record_creation_date=? WHERE data_id=?`, ownerPID, now, courseID).Exec(); err != nil {
log.Fatal(err)
}
}
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET world_record_pid=?, world_record_update_date=?, world_record=? WHERE data_id=?`, ownerPID, now, score, courseID).Exec(); err != nil {
log.Fatal(err)
}
}
func incrementCourseClearCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET completions=completions+1 WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}
func incrementCourseStarCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET stars=stars+1 WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}
func incrementCourseFailCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET failures=failures+1 WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}
func incrementCourseAttemptCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET attempts=attempts+1 WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}
func getUserStarredCourses(pid uint32) []*CourseMetadata {
var dataIDs []uint64
_ = cassandraClusterSession.Query(`SELECT starred_courses FROM pretendo_smm.user_play_info WHERE pid=?`, pid).Scan(&dataIDs)
return getCourseMetadataByDataIDs(dataIDs)
}
//////////////////////////////
// //
// MongoDB database methods //
// //
//////////////////////////////
func getUserMiiInfoByPID(pid uint32) bson.M {
var result bson.M
err := mongoCollection.FindOne(context.TODO(), bson.D{{Key: "pid", Value: pid}}, options.FindOne()).Decode(&result)
if err != nil {
if err == mongo.ErrNoDocuments {
return nil
}
panic(err)
}
return result["mii"].(bson.M)
}

6
database/connect_all.go Normal file
View File

@@ -0,0 +1,6 @@
package database
func ConnectAll() {
connectMongo()
connectCassandra()
}

View File

@@ -0,0 +1,122 @@
package database
import (
"flag"
"fmt"
"log"
"time"
"github.com/gocql/gocql"
)
var cluster *gocql.ClusterConfig
var cassandraClusterSession *gocql.Session
func connectCassandra() {
// Connect to Cassandra
var err error
cluster = gocql.NewCluster("127.0.0.1")
cluster.Timeout = 30 * time.Second
createKeyspace("pretendo_smm")
cluster.Keyspace = "pretendo_smm"
cassandraClusterSession, err = cluster.CreateSession()
if err != nil {
panic(err)
}
// Create tables if missing
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.courses (
data_id bigint PRIMARY KEY,
playable boolean,
owner_pid int,
name text,
size int,
creation_date bigint,
update_date bigint,
world_record_first_pid int,
world_record_pid int,
world_record_creation_date bigint,
world_record_update_date bigint,
world_record int,
meta_binary blob,
flag int,
extra_data list<text>,
data_type smallint,
period smallint
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.courses")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.ratings (
data_id bigint PRIMARY KEY,
stars counter,
attempts counter,
failures counter,
completions counter
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.ratings")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.buffer_queues (
id uuid PRIMARY KEY,
data_id bigint,
slot int,
buffer blob
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.buffer_queues")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.generator_last_id (
node_id int PRIMARY KEY,
last_id int
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.generator_last_id")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.user_play_info (
pid int PRIMARY KEY,
starred_courses set<bigint>,
played_courses set<bigint>
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.user_play_info")
log.Fatal(err)
}
fmt.Println("Connected to Cassandra")
}
// Adapted from gocql common_test.go
func createKeyspace(keyspace string) {
flagRF := flag.Int("rf", 1, "replication factor for pretendo_smm keyspace")
c := *cluster
c.Keyspace = "system"
c.Timeout = 30 * time.Second
s, err := c.CreateSession()
if err != nil {
panic(err)
}
defer s.Close()
if err := s.Query(fmt.Sprintf(`CREATE KEYSPACE IF NOT EXISTS %s
WITH replication = {
'class' : 'SimpleStrategy',
'replication_factor' : %d
}`, keyspace, *flagRF)).Exec(); err != nil {
log.Fatal(err)
}
}

24
database/connect_mongo.go Normal file
View File

@@ -0,0 +1,24 @@
package database
import (
"context"
"os"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var mongoClient *mongo.Client
var mongoContext context.Context
var mongoDatabase *mongo.Database
var mongoCollection *mongo.Collection
func connectMongo() {
mongoClient, _ = mongo.NewClient(options.Client().ApplyURI(os.Getenv("MONGO_URI")))
mongoContext, _ = context.WithTimeout(context.Background(), 10*time.Second)
_ = mongoClient.Connect(mongoContext)
mongoDatabase = mongoClient.Database("pretendo")
mongoCollection = mongoDatabase.Collection("pnids")
}

View File

@@ -0,0 +1,9 @@
package database
import "log"
func CreateDataStoreIDGeneratorRow(nodeID int) {
if err := cassandraClusterSession.Query(`INSERT INTO pretendo_smm.generator_last_id(node_id, last_id) VALUES (?, ?) IF NOT EXISTS`, nodeID, 0).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@@ -1,4 +1,4 @@
package main
package database
import (
"encoding/binary"

View File

@@ -0,0 +1,20 @@
package database
import "log"
func GetBufferQueueDeathData(dataID uint64) [][]byte {
pBufferQueue := make([][]byte, 0)
var sliceMap []map[string]interface{}
var err error
if sliceMap, err = cassandraClusterSession.Query(`SELECT buffer FROM pretendo_smm.buffer_queues WHERE data_id=? AND slot=3 ALLOW FILTERING`, dataID).Iter().SliceMap(); err != nil {
log.Fatal(err)
}
for _, bufferQueue := range sliceMap {
pBufferQueue = append(pBufferQueue, bufferQueue["buffer"].([]byte))
}
return pBufferQueue
}

View File

@@ -0,0 +1,57 @@
package database
import (
"log"
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/super-mario-maker-secure/types"
"github.com/gocql/gocql"
)
func GetCourseMetadataByDataID(dataID uint64) *types.CourseMetadata {
var ownerPID uint32
var size uint32
var name string
var metaBinary []byte
var flag uint32
var createdTime uint64
var updatedTime uint64
var dataType uint16
var period uint16
err := cassandraClusterSession.Query(`SELECT owner_pid, size, name, meta_binary, flag, creation_date, update_date, data_type, period FROM pretendo_smm.courses WHERE data_id=?`, dataID).Scan(&ownerPID, &size, &name, &metaBinary, &flag, &createdTime, &updatedTime, &dataType, &period)
if err != nil {
if err == gocql.ErrNotFound {
return nil
} else {
log.Fatal(err)
}
}
var stars uint32
var attempts uint32
var failures uint32
var completions uint32
_ = cassandraClusterSession.Query(`SELECT stars, attempts, failures, completions FROM pretendo_smm.ratings WHERE data_id=?`, dataID).Scan(&stars, &attempts, &failures, &completions)
courseMetadata := &types.CourseMetadata{
DataID: dataID,
OwnerPID: ownerPID,
Size: size,
CreatedTime: nex.NewDateTime(createdTime),
UpdatedTime: nex.NewDateTime(updatedTime),
Name: name,
MetaBinary: metaBinary,
Stars: stars,
Attempts: attempts,
Failures: failures,
Completions: completions,
Flag: flag,
DataType: dataType,
Period: period,
}
return courseMetadata
}

View File

@@ -0,0 +1,18 @@
package database
import "github.com/PretendoNetwork/super-mario-maker-secure/types"
func GetCourseMetadataByDataIDs(dataIDs []uint64) []*types.CourseMetadata {
// TODO: Do this in one query?
courseMetadatas := make([]*types.CourseMetadata, 0)
for _, dataID := range dataIDs {
courseMetadata := GetCourseMetadataByDataID(dataID)
if courseMetadata != nil {
courseMetadatas = append(courseMetadatas, courseMetadata)
}
}
return courseMetadatas
}

View File

@@ -0,0 +1,51 @@
package database
import (
"log"
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/super-mario-maker-secure/types"
)
func GetCourseMetadatasByLimit(limit uint32) []*types.CourseMetadata {
var sliceMap []map[string]interface{}
var err error
if sliceMap, err = cassandraClusterSession.Query(`SELECT data_id, owner_pid, size, name, meta_binary, flag, creation_date, update_date, data_type, period FROM pretendo_smm.courses LIMIT ?`, limit).Iter().SliceMap(); err != nil {
log.Fatal(err)
}
courseMetadatas := make([]*types.CourseMetadata, 0)
for _, course := range sliceMap {
dataID := uint64(course["data_id"].(int64))
var stars uint32
var attempts uint32
var failures uint32
var completions uint32
_ = cassandraClusterSession.Query(`SELECT stars, attempts, failures, completions FROM pretendo_smm.ratings WHERE data_id=?`, dataID).Scan(&stars, &attempts, &failures, &completions)
courseMetadata := &types.CourseMetadata{
DataID: dataID,
OwnerPID: uint32(course["owner_pid"].(int)),
Size: uint32(course["size"].(int)),
CreatedTime: nex.NewDateTime(uint64(course["creation_date"].(int64))),
UpdatedTime: nex.NewDateTime(uint64(course["update_date"].(int64))),
Name: course["name"].(string),
MetaBinary: course["meta_binary"].([]byte),
Stars: stars,
Attempts: attempts,
Failures: failures,
Completions: completions,
Flag: uint32(course["flag"].(int)),
DataType: uint16(course["data_type"].(int16)),
Period: uint16(course["period"].(int16)),
}
courseMetadatas = append(courseMetadatas, courseMetadata)
}
return courseMetadatas
}

View File

@@ -0,0 +1,26 @@
package database
import (
"log"
"github.com/PretendoNetwork/super-mario-maker-secure/types"
)
func GetCourseMetadatasByPID(pid uint32) []*types.CourseMetadata {
courseMetadatas := make([]*types.CourseMetadata, 0)
// TODO: Fix this query? Seems like a weird way of doing this...
var sliceMap []map[string]interface{}
var err error
if sliceMap, err = cassandraClusterSession.Query(`SELECT data_id FROM pretendo_smm.courses WHERE owner_pid=? ALLOW FILTERING`, pid).Iter().SliceMap(); err != nil {
log.Fatal(err)
}
for _, course := range sliceMap {
dataID := uint64(course["data_id"].(int64))
courseMetadatas = append(courseMetadatas, GetCourseMetadataByDataID(dataID))
}
return courseMetadatas
}

View File

@@ -0,0 +1,28 @@
package database
import (
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/super-mario-maker-secure/types"
)
func GetCourseWorldRecord(dataID uint64) *types.CourseWorldRecord {
var worldRecordFirstPID uint32
var worldRecordPID uint32
var worldRecordCreatedTime uint64
var worldRecordUpdatedTime uint64
var worldRecord int32
_ = cassandraClusterSession.Query(`SELECT world_record_first_pid, world_record_pid, world_record_creation_date, world_record_update_date, world_record FROM pretendo_smm.courses WHERE data_id=?`, dataID).Scan(&worldRecordFirstPID, &worldRecordPID, &worldRecordCreatedTime, &worldRecordUpdatedTime, &worldRecord)
if worldRecordFirstPID == 0 {
return nil
}
return &types.CourseWorldRecord{
FirstPID: worldRecordFirstPID,
BestPID: worldRecordPID,
CreatedTime: nex.NewDateTime(worldRecordCreatedTime),
UpdatedTime: nex.NewDateTime(worldRecordUpdatedTime),
Score: worldRecord,
}
}

View File

@@ -0,0 +1,8 @@
package database
func GetDataStoreIDGeneratorLastID(nodeID int) uint32 {
var lastID uint32
_ = cassandraClusterSession.Query(`SELECT last_id FROM pretendo_smm.generator_last_id WHERE node_id=?`, nodeID).Scan(&lastID)
return lastID
}

View File

@@ -0,0 +1,25 @@
package database
import (
"context"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func GetUserMiiInfoByPID(pid uint32) bson.M {
var result bson.M
err := mongoCollection.FindOne(context.TODO(), bson.D{{Key: "pid", Value: pid}}, options.FindOne()).Decode(&result)
if err != nil {
if err == mongo.ErrNoDocuments {
return nil
}
panic(err)
}
return result["mii"].(bson.M)
}

View File

@@ -0,0 +1,10 @@
package database
import "github.com/PretendoNetwork/super-mario-maker-secure/types"
func GetUserStarredCourses(pid uint32) []*types.CourseMetadata {
var dataIDs []uint64
_ = cassandraClusterSession.Query(`SELECT starred_courses FROM pretendo_smm.user_play_info WHERE pid=?`, pid).Scan(&dataIDs)
return GetCourseMetadataByDataIDs(dataIDs)
}

View File

@@ -0,0 +1,9 @@
package database
import "log"
func IncrementCourseAttemptCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET attempts=attempts+1 WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,9 @@
package database
import "log"
func IncrementCourseClearCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET completions=completions+1 WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,9 @@
package database
import "log"
func IncrementCourseFailCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET failures=failures+1 WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,9 @@
package database
import "log"
func IncrementCourseStarCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET stars=stars+1 WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,56 @@
package database
import (
"log"
"github.com/PretendoNetwork/nex-go"
)
func InitializeCourseData(courseID uint64, ownerPID uint32, size uint32, name string, flag uint32, extraData []string, dataType uint16, period uint16) {
datetime := nex.NewDateTime(0)
now := datetime.Now()
if err := cassandraClusterSession.Query(`INSERT INTO pretendo_smm.courses(
data_id,
owner_pid,
size,
name,
flag,
extra_data,
playable,
creation_date,
update_date,
world_record_first_pid,
world_record_pid,
world_record_creation_date,
world_record_update_date,
world_record,
data_type,
period
)
VALUES (
?,
?,
?,
?,
?,
?,
false,
?,
?,
0,
0,
0,
0,
0,
?,
?
) IF NOT EXISTS`,
courseID, ownerPID, size, name, flag, extraData, now, now, dataType, period).Exec(); err != nil {
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET stars=stars+0, attempts=attempts+0, failures=failures+0, completions=completions+0 WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,9 @@
package database
import "log"
func InsertBufferQueueData(dataID uint64, slot uint32, buffer []byte) {
if err := cassandraClusterSession.Query(`INSERT INTO pretendo_smm.buffer_queues( id, data_id, slot, buffer ) VALUES ( now(), ?, ?, ? ) IF NOT EXISTS`, dataID, slot, buffer).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,9 @@
package database
import "log"
func SetCoursePlayable(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET playable=true WHERE data_id=?`, courseID).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,9 @@
package database
import "log"
func SetDataStoreIDGeneratorLastID(nodeID int, value uint32) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.generator_last_id SET last_id=? WHERE node_id=?`, value, nodeID).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,9 @@
package database
import "log"
func UpdateCourseMetaBinary(courseID uint64, metaBinary []byte) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET meta_binary=? WHERE data_id=?`, metaBinary, courseID).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@@ -0,0 +1,22 @@
package database
import (
"log"
"github.com/PretendoNetwork/nex-go"
)
func UpdateCourseWorldRecord(courseID uint64, ownerPID uint32, score int32) {
datetime := nex.NewDateTime(0)
now := datetime.Now()
if GetCourseWorldRecord(courseID) == nil {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET world_record_first_pid=?, world_record_creation_date=? WHERE data_id=?`, ownerPID, now, courseID).Exec(); err != nil {
log.Fatal(err)
}
}
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET world_record_pid=?, world_record_update_date=?, world_record=? WHERE data_id=?`, ownerPID, now, score, courseID).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@@ -1,42 +0,0 @@
package main
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func followingsLatestCourseSearchObject(err error, client *nex.Client, callID uint32, dataStoreSearchParam *nexproto.DataStoreSearchParam, extraData []string) {
pRankingResults := make([]*nexproto.DataStoreCustomRankingResult, 0)
for _, pid := range dataStoreSearchParam.OwnerIds {
courseMetadatas := getCourseMetadatasByPID(pid)
for _, courseMetadata := range courseMetadatas {
pRankingResults = append(pRankingResults, courseMetadataToDataStoreCustomRankingResult(courseMetadata))
}
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream.WriteListStructure(pRankingResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodFollowingsLatestCourseSearchObject, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}

View File

@@ -1,94 +0,0 @@
package main
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func getCustomRankingByDataId(err error, client *nex.Client, callID uint32, param *nexproto.DataStoreGetCustomRankingByDataIdParam) {
var pRankingResult []*nexproto.DataStoreCustomRankingResult
var pResults []uint32
switch param.ApplicationId {
case 0:
if len(param.DataIdList) == 0 { // Starred courses
pRankingResult, pResults = getCustomRankingByDataIdStarredCourses(client.PID())
} else { // Played courses
pRankingResult, pResults = getCustomRankingByDataIdCourseMetadata(param)
}
case 300000000: // Mii data
pRankingResult, pResults = getCustomRankingByDataIdMiiData(param)
default: // Normal metadata
pRankingResult, pResults = getCustomRankingByDataIdCourseMetadata(param)
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream.WriteListStructure(pRankingResult)
rmcResponseStream.WriteListUInt32LE(pResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodGetCustomRankingByDataId, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}
func getCustomRankingByDataIdStarredCourses(pid uint32) ([]*nexproto.DataStoreCustomRankingResult, []uint32) {
courseMetadatas := getUserStarredCourses(pid)
pRankingResult := make([]*nexproto.DataStoreCustomRankingResult, 0)
pResults := make([]uint32, 0)
for _, courseMetadata := range courseMetadatas {
pRankingResult = append(pRankingResult, courseMetadataToDataStoreCustomRankingResult(courseMetadata))
pResults = append(pResults, 0x690001)
}
return pRankingResult, pResults
}
func getCustomRankingByDataIdMiiData(param *nexproto.DataStoreGetCustomRankingByDataIdParam) ([]*nexproto.DataStoreCustomRankingResult, []uint32) {
pRankingResult := make([]*nexproto.DataStoreCustomRankingResult, 0)
pResults := make([]uint32, 0)
for _, pid := range param.DataIdList {
pid := uint32(pid)
miiInfo := getUserMiiInfoByPID(pid) // This isn't actually a PID when using the official servers! I set it as one to make this easier for me
if miiInfo != nil {
pRankingResult = append(pRankingResult, userMiiDataToDataStoreCustomRankingResult(pid, miiInfo))
pResults = append(pResults, 0x690001)
}
}
return pRankingResult, pResults
}
func getCustomRankingByDataIdCourseMetadata(param *nexproto.DataStoreGetCustomRankingByDataIdParam) ([]*nexproto.DataStoreCustomRankingResult, []uint32) {
courseMetadatas := getCourseMetadataByDataIDs(param.DataIdList)
pRankingResult := make([]*nexproto.DataStoreCustomRankingResult, 0)
pResults := make([]uint32, 0)
for _, courseMetadata := range courseMetadatas {
pRankingResult = append(pRankingResult, courseMetadataToDataStoreCustomRankingResult(courseMetadata))
pResults = append(pResults, 0x690001)
}
return pRankingResult, pResults
}

View File

@@ -1,54 +0,0 @@
package main
import (
"fmt"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func getMetasMultipleParam(err error, client *nex.Client, callID uint32, params []*nexproto.DataStoreGetMetaParam) {
pMetaInfo := make([]*nexproto.DataStoreMetaInfo, 0)
pResults := make([]uint32, 0)
for _, param := range params {
if param.DataID == 0 {
pMetaInfo = append(pMetaInfo, getMetasMultipleParamMiiData(param))
} else {
fmt.Println("Unknown meta multiple data ID")
}
pResults = append(pResults, 0x690001)
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream.WriteListStructure(pMetaInfo)
rmcResponseStream.WriteListUInt32LE(pResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreMethodGetMetasMultipleParam, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}
func getMetasMultipleParamMiiData(param *nexproto.DataStoreGetMetaParam) *nexproto.DataStoreMetaInfo {
miiInfo := getUserMiiInfoByPID(param.PersistenceTarget.OwnerID)
return userMiiDataToDataStoreMetaInfo(param.PersistenceTarget.OwnerID, miiInfo)
}

View File

@@ -1,36 +0,0 @@
package main
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func getMetasWithCourseRecord(err error, client *nex.Client, callID uint32, dataStoreGetCourseRecordParams []*nexproto.DataStoreGetCourseRecordParam, dataStoreGetMetaParam *nexproto.DataStoreGetMetaParam) {
// TODO: complete this
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream.WriteUInt32LE(0x00000000) // pMetaInfo List length 0
rmcResponseStream.WriteUInt32LE(0x00000000) // pCourseResults List length 0
rmcResponseStream.WriteUInt32LE(0x00000000) // pResults List length 0
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodGetMetasWithCourseRecord, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}

View File

@@ -1,52 +0,0 @@
package main
import (
"fmt"
"os"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func getObjectInfos(err error, client *nex.Client, callID uint32, dataIDs []uint64) {
pInfos := make([]*nexproto.DataStoreFileServerObjectInfo, 0)
courseMetadatas := getCourseMetadataByDataIDs(dataIDs)
for _, courseMetadata := range courseMetadatas {
info := nexproto.NewDataStoreFileServerObjectInfo()
info.DataID = courseMetadata.DataID
info.GetInfo = nexproto.NewDataStoreReqGetInfo()
info.GetInfo.URL = fmt.Sprintf("http://%s.b-cdn.net/course/%d.bin", os.Getenv("S3_BUCKET_NAME"), courseMetadata.DataID)
info.GetInfo.RequestHeaders = []*nexproto.DataStoreKeyValue{}
info.GetInfo.Size = courseMetadata.Size
info.GetInfo.RootCA = []byte{}
info.GetInfo.DataID = courseMetadata.DataID
pInfos = append(pInfos, info)
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream.WriteListStructure(pInfos)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodGetObjectInfos, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}

14
globals/globals.go Normal file
View File

@@ -0,0 +1,14 @@
package globals
import (
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/plogger-go"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
var Logger = plogger.NewLogger()
var NEXServer *nex.Server
var S3Client *s3.Client
var HMACSecret []byte
var DataStoreIDGenerators []*database.DataStoreIDGenerator

48
go.mod Normal file
View File

@@ -0,0 +1,48 @@
module github.com/PretendoNetwork/super-mario-maker-secure
go 1.19
require (
github.com/PretendoNetwork/nex-go v1.0.16
github.com/PretendoNetwork/nex-protocols-common-go v1.0.17
github.com/PretendoNetwork/nex-protocols-go v1.0.20
github.com/PretendoNetwork/plogger-go v1.0.2
github.com/aws/aws-sdk-go-v2/service/s3 v1.31.2
github.com/gocql/gocql v1.3.2
github.com/joho/godotenv v1.5.1
go.mongodb.org/mongo-driver v1.11.4
)
require (
github.com/aws/aws-sdk-go-v2 v1.17.8 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.32 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.26 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.24 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.27 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.26 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.1 // indirect
github.com/aws/smithy-go v1.13.5 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/golang/snappy v0.0.3 // indirect
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
github.com/jwalton/go-supportscolor v1.1.0 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/superwhiskers/crunch/v3 v3.5.7 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
github.com/xdg-go/stringprep v1.0.3 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/term v0.7.0 // indirect
golang.org/x/text v0.4.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
)

125
go.sum Normal file
View File

@@ -0,0 +1,125 @@
github.com/PretendoNetwork/nex-go v1.0.16 h1:g2lJW8G+WOS6/8qsgQ0+jLlzemjJ60tQtLqloLTjElo=
github.com/PretendoNetwork/nex-go v1.0.16/go.mod h1:Bx2ONeSefnbJyE0IDIwGopxrjRrnszOV/uQv74Cx+m0=
github.com/PretendoNetwork/nex-protocols-common-go v1.0.17 h1:w0n+RJAHANgX/iVnL5qRiyPJeDHcwr8w6DzDeFqxkqk=
github.com/PretendoNetwork/nex-protocols-common-go v1.0.17/go.mod h1:5Y3jRIbvDxasj0CIvd024za+t9LMbD0OZkBwyKICijg=
github.com/PretendoNetwork/nex-protocols-go v1.0.20 h1:vUoYHFvVWWx9Bm9/2JiN1siW03tFxtD4NY9w/WfC878=
github.com/PretendoNetwork/nex-protocols-go v1.0.20/go.mod h1:Bt7hI7hJ+8r6UU5LSs+3xx4xzsvMVeEUkAW8Cg3lGjQ=
github.com/PretendoNetwork/plogger-go v1.0.2 h1:vWKEnEmJJzYwqLxLyiSsAvCrZV6qnnu/a0GQOjIfzY0=
github.com/PretendoNetwork/plogger-go v1.0.2/go.mod h1:7kD6M4vPq1JL4LTuPg6kuB1OvUBOwQOtAvTaUwMbwvU=
github.com/aws/aws-sdk-go-v2 v1.17.8 h1:GMupCNNI7FARX27L7GjCJM8NgivWbRgpjNI/hOQjFS8=
github.com/aws/aws-sdk-go-v2 v1.17.8/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.32 h1:dpbVNUjczQ8Ae3QKHbpHBpfvaVkRdesxpTOe9pTouhU=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.32/go.mod h1:RudqOgadTWdcS3t/erPQo24pcVEoYyqj/kKW5Vya21I=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.26 h1:QH2kOS3Ht7x+u0gHCh06CXL/h6G8LQJFpZfFBYBNboo=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.26/go.mod h1:vq86l7956VgFr0/FWQ2BWnK07QC3WYsepKzy33qqY5U=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.24 h1:zsg+5ouVLLbePknVZlUMm1ptwyQLkjjLMWnN+kVs5dA=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.24/go.mod h1:+fFaIjycTmpV6hjmPTbyU9Kp5MI/lA+bbibcAtmlhYA=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.27 h1:qIw7Hg5eJEc1uSxg3hRwAthPAO7NeOd4dPxhaTi0yB0=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.27/go.mod h1:Zz0kvhcSlu3NX4XJkaGgdjaa+u7a9LYuy8JKxA5v3RM=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.26 h1:uUt4XctZLhl9wBE1L8lobU3bVN8SNUP7T+olb0bWBO4=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.26/go.mod h1:Bd4C/4PkVGubtNe5iMXu5BNnaBi/9t/UsFspPt4ram8=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.1 h1:lRWp3bNu5wy0X3a8GS42JvZFlv++AKsMdzEnoiVJrkg=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.1/go.mod h1:VXBHSxdN46bsJrkniN68psSwbyBKsazQfU2yX/iSDso=
github.com/aws/aws-sdk-go-v2/service/s3 v1.31.2 h1:iOZoYePk+EuBI1tC7bxeRjO+JvClcYm2fZYW5WPIOMQ=
github.com/aws/aws-sdk-go-v2/service/s3 v1.31.2/go.mod h1:aSl9/LJltSz1cVusiR/Mu8tvI4Sv/5w/WWrJmmkNii0=
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/gocql/gocql v1.3.2 h1:ox3T+R7VFibHSIGxRkuUi1uIvAv8jBHCWxc+9aFQ/LA=
github.com/gocql/gocql v1.3.2/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/jwalton/go-supportscolor v1.1.0 h1:HsXFJdMPjRUAx8cIW6g30hVSFYaxh9yRQwEWgkAR7lQ=
github.com/jwalton/go-supportscolor v1.1.0/go.mod h1:hFVUAZV2cWg+WFFC4v8pT2X/S2qUUBYMioBD9AINXGs=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/superwhiskers/crunch/v3 v3.5.7 h1:N9RLxaR65C36i26BUIpzPXGy2f6pQ7wisu2bawbKNqg=
github.com/superwhiskers/crunch/v3 v3.5.7/go.mod h1:4ub2EKgF1MAhTjoOCTU4b9uLMsAweHEa89aRrfAypXA=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
go.mongodb.org/mongo-driver v1.11.4 h1:4ayjakA013OdpGyL2K3ZqylTac/rMjrJOMZ1EHizXas=
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

20
init.go
View File

@@ -5,12 +5,11 @@ import (
"log"
"runtime"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/joho/godotenv"
)
var hmacSecret []byte
var dataStoreIDGenerators []*DataStoreIDGenerator
func init() {
var err error
@@ -19,27 +18,26 @@ func init() {
log.Fatal("Error loading .env file")
}
hmacSecret, err = ioutil.ReadFile("secret.key")
globals.HMACSecret, err = ioutil.ReadFile("secret.key")
if err != nil {
panic(err)
}
// Connect to and setup databases
connectMongo()
connectCassandra()
database.ConnectAll()
createDataStoreIDGenerators()
}
func createDataStoreIDGenerators() {
dataStoreIDGenerators = make([]*DataStoreIDGenerator, 0)
globals.DataStoreIDGenerators = make([]*database.DataStoreIDGenerator, 0)
regionID := 0 // USA
for corenum := 0; corenum < runtime.NumCPU(); corenum++ {
createDataStoreIDGeneratorRow(corenum)
database.CreateDataStoreIDGeneratorRow(corenum)
lastID := getDataStoreIDGeneratorLastID(corenum)
lastID := database.GetDataStoreIDGeneratorLastID(corenum)
generator := NewDataStoreIDGenerator(uint8(regionID), uint8(corenum), lastID)
dataStoreIDGenerators = append(dataStoreIDGenerators, generator)
generator := database.NewDataStoreIDGenerator(uint8(regionID), uint8(corenum), lastID)
globals.DataStoreIDGenerators = append(globals.DataStoreIDGenerators, generator)
}
}

0
log/all.log Normal file
View File

0
log/critical.log Normal file
View File

0
log/error.log Normal file
View File

0
log/info.log Normal file
View File

0
log/success.log Normal file
View File

0
log/warning.log Normal file
View File

91
main.go
View File

@@ -1,95 +1,18 @@
package main
import (
"fmt"
"os"
"sync"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/PretendoNetwork/super-mario-maker-secure/nex"
)
var nexServer *nex.Server
var secureServer *nexproto.SecureProtocol
var s3Client *s3.S3
var wg sync.WaitGroup
func main() {
key := os.Getenv("S3_KEY")
secret := os.Getenv("S3_SECRET")
wg.Add(1)
s3Config := &aws.Config{
Credentials: credentials.NewStaticCredentials(key, secret, ""),
Endpoint: aws.String("http://b-cdn.net"),
Region: aws.String("us-east-1"),
}
// TODO - Add gRPC server
go nex.StartNEXServer()
newSession, _ := session.NewSession(s3Config)
s3Client = s3.New(newSession)
nexServer = nex.NewServer()
nexServer.SetPrudpVersion(1)
nexServer.SetNexVersion(4)
nexServer.SetKerberosKeySize(32)
nexServer.SetFragmentSize(1300)
nexServer.SetPingTimeout(20)
nexServer.SetAccessKey("9f2b4678")
nexServer.On("Data", func(packet *nex.PacketV1) {
request := packet.RMCRequest()
fmt.Println("==SMM1 - Secure==")
fmt.Printf("Protocol ID: %#v\n", request.ProtocolID())
fmt.Printf("Method ID: %#v\n", request.MethodID())
fmt.Println("=================")
})
nexServer.On("Kick", func(packet *nex.PacketV1) {
fmt.Println("Leaving")
})
nexServer.On("Ping", func(packet *nex.PacketV1) {
fmt.Println("Pinged")
})
secureServer = nexproto.NewSecureProtocol(nexServer)
dataStoreSmmServer := nexproto.NewDataStoreSMMProtocol(nexServer)
messageDeliveryServer := nexproto.NewMessageDeliveryProtocol(nexServer)
// Handle PRUDP CONNECT packet (not an RMC method)
nexServer.On("Connect", connect)
secureServer.Register(register)
dataStoreSmmServer.GetMeta(getMeta)
dataStoreSmmServer.PreparePostObject(preparePostObject)
dataStoreSmmServer.PrepareGetObject(prepareGetObject)
dataStoreSmmServer.CompletePostObject(completePostObject)
dataStoreSmmServer.GetMetasMultipleParam(getMetasMultipleParam)
dataStoreSmmServer.ChangeMeta(changeMeta)
dataStoreSmmServer.RateObjects(rateObjects)
dataStoreSmmServer.GetObjectInfos(getObjectInfos)
dataStoreSmmServer.RateCustomRanking(rateCustomRanking)
dataStoreSmmServer.GetCustomRankingByDataId(getCustomRankingByDataId)
dataStoreSmmServer.AddToBufferQueues(addToBufferQueues)
dataStoreSmmServer.GetBufferQueue(getBufferQueue)
dataStoreSmmServer.CompleteAttachFile(completeAttachFile)
dataStoreSmmServer.PrepareAttachFile(prepareAttachFile)
dataStoreSmmServer.GetApplicationConfig(getApplicationConfig)
dataStoreSmmServer.FollowingsLatestCourseSearchObject(followingsLatestCourseSearchObject)
dataStoreSmmServer.RecommendedCourseSearchObject(recommendedCourseSearchObject)
dataStoreSmmServer.SuggestedCourseSearchObject(suggestedCourseSearchObject)
dataStoreSmmServer.UploadCourseRecord(uploadCourseRecord)
dataStoreSmmServer.GetCourseRecord(getCourseRecord)
dataStoreSmmServer.GetApplicationConfigString(getApplicationConfigString)
dataStoreSmmServer.GetDeletionReason(getDeletionReason)
dataStoreSmmServer.GetMetasWithCourseRecord(getMetasWithCourseRecord)
dataStoreSmmServer.CheckRateCustomRankingCounter(checkRateCustomRankingCounter)
dataStoreSmmServer.CTRPickUpCourseSearchObject(ctrPickUpCourseSearchObject)
messageDeliveryServer.DeliverMessage(deliverMessage)
nexServer.Listen(":60003")
wg.Wait()
}

View File

@@ -1,15 +1,16 @@
package main
package nex_datastore
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func changeMeta(err error, client *nex.Client, callID uint32, dataStoreChangeMetaParam *nexproto.DataStoreChangeMetaParam) {
func ChangeMeta(err error, client *nex.Client, callID uint32, dataStoreChangeMetaParam *datastore.DataStoreChangeMetaParam) {
// STUBBED
// TODO: DO SOMETHING WITH THE DATA
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreMethodChangeMeta, nil)
rmcResponse := nex.NewRMCResponse(datastore.ProtocolID, callID)
rmcResponse.SetSuccess(datastore.MethodChangeMeta, nil)
rmcResponseBytes := rmcResponse.Bytes()
@@ -24,5 +25,5 @@ func changeMeta(err error, client *nex.Client, callID uint32, dataStoreChangeMet
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -1,15 +1,16 @@
package main
package nex_datastore
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func completePostObject(err error, client *nex.Client, callID uint32, dataStoreCompletePostParam *nexproto.DataStoreCompletePostParam) {
func CompletePostObject(err error, client *nex.Client, callID uint32, dataStoreCompletePostParam *datastore.DataStoreCompletePostParam) {
// TODO: DO SOMETHING WITH THE DATA
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreMethodCompletePostObject, nil)
rmcResponse := nex.NewRMCResponse(datastore.ProtocolID, callID)
rmcResponse.SetSuccess(datastore.MethodCompletePostObject, nil)
rmcResponseBytes := rmcResponse.Bytes()
@@ -24,5 +25,5 @@ func completePostObject(err error, client *nex.Client, callID uint32, dataStoreC
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -1,14 +1,17 @@
package main
package nex_datastore
import (
"fmt"
"os"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/PretendoNetwork/super-mario-maker-secure/utility"
)
func getMeta(err error, client *nex.Client, callID uint32, param *nexproto.DataStoreGetMetaParam) {
func GetMeta(err error, client *nex.Client, callID uint32, param *datastore.DataStoreGetMetaParam) {
switch param.DataID {
case 0: // Mii Data
getMetaMiiData(client, callID, param)
@@ -19,18 +22,18 @@ func getMeta(err error, client *nex.Client, callID uint32, param *nexproto.DataS
}
}
func getMetaMiiData(client *nex.Client, callID uint32, param *nexproto.DataStoreGetMetaParam) {
miiInfo := getUserMiiInfoByPID(param.PersistenceTarget.OwnerID)
func getMetaMiiData(client *nex.Client, callID uint32, param *datastore.DataStoreGetMetaParam) {
miiInfo := database.GetUserMiiInfoByPID(param.PersistenceTarget.OwnerID)
pMetaInfo := userMiiDataToDataStoreMetaInfo(param.PersistenceTarget.OwnerID, miiInfo)
pMetaInfo := utility.UserMiiDataToDataStoreMetaInfo(param.PersistenceTarget.OwnerID, miiInfo)
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteStructure(pMetaInfo)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreMethodGetMeta, rmcResponseBody)
rmcResponse := nex.NewRMCResponse(datastore.ProtocolID, callID)
rmcResponse.SetSuccess(datastore.MethodGetMeta, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
@@ -45,23 +48,23 @@ func getMetaMiiData(client *nex.Client, callID uint32, param *nexproto.DataStore
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}
func getMetaEventCourseNewsData(client *nex.Client, callID uint32, param *nexproto.DataStoreGetMetaParam) {
objectSize, _ := s3ObjectSize(os.Getenv("S3_BUCKET_NAME"), "special/900000.bin")
func getMetaEventCourseNewsData(client *nex.Client, callID uint32, param *datastore.DataStoreGetMetaParam) {
objectSize, _ := utility.S3ObjectSize(os.Getenv("S3_BUCKET_NAME"), "special/900000.bin")
pMetaInfo := nexproto.NewDataStoreMetaInfo()
pMetaInfo := datastore.NewDataStoreMetaInfo()
pMetaInfo.DataID = 900000
pMetaInfo.OwnerID = 2
pMetaInfo.Size = uint32(objectSize)
pMetaInfo.Name = ""
pMetaInfo.DataType = 50 // Metdata?
pMetaInfo.MetaBinary = []byte{}
pMetaInfo.Permission = nexproto.NewDataStorePermission()
pMetaInfo.Permission = datastore.NewDataStorePermission()
pMetaInfo.Permission.Permission = 0 // idk?
pMetaInfo.Permission.RecipientIds = []uint32{}
pMetaInfo.DelPermission = nexproto.NewDataStorePermission()
pMetaInfo.DelPermission = datastore.NewDataStorePermission()
pMetaInfo.DelPermission.Permission = 0 // idk?
pMetaInfo.DelPermission.RecipientIds = []uint32{}
pMetaInfo.CreatedTime = nex.NewDateTime(135271087238) // Reused from Nintendo
@@ -74,15 +77,15 @@ func getMetaEventCourseNewsData(client *nex.Client, callID uint32, param *nexpro
pMetaInfo.ReferredTime = nex.NewDateTime(135271087238) // Reused from Nintendo
pMetaInfo.ExpireTime = nex.NewDateTime(671075926016) // Reused from Nintendo
pMetaInfo.Tags = []string{} // idk?
pMetaInfo.Ratings = []*nexproto.DataStoreRatingInfoWithSlot{}
pMetaInfo.Ratings = []*datastore.DataStoreRatingInfoWithSlot{}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteStructure(pMetaInfo)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreMethodGetMeta, rmcResponseBody)
rmcResponse := nex.NewRMCResponse(datastore.ProtocolID, callID)
rmcResponse.SetSuccess(datastore.MethodGetMeta, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
@@ -97,5 +100,5 @@ func getMetaEventCourseNewsData(client *nex.Client, callID uint32, param *nexpro
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,57 @@
package nex_datastore
import (
"fmt"
nex "github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/PretendoNetwork/super-mario-maker-secure/utility"
)
func GetMetasMultipleParam(err error, client *nex.Client, callID uint32, params []*datastore.DataStoreGetMetaParam) {
pMetaInfo := make([]*datastore.DataStoreMetaInfo, 0)
pResults := make([]uint32, 0)
for _, param := range params {
if param.DataID == 0 {
pMetaInfo = append(pMetaInfo, getMetasMultipleParamMiiData(param))
} else {
fmt.Println("Unknown meta multiple data ID")
}
pResults = append(pResults, 0x690001)
}
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteListStructure(pMetaInfo)
rmcResponseStream.WriteListUInt32LE(pResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(datastore.ProtocolID, callID)
rmcResponse.SetSuccess(datastore.MethodGetMetasMultipleParam, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}
func getMetasMultipleParamMiiData(param *datastore.DataStoreGetMetaParam) *datastore.DataStoreMetaInfo {
miiInfo := database.GetUserMiiInfoByPID(param.PersistenceTarget.OwnerID)
return utility.UserMiiDataToDataStoreMetaInfo(param.PersistenceTarget.OwnerID, miiInfo)
}

View File

@@ -1,42 +1,45 @@
package main
package nex_datastore
import (
"fmt"
"os"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/PretendoNetwork/super-mario-maker-secure/utility"
)
func prepareGetObject(err error, client *nex.Client, callID uint32, dataStorePrepareGetParam *nexproto.DataStorePrepareGetParam) {
pReqGetInfo := nexproto.NewDataStoreReqGetInfo()
func PrepareGetObject(err error, client *nex.Client, callID uint32, dataStorePrepareGetParam *datastore.DataStorePrepareGetParam) {
pReqGetInfo := datastore.NewDataStoreReqGetInfo()
if dataStorePrepareGetParam.DataID == 900000 {
objectSize, _ := s3ObjectSize(os.Getenv("S3_BUCKET_NAME"), "special/900000.bin")
objectSize, _ := utility.S3ObjectSize(os.Getenv("S3_BUCKET_NAME"), "special/900000.bin")
pReqGetInfo.URL = fmt.Sprintf("http://%s.b-cdn.net/special/900000.bin", "pds-AMAJ-d1")
pReqGetInfo.RequestHeaders = []*nexproto.DataStoreKeyValue{}
pReqGetInfo.RequestHeaders = []*datastore.DataStoreKeyValue{}
pReqGetInfo.Size = uint32(objectSize)
pReqGetInfo.RootCA = []byte{}
pReqGetInfo.DataID = 900000
} else {
courseMetadata := getCourseMetadataByDataID(dataStorePrepareGetParam.DataID)
courseMetadata := database.GetCourseMetadataByDataID(dataStorePrepareGetParam.DataID)
pReqGetInfo.URL = fmt.Sprintf("http://%s.b-cdn.net/course/%d.bin", os.Getenv("S3_BUCKET_NAME"), dataStorePrepareGetParam.DataID)
pReqGetInfo.RequestHeaders = []*nexproto.DataStoreKeyValue{}
pReqGetInfo.RequestHeaders = []*datastore.DataStoreKeyValue{}
pReqGetInfo.Size = courseMetadata.Size
pReqGetInfo.RootCA = []byte{}
pReqGetInfo.DataID = dataStorePrepareGetParam.DataID
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteStructure(pReqGetInfo)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreMethodPrepareGetObject, rmcResponseBody)
rmcResponse := nex.NewRMCResponse(datastore.ProtocolID, callID)
rmcResponse.SetSuccess(datastore.MethodPrepareGetObject, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
@@ -51,5 +54,5 @@ func prepareGetObject(err error, client *nex.Client, callID uint32, dataStorePre
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,100 @@
package nex_datastore
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"math/rand"
"os"
"strconv"
"time"
nex "github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func PreparePostObject(err error, client *nex.Client, callID uint32, param *datastore.DataStorePreparePostParam) {
rand.Seed(time.Now().UnixNano())
nodeID := rand.Intn(len(globals.DataStoreIDGenerators))
dataStoreIDGenerator := globals.DataStoreIDGenerators[nodeID]
dataID := dataStoreIDGenerator.Next()
database.SetDataStoreIDGeneratorLastID(nodeID, dataStoreIDGenerator.Value)
database.InitializeCourseData(dataID, client.PID(), param.Size, param.Name, param.Flag, param.ExtraData, param.DataType, param.Period)
if param.DataType != 1 { // 1 is Mii data, assume other values are course meta data
database.UpdateCourseMetaBinary(dataID, param.MetaBinary)
}
key := fmt.Sprintf("course/%d.bin", dataID)
bucket := os.Getenv("S3_BUCKET_NAME")
date := strconv.Itoa(int(time.Now().Unix()))
pid := strconv.Itoa(int(client.PID()))
data := pid + bucket + key + date
hmac := hmac.New(sha256.New, globals.HMACSecret)
hmac.Write([]byte(data))
signature := hex.EncodeToString(hmac.Sum(nil))
fieldBucket := datastore.NewDataStoreKeyValue()
fieldBucket.Key = "bucket"
fieldBucket.Value = bucket
fieldKey := datastore.NewDataStoreKeyValue()
fieldKey.Key = "key"
fieldKey.Value = key
fieldACL := datastore.NewDataStoreKeyValue()
fieldACL.Key = "acl"
fieldACL.Value = "private"
fieldPID := datastore.NewDataStoreKeyValue()
fieldPID.Key = "pid"
fieldPID.Value = pid
fieldDate := datastore.NewDataStoreKeyValue()
fieldDate.Key = "date"
fieldDate.Value = date
fieldSignature := datastore.NewDataStoreKeyValue()
fieldSignature.Key = "signature"
fieldSignature.Value = signature
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
pReqPostInfo := datastore.NewDataStoreReqPostInfo()
pReqPostInfo.DataID = dataID
pReqPostInfo.URL = os.Getenv("DATASTORE_UPLOAD_URL")
pReqPostInfo.RequestHeaders = []*datastore.DataStoreKeyValue{}
pReqPostInfo.FormFields = []*datastore.DataStoreKeyValue{fieldBucket, fieldKey, fieldACL, fieldPID, fieldDate, fieldSignature}
pReqPostInfo.RootCACert = []byte{}
rmcResponseStream.WriteStructure(pReqPostInfo)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(datastore.ProtocolID, callID)
rmcResponse.SetSuccess(datastore.MethodPreparePostObject, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -1,22 +1,23 @@
package main
package nex_datastore
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func rateObjects(err error, client *nex.Client, callID uint32, targets []*nexproto.DataStoreRatingTarget, params []*nexproto.DataStoreRateObjectParam, transactional bool, fetchRatings bool) {
func RateObjects(err error, client *nex.Client, callID uint32, targets []*datastore.DataStoreRatingTarget, params []*datastore.DataStoreRateObjectParam, transactional bool, fetchRatings bool) {
// TODO: complete this
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteUInt32LE(0x00000000) // pRatings List length 0
rmcResponseStream.WriteUInt32LE(0x00000000) // pResults List length 0
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreMethodRateObjects, rmcResponseBody)
rmcResponse := nex.NewRMCResponse(datastore.ProtocolID, callID)
rmcResponse.SetSuccess(datastore.MethodRateObjects, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
@@ -31,5 +32,5 @@ func rateObjects(err error, client *nex.Client, callID uint32, targets []*nexpro
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,46 @@
package nex_datastore_super_mario_maker
import (
nex "github.com/PretendoNetwork/nex-go"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func AddToBufferQueues(err error, client *nex.Client, callID uint32, params []*datastore_super_mario_maker.BufferQueueParam, buffers [][]byte) {
pResults := make([]uint32, 0)
for i := 0; i < len(params); i++ {
buffer := buffers[i]
param := params[i]
database.InsertBufferQueueData(param.DataID, param.Slot, buffer)
database.IncrementCourseFailCount(param.DataID)
pResults = append(pResults, 0x690001)
}
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteListUInt32LE(pResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodAddToBufferQueues, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -1,13 +1,14 @@
package main
package nex_datastore_super_mario_maker
import (
"fmt"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func checkRateCustomRankingCounter(err error, client *nex.Client, callID uint32, applicationID uint32) {
func CheckRateCustomRankingCounter(err error, client *nex.Client, callID uint32, applicationID uint32) {
var isBelowThreshold uint8
switch applicationID {
@@ -17,14 +18,14 @@ func checkRateCustomRankingCounter(err error, client *nex.Client, callID uint32,
fmt.Printf("[Warning] DataStoreSMMProtocol::CheckRateCustomRankingCounter Unsupported applicationID: %v\n", applicationID)
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteUInt8(isBelowThreshold)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodCheckRateCustomRankingCounter, rmcResponseBody)
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodCheckRateCustomRankingCounter, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
@@ -39,5 +40,5 @@ func checkRateCustomRankingCounter(err error, client *nex.Client, callID uint32,
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,39 @@
package nex_datastore_super_mario_maker
import (
"fmt"
"os"
nex "github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func CompleteAttachFile(err error, client *nex.Client, callID uint32, dataStoreCompletePostParam *datastore.DataStoreCompletePostParam) {
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
// TODO: complete this
rmcResponseStream.WriteString(fmt.Sprintf("http://%s.b-cdn.net/image/%d.jpg", os.Getenv("S3_BUCKET_NAME"), dataStoreCompletePostParam.DataID))
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodCompleteAttachFile, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,46 @@
package nex_datastore_super_mario_maker
import (
nex "github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/PretendoNetwork/super-mario-maker-secure/utility"
)
// This is the same as DataStoreSMM::RecommendedCourseSearchObject
// Not sure why they used a different method here?
func CTRPickUpCourseSearchObject(err error, client *nex.Client, callID uint32, dataStoreSearchParam *datastore.DataStoreSearchParam, extraData []string) {
pRankingResults := make([]*datastore_super_mario_maker.DataStoreCustomRankingResult, 0)
courseMetadatas := database.GetCourseMetadatasByLimit(100) // In PCAPs param.minimalRatingFrequency is 100 but is 0 here?
for _, courseMetadata := range courseMetadatas {
pRankingResults = append(pRankingResults, utility.CourseMetadataToDataStoreCustomRankingResult(courseMetadata))
}
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteListStructure(pRankingResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodCTRPickUpCourseSearchObject, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,46 @@
package nex_datastore_super_mario_maker
import (
nex "github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/PretendoNetwork/super-mario-maker-secure/utility"
)
func FollowingsLatestCourseSearchObject(err error, client *nex.Client, callID uint32, dataStoreSearchParam *datastore.DataStoreSearchParam, extraData []string) {
pRankingResults := make([]*datastore_super_mario_maker.DataStoreCustomRankingResult, 0)
for _, pid := range dataStoreSearchParam.OwnerIds {
courseMetadatas := database.GetCourseMetadatasByPID(pid)
for _, courseMetadata := range courseMetadatas {
pRankingResults = append(pRankingResults, utility.CourseMetadataToDataStoreCustomRankingResult(courseMetadata))
}
}
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteListStructure(pRankingResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodFollowingsLatestCourseSearchObject, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -1,15 +1,16 @@
package main
package nex_datastore_super_mario_maker
import (
"fmt"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
var MAX_COURSE_UPLOADS uint32 = 0x64 // Nintendo has this set to 100, but we can change it if we want
func getApplicationConfig(err error, client *nex.Client, callID uint32, applicationID uint32) {
func GetApplicationConfig(err error, client *nex.Client, callID uint32, applicationID uint32) {
config := make([]uint32, 0)
@@ -26,14 +27,14 @@ func getApplicationConfig(err error, client *nex.Client, callID uint32, applicat
fmt.Printf("[Warning] DataStoreSMMProtocol::GetApplicationConfig Unsupported applicationID: %v\n", applicationID)
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteListUInt32LE(config)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodGetApplicationConfig, rmcResponseBody)
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodGetApplicationConfig, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
@@ -48,7 +49,7 @@ func getApplicationConfig(err error, client *nex.Client, callID uint32, applicat
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}
func getApplicationConfig_Unknown0() []uint32 {

View File

@@ -1,13 +1,14 @@
package main
package nex_datastore_super_mario_maker
import (
"fmt"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func getApplicationConfigString(err error, client *nex.Client, callID uint32, applicationID uint32) {
func GetApplicationConfigString(err error, client *nex.Client, callID uint32, applicationID uint32) {
// Word blacklists?
config := make([]string, 0)
@@ -22,14 +23,14 @@ func getApplicationConfigString(err error, client *nex.Client, callID uint32, ap
fmt.Printf("[Warning] DataStoreSMMProtocol::GetApplicationConfigString Unsupported applicationID: %v\n", applicationID)
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteListString(config)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodGetApplicationConfigString, rmcResponseBody)
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodGetApplicationConfigString, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
@@ -44,7 +45,7 @@ func getApplicationConfigString(err error, client *nex.Client, callID uint32, ap
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}
func getApplicationConfigString_WordBlacklist1() []string {

View File

@@ -1,16 +1,18 @@
package main
package nex_datastore_super_mario_maker
import (
"fmt"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func getBufferQueue(err error, client *nex.Client, callID uint32, param *nexproto.BufferQueueParam) {
func GetBufferQueue(err error, client *nex.Client, callID uint32, param *datastore_super_mario_maker.BufferQueueParam) {
// TODO: complete this
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
var pBufferQueue [][]byte
@@ -18,7 +20,7 @@ func getBufferQueue(err error, client *nex.Client, callID uint32, param *nexprot
case 0: // unknown
pBufferQueue = make([][]byte, 0)
case 3: // death data
pBufferQueue = getBufferQueueDeathData(param.DataID)
pBufferQueue = database.GetBufferQueueDeathData(param.DataID)
default:
fmt.Printf("[Warning] DataStoreSMMProtocol::GetBufferQueue Unsupported slot: %v\n", param.Slot)
}
@@ -27,8 +29,8 @@ func getBufferQueue(err error, client *nex.Client, callID uint32, param *nexprot
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodGetBufferQueue, rmcResponseBody)
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodGetBufferQueue, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
@@ -43,5 +45,5 @@ func getBufferQueue(err error, client *nex.Client, callID uint32, param *nexprot
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -1,19 +1,21 @@
package main
package nex_datastore_super_mario_maker
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func getCourseRecord(err error, client *nex.Client, callID uint32, param *nexproto.DataStoreGetCourseRecordParam) {
worldRecord := getCourseWorldRecord(param.DataID)
func GetCourseRecord(err error, client *nex.Client, callID uint32, param *datastore_super_mario_maker.DataStoreGetCourseRecordParam) {
worldRecord := database.GetCourseWorldRecord(param.DataID)
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
if worldRecord == nil {
rmcResponse.SetError(0x690004)
} else {
result := nexproto.NewDataStoreGetCourseRecordResult()
result := datastore_super_mario_maker.NewDataStoreGetCourseRecordResult()
result.DataID = param.DataID
result.Slot = param.Slot
result.FirstPID = worldRecord.FirstPID
@@ -22,12 +24,12 @@ func getCourseRecord(err error, client *nex.Client, callID uint32, param *nexpro
result.CreatedTime = worldRecord.CreatedTime
result.UpdatedTime = worldRecord.UpdatedTime
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteStructure(result)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodGetCourseRecord, rmcResponseBody)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodGetCourseRecord, rmcResponseBody)
}
rmcResponseBytes := rmcResponse.Bytes()
@@ -43,5 +45,5 @@ func getCourseRecord(err error, client *nex.Client, callID uint32, param *nexpro
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,97 @@
package nex_datastore_super_mario_maker
import (
nex "github.com/PretendoNetwork/nex-go"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/PretendoNetwork/super-mario-maker-secure/utility"
)
func GetCustomRankingByDataId(err error, client *nex.Client, callID uint32, param *datastore_super_mario_maker.DataStoreGetCustomRankingByDataIdParam) {
var pRankingResult []*datastore_super_mario_maker.DataStoreCustomRankingResult
var pResults []uint32
switch param.ApplicationId {
case 0:
if len(param.DataIdList) == 0 { // Starred courses
pRankingResult, pResults = getCustomRankingByDataIdStarredCourses(client.PID())
} else { // Played courses
pRankingResult, pResults = getCustomRankingByDataIdCourseMetadata(param)
}
case 300000000: // Mii data
pRankingResult, pResults = getCustomRankingByDataIdMiiData(param)
default: // Normal metadata
pRankingResult, pResults = getCustomRankingByDataIdCourseMetadata(param)
}
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteListStructure(pRankingResult)
rmcResponseStream.WriteListUInt32LE(pResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodGetCustomRankingByDataId, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}
func getCustomRankingByDataIdStarredCourses(pid uint32) ([]*datastore_super_mario_maker.DataStoreCustomRankingResult, []uint32) {
courseMetadatas := database.GetUserStarredCourses(pid)
pRankingResult := make([]*datastore_super_mario_maker.DataStoreCustomRankingResult, 0)
pResults := make([]uint32, 0)
for _, courseMetadata := range courseMetadatas {
pRankingResult = append(pRankingResult, utility.CourseMetadataToDataStoreCustomRankingResult(courseMetadata))
pResults = append(pResults, 0x690001)
}
return pRankingResult, pResults
}
func getCustomRankingByDataIdMiiData(param *datastore_super_mario_maker.DataStoreGetCustomRankingByDataIdParam) ([]*datastore_super_mario_maker.DataStoreCustomRankingResult, []uint32) {
pRankingResult := make([]*datastore_super_mario_maker.DataStoreCustomRankingResult, 0)
pResults := make([]uint32, 0)
for _, pid := range param.DataIdList {
pid := uint32(pid)
miiInfo := database.GetUserMiiInfoByPID(pid) // This isn't actually a PID when using the official servers! I set it as one to make this easier for me
if miiInfo != nil {
pRankingResult = append(pRankingResult, utility.UserMiiDataToDataStoreCustomRankingResult(pid, miiInfo))
pResults = append(pResults, 0x690001)
}
}
return pRankingResult, pResults
}
func getCustomRankingByDataIdCourseMetadata(param *datastore_super_mario_maker.DataStoreGetCustomRankingByDataIdParam) ([]*datastore_super_mario_maker.DataStoreCustomRankingResult, []uint32) {
courseMetadatas := database.GetCourseMetadataByDataIDs(param.DataIdList)
pRankingResult := make([]*datastore_super_mario_maker.DataStoreCustomRankingResult, 0)
pResults := make([]uint32, 0)
for _, courseMetadata := range courseMetadatas {
pRankingResult = append(pRankingResult, utility.CourseMetadataToDataStoreCustomRankingResult(courseMetadata))
pResults = append(pResults, 0x690001)
}
return pRankingResult, pResults
}

View File

@@ -1,11 +1,12 @@
package main
package nex_datastore_super_mario_maker
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func getDeletionReason(err error, client *nex.Client, callID uint32, dataIdLst []uint64) {
func GetDeletionReason(err error, client *nex.Client, callID uint32, dataIdLst []uint64) {
// TODO: Complete this
pDeletionReasons := make([]uint32, 0)
@@ -16,14 +17,14 @@ func getDeletionReason(err error, client *nex.Client, callID uint32, dataIdLst [
pDeletionReasons = append(pDeletionReasons, 0x690007)
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteListUInt32LE(pDeletionReasons)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodGetDeletionReason, rmcResponseBody)
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodGetDeletionReason, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
@@ -38,5 +39,5 @@ func getDeletionReason(err error, client *nex.Client, callID uint32, dataIdLst [
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,38 @@
package nex_datastore_super_mario_maker
import (
nex "github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func GetMetasWithCourseRecord(err error, client *nex.Client, callID uint32, dataStoreGetCourseRecordParams []*datastore_super_mario_maker.DataStoreGetCourseRecordParam, dataStoreGetMetaParam *datastore.DataStoreGetMetaParam) {
// TODO: complete this
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteUInt32LE(0x00000000) // pMetaInfo List length 0
rmcResponseStream.WriteUInt32LE(0x00000000) // pCourseResults List length 0
rmcResponseStream.WriteUInt32LE(0x00000000) // pResults List length 0
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodGetMetasWithCourseRecord, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,55 @@
package nex_datastore_super_mario_maker
import (
"fmt"
"os"
nex "github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func GetObjectInfos(err error, client *nex.Client, callID uint32, dataIDs []uint64) {
pInfos := make([]*datastore_super_mario_maker.DataStoreFileServerObjectInfo, 0)
courseMetadatas := database.GetCourseMetadataByDataIDs(dataIDs)
for _, courseMetadata := range courseMetadatas {
info := datastore_super_mario_maker.NewDataStoreFileServerObjectInfo()
info.DataID = courseMetadata.DataID
info.GetInfo = datastore.NewDataStoreReqGetInfo()
info.GetInfo.URL = fmt.Sprintf("http://%s.b-cdn.net/course/%d.bin", os.Getenv("S3_BUCKET_NAME"), courseMetadata.DataID)
info.GetInfo.RequestHeaders = []*datastore.DataStoreKeyValue{}
info.GetInfo.Size = courseMetadata.Size
info.GetInfo.RootCA = []byte{}
info.GetInfo.DataID = courseMetadata.DataID
pInfos = append(pInfos, info)
}
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteListStructure(pInfos)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodGetObjectInfos, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -1,4 +1,4 @@
package main
package nex_datastore_super_mario_maker
import (
"crypto/hmac"
@@ -10,10 +10,12 @@ import (
"time"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func prepareAttachFile(err error, client *nex.Client, callID uint32, dataStoreAttachFileParam *nexproto.DataStoreAttachFileParam) {
func PrepareAttachFile(err error, client *nex.Client, callID uint32, dataStoreAttachFileParam *datastore_super_mario_maker.DataStoreAttachFileParam) {
key := fmt.Sprintf("image/%d.jpg", dataStoreAttachFileParam.ReferDataID)
bucket := os.Getenv("S3_BUCKET_NAME")
date := strconv.Itoa(int(time.Now().Unix()))
@@ -21,55 +23,55 @@ func prepareAttachFile(err error, client *nex.Client, callID uint32, dataStoreAt
data := pid + bucket + key + date
hmac := hmac.New(sha256.New, hmacSecret)
hmac := hmac.New(sha256.New, globals.HMACSecret)
hmac.Write([]byte(data))
signature := hex.EncodeToString(hmac.Sum(nil))
fieldBucket := nexproto.NewDataStoreKeyValue()
fieldBucket := datastore.NewDataStoreKeyValue()
fieldBucket.Key = "bucket"
fieldBucket.Value = bucket
fieldKey := nexproto.NewDataStoreKeyValue()
fieldKey := datastore.NewDataStoreKeyValue()
fieldKey.Key = "key"
fieldKey.Value = key
fieldACL := nexproto.NewDataStoreKeyValue()
fieldACL := datastore.NewDataStoreKeyValue()
fieldACL.Key = "acl"
fieldACL.Value = "public-read"
fieldContentType := nexproto.NewDataStoreKeyValue()
fieldContentType := datastore.NewDataStoreKeyValue()
fieldContentType.Key = "content-type"
fieldContentType.Value = "image/jpeg"
fieldPID := nexproto.NewDataStoreKeyValue()
fieldPID := datastore.NewDataStoreKeyValue()
fieldPID.Key = "pid"
fieldPID.Value = pid
fieldDate := nexproto.NewDataStoreKeyValue()
fieldDate := datastore.NewDataStoreKeyValue()
fieldDate.Key = "date"
fieldDate.Value = date
fieldSignature := nexproto.NewDataStoreKeyValue()
fieldSignature := datastore.NewDataStoreKeyValue()
fieldSignature.Key = "signature"
fieldSignature.Value = signature
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
pReqPostInfo := nexproto.NewDataStoreReqPostInfo()
pReqPostInfo := datastore.NewDataStoreReqPostInfo()
pReqPostInfo.DataID = dataStoreAttachFileParam.ReferDataID
pReqPostInfo.URL = os.Getenv("DATASTORE_UPLOAD_URL")
pReqPostInfo.RequestHeaders = []*nexproto.DataStoreKeyValue{}
pReqPostInfo.FormFields = []*nexproto.DataStoreKeyValue{fieldBucket, fieldKey, fieldACL, fieldContentType, fieldPID, fieldDate, fieldSignature}
pReqPostInfo.RequestHeaders = []*datastore.DataStoreKeyValue{}
pReqPostInfo.FormFields = []*datastore.DataStoreKeyValue{fieldBucket, fieldKey, fieldACL, fieldContentType, fieldPID, fieldDate, fieldSignature}
pReqPostInfo.RootCACert = []byte{}
rmcResponseStream.WriteStructure(pReqPostInfo)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodPrepareAttachFile, rmcResponseBody)
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodPrepareAttachFile, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
@@ -84,5 +86,5 @@ func prepareAttachFile(err error, client *nex.Client, callID uint32, dataStoreAt
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -1,11 +1,13 @@
package main
package nex_datastore_super_mario_maker
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func rateCustomRanking(err error, client *nex.Client, callID uint32, params []*nexproto.DataStoreRateCustomRankingParam) {
func RateCustomRanking(err error, client *nex.Client, callID uint32, params []*datastore_super_mario_maker.DataStoreRateCustomRankingParam) {
/*
This has to change. We need to figure out what DataStoreRateCustomRankingParam.applicationId means.
@@ -81,16 +83,16 @@ func rateCustomRanking(err error, client *nex.Client, callID uint32, params []*n
if len(params) == 2 {
// assume "course clear" action
incrementCourseClearCount(params[0].DataID)
database.IncrementCourseClearCount(params[0].DataID)
}
if len(params) == 12 {
// assume "star course" action
incrementCourseStarCount(params[0].DataID)
database.IncrementCourseStarCount(params[0].DataID)
}
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodRateCustomRanking, nil)
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodRateCustomRanking, nil)
rmcResponseBytes := rmcResponse.Bytes()
@@ -105,5 +107,5 @@ func rateCustomRanking(err error, client *nex.Client, callID uint32, params []*n
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,52 @@
package nex_datastore_super_mario_maker
import (
nex "github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/PretendoNetwork/super-mario-maker-secure/utility"
)
func RecommendedCourseSearchObject(err error, client *nex.Client, callID uint32, param *datastore.DataStoreSearchParam, extraData []string) {
// TODO: complete this
pRankingResults := make([]*datastore_super_mario_maker.DataStoreCustomRankingResult, 0)
// TEMP FOR SHUTTER TO TEST THINGS
if client.PID() == 1049991375 {
courseMetadata := database.GetCourseMetadataByDataID(145) // specific course shutter wants
pRankingResults = append(pRankingResults, utility.CourseMetadataToDataStoreCustomRankingResult(courseMetadata))
} else {
courseMetadatas := database.GetCourseMetadatasByLimit(100) // In PCAPs param.minimalRatingFrequency is 100 but is 0 here?
for _, courseMetadata := range courseMetadatas {
pRankingResults = append(pRankingResults, utility.CourseMetadataToDataStoreCustomRankingResult(courseMetadata))
}
}
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteListStructure(pRankingResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodRecommendedCourseSearchObject, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,54 @@
package nex_datastore_super_mario_maker
import (
"strconv"
nex "github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/PretendoNetwork/super-mario-maker-secure/utility"
)
func SuggestedCourseSearchObject(err error, client *nex.Client, callID uint32, param *datastore.DataStoreSearchParam, extraData []string) {
// TODO: complete this
courseID, _ := strconv.ParseUint(extraData[0], 0, 64)
if utility.UserNotOwnCourse(courseID, client.PID()) {
database.IncrementCourseAttemptCount(courseID) // We also know this is when a user attempts a course
}
pRankingResults := make([]*datastore_super_mario_maker.DataStoreCustomRankingResult, 0)
courseMetadatas := database.GetCourseMetadatasByLimit(4) // In PCAPs param.minimalRatingFrequency is 4 but is 0 here?
for _, courseMetadata := range courseMetadatas {
pRankingResults = append(pRankingResults, utility.CourseMetadataToDataStoreCustomRankingResult(courseMetadata))
}
rmcResponseStream := nex.NewStreamOut(globals.NEXServer)
rmcResponseStream.WriteListStructure(pRankingResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodSuggestedCourseSearchObject, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,30 @@
package nex_datastore_super_mario_maker
import (
nex "github.com/PretendoNetwork/nex-go"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func UploadCourseRecord(err error, client *nex.Client, callID uint32, param *datastore_super_mario_maker.DataStoreUploadCourseRecordParam) {
database.UpdateCourseWorldRecord(param.DataID, client.PID(), param.Score)
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
rmcResponse.SetSuccess(datastore_super_mario_maker.MethodUploadCourseRecord, nil)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -2,12 +2,13 @@ package main
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
message_delivery "github.com/PretendoNetwork/nex-protocols-go/message-delivery"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func deliverMessage(err error, client *nex.Client, callID uint32, oUserMessage nex.StructureInterface) {
rmcResponse := nex.NewRMCResponse(nexproto.MessageDeliveryProtocolID, callID)
rmcResponse.SetSuccess(nexproto.MessageDeliveryMethodDeliverMessage, nil)
func DeliverMessage(err error, client *nex.Client, callID uint32, oUserMessage nex.StructureInterface) {
rmcResponse := nex.NewRMCResponse(message_delivery.ProtocolID, callID)
rmcResponse.SetSuccess(message_delivery.MethodDeliverMessage, nil)
rmcResponseBytes := rmcResponse.Bytes()
@@ -22,5 +23,5 @@ func deliverMessage(err error, client *nex.Client, callID uint32, oUserMessage n
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
globals.NEXServer.Send(responsePacket)
}

View File

@@ -0,0 +1,15 @@
package nex
import (
secureconnection "github.com/PretendoNetwork/nex-protocols-common-go/secure-connection"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
nex_secure_connection_common "github.com/PretendoNetwork/super-mario-maker-secure/nex/secure-connection/common"
)
func registerCommonProtocols() {
secureConnectionProtocol := secureconnection.NewCommonSecureConnectionProtocol(globals.NEXServer)
secureConnectionProtocol.AddConnection(nex_secure_connection_common.AddConnection) // * Stubbed
secureConnectionProtocol.UpdateConnection(nex_secure_connection_common.UpdateConnection) // * Stubbed
secureConnectionProtocol.DoesConnectionExist(nex_secure_connection_common.DoesConnectionExist) // * Stubbed
}

View File

@@ -0,0 +1,42 @@
package nex
import (
"github.com/PretendoNetwork/nex-protocols-go/datastore"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
nex_datastore "github.com/PretendoNetwork/super-mario-maker-secure/nex/datastore"
nex_datastore_super_mario_maker "github.com/PretendoNetwork/super-mario-maker-secure/nex/datastore/super-mario-maker"
)
func registerNEXProtocols() {
datastoreProtocol := datastore.NewDataStoreProtocol(globals.NEXServer)
datastoreProtocol.GetMeta(nex_datastore.GetMeta)
datastoreProtocol.PreparePostObject(nex_datastore.PreparePostObject)
datastoreProtocol.PrepareGetObject(nex_datastore.PrepareGetObject)
datastoreProtocol.CompletePostObject(nex_datastore.CompletePostObject)
datastoreProtocol.GetMetasMultipleParam(nex_datastore.GetMetasMultipleParam)
datastoreProtocol.ChangeMeta(nex_datastore.ChangeMeta)
datastoreProtocol.RateObjects(nex_datastore.RateObjects)
datastoreSMMProtocol := datastore_super_mario_maker.NewDataStoreSuperMarioMakerProtocol(globals.NEXServer)
datastoreSMMProtocol.GetObjectInfos(nex_datastore_super_mario_maker.GetObjectInfos)
datastoreSMMProtocol.RateCustomRanking(nex_datastore_super_mario_maker.RateCustomRanking)
datastoreSMMProtocol.GetCustomRankingByDataId(nex_datastore_super_mario_maker.GetCustomRankingByDataId)
datastoreSMMProtocol.AddToBufferQueues(nex_datastore_super_mario_maker.AddToBufferQueues)
datastoreSMMProtocol.GetBufferQueue(nex_datastore_super_mario_maker.GetBufferQueue)
datastoreSMMProtocol.CompleteAttachFile(nex_datastore_super_mario_maker.CompleteAttachFile)
datastoreSMMProtocol.PrepareAttachFile(nex_datastore_super_mario_maker.PrepareAttachFile)
datastoreSMMProtocol.GetApplicationConfig(nex_datastore_super_mario_maker.GetApplicationConfig)
datastoreSMMProtocol.FollowingsLatestCourseSearchObject(nex_datastore_super_mario_maker.FollowingsLatestCourseSearchObject)
datastoreSMMProtocol.RecommendedCourseSearchObject(nex_datastore_super_mario_maker.RecommendedCourseSearchObject)
datastoreSMMProtocol.SuggestedCourseSearchObject(nex_datastore_super_mario_maker.SuggestedCourseSearchObject)
datastoreSMMProtocol.UploadCourseRecord(nex_datastore_super_mario_maker.UploadCourseRecord)
datastoreSMMProtocol.GetCourseRecord(nex_datastore_super_mario_maker.GetCourseRecord)
datastoreSMMProtocol.GetApplicationConfigString(nex_datastore_super_mario_maker.GetApplicationConfigString)
datastoreSMMProtocol.GetDeletionReason(nex_datastore_super_mario_maker.GetDeletionReason)
datastoreSMMProtocol.GetMetasWithCourseRecord(nex_datastore_super_mario_maker.GetMetasWithCourseRecord)
datastoreSMMProtocol.CheckRateCustomRankingCounter(nex_datastore_super_mario_maker.CheckRateCustomRankingCounter)
datastoreSMMProtocol.CTRPickUpCourseSearchObject(nex_datastore_super_mario_maker.CTRPickUpCourseSearchObject)
}

View File

@@ -0,0 +1,5 @@
package nex_secure_connection_common
func AddConnection(rvcid uint32, urls []string, ip string, port string) {
// TODO - Stubbed
}

View File

@@ -0,0 +1,7 @@
package nex_secure_connection_common
func DoesConnectionExist(rvcid uint32) bool {
// TODO - Stubbed
return false
}

View File

@@ -0,0 +1,5 @@
package nex_secure_connection_common
func UpdateConnection(rvcid uint32, urls []string, ip string, port string) {
// TODO - Stubbed
}

37
nex/server.go Normal file
View File

@@ -0,0 +1,37 @@
package nex
import (
"fmt"
"os"
nex "github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func StartNEXServer() {
globals.NEXServer = nex.NewServer()
globals.NEXServer.SetPRUDPVersion(1)
globals.NEXServer.SetPRUDPProtocolMinorVersion(2)
globals.NEXServer.SetDefaultNEXVersion(&nex.NEXVersion{
Major: 3,
Minor: 8,
Patch: 3,
})
globals.NEXServer.SetKerberosPassword(os.Getenv("KERBEROS_PASSWORD"))
globals.NEXServer.SetAccessKey("9f2b4678")
globals.NEXServer.On("Data", func(packet *nex.PacketV1) {
request := packet.RMCRequest()
fmt.Println("==SMM1 - Secure==")
fmt.Printf("Protocol ID: %#v\n", request.ProtocolID())
fmt.Printf("Method ID: %#v\n", request.MethodID())
fmt.Println("===============")
})
// * Register the common handlers first so that they can be overridden if needed
registerCommonProtocols()
registerNEXProtocols()
globals.NEXServer.Listen(":60003")
}

View File

@@ -1,98 +0,0 @@
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"math/rand"
"os"
"strconv"
"time"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func preparePostObject(err error, client *nex.Client, callID uint32, param *nexproto.DataStorePreparePostParam) {
rand.Seed(time.Now().UnixNano())
nodeID := rand.Intn(len(dataStoreIDGenerators))
dataStoreIDGenerator := dataStoreIDGenerators[nodeID]
dataID := dataStoreIDGenerator.Next()
setDataStoreIDGeneratorLastID(nodeID, dataStoreIDGenerator.Value)
initializeCourseData(dataID, client.PID(), param.Size, param.Name, param.Flag, param.ExtraData, param.DataType, param.Period)
if param.DataType != 1 { // 1 is Mii data, assume other values are course meta data
updateCourseMetaBinary(dataID, param.MetaBinary)
}
key := fmt.Sprintf("course/%d.bin", dataID)
bucket := os.Getenv("S3_BUCKET_NAME")
date := strconv.Itoa(int(time.Now().Unix()))
pid := strconv.Itoa(int(client.PID()))
data := pid + bucket + key + date
hmac := hmac.New(sha256.New, hmacSecret)
hmac.Write([]byte(data))
signature := hex.EncodeToString(hmac.Sum(nil))
fieldBucket := nexproto.NewDataStoreKeyValue()
fieldBucket.Key = "bucket"
fieldBucket.Value = bucket
fieldKey := nexproto.NewDataStoreKeyValue()
fieldKey.Key = "key"
fieldKey.Value = key
fieldACL := nexproto.NewDataStoreKeyValue()
fieldACL.Key = "acl"
fieldACL.Value = "private"
fieldPID := nexproto.NewDataStoreKeyValue()
fieldPID.Key = "pid"
fieldPID.Value = pid
fieldDate := nexproto.NewDataStoreKeyValue()
fieldDate.Key = "date"
fieldDate.Value = date
fieldSignature := nexproto.NewDataStoreKeyValue()
fieldSignature.Key = "signature"
fieldSignature.Value = signature
rmcResponseStream := nex.NewStreamOut(nexServer)
pReqPostInfo := nexproto.NewDataStoreReqPostInfo()
pReqPostInfo.DataID = dataID
pReqPostInfo.URL = os.Getenv("DATASTORE_UPLOAD_URL")
pReqPostInfo.RequestHeaders = []*nexproto.DataStoreKeyValue{}
pReqPostInfo.FormFields = []*nexproto.DataStoreKeyValue{fieldBucket, fieldKey, fieldACL, fieldPID, fieldDate, fieldSignature}
pReqPostInfo.RootCACert = []byte{}
rmcResponseStream.WriteStructure(pReqPostInfo)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreMethodPreparePostObject, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}

View File

@@ -1,48 +0,0 @@
package main
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func recommendedCourseSearchObject(err error, client *nex.Client, callID uint32, param *nexproto.DataStoreSearchParam, extraData []string) {
// TODO: complete this
pRankingResults := make([]*nexproto.DataStoreCustomRankingResult, 0)
// TEMP FOR SHUTTER TO TEST THINGS
if client.PID() == 1049991375 {
courseMetadata := getCourseMetadataByDataID(145) // specific course shutter wants
pRankingResults = append(pRankingResults, courseMetadataToDataStoreCustomRankingResult(courseMetadata))
} else {
courseMetadatas := getCourseMetadatasByLimit(100) // In PCAPs param.minimalRatingFrequency is 100 but is 0 here?
for _, courseMetadata := range courseMetadatas {
pRankingResults = append(pRankingResults, courseMetadataToDataStoreCustomRankingResult(courseMetadata))
}
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream.WriteListStructure(pRankingResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodRecommendedCourseSearchObject, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}

View File

@@ -1,47 +0,0 @@
package main
import (
"strconv"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func register(err error, client *nex.Client, callID uint32, stationUrls []*nex.StationURL) {
localStation := stationUrls[0]
address := client.Address().IP.String()
port := strconv.Itoa(client.Address().Port)
localStation.SetAddress(&address)
localStation.SetPort(&port)
localStationURL := localStation.EncodeToString()
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream.WriteUInt32LE(0x10001) // Success
rmcResponseStream.WriteUInt32LE(nexServer.ConnectionIDCounter().Increment())
rmcResponseStream.WriteString(localStationURL)
rmcResponseBody := rmcResponseStream.Bytes()
// Build response packet
rmcResponse := nex.NewRMCResponse(nexproto.SecureProtocolID, callID)
rmcResponse.SetSuccess(nexproto.SecureMethodRegisterEx, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}

View File

@@ -1,50 +0,0 @@
package main
import (
"strconv"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func suggestedCourseSearchObject(err error, client *nex.Client, callID uint32, param *nexproto.DataStoreSearchParam, extraData []string) {
// TODO: complete this
courseID, _ := strconv.ParseUint(extraData[0], 0, 64)
if userNotOwnCourse(courseID, client.PID()) {
incrementCourseAttemptCount(courseID) // We also know this is when a user attempts a course
}
pRankingResults := make([]*nexproto.DataStoreCustomRankingResult, 0)
courseMetadatas := getCourseMetadatasByLimit(4) // In PCAPs param.minimalRatingFrequency is 4 but is 0 here?
for _, courseMetadata := range courseMetadatas {
pRankingResults = append(pRankingResults, courseMetadataToDataStoreCustomRankingResult(courseMetadata))
}
rmcResponseStream := nex.NewStreamOut(nexServer)
rmcResponseStream.WriteListStructure(pRankingResults)
rmcResponseBody := rmcResponseStream.Bytes()
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreSMMProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodSuggestedCourseSearchObject, rmcResponseBody)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}

View File

@@ -1,4 +1,4 @@
package main
package types
import "github.com/PretendoNetwork/nex-go"
@@ -18,11 +18,3 @@ type CourseMetadata struct {
DataType uint16
Period uint16
}
type CourseWorldRecord struct {
FirstPID uint32
BestPID uint32
CreatedTime *nex.DateTime
UpdatedTime *nex.DateTime
Score int32
}

View File

@@ -0,0 +1,11 @@
package types
import "github.com/PretendoNetwork/nex-go"
type CourseWorldRecord struct {
FirstPID uint32
BestPID uint32
CreatedTime *nex.DateTime
UpdatedTime *nex.DateTime
Score int32
}

View File

@@ -1,28 +0,0 @@
package main
import (
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
)
func uploadCourseRecord(err error, client *nex.Client, callID uint32, param *nexproto.DataStoreUploadCourseRecordParam) {
updateCourseWorldRecord(param.DataID, client.PID(), param.Score)
rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID)
rmcResponse.SetSuccess(nexproto.DataStoreSMMMethodUploadCourseRecord, nil)
rmcResponseBytes := rmcResponse.Bytes()
responsePacket, _ := nex.NewPacketV1(client, nil)
responsePacket.SetVersion(1)
responsePacket.SetSource(0xA1)
responsePacket.SetDestination(0xAF)
responsePacket.SetType(nex.DataPacket)
responsePacket.SetPayload(rmcResponseBytes)
responsePacket.AddFlag(nex.FlagNeedsAck)
responsePacket.AddFlag(nex.FlagReliable)
nexServer.Send(responsePacket)
}

View File

@@ -1,28 +1,32 @@
package main
package utility
import (
"context"
"encoding/base64"
"time"
nex "github.com/PretendoNetwork/nex-go"
nexproto "github.com/PretendoNetwork/nex-protocols-go"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/PretendoNetwork/nex-protocols-go/datastore"
datastore_super_mario_maker "github.com/PretendoNetwork/nex-protocols-go/datastore/super-mario-maker"
"github.com/PretendoNetwork/super-mario-maker-secure/database"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/PretendoNetwork/super-mario-maker-secure/types"
"github.com/aws/aws-sdk-go-v2/service/s3"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func courseMetadataToDataStoreCustomRankingResult(courseMetadata *CourseMetadata) *nexproto.DataStoreCustomRankingResult {
rankingResult := nexproto.NewDataStoreCustomRankingResult()
func CourseMetadataToDataStoreCustomRankingResult(courseMetadata *types.CourseMetadata) *datastore_super_mario_maker.DataStoreCustomRankingResult {
rankingResult := datastore_super_mario_maker.NewDataStoreCustomRankingResult()
rankingResult.Order = 0 // unknown
rankingResult.Score = courseMetadata.Stars
rankingResult.MetaInfo = courseMetadataToDataStoreMetaInfo(courseMetadata)
rankingResult.MetaInfo = CourseMetadataToDataStoreMetaInfo(courseMetadata)
return rankingResult
}
func courseMetadataToDataStoreMetaInfo(courseMetadata *CourseMetadata) *nexproto.DataStoreMetaInfo {
metaInfo := nexproto.NewDataStoreMetaInfo()
func CourseMetadataToDataStoreMetaInfo(courseMetadata *types.CourseMetadata) *datastore.DataStoreMetaInfo {
metaInfo := datastore.NewDataStoreMetaInfo()
metaInfo.DataID = courseMetadata.DataID
metaInfo.OwnerID = courseMetadata.OwnerPID
@@ -30,10 +34,10 @@ func courseMetadataToDataStoreMetaInfo(courseMetadata *CourseMetadata) *nexproto
metaInfo.Name = courseMetadata.Name
metaInfo.DataType = courseMetadata.DataType
metaInfo.MetaBinary = courseMetadata.MetaBinary
metaInfo.Permission = nexproto.NewDataStorePermission()
metaInfo.Permission = datastore.NewDataStorePermission()
metaInfo.Permission.Permission = 0 // unknown
metaInfo.Permission.RecipientIds = []uint32{}
metaInfo.DelPermission = nexproto.NewDataStorePermission()
metaInfo.DelPermission = datastore.NewDataStorePermission()
metaInfo.DelPermission.Permission = 3 // unknown
metaInfo.DelPermission.RecipientIds = []uint32{}
metaInfo.CreatedTime = courseMetadata.CreatedTime
@@ -46,61 +50,61 @@ func courseMetadataToDataStoreMetaInfo(courseMetadata *CourseMetadata) *nexproto
metaInfo.ReferredTime = courseMetadata.CreatedTime
metaInfo.ExpireTime = nex.NewDateTime(671075926016) // December 31st, year 9999
metaInfo.Tags = []string{""} // unknown
metaInfo.Ratings = []*nexproto.DataStoreRatingInfoWithSlot{
nexproto.NewDataStoreRatingInfoWithSlot(), // attempts
nexproto.NewDataStoreRatingInfoWithSlot(), // unknown
nexproto.NewDataStoreRatingInfoWithSlot(), // completions
nexproto.NewDataStoreRatingInfoWithSlot(), // failures
nexproto.NewDataStoreRatingInfoWithSlot(), // unknown
nexproto.NewDataStoreRatingInfoWithSlot(), // unknown
nexproto.NewDataStoreRatingInfoWithSlot(), // unknown
metaInfo.Ratings = []*datastore.DataStoreRatingInfoWithSlot{
datastore.NewDataStoreRatingInfoWithSlot(), // attempts
datastore.NewDataStoreRatingInfoWithSlot(), // unknown
datastore.NewDataStoreRatingInfoWithSlot(), // completions
datastore.NewDataStoreRatingInfoWithSlot(), // failures
datastore.NewDataStoreRatingInfoWithSlot(), // unknown
datastore.NewDataStoreRatingInfoWithSlot(), // unknown
datastore.NewDataStoreRatingInfoWithSlot(), // unknown
}
// attempts
metaInfo.Ratings[0].Slot = 0
metaInfo.Ratings[0].Rating = nexproto.NewDataStoreRatingInfo()
metaInfo.Ratings[0].Rating = datastore.NewDataStoreRatingInfo()
metaInfo.Ratings[0].Rating.TotalValue = int64(courseMetadata.Attempts)
metaInfo.Ratings[0].Rating.Count = courseMetadata.Attempts
metaInfo.Ratings[0].Rating.InitialValue = 0
// unknown
metaInfo.Ratings[1].Slot = 1
metaInfo.Ratings[1].Rating = nexproto.NewDataStoreRatingInfo()
metaInfo.Ratings[1].Rating = datastore.NewDataStoreRatingInfo()
metaInfo.Ratings[1].Rating.TotalValue = 2
metaInfo.Ratings[1].Rating.Count = 2
metaInfo.Ratings[1].Rating.InitialValue = 0
// completions
metaInfo.Ratings[2].Slot = 2
metaInfo.Ratings[2].Rating = nexproto.NewDataStoreRatingInfo()
metaInfo.Ratings[2].Rating = datastore.NewDataStoreRatingInfo()
metaInfo.Ratings[2].Rating.TotalValue = int64(courseMetadata.Completions)
metaInfo.Ratings[2].Rating.Count = courseMetadata.Completions
metaInfo.Ratings[2].Rating.InitialValue = 0
// failures
metaInfo.Ratings[3].Slot = 3
metaInfo.Ratings[3].Rating = nexproto.NewDataStoreRatingInfo()
metaInfo.Ratings[3].Rating = datastore.NewDataStoreRatingInfo()
metaInfo.Ratings[3].Rating.TotalValue = int64(courseMetadata.Failures)
metaInfo.Ratings[3].Rating.Count = courseMetadata.Failures
metaInfo.Ratings[3].Rating.InitialValue = 0
// unknown
metaInfo.Ratings[4].Slot = 4
metaInfo.Ratings[4].Rating = nexproto.NewDataStoreRatingInfo()
metaInfo.Ratings[4].Rating = datastore.NewDataStoreRatingInfo()
metaInfo.Ratings[4].Rating.TotalValue = 5
metaInfo.Ratings[4].Rating.Count = 5
metaInfo.Ratings[4].Rating.InitialValue = 0
// unknown
metaInfo.Ratings[5].Slot = 5
metaInfo.Ratings[5].Rating = nexproto.NewDataStoreRatingInfo()
metaInfo.Ratings[5].Rating = datastore.NewDataStoreRatingInfo()
metaInfo.Ratings[5].Rating.TotalValue = 6
metaInfo.Ratings[5].Rating.Count = 6
metaInfo.Ratings[5].Rating.InitialValue = 0
// Number of new Miiverse comments
metaInfo.Ratings[6].Slot = 6
metaInfo.Ratings[6].Rating = nexproto.NewDataStoreRatingInfo()
metaInfo.Ratings[6].Rating = datastore.NewDataStoreRatingInfo()
metaInfo.Ratings[6].Rating.TotalValue = 0
metaInfo.Ratings[6].Rating.Count = 0
metaInfo.Ratings[6].Rating.InitialValue = 0
@@ -108,21 +112,21 @@ func courseMetadataToDataStoreMetaInfo(courseMetadata *CourseMetadata) *nexproto
return metaInfo
}
func userMiiDataToDataStoreCustomRankingResult(ownerID uint32, miiInfo primitive.M) *nexproto.DataStoreCustomRankingResult {
rankingResult := nexproto.NewDataStoreCustomRankingResult()
func UserMiiDataToDataStoreCustomRankingResult(ownerID uint32, miiInfo primitive.M) *datastore_super_mario_maker.DataStoreCustomRankingResult {
rankingResult := datastore_super_mario_maker.NewDataStoreCustomRankingResult()
rankingResult.Order = 0
rankingResult.Score = 0
rankingResult.MetaInfo = userMiiDataToDataStoreMetaInfo(ownerID, miiInfo)
rankingResult.MetaInfo = UserMiiDataToDataStoreMetaInfo(ownerID, miiInfo)
return rankingResult
}
func userMiiDataToDataStoreMetaInfo(ownerID uint32, miiInfo primitive.M) *nexproto.DataStoreMetaInfo {
func UserMiiDataToDataStoreMetaInfo(ownerID uint32, miiInfo primitive.M) *datastore.DataStoreMetaInfo {
encodedMiiData := miiInfo["data"].(string)
decodedMiiData, _ := base64.StdEncoding.DecodeString(encodedMiiData)
metaBinaryStream := nex.NewStreamOut(nexServer)
metaBinaryStream := nex.NewStreamOut(globals.NEXServer)
metaBinaryStream.Grow(140)
metaBinaryStream.WriteBytesNext([]byte{
0x42, 0x50, 0x46, 0x43, // BPFC magic
@@ -143,17 +147,17 @@ func userMiiDataToDataStoreMetaInfo(ownerID uint32, miiInfo primitive.M) *nexpro
now := uint64(time.Now().Unix())
metaInfo := nexproto.NewDataStoreMetaInfo()
metaInfo := datastore.NewDataStoreMetaInfo()
metaInfo.DataID = uint64(ownerID) // This isn;t actually a user PID in Nintendo's servers, but it makes it much easier for us to do it this way
metaInfo.OwnerID = ownerID
metaInfo.Size = 0
metaInfo.Name = miiInfo["name"].(string)
metaInfo.DataType = 1 // Mii data type?
metaInfo.MetaBinary = metaBinaryStream.Bytes()
metaInfo.Permission = nexproto.NewDataStorePermission()
metaInfo.Permission = datastore.NewDataStorePermission()
metaInfo.Permission.Permission = 0 // idk?
metaInfo.Permission.RecipientIds = []uint32{}
metaInfo.DelPermission = nexproto.NewDataStorePermission()
metaInfo.DelPermission = datastore.NewDataStorePermission()
metaInfo.DelPermission.Permission = 3 // idk?
metaInfo.DelPermission.RecipientIds = []uint32{}
metaInfo.CreatedTime = nex.NewDateTime(now)
@@ -166,26 +170,38 @@ func userMiiDataToDataStoreMetaInfo(ownerID uint32, miiInfo primitive.M) *nexpro
metaInfo.ReferredTime = nex.NewDateTime(now)
metaInfo.ExpireTime = nex.NewDateTime(now)
metaInfo.Tags = []string{"49"} // idk?
metaInfo.Ratings = []*nexproto.DataStoreRatingInfoWithSlot{}
metaInfo.Ratings = []*datastore.DataStoreRatingInfoWithSlot{}
return metaInfo
}
func userNotOwnCourse(courseID uint64, pid uint32) bool {
courseMetadata := getCourseMetadataByDataID(courseID)
func UserNotOwnCourse(courseID uint64, pid uint32) bool {
courseMetadata := database.GetCourseMetadataByDataID(courseID)
return courseMetadata.OwnerPID != pid
}
func s3ObjectSize(bucket, key string) (uint64, error) {
headObj := s3.HeadObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
func S3HeadRequest(bucket, key string) (*s3.HeadObjectOutput, error) {
input := &s3.HeadObjectInput{
Bucket: &bucket,
Key: &key,
}
result, err := s3Client.HeadObject(&headObj)
res, err := globals.S3Client.HeadObject(context.TODO(), input)
if err != nil {
return nil, err
}
return res, nil
}
func S3ObjectSize(bucket, key string) (uint64, error) {
res, err := S3HeadRequest(bucket, key)
if err != nil {
return 0, err
}
return uint64(aws.Int64Value(result.ContentLength)), nil
return uint64(res.ContentLength), nil
}