- ASP.NET Core 8 REST API server - 12 API endpoints matching EA Synergy protocol - SQLite database with Entity Framework Core - Web admin panel with Bootstrap 5 - User, Catalog, Session, Purchase management - Comprehensive documentation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
628 lines
15 KiB
Markdown
628 lines
15 KiB
Markdown
# Real Racing 3 Community Server - Implementation Guide
|
|
|
|
## 🎮 Overview
|
|
|
|
This is a fully functional, cross-platform .NET 8 community server for Real Racing 3 that emulates EA's Synergy backend infrastructure. This enables:
|
|
|
|
- **Private servers** for offline/LAN play
|
|
- **Game preservation** when official servers shut down
|
|
- **Custom content** and modifications
|
|
- **Educational purposes** for understanding client-server architecture
|
|
|
|
---
|
|
|
|
## ✅ What's Implemented
|
|
|
|
### Core Infrastructure
|
|
- ✅ **ASP.NET Core 8.0** Web API (cross-platform: Windows, Linux, macOS)
|
|
- ✅ **SQLite Database** for data persistence
|
|
- ✅ **Entity Framework Core** for ORM
|
|
- ✅ **Swagger UI** for API documentation and testing
|
|
|
|
### API Endpoints (100% Core Functionality)
|
|
|
|
#### 1. Director/Service Discovery
|
|
- `GET /director/api/android/getDirectionByPackage` - Service URLs routing
|
|
|
|
#### 2. User Management
|
|
- `GET /user/api/android/getDeviceID` - Device registration
|
|
- `GET /user/api/android/validateDeviceID` - Device validation
|
|
- `GET /user/api/android/getAnonUid` - Anonymous user ID generation
|
|
|
|
#### 3. Product Catalog
|
|
- `GET /product/api/core/getAvailableItems` - Item catalog
|
|
- `GET /product/api/core/getMTXGameCategories` - Categories
|
|
- `POST /product/api/core/getDownloadItemUrl` - Download URLs
|
|
|
|
#### 4. DRM & Purchases
|
|
- `GET /drm/api/core/getNonce` - DRM nonce generation
|
|
- `GET /drm/api/core/getPurchasedItems` - Purchase history
|
|
- `POST /drm/api/android/verifyAndRecordPurchase` - Purchase verification
|
|
|
|
#### 5. Analytics/Tracking
|
|
- `POST /tracking/api/core/logEvent` - Event logging
|
|
- `POST /tracking/api/core/logEvents` - Batch event logging
|
|
|
|
### Middleware
|
|
- ✅ **Synergy Headers Middleware** - Extracts and logs EA custom headers
|
|
- ✅ **Session Validation Middleware** - Validates sessions (lenient for community use)
|
|
|
|
### Services
|
|
- ✅ **Session Management** - UUID-based session tracking
|
|
- ✅ **User Service** - Device/user management
|
|
- ✅ **Catalog Service** - Product catalog management
|
|
- ✅ **DRM Service** - Nonce generation and purchase tracking
|
|
|
|
---
|
|
|
|
## 🚀 Quick Start
|
|
|
|
### Prerequisites
|
|
- **[.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)** or later
|
|
- **Port 443 or 5001** available for HTTPS
|
|
- **Administrative privileges** (for hosts file modification)
|
|
|
|
### Step 1: Build and Run
|
|
|
|
```bash
|
|
# Navigate to server directory
|
|
cd E:\rr3\RR3CommunityServer\RR3CommunityServer
|
|
|
|
# Restore dependencies
|
|
dotnet restore
|
|
|
|
# Build the project
|
|
dotnet build
|
|
|
|
# Run the server
|
|
dotnet run
|
|
```
|
|
|
|
You should see:
|
|
```
|
|
╔══════════════════════════════════════════════════════════╗
|
|
║ Real Racing 3 Community Server - RUNNING ║
|
|
╠══════════════════════════════════════════════════════════╣
|
|
║ Server is ready to accept connections ║
|
|
║ Ensure DNS/hosts file points EA servers to this IP ║
|
|
╚══════════════════════════════════════════════════════════╝
|
|
|
|
Listening on: https://localhost:5001
|
|
Director endpoint: /director/api/android/getDirectionByPackage
|
|
```
|
|
|
|
### Step 2: Redirect Game Traffic
|
|
|
|
The game needs to connect to **your server** instead of EA's servers.
|
|
|
|
#### Option A: Hosts File (Localhost Only)
|
|
|
|
**Windows:**
|
|
1. Open `C:\Windows\System32\drivers\etc\hosts` as Administrator
|
|
2. Add these lines:
|
|
```
|
|
127.0.0.1 syn-dir.sn.eamobile.com
|
|
127.0.0.1 director-stage.sn.eamobile.com
|
|
```
|
|
|
|
**Linux/macOS:**
|
|
1. Edit `/etc/hosts` with sudo:
|
|
```bash
|
|
sudo nano /etc/hosts
|
|
```
|
|
2. Add:
|
|
```
|
|
127.0.0.1 syn-dir.sn.eamobile.com
|
|
127.0.0.1 director-stage.sn.eamobile.com
|
|
```
|
|
|
|
#### Option B: Network-Wide Redirect (For LAN/Mobile Devices)
|
|
|
|
1. **DNS Override** - Configure your router/DNS server to point EA domains to your server IP
|
|
2. **Hosts file on mobile** (Android requires root):
|
|
```
|
|
<YOUR_SERVER_IP> syn-dir.sn.eamobile.com
|
|
```
|
|
|
|
#### Option C: SSL Interception (Advanced)
|
|
|
|
Use **mitmproxy** or similar tools for full HTTPS interception:
|
|
```bash
|
|
# Install mitmproxy
|
|
pip install mitmproxy
|
|
|
|
# Run proxy
|
|
mitmproxy --mode reverse:https://localhost:5001@*
|
|
|
|
# Install mitmproxy CA certificate on device
|
|
# Follow: https://docs.mitmproxy.org/stable/concepts-certificates/
|
|
```
|
|
|
|
### Step 3: Test the Server
|
|
|
|
#### Using Browser
|
|
Navigate to: `https://localhost:5001/director/api/android/getDirectionByPackage?packageName=com.ea.games.r3_row`
|
|
|
|
You should see JSON response:
|
|
```json
|
|
{
|
|
"resultCode": 0,
|
|
"message": "Success",
|
|
"data": {
|
|
"serverUrls": {
|
|
"synergy.product": "https://localhost:5001",
|
|
"synergy.drm": "https://localhost:5001",
|
|
...
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Using curl
|
|
```bash
|
|
curl -k https://localhost:5001/user/api/android/getDeviceID?deviceId=test123&hardwareId=hw456
|
|
```
|
|
|
|
#### Using Swagger UI
|
|
Navigate to: `https://localhost:5001/swagger`
|
|
|
|
---
|
|
|
|
## 📁 Project Structure
|
|
|
|
```
|
|
RR3CommunityServer/
|
|
├── Controllers/ # API endpoints
|
|
│ ├── DirectorController.cs # Service discovery
|
|
│ ├── UserController.cs # User management
|
|
│ ├── ProductController.cs # Catalog
|
|
│ ├── DrmController.cs # Purchases
|
|
│ └── TrackingController.cs # Analytics
|
|
│
|
|
├── Models/
|
|
│ └── ApiModels.cs # DTOs for requests/responses
|
|
│
|
|
├── Services/
|
|
│ ├── IServices.cs # Service interfaces
|
|
│ └── ServiceImplementations.cs # Business logic
|
|
│
|
|
├── Data/
|
|
│ └── RR3DbContext.cs # Entity Framework context
|
|
│
|
|
├── Middleware/
|
|
│ └── SynergyMiddleware.cs # Request processing
|
|
│
|
|
├── Program.cs # App entry point
|
|
├── appsettings.json # Configuration
|
|
└── RR3CommunityServer.csproj # Project file
|
|
```
|
|
|
|
---
|
|
|
|
## 🗄️ Database
|
|
|
|
The server uses **SQLite** with Entity Framework Core.
|
|
|
|
### Location
|
|
`rr3community.db` (created automatically in project directory)
|
|
|
|
### Tables
|
|
- **Devices** - Registered devices
|
|
- **Users** - Synergy user accounts
|
|
- **Sessions** - Active sessions
|
|
- **Purchases** - Purchase records
|
|
- **CatalogItems** - Available items
|
|
|
|
### Viewing Database
|
|
```bash
|
|
# Install SQLite viewer
|
|
dotnet tool install -g dotnet-sqlite
|
|
|
|
# View database
|
|
dotnet sqlite rr3community.db
|
|
```
|
|
|
|
Or use GUI tools:
|
|
- [DB Browser for SQLite](https://sqlitebrowser.org/)
|
|
- [DBeaver](https://dbeaver.io/)
|
|
|
|
---
|
|
|
|
## ⚙️ Configuration
|
|
|
|
Edit `appsettings.json` to customize behavior:
|
|
|
|
```json
|
|
{
|
|
"Logging": {
|
|
"LogLevel": {
|
|
"Default": "Information",
|
|
"Microsoft.AspNetCore": "Warning"
|
|
}
|
|
},
|
|
"AllowedHosts": "*",
|
|
"Server": {
|
|
"Port": 5001,
|
|
"EnableSwagger": true
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔌 API Protocol
|
|
|
|
### Request Headers (Required)
|
|
```
|
|
Content-Type: application/json
|
|
SDK-VERSION: 1.63.0.2 # Nimble SDK version
|
|
SDK-TYPE: Nimble # EA framework identifier
|
|
EAM-SESSION: <session-uuid> # Session ID (auto-generated)
|
|
EAM-USER-ID: <synergy-id> # User identifier (optional)
|
|
EA-SELL-ID: <store-id> # Store ID (e.g., GOOGLE_PLAY)
|
|
```
|
|
|
|
### Response Format
|
|
All responses follow Synergy protocol:
|
|
```json
|
|
{
|
|
"resultCode": 0, // 0 = success, negative = error
|
|
"message": "Success", // Human-readable message
|
|
"data": { ... } // Response payload
|
|
}
|
|
```
|
|
|
|
### Error Codes
|
|
- `0` - Success
|
|
- `-1` - Generic error
|
|
- `-100` - Invalid device
|
|
- `-200` - Session expired
|
|
- `-300` - Purchase verification failed
|
|
|
|
---
|
|
|
|
## 🛠️ Development
|
|
|
|
### Running in Development Mode
|
|
```bash
|
|
# Watch mode (auto-reload on file changes)
|
|
dotnet watch run
|
|
```
|
|
|
|
### Adding New Endpoints
|
|
|
|
1. **Create Controller**:
|
|
```csharp
|
|
[ApiController]
|
|
[Route("myservice/api/core")]
|
|
public class MyController : ControllerBase
|
|
{
|
|
[HttpGet("myEndpoint")]
|
|
public ActionResult<SynergyResponse<object>> MyEndpoint()
|
|
{
|
|
return Ok(new SynergyResponse<object>
|
|
{
|
|
resultCode = 0,
|
|
data = new { hello = "world" }
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
2. **Add Service (if needed)**:
|
|
- Create interface in `IServices.cs`
|
|
- Implement in `ServiceImplementations.cs`
|
|
- Register in `Program.cs`: `builder.Services.AddScoped<IMyService, MyService>()`
|
|
|
|
3. **Update Database Model (if needed)**:
|
|
- Add entity to `RR3DbContext.cs`
|
|
- Run migration:
|
|
```bash
|
|
dotnet ef migrations add MyFeature
|
|
dotnet ef database update
|
|
```
|
|
|
|
### Debugging
|
|
```bash
|
|
# Enable detailed logging
|
|
export ASPNETCORE_ENVIRONMENT=Development
|
|
dotnet run
|
|
|
|
# View logs
|
|
tail -f <project-dir>/logs/app.log
|
|
```
|
|
|
|
---
|
|
|
|
## 🌐 Cross-Platform Deployment
|
|
|
|
### Windows (Standalone)
|
|
```bash
|
|
# Publish self-contained
|
|
dotnet publish -c Release -r win-x64 --self-contained
|
|
|
|
# Run
|
|
.\bin\Release\net8.0\win-x64\publish\RR3CommunityServer.exe
|
|
```
|
|
|
|
### Linux (Server)
|
|
```bash
|
|
# Publish for Linux
|
|
dotnet publish -c Release -r linux-x64 --self-contained
|
|
|
|
# Copy to server
|
|
scp -r bin/Release/net8.0/linux-x64/publish/ user@server:/opt/rr3server/
|
|
|
|
# Run as service
|
|
sudo systemctl enable rr3server
|
|
sudo systemctl start rr3server
|
|
```
|
|
|
|
**Service file** (`/etc/systemd/system/rr3server.service`):
|
|
```ini
|
|
[Unit]
|
|
Description=Real Racing 3 Community Server
|
|
|
|
[Service]
|
|
WorkingDirectory=/opt/rr3server
|
|
ExecStart=/opt/rr3server/RR3CommunityServer
|
|
Restart=always
|
|
User=www-data
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
### macOS
|
|
```bash
|
|
# Publish
|
|
dotnet publish -c Release -r osx-x64 --self-contained
|
|
|
|
# Run
|
|
./bin/Release/net8.0/osx-x64/publish/RR3CommunityServer
|
|
```
|
|
|
|
### Docker
|
|
```dockerfile
|
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
|
WORKDIR /src
|
|
COPY RR3CommunityServer.csproj .
|
|
RUN dotnet restore
|
|
COPY . .
|
|
RUN dotnet publish -c Release -o /app
|
|
|
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0
|
|
WORKDIR /app
|
|
COPY --from=build /app .
|
|
EXPOSE 5001
|
|
ENTRYPOINT ["dotnet", "RR3CommunityServer.dll"]
|
|
```
|
|
|
|
```bash
|
|
# Build and run
|
|
docker build -t rr3-server .
|
|
docker run -p 5001:5001 rr3-server
|
|
```
|
|
|
|
---
|
|
|
|
## 🔒 SSL/HTTPS Setup
|
|
|
|
### Development (Self-Signed Certificate)
|
|
```bash
|
|
# Trust dev certificate
|
|
dotnet dev-certs https --trust
|
|
```
|
|
|
|
### Production (Let's Encrypt)
|
|
```bash
|
|
# Install certbot
|
|
sudo apt install certbot
|
|
|
|
# Get certificate
|
|
sudo certbot certonly --standalone -d yourdomain.com
|
|
|
|
# Configure in appsettings.json
|
|
{
|
|
"Kestrel": {
|
|
"Endpoints": {
|
|
"Https": {
|
|
"Url": "https://*:443",
|
|
"Certificate": {
|
|
"Path": "/etc/letsencrypt/live/yourdomain.com/fullchain.pem",
|
|
"KeyPath": "/etc/letsencrypt/live/yourdomain.com/privkey.pem"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Monitoring & Logging
|
|
|
|
### View Logs
|
|
```bash
|
|
# Real-time logs
|
|
dotnet run | tee server.log
|
|
|
|
# Filter errors only
|
|
dotnet run 2>&1 | grep "ERROR"
|
|
```
|
|
|
|
### Health Check Endpoint
|
|
Add to `Program.cs`:
|
|
```csharp
|
|
app.MapGet("/health", () => Results.Ok(new { status = "healthy", timestamp = DateTime.UtcNow }));
|
|
```
|
|
|
|
---
|
|
|
|
## 🧪 Testing
|
|
|
|
### Manual Testing with curl
|
|
```bash
|
|
# Test director endpoint
|
|
curl -k https://localhost:5001/director/api/android/getDirectionByPackage?packageName=test
|
|
|
|
# Test device ID
|
|
curl -k -H "SDK-VERSION: 1.63.0.2" \
|
|
-H "SDK-TYPE: Nimble" \
|
|
https://localhost:5001/user/api/android/getDeviceID?deviceId=test123&hardwareId=hw456
|
|
|
|
# Test catalog
|
|
curl -k -H "EAM-SESSION: test-session" \
|
|
https://localhost:5001/product/api/core/getAvailableItems
|
|
```
|
|
|
|
### Automated Testing
|
|
Create `Tests/` directory with xUnit tests:
|
|
```csharp
|
|
public class DirectorControllerTests
|
|
{
|
|
[Fact]
|
|
public async Task GetDirection_ReturnsSuccess()
|
|
{
|
|
// Arrange
|
|
var controller = new DirectorController(logger, config);
|
|
|
|
// Act
|
|
var result = controller.GetDirection("com.ea.games.r3_row");
|
|
|
|
// Assert
|
|
Assert.Equal(0, result.Value.resultCode);
|
|
}
|
|
}
|
|
```
|
|
|
|
Run tests:
|
|
```bash
|
|
dotnet test
|
|
```
|
|
|
|
---
|
|
|
|
## 🎮 Using with Real Racing 3
|
|
|
|
### Step-by-Step Connection
|
|
|
|
1. **Start the server**:
|
|
```bash
|
|
dotnet run
|
|
```
|
|
|
|
2. **Modify hosts file** (see Step 2 above)
|
|
|
|
3. **Clear app data** (Android/iOS):
|
|
- Android: Settings > Apps > Real Racing 3 > Clear Data
|
|
- iOS: Delete and reinstall app
|
|
|
|
4. **Launch Real Racing 3** - it should now connect to your server!
|
|
|
|
5. **Verify connection** by watching server logs:
|
|
```
|
|
[INFO] Synergy Request: Path=/director/api/android/getDirectionByPackage
|
|
[INFO] GetDeviceID request: existing=null, hardware=abc123
|
|
```
|
|
|
|
---
|
|
|
|
## ⚠️ Security & Legal
|
|
|
|
### For Community Use Only
|
|
This server is intended for:
|
|
- ✅ Private/LAN gameplay
|
|
- ✅ Game preservation when official servers shut down
|
|
- ✅ Educational purposes
|
|
- ✅ Offline gameplay
|
|
|
|
**NOT for:**
|
|
- ❌ Piracy or bypassing purchases
|
|
- ❌ Cheating in official multiplayer
|
|
- ❌ Distributing EA's copyrighted content
|
|
- ❌ Commercial use
|
|
|
|
### Security Recommendations
|
|
- Use **strong SSL certificates** in production
|
|
- Implement **authentication** for public servers
|
|
- Enable **rate limiting** to prevent abuse
|
|
- **Disable Swagger UI** in production (`"EnableSwagger": false`)
|
|
|
|
---
|
|
|
|
## 🐛 Troubleshooting
|
|
|
|
### Issue: "Cannot connect to server"
|
|
**Solution:**
|
|
- Verify server is running: `curl -k https://localhost:5001/health`
|
|
- Check hosts file is correctly configured
|
|
- Ensure port 5001/443 is not blocked by firewall
|
|
- Check game logs for connection errors
|
|
|
|
### Issue: "SSL Certificate Error"
|
|
**Solution:**
|
|
- Trust development certificate: `dotnet dev-certs https --trust`
|
|
- Or use `mitmproxy` with custom CA certificate
|
|
|
|
### Issue: "Database error on startup"
|
|
**Solution:**
|
|
```bash
|
|
# Delete and recreate database
|
|
rm rr3community.db
|
|
dotnet run
|
|
```
|
|
|
|
### Issue: "Game doesn't recognize purchases"
|
|
**Solution:**
|
|
- For community servers, all purchases are automatically accepted
|
|
- Check DRM endpoint is responding correctly
|
|
- Verify purchase records in database
|
|
|
|
---
|
|
|
|
## 🔗 Resources
|
|
|
|
- **Protocol Documentation**: `E:\rr3\NETWORK_COMMUNICATION_ANALYSIS.md`
|
|
- **Decompiled APK**: `E:\rr3\decompiled\`
|
|
- **.NET Documentation**: https://docs.microsoft.com/dotnet/
|
|
- **Entity Framework Core**: https://docs.microsoft.com/ef/core/
|
|
- **ASP.NET Core**: https://docs.microsoft.com/aspnet/core/
|
|
|
|
---
|
|
|
|
## 👥 Contributing
|
|
|
|
Want to improve the server? Here's how:
|
|
|
|
1. **Fork the repository**
|
|
2. **Add features**:
|
|
- More robust purchase verification
|
|
- Multiplayer/leaderboard support
|
|
- Admin web UI
|
|
- Content modding tools
|
|
3. **Submit pull request**
|
|
|
|
---
|
|
|
|
## 📜 Changelog
|
|
|
|
### Version 1.0.0 (February 2026)
|
|
- ✅ Initial release
|
|
- ✅ All core Synergy API endpoints
|
|
- ✅ SQLite database persistence
|
|
- ✅ Cross-platform support (Windows/Linux/macOS)
|
|
- ✅ Swagger UI documentation
|
|
- ✅ Session management
|
|
- ✅ Device registration
|
|
- ✅ Catalog system
|
|
- ✅ DRM/Purchase tracking
|
|
|
|
---
|
|
|
|
## 🎉 Success!
|
|
|
|
You now have a fully functional Real Racing 3 community server! The game can connect, authenticate, retrieve catalogs, and track progress—all on your own infrastructure.
|
|
|
|
**Happy Racing! 🏁**
|