Files
rr3-server/IMPLEMENTATION_GUIDE.md
Daniel Elliott 0a327f3a8b Initial commit: RR3 Community Server with web admin panel
- 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>
2026-02-17 22:02:12 -08:00

15 KiB

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 or later
  • Port 443 or 5001 available for HTTPS
  • Administrative privileges (for hosts file modification)

Step 1: Build and Run

# 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:
    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:

# 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:

{
  "resultCode": 0,
  "message": "Success",
  "data": {
    "serverUrls": {
      "synergy.product": "https://localhost:5001",
      "synergy.drm": "https://localhost:5001",
      ...
    }
  }
}

Using curl

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

# Install SQLite viewer
dotnet tool install -g dotnet-sqlite

# View database
dotnet sqlite rr3community.db

Or use GUI tools:


⚙️ Configuration

Edit appsettings.json to customize behavior:

{
  "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:

{
  "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

# Watch mode (auto-reload on file changes)
dotnet watch run

Adding New Endpoints

  1. Create Controller:

    [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:
      dotnet ef migrations add MyFeature
      dotnet ef database update
      

Debugging

# Enable detailed logging
export ASPNETCORE_ENVIRONMENT=Development
dotnet run

# View logs
tail -f <project-dir>/logs/app.log

🌐 Cross-Platform Deployment

Windows (Standalone)

# Publish self-contained
dotnet publish -c Release -r win-x64 --self-contained

# Run
.\bin\Release\net8.0\win-x64\publish\RR3CommunityServer.exe

Linux (Server)

# 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):

[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

# Publish
dotnet publish -c Release -r osx-x64 --self-contained

# Run
./bin/Release/net8.0/osx-x64/publish/RR3CommunityServer

Docker

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"]
# Build and run
docker build -t rr3-server .
docker run -p 5001:5001 rr3-server

🔒 SSL/HTTPS Setup

Development (Self-Signed Certificate)

# Trust dev certificate
dotnet dev-certs https --trust

Production (Let's Encrypt)

# 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

# Real-time logs
dotnet run | tee server.log

# Filter errors only
dotnet run 2>&1 | grep "ERROR"

Health Check Endpoint

Add to Program.cs:

app.MapGet("/health", () => Results.Ok(new { status = "healthy", timestamp = DateTime.UtcNow }));

🧪 Testing

Manual Testing with curl

# 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:

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:

dotnet test

🎮 Using with Real Racing 3

Step-by-Step Connection

  1. Start the server:

    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
    

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:

# 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


👥 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! 🏁