diff --git a/ecs.go b/ecs.go index b69c792..d3555d4 100644 --- a/ecs.go +++ b/ecs.go @@ -18,10 +18,24 @@ package main import ( + "database/sql" "fmt" "github.com/antchfx/xmlquery" + "log" ) +var ownedTitles *sql.Stmt + +func ecsInitialize() { + var err error + ownedTitles, err = db.Prepare(`SELECT o.ticket_id, o.title_id, s.version, o.revocation_date + FROM owned_titles o JOIN shop_titles s + WHERE o.title_id = s.title_id AND o.account_id = ?`) + if err != nil { + log.Fatalf("ecs initialize: error preparing statement: %v\n", err) + } +} + func ecsHandler(e Envelope, doc *xmlquery.Node) (bool, string) { // All actions below are for ECS-related functions. switch e.Action() { @@ -48,8 +62,42 @@ func ecsHandler(e Envelope, doc *xmlquery.Node) (bool, string) { break case "ListETickets": - // that's all you've got for me? ;3 + fmt.Println("The request is valid! Responding...") + rows, err := ownedTitles.Query("todo, sorry") + if err != nil { + return e.ReturnError(2, "that's all you've got for me? ;3", err) + } + // Add all available titles for this account. + defer rows.Close() + for rows.Next() { + var ticketId string + var titleId string + var version int + var revocationDate int + err = rows.Scan(&ticketId, &titleId, &version, &revocationDate) + if err != nil { + return e.ReturnError(2, "that's all you've got for me? ;3", err) + } + + e.AddCustomType(Tickets{ + TicketId: ticketId, + TitleId: titleId, + Version: version, + RevokeDate: revocationDate, + + // We do not support migration. + MigrateCount: 0, + MigrateLimit: 0, + }) + } + + e.AddKVNode("ForceSyncTime", "0") + e.AddKVNode("ExtTicketTime", e.Timestamp()) + e.AddKVNode("SyncTime", e.Timestamp()) + break + + case "GetETickets": fmt.Println("The request is valid! Responding...") e.AddKVNode("ForceSyncTime", "0") e.AddKVNode("ExtTicketTime", e.Timestamp()) diff --git a/ias.go b/ias.go index 376eb3f..3358a61 100644 --- a/ias.go +++ b/ias.go @@ -20,6 +20,7 @@ package main import ( "crypto/md5" sha2562 "crypto/sha256" + "database/sql" "errors" "fmt" "github.com/RiiConnect24/wiino/golang" @@ -30,6 +31,16 @@ import ( "strconv" ) +var registerUser *sql.Stmt + +func iasInitialize() { + var err error + registerUser, err = db.Prepare(`INSERT INTO wiisoap.userbase (DeviceId, DeviceToken, AccountId, Region, Country, Language, SerialNo, DeviceCode) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`) + if err != nil { + log.Fatalf("ias initialize: error preparing statement: %v\n", err) + } +} + func iasHandler(e Envelope, doc *xmlquery.Node) (bool, string) { // All IAS-related functions should contain these keys. region, err := getKey(doc, "Region") @@ -138,12 +149,7 @@ func iasHandler(e Envelope, doc *xmlquery.Node) (bool, string) { doublyHashedDeviceToken := fmt.Sprintf("%x", sha2562.Sum256([]byte(md5DeviceToken))) // Insert all of our obtained values to the database.. - stmt, err := db.Prepare(`INSERT INTO wiisoap.userbase (DeviceId, DeviceToken, AccountId, Region, Country, Language, SerialNo, DeviceCode) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`) - if err != nil { - log.Printf("error preparing statement: %v\n", err) - return e.ReturnError(7, reason, errors.New("failed to prepare statement")) - } - _, err = stmt.Exec(e.DeviceId(), doublyHashedDeviceToken, accountId, region, country, language, serialNo, deviceCode) + _, err = registerUser.Exec(e.DeviceId(), doublyHashedDeviceToken, accountId, region, country, language, serialNo, deviceCode) if err != nil { // It's okay if this isn't a MySQL error, as perhaps other issues have come in. if driverErr, ok := err.(*mysql.MySQLError); ok { diff --git a/main.go b/main.go index fcb303e..f649423 100644 --- a/main.go +++ b/main.go @@ -26,6 +26,7 @@ import ( "log" "net/http" "strings" + "time" ) const ( @@ -64,6 +65,13 @@ func main() { defer db.Close() err = db.Ping() checkError(err) + db.SetConnMaxLifetime(time.Minute * 3) + db.SetMaxOpenConns(10) + db.SetMaxIdleConns(10) + + // Initialize handlers. + ecsInitialize() + iasInitialize() // Start the HTTP server. fmt.Printf("Starting HTTP connection (%s)...\nNot using the usual port for HTTP?\nBe sure to use a proxy, otherwise the Wii can't connect!\n", CON.Address) diff --git a/structure.go b/structure.go index e4a2918..e44d587 100644 --- a/structure.go +++ b/structure.go @@ -96,3 +96,14 @@ type Transactions struct { Date string `xml:"Date"` Type string `xml:"Type"` } + +// Tickets represents the format to inform a console of available titles for its consumption. +type Tickets struct { + XMLName xml.Name `xml:"Tickets"` + TicketId string `xml:"TicketId"` + TitleId string `xml:"TitleId"` + RevokeDate int `xml:"RevokeDate"` + Version int `xml:"Version"` + MigrateCount int `xml:"MigrateCount"` + MigrateLimit int `xml:"MigrateLimit"` +} \ No newline at end of file