diff --git a/.gitignore b/.gitignore index 0973d20..fa187d1 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ # custom build .env +*.key diff --git a/complete_post_object.go b/complete_post_object.go index 1602da5..0555ecb 100644 --- a/complete_post_object.go +++ b/complete_post_object.go @@ -1,6 +1,8 @@ package main import ( + "fmt" + nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) @@ -8,6 +10,8 @@ import ( func completePostObject(err error, client *nex.Client, callID uint32, dataStoreCompletePostParam *nexproto.DataStoreCompletePostParam) { // STUBBED // TODO: DO SOMETHING WITH THE DATA + + fmt.Printf("%+v\n", dataStoreCompletePostParam) rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID) rmcResponse.SetSuccess(nexproto.DataStoreMethodCompletePostObject, nil) diff --git a/connect.go b/connect.go index 5acba08..182e540 100644 --- a/connect.go +++ b/connect.go @@ -19,7 +19,8 @@ func connect(packet *nex.PacketV1) { checkDataDecrypted := kerberos.Decrypt(checkData) checkDataStream := nex.NewStreamIn(checkDataDecrypted, nexServer) - _ = checkDataStream.ReadUInt32LE() // User PID + userPID := checkDataStream.ReadUInt32LE() // User PID + packet.Sender().SetPID(userPID) _ = checkDataStream.ReadUInt32LE() //CID of secure server station url responseCheck := checkDataStream.ReadUInt32LE() diff --git a/database.go b/database.go new file mode 100644 index 0000000..da16e96 --- /dev/null +++ b/database.go @@ -0,0 +1,110 @@ +package main + +import ( + "context" + "flag" + "fmt" + "log" + "time" + + "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("mongodb://127.0.0.1:27017/")) + mongoContext, _ = context.WithTimeout(context.Background(), 10*time.Second) + _ = mongoClient.Connect(mongoContext) + + mongoDatabase = mongoClient.Database("pretendo") + mongoCollection = mongoDatabase.Collection("pnids") +} + +func connectCassandra() { + // Connect to Cassandra + return + + 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 + + // TODO: Add tables + + 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 // +// // +//////////////////////////////// + +////////////////////////////// +// // +// 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) +} diff --git a/get_custom_ranking_by_data_id.go b/get_custom_ranking_by_data_id.go index 0723252..26c9474 100644 --- a/get_custom_ranking_by_data_id.go +++ b/get_custom_ranking_by_data_id.go @@ -1,11 +1,115 @@ package main import ( + "encoding/base64" + "time" + nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) -func getCustomRankingByDataId(err error, client *nex.Client, callID uint32, dataStoreGetCustomRankingByDataIdParam *nexproto.DataStoreGetCustomRankingByDataIdParam) { +func getCustomRankingByDataId(err error, client *nex.Client, callID uint32, param *nexproto.DataStoreGetCustomRankingByDataIdParam) { + if param.ApplicationId == 300000000 { + // Mii Data + getCustomRankingByDataIdMiiData(client, callID, param) + } else { + // Course Metadata + getCustomRankingByDataIdCourseMetadata(client, callID, param) + } +} + +func getCustomRankingByDataIdMiiData(client *nex.Client, callID uint32, param *nexproto.DataStoreGetCustomRankingByDataIdParam) { + ownerID := uint32(param.DataIdList[0]) // This isn't actually a PID when using the official servers! I set it as one to make this easier for me + miiInfo := getUserMiiInfoByPID(ownerID) + + pRankingResult := make([]*nexproto.DataStoreCustomRankingResult, 0) + + if miiInfo != nil { + encodedMiiData := miiInfo["data"].(string) + decodedMiiData, _ := base64.StdEncoding.DecodeString(encodedMiiData) + + metaBinaryStream := nex.NewStreamOut(nexServer) + metaBinaryStream.Grow(140) + metaBinaryStream.WriteBytesNext([]byte{ + 0x42, 0x50, 0x46, 0x43, // BPFC magic + 0x00, 0x00, 0x00, 0x01, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x01, 0x00, 0x00, // Unknown + }) + metaBinaryStream.WriteBytesNext(decodedMiiData) // Actual Mii data + metaBinaryStream.WriteBytesNext([]byte{ + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x01, // Unknown + }) + + now := uint64(time.Now().Unix()) + + rankingResult := nexproto.NewDataStoreCustomRankingResult() + + rankingResult.Order = 0 + rankingResult.Score = 0 + rankingResult.MetaInfo = nexproto.NewDataStoreMetaInfo() + rankingResult.MetaInfo.DataID = uint64(ownerID) // idk what this is, but it gets used elsewhere for request Mii data again. Setting it as a PID makes that easier for me + rankingResult.MetaInfo.OwnerID = ownerID + rankingResult.MetaInfo.Size = 0 + rankingResult.MetaInfo.Name = miiInfo["name"].(string) + rankingResult.MetaInfo.DataType = 1 // Mii data type? + rankingResult.MetaInfo.MetaBinary = metaBinaryStream.Bytes() + rankingResult.MetaInfo.Permission = nexproto.NewDataStorePermission() + rankingResult.MetaInfo.Permission.Permission = 0 // idk? + rankingResult.MetaInfo.Permission.RecipientIds = []uint32{} + rankingResult.MetaInfo.DelPermission = nexproto.NewDataStorePermission() + rankingResult.MetaInfo.DelPermission.Permission = 3 // idk? + rankingResult.MetaInfo.DelPermission.RecipientIds = []uint32{} + rankingResult.MetaInfo.CreatedTime = nex.NewDateTime(now) + rankingResult.MetaInfo.UpdatedTime = nex.NewDateTime(now) + rankingResult.MetaInfo.Period = 90 // idk? + rankingResult.MetaInfo.Status = 0 + rankingResult.MetaInfo.ReferredCnt = 0 + rankingResult.MetaInfo.ReferDataID = 0 + rankingResult.MetaInfo.Flag = 256 // idk? + rankingResult.MetaInfo.ReferredTime = nex.NewDateTime(now) + rankingResult.MetaInfo.ExpireTime = nex.NewDateTime(now) + rankingResult.MetaInfo.Tags = []string{"49"} // idk? + rankingResult.MetaInfo.Ratings = []*nexproto.DataStoreRatingInfoWithSlot{} + + pRankingResult = append(pRankingResult, rankingResult) + } + + pResults := []uint32{0x690001} + + 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 getCustomRankingByDataIdCourseMetadata(client *nex.Client, callID uint32, param *nexproto.DataStoreGetCustomRankingByDataIdParam) { rmcResponseStream := nex.NewStreamOut(nexServer) // TODO complete this diff --git a/get_meta.go b/get_meta.go index 0a761b8..d0f3c4d 100644 --- a/get_meta.go +++ b/get_meta.go @@ -1,30 +1,86 @@ package main import ( + "encoding/base64" "encoding/hex" "fmt" + "time" nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) -func getMeta(err error, client *nex.Client, callID uint32, dataStoreGetMetaParam *nexproto.DataStoreGetMetaParam) { - switch dataStoreGetMetaParam.DataID { +func getMeta(err error, client *nex.Client, callID uint32, param *nexproto.DataStoreGetMetaParam) { + switch param.DataID { case 0: // Mii Data - getMetaMiiData(client, callID, dataStoreGetMetaParam) + getMetaMiiData(client, callID, param) case 900000: // Course ID - getCourseMetadata(client, callID, dataStoreGetMetaParam) + getMetaCourseMetadata(client, callID, param) default: - fmt.Printf("[Warning] DataStoreProtocol::GetMeta Unsupported dataId: %v\n", dataStoreGetMetaParam.DataID) + fmt.Printf("[Warning] DataStoreProtocol::GetMeta Unsupported dataId: %v\n", param.DataID) } } -func getMetaMiiData(client *nex.Client, callID uint32, dataStoreGetMetaParam *nexproto.DataStoreGetMetaParam) { - const examplePayload = "00fc000000f86584030000000004395068000000000a005265644475636b73730001008c0042504643000000010000000000000000000000000001000003007330d94dae0fe5c6c34093aaf6a740f40769fe720000d2125200650064004400750063006b00730000000000642b000016010268441826344614811217688d008a25814948505200650064004400750063006b007300730000000000bf270000000000000000000000000000000000000001000500000000000000000005000000030000000073305f881f00000073305f881f0000005a000000000000000000000001000073305f881f00000000003e3f9c00000001000000030034390000000000" - examplePayloadBytes, _ := hex.DecodeString(examplePayload) +func getMetaMiiData(client *nex.Client, callID uint32, param *nexproto.DataStoreGetMetaParam) { + miiInfo := getUserMiiInfoByPID(param.PersistenceTarget.OwnerID) + + encodedMiiData := miiInfo["data"].(string) + decodedMiiData, _ := base64.StdEncoding.DecodeString(encodedMiiData) + + metaBinaryStream := nex.NewStreamOut(nexServer) + metaBinaryStream.Grow(140) + metaBinaryStream.WriteBytesNext([]byte{ + 0x42, 0x50, 0x46, 0x43, // BPFC magic + 0x00, 0x00, 0x00, 0x01, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x01, 0x00, 0x00, // Unknown + }) + metaBinaryStream.WriteBytesNext(decodedMiiData) // Actual Mii data + metaBinaryStream.WriteBytesNext([]byte{ + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x01, // Unknown + }) + + now := uint64(time.Now().Unix()) + + pMetaInfo := nexproto.NewDataStoreMetaInfo() + + pMetaInfo.DataID = uint64(param.PersistenceTarget.OwnerID) // idk what this is, but it gets used elsewhere for request Mii data again. Setting it as a PID makes that easier for me + pMetaInfo.OwnerID = param.PersistenceTarget.OwnerID + pMetaInfo.Size = 0 + pMetaInfo.Name = miiInfo["name"].(string) + pMetaInfo.DataType = 1 // Mii data type? + pMetaInfo.MetaBinary = metaBinaryStream.Bytes() + pMetaInfo.Permission = nexproto.NewDataStorePermission() + pMetaInfo.Permission.Permission = 0 // idk? + pMetaInfo.Permission.RecipientIds = []uint32{} + pMetaInfo.DelPermission = nexproto.NewDataStorePermission() + pMetaInfo.DelPermission.Permission = 3 // idk? + pMetaInfo.DelPermission.RecipientIds = []uint32{} + pMetaInfo.CreatedTime = nex.NewDateTime(now) + pMetaInfo.UpdatedTime = nex.NewDateTime(now) + pMetaInfo.Period = 90 // idk? + pMetaInfo.Status = 0 + pMetaInfo.ReferredCnt = 0 + pMetaInfo.ReferDataID = 0 + pMetaInfo.Flag = 256 // idk? + pMetaInfo.ReferredTime = nex.NewDateTime(now) + pMetaInfo.ExpireTime = nex.NewDateTime(now) + pMetaInfo.Tags = []string{"49"} // idk? + pMetaInfo.Ratings = []*nexproto.DataStoreRatingInfoWithSlot{} + + rmcResponseStream := nex.NewStreamOut(nexServer) + rmcResponseStream.WriteStructure(pMetaInfo) + + rmcResponseBody := rmcResponseStream.Bytes() rmcResponse := nex.NewRMCResponse(nexproto.DataStoreProtocolID, callID) - rmcResponse.SetSuccess(nexproto.DataStoreMethodGetMeta, examplePayloadBytes) + rmcResponse.SetSuccess(nexproto.DataStoreMethodGetMeta, rmcResponseBody) rmcResponseBytes := rmcResponse.Bytes() @@ -42,7 +98,7 @@ func getMetaMiiData(client *nex.Client, callID uint32, dataStoreGetMetaParam *ne nexServer.Send(responsePacket) } -func getCourseMetadata(client *nex.Client, callID uint32, dataStoreGetMetaParam *nexproto.DataStoreGetMetaParam) { +func getMetaCourseMetadata(client *nex.Client, callID uint32, param *nexproto.DataStoreGetMetaParam) { const examplePayload = "0062000000a0bb0d00000000000200000014de060001000032000000000500000000000000000005000000000000000086fcc87e1f0000001605a2861f00000032fb0000000000000000000000000086fcc87e1f00000000003e3f9c0000000000000000000000" examplePayloadBytes, _ := hex.DecodeString(examplePayload) diff --git a/get_metas_multiple_param.go b/get_metas_multiple_param.go index 64aa6a9..7c747b6 100644 --- a/get_metas_multiple_param.go +++ b/get_metas_multiple_param.go @@ -1,17 +1,34 @@ package main import ( + "encoding/base64" + "fmt" + "time" + nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) -func getMetasMultipleParam(err error, client *nex.Client, callID uint32, dataStoreGetMetaParams []*nexproto.DataStoreGetMetaParam) { +func getMetasMultipleParam(err error, client *nex.Client, callID uint32, params []*nexproto.DataStoreGetMetaParam) { + pMetaInfo := make([]*nexproto.DataStoreMetaInfo, 0) + pResults := make([]uint32, 0) + + for i := 0; i < len(params); i++ { + param := params[i] + + 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) - // TODO complete this - - rmcResponseStream.WriteUInt32LE(0x00000000) // pMetaInfo List length 0 - rmcResponseStream.WriteUInt32LE(0x00000000) // pResults List length 0 + rmcResponseStream.WriteListStructure(pMetaInfo) + rmcResponseStream.WriteListUInt32LE(pResults) rmcResponseBody := rmcResponseStream.Bytes() @@ -33,3 +50,59 @@ func getMetasMultipleParam(err error, client *nex.Client, callID uint32, dataSto nexServer.Send(responsePacket) } + +func getMetasMultipleParamMiiData(param *nexproto.DataStoreGetMetaParam) *nexproto.DataStoreMetaInfo { + miiInfo := getUserMiiInfoByPID(param.PersistenceTarget.OwnerID) + + encodedMiiData := miiInfo["data"].(string) + decodedMiiData, _ := base64.StdEncoding.DecodeString(encodedMiiData) + + metaBinaryStream := nex.NewStreamOut(nexServer) + metaBinaryStream.Grow(140) + metaBinaryStream.WriteBytesNext([]byte{ + 0x42, 0x50, 0x46, 0x43, // BPFC magic + 0x00, 0x00, 0x00, 0x01, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x01, 0x00, 0x00, // Unknown + }) + metaBinaryStream.WriteBytesNext(decodedMiiData) // Actual Mii data + metaBinaryStream.WriteBytesNext([]byte{ + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x00, // Unknown + 0x00, 0x00, 0x00, 0x01, // Unknown + }) + + now := uint64(time.Now().Unix()) + + pMetaInfo := nexproto.NewDataStoreMetaInfo() + + pMetaInfo.DataID = uint64(param.PersistenceTarget.OwnerID) // idk what this is, but it gets used elsewhere for request Mii data again. Setting it as a PID makes that easier for me + pMetaInfo.OwnerID = param.PersistenceTarget.OwnerID + pMetaInfo.Size = 0 + pMetaInfo.Name = miiInfo["name"].(string) + pMetaInfo.DataType = 1 // Mii data type? + pMetaInfo.MetaBinary = metaBinaryStream.Bytes() + pMetaInfo.Permission = nexproto.NewDataStorePermission() + pMetaInfo.Permission.Permission = 0 // idk? + pMetaInfo.Permission.RecipientIds = []uint32{} + pMetaInfo.DelPermission = nexproto.NewDataStorePermission() + pMetaInfo.DelPermission.Permission = 3 // idk? + pMetaInfo.DelPermission.RecipientIds = []uint32{} + pMetaInfo.CreatedTime = nex.NewDateTime(now) + pMetaInfo.UpdatedTime = nex.NewDateTime(now) + pMetaInfo.Period = 90 // idk? + pMetaInfo.Status = 0 + pMetaInfo.ReferredCnt = 0 + pMetaInfo.ReferDataID = 0 + pMetaInfo.Flag = 256 // idk? + pMetaInfo.ReferredTime = nex.NewDateTime(now) + pMetaInfo.ExpireTime = nex.NewDateTime(now) + pMetaInfo.Tags = []string{"49"} // idk? + pMetaInfo.Ratings = []*nexproto.DataStoreRatingInfoWithSlot{} + + return pMetaInfo +} diff --git a/get_object_infos.go b/get_object_infos.go new file mode 100644 index 0000000..44535bf --- /dev/null +++ b/get_object_infos.go @@ -0,0 +1,47 @@ +package main + +import ( + nex "github.com/PretendoNetwork/nex-go" + nexproto "github.com/PretendoNetwork/nex-protocols-go" +) + +func getObjectInfos(err error, client *nex.Client, callID uint32, dataIDs []uint64) { + // TODO: CDN + + pInfos := make([]*nexproto.DataStoreFileServerObjectInfo, 0) + + info := nexproto.NewDataStoreFileServerObjectInfo() + info.DataID = 1 + info.GetInfo = nexproto.NewDataStoreReqGetInfo() + info.GetInfo.URL = "http://pds-AMAJ-d1.b-cdn.net/course/1.bin" + info.GetInfo.RequestHeaders = []*nexproto.DataStoreKeyValue{} + info.GetInfo.Size = 42516 + info.GetInfo.RootCA = []byte{} + info.GetInfo.DataID = 1 + + 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) +} diff --git a/init.go b/init.go new file mode 100644 index 0000000..75dca28 --- /dev/null +++ b/init.go @@ -0,0 +1,26 @@ +package main + +import "io/ioutil" + +/* +type Config struct { + Mongo struct { + } + Cassandra struct{} +} +*/ + +var hmacSecret []byte + +func init() { + var err error + + hmacSecret, err = ioutil.ReadFile("secret.key") + if err != nil { + panic(err) + } + + // Connect to and setup databases + connectMongo() + connectCassandra() +} diff --git a/main.go b/main.go index 5156dd3..3f34a66 100644 --- a/main.go +++ b/main.go @@ -58,6 +58,7 @@ func main() { dataStoreSmmServer.GetMetasMultipleParam(getMetasMultipleParam) dataStoreSmmServer.ChangeMeta(changeMeta) dataStoreSmmServer.RateObjects(rateObjects) + dataStoreSmmServer.GetObjectInfos(getObjectInfos) dataStoreSmmServer.RateCustomRanking(rateCustomRanking) dataStoreSmmServer.GetCustomRankingByDataId(getCustomRankingByDataId) dataStoreSmmServer.GetBufferQueue(getBufferQueue) diff --git a/prepare_attach_file.go b/prepare_attach_file.go index a99e07d..6d69734 100644 --- a/prepare_attach_file.go +++ b/prepare_attach_file.go @@ -1,18 +1,36 @@ package main import ( + "crypto/hmac" + "crypto/sha256" + "encoding/hex" + "strconv" + "time" + nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) func prepareAttachFile(err error, client *nex.Client, callID uint32, dataStoreAttachFileParam *nexproto.DataStoreAttachFileParam) { + key := "image/1.jpg" + bucket := "pds-amaj-d1" + 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 = "pds-amaj-d1" + fieldBucket.Value = bucket fieldKey := nexproto.NewDataStoreKeyValue() fieldKey.Key = "key" - fieldKey.Value = "image/1.jpg" + fieldKey.Value = key fieldACL := nexproto.NewDataStoreKeyValue() fieldACL.Key = "acl" @@ -22,6 +40,18 @@ func prepareAttachFile(err error, client *nex.Client, callID uint32, dataStoreAt fieldContentType.Key = "content-type" fieldContentType.Value = "image/jpeg" + 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() @@ -29,7 +59,7 @@ func prepareAttachFile(err error, client *nex.Client, callID uint32, dataStoreAt pReqPostInfo.DataID = 1 pReqPostInfo.URL = "http://datastore.pretendo.cc/upload" pReqPostInfo.RequestHeaders = []*nexproto.DataStoreKeyValue{} - pReqPostInfo.FormFields = []*nexproto.DataStoreKeyValue{fieldBucket, fieldKey, fieldACL, fieldContentType} + pReqPostInfo.FormFields = []*nexproto.DataStoreKeyValue{fieldBucket, fieldKey, fieldACL, fieldContentType, fieldPID, fieldDate, fieldSignature} pReqPostInfo.RootCACert = []byte{} rmcResponseStream.WriteStructure(pReqPostInfo) diff --git a/prepare_get_object.go b/prepare_get_object.go index 1f4e544..0b1c46b 100644 --- a/prepare_get_object.go +++ b/prepare_get_object.go @@ -7,14 +7,24 @@ import ( func prepareGetObject(err error, client *nex.Client, callID uint32, dataStorePrepareGetParam *nexproto.DataStorePrepareGetParam) { // TODO: CDN - rmcResponseStream := nex.NewStreamOut(nexServer) pReqGetInfo := nexproto.NewDataStoreReqGetInfo() - pReqGetInfo.URL = "http://pds-AMAJ-d1.b-cdn.net/special/900000.bin" - pReqGetInfo.RequestHeaders = []*nexproto.DataStoreKeyValue{} - pReqGetInfo.Size = 450068 - pReqGetInfo.RootCA = []byte{} - pReqGetInfo.DataID = 900000 + + if dataStorePrepareGetParam.DataID == 900000 { + pReqGetInfo.URL = "http://pds-AMAJ-d1.b-cdn.net/special/900000.bin" + pReqGetInfo.RequestHeaders = []*nexproto.DataStoreKeyValue{} + pReqGetInfo.Size = 450068 + pReqGetInfo.RootCA = []byte{} + pReqGetInfo.DataID = 900000 + } else { + pReqGetInfo.URL = "http://pds-AMAJ-d1.b-cdn.net/course/1.bin" + pReqGetInfo.RequestHeaders = []*nexproto.DataStoreKeyValue{} + pReqGetInfo.Size = 42516 + pReqGetInfo.RootCA = []byte{} + pReqGetInfo.DataID = 1 + } + + rmcResponseStream := nex.NewStreamOut(nexServer) rmcResponseStream.WriteStructure(pReqGetInfo) diff --git a/prepare_post_object.go b/prepare_post_object.go index 1bb2df9..b5b3c98 100644 --- a/prepare_post_object.go +++ b/prepare_post_object.go @@ -1,28 +1,53 @@ package main import ( + "crypto/hmac" + "crypto/sha256" "encoding/hex" - "fmt" + "strconv" + "time" nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) func preparePostObject(err error, client *nex.Client, callID uint32, dataStorePreparePostParam *nexproto.DataStorePreparePostParam) { - fmt.Println(hex.EncodeToString(dataStorePreparePostParam.MetaBinary)) + key := "courses/1.bin" + bucket := "pds-amaj-d1" + 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 = "pds-amaj-d1" + fieldBucket.Value = bucket fieldKey := nexproto.NewDataStoreKeyValue() fieldKey.Key = "key" - fieldKey.Value = "course/1.bin" + 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() @@ -30,7 +55,7 @@ func preparePostObject(err error, client *nex.Client, callID uint32, dataStorePr pReqPostInfo.DataID = 1 pReqPostInfo.URL = "http://datastore.pretendo.cc/upload" pReqPostInfo.RequestHeaders = []*nexproto.DataStoreKeyValue{} - pReqPostInfo.FormFields = []*nexproto.DataStoreKeyValue{fieldBucket, fieldKey, fieldACL} + pReqPostInfo.FormFields = []*nexproto.DataStoreKeyValue{fieldBucket, fieldKey, fieldACL, fieldPID, fieldDate, fieldSignature} pReqPostInfo.RootCACert = []byte{} rmcResponseStream.WriteStructure(pReqPostInfo) diff --git a/recommended_course_search_object.go b/recommended_course_search_object.go index 9cc18b9..91986fd 100644 --- a/recommended_course_search_object.go +++ b/recommended_course_search_object.go @@ -1,17 +1,54 @@ package main import ( + "encoding/hex" + "time" + nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) func recommendedCourseSearchObject(err error, client *nex.Client, callID uint32, dataStoreSearchParam *nexproto.DataStoreSearchParam, extraData []string) { + // TODO complete this + + now := uint64(time.Now().Unix()) + + pRankingResults := make([]*nexproto.DataStoreCustomRankingResult, 0) + rankingResult := nexproto.NewDataStoreCustomRankingResult() + + rankingResult.Order = 0 + rankingResult.Score = 100 + rankingResult.MetaInfo = nexproto.NewDataStoreMetaInfo() + rankingResult.MetaInfo.DataID = 1 + rankingResult.MetaInfo.OwnerID = 1730592963 + rankingResult.MetaInfo.Size = 42516 + rankingResult.MetaInfo.Name = "test" + rankingResult.MetaInfo.DataType = 6 // idk? + rankingResult.MetaInfo.MetaBinary, _ = hex.DecodeString("0000000100000000000004cc000000c00000268c000079fc00000001cb3881aadd9adac3eef1189f7a57f871") + rankingResult.MetaInfo.Permission = nexproto.NewDataStorePermission() + rankingResult.MetaInfo.Permission.Permission = 0 // idk? + rankingResult.MetaInfo.Permission.RecipientIds = []uint32{} + rankingResult.MetaInfo.DelPermission = nexproto.NewDataStorePermission() + rankingResult.MetaInfo.DelPermission.Permission = 3 // idk? + rankingResult.MetaInfo.DelPermission.RecipientIds = []uint32{} + rankingResult.MetaInfo.CreatedTime = nex.NewDateTime(now) + rankingResult.MetaInfo.UpdatedTime = nex.NewDateTime(now) + rankingResult.MetaInfo.Period = 90 // idk? + rankingResult.MetaInfo.Status = 0 + rankingResult.MetaInfo.ReferredCnt = 0 + rankingResult.MetaInfo.ReferDataID = 0 + rankingResult.MetaInfo.Flag = 0 // idk? + rankingResult.MetaInfo.ReferredTime = nex.NewDateTime(now) + rankingResult.MetaInfo.ExpireTime = nex.NewDateTime(now) + rankingResult.MetaInfo.Tags = []string{""} // idk? + rankingResult.MetaInfo.Ratings = []*nexproto.DataStoreRatingInfoWithSlot{} + + pRankingResults = append(pRankingResults, rankingResult) + //0000000100000000000004cc000000c00000268c000079fc00000001cb3881aadd9adac3eef1189f7a57f871 + rmcResponseStream := nex.NewStreamOut(nexServer) - // TODO complete this - // rankingResults = make([]*nexproto.DataStoreCustomRankingResult, 0) - - rmcResponseStream.WriteUInt32LE(0x00000000) // pRankingResults List length 0 + rmcResponseStream.WriteListStructure(pRankingResults) rmcResponseBody := rmcResponseStream.Bytes()