# Apache Traffic Server - GitHub Copilot Instructions

## Repository Overview

Apache Traffic Server (ATS) is a high-performance HTTP/HTTPS caching proxy server written in C++20. It processes large-scale web traffic using an event-driven, multi-threaded architecture with a sophisticated plugin system.

**Key Facts:**
- ~500K lines of C++20 code (strict - no C++23)
- Event-driven architecture using Continuation callbacks
- Handles HTTP/1.1, HTTP/2, HTTP/3 (QUIC)
- Supports TLS termination and caching
- Extensible via C/C++ plugins

## Code Style Requirements

### C++ Style Guidelines

Some of these rules are enforced automatically by CI (via clang-format and clang-tidy); others are recommended conventions that will not themselves cause CI failures but should still be followed in code reviews.
**Formatting Rules:**
- **Line length:** 132 characters maximum
- **Indentation:** 2 spaces (never tabs)
- **Braces:** Linux kernel style (opening brace on same line)
```cpp
if (condition) {
  // code here
}
```
- **Pointer/reference alignment:** Right side
```cpp
Type *ptr;        // Correct
Type &ref;        // Correct
Type* ptr;        // Wrong
```
- **Empty line after declarations:**
```cpp
void function() {
  int x = 5;
  std::string name = "test";

  // Empty line before first code statement
  process_data(x, name);
}
```
- **Always use braces** for if/while/for (no naked conditions):
```cpp
if (x > 0) {    // Correct
  foo();
}

if (x > 0)      // Wrong - missing braces
  foo();
```
- **Keep variable declarations together:**
```cpp
// Correct - declarations grouped together
void function() {
  int count = 0;
  std::string name = "test";
  auto *buffer = new_buffer();

  // Empty line before first code statement
  process_data(count, name, buffer);
}

// Wrong - declarations scattered
void function() {
  int count = 0;
  process_count(count);
  std::string name = "test";  // Don't scatter declarations
}
```

**Naming Conventions:**
- Classes: `CamelCase` → `HttpSM`, `NetVConnection`, `CacheProcessor`
- Functions/variables: `snake_case` → `handle_request()`, `server_port`, `cache_key`
- Constants/macros: `UPPER_CASE` → `HTTP_STATUS_OK`, `MAX_BUFFER_SIZE`
- Member variables: `snake_case` with no prefix → `connection_count`, `buffer_size`

**C++20 Patterns (Use These):**
```cpp
// GOOD - Modern C++20
auto buffer = std::make_unique<MIOBuffer>(size);
for (const auto &entry : container) {
  if (auto *ptr = entry.get(); ptr != nullptr) {
    process(ptr);
  }
}

// AVOID - Legacy C-style
MIOBuffer *buffer = (MIOBuffer*)malloc(sizeof(MIOBuffer));
for (int i = 0; i < container.size(); i++) {
  process(container[i]);
}
```

**Memory Management:**
- Use RAII and smart pointers (`std::unique_ptr`, `std::shared_ptr`)
- Prefer smart pointers over raw `new`/`delete` when possible
- Use `ats_malloc()`/`ats_free()` for large allocations (not `malloc`)
- Use `IOBuffer` for network data (zero-copy design)
- Note: Some subsystems legitimately use explicit deletes / `delete this` (e.g., continuation-based code)

**What NOT to Use:**
- ❌ C++23 features (code must compile with C++20)
- ❌ `malloc`/`free` for large allocations (use `ats_malloc`), or prefer heaps or stack allocations
- ❌ Blocking operations in event threads
- ❌ Creating threads manually (use async event system)

### Comments and Documentation

**Minimal comments philosophy:**
- Only add comments where code isn't self-explanatory
- **Don't** describe what the code does (the code already shows that)
- **Do** explain *why* something is done if not obvious
- Avoid stating the obvious

```cpp
// BAD - stating the obvious
// Increment the counter
counter++;

// GOOD - explaining why
// Skip the first element since it's always the sentinel value
counter++;

// BAD - describing what
// Loop through all connections and close them
for (auto &conn : connections) {
  conn.close();
}

// GOOD - explaining why (if not obvious)
// Must close connections before destroying the acceptor to avoid use-after-free
for (auto &conn : connections) {
  conn.close();
}
```

**When to add comments:**
- Non-obvious algorithms or math
- Workarounds for bugs in dependencies
- Performance optimizations that reduce clarity
- Security-critical sections
- Complex state machine transitions

**When NOT to add comments:**
- Self-documenting code
- Obvious operations
- Function/variable names that explain themselves

### Python Style

- Python 3.11+ with type hints
- 4-space indentation (never tabs)
- Type annotations on all function signatures

### License Headers

**New source and test files** must start with Apache License 2.0 header (`.cc`, `.h`, `.py`, and other code files):
```cpp
/** @file
 *
 *  Brief description of file
 *
 *  @section license License
 *
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
```

## Architecture Patterns

### Event-Driven Model (CRITICAL)

ATS uses **Continuation-based** asynchronous programming:

```cpp
// Continuation is the core callback pattern
class MyContinuation : public Continuation {
  int handle_event(int event, void *data) {
    switch (event) {
    case EVENT_SUCCESS:
      // Handle success
      return EVENT_DONE;
    case EVENT_ERROR:
      // Handle error
      return EVENT_ERROR;
    }
    return EVENT_CONT;
  }
};
```

**Key Rules:**
- ⚠️ **NEVER block in event threads** - use async I/O or thread pools
- All async operations use `Continuation` callbacks
- Return `EVENT_DONE`, `EVENT_CONT`, or `EVENT_ERROR` from handlers
- Use `EThread::schedule()` for deferred work

### HTTP State Machine

The `HttpSM` class orchestrates HTTP request processing:

```cpp
// HttpSM is the central state machine
class HttpSM : public Continuation {
  // Processes requests through various states
  // Hook into appropriate stage via plugin hooks
  // Access transaction state via HttpTxn
};
```

**Common hooks:**
- `TS_HTTP_READ_REQUEST_HDR_HOOK` - After reading client request
- `TS_HTTP_SEND_REQUEST_HDR_HOOK` - Before sending to origin
- `TS_HTTP_READ_RESPONSE_HDR_HOOK` - After reading origin response
- `TS_HTTP_SEND_RESPONSE_HDR_HOOK` - Before sending to client

### Threading Model

- **Event threads:** Handle most async work (never block here)
- **DNS threads:** Dedicated DNS resolution pool
- **Disk I/O threads:** Cache disk operations
- **Network threads:** Actually event threads handling network I/O

**Rule:** Don't create threads. Use the event system or existing thread pools.

### Debug Logging Pattern

```cpp
// At file scope
static DbgCtl dbg_ctl{"http_sm"};

// In code (preferred)
Dbg(dbg_ctl, "Processing request for URL: %s", url);

// Alternative (less common)
DbgPrint(dbg_ctl, "Processing request for URL: %s", url);
```

**Note:** Use `Dbg()` for new code. `DbgPrint()` exists but is rarely used (~60 vs ~3400 uses).

## Project Structure (Key Paths)

```
trafficserver/
├── src/
│   ├── iocore/              # I/O subsystem
│   │   ├── eventsystem/    # Event engine (Continuation.h is core)
│   │   ├── cache/          # Cache implementation
│   │   ├── net/            # Network I/O, TLS, QUIC
│   │   └── dns/            # DNS resolution
│   ├── proxy/              # HTTP proxy logic
│   │   ├── http/           # HTTP/1.1 (HttpSM.cc is central)
│   │   ├── http2/          # HTTP/2
│   │   ├── http3/          # HTTP/3
│   │   ├── hdrs/           # Header parsing
│   │   └── logging/        # Logging
│   ├── tscore/             # Core utilities
│   ├── tsutil/             # Utilities (metrics, debugging)
│   └── api/                # Plugin API implementation
│
├── include/
│   ├── ts/                 # Public plugin API (ts.h)
│   ├── tscpp/              # C++ plugin API
│   └── iocore/             # Internal headers
│
├── plugins/                # Stable plugins
│   ├── header_rewrite/    # Header manipulation (see HRW.instructions.md)
│   └── experimental/      # Experimental plugins
│
└── tools/
    └── hrw4u/             # Header Rewrite DSL compiler

```

### Key Files to Understand

- `include/iocore/eventsystem/Continuation.h` - Core async pattern
- `src/proxy/http/HttpSM.cc` - HTTP state machine (most important)
- `src/iocore/cache/Cache.cc` - Cache implementation
- `include/ts/ts.h` - Plugin API (most stable interface)
- `include/tscore/ink_memory.h` - Memory allocation functions

## Common Patterns

### Finding Examples

**Before writing new code, look for similar existing code:**
- Plugin examples: `example/plugins/` for simple patterns
- Stable plugins: `plugins/` for production patterns
- Experimental plugins: `plugins/experimental/` for newer approaches

**Pattern discovery:**
- Search for similar functionality in existing code
- Check `include/ts/ts.h` for plugin API patterns
- Look at tests in `tests/gold_tests/` for usage examples

### Code Organization

**Typical file structure for a plugin:**
```
plugins/my_plugin/
├── my_plugin.cc        # Main plugin logic
├── handler.cc          # Request/response handlers
├── handler.h           # Handler interface
├── config.cc           # Configuration parsing
└── CMakeLists.txt      # Build configuration
```

**Typical class structure:**
- Inherit from `Continuation` for async operations
- Implement `handle_event()` for event processing
- Store state in class members, not globals
- Clean up resources in destructor (RAII)

### Async Operation Pattern

**General structure for async operations:**
1. Create continuation with callback
2. Initiate async operation (returns `Action*`)
3. Handle callback events in `handle_event()`
4. Return `EVENT_DONE` when complete

**Always async, never blocking:**
- Network I/O → Use VConnection
- Cache operations → Use CacheProcessor
- DNS lookups → Use DNSProcessor
- Delayed work → Use `schedule_in()` or `schedule_at()`

### Error Handling

**Recoverable errors:**
- Return error codes
- Log with appropriate severity
- Clean up resources (RAII helps)

**Unrecoverable errors:**
- Use `ink_release_assert()` for conditions that should never happen
- Log detailed context before asserting

### Testing Approach

**When adding new functionality:**
1. Check if unit tests exist in same directory (Catch2)
2. Add integration tests in `tests/gold_tests/` (autest)
3. Prefer `Test.ATSReplayTest()` with `replay.yaml` format (Proxy Verifier)
4. Test both success and error paths

## Configuration

### Adding New Configuration Records

1. Define in `src/records/RecordsConfig.cc`:
```cpp
{RECT_CONFIG, "proxy.config.my_feature.enabled", RECD_INT, "0", RECU_RESTART_TS, RR_NULL, RECC_INT, nullptr, RECA_NULL}
```

2. Read in code:
```cpp
int enabled = 0;
REC_ReadConfigInteger(enabled, "proxy.config.my_feature.enabled");
```

## What to Avoid

### Common Mistakes

❌ **Blocking in event threads:**
```cpp
// WRONG - blocks event thread
sleep(5);
blocking_network_call();
```

✅ **Use async operations:**
```cpp
// CORRECT - schedules continuation
eventProcessor.schedule_in(this, HRTIME_SECONDS(5));
```

❌ **Manual memory management:**
```cpp
// WRONG
auto *obj = new MyObject();
// ... might leak if exception thrown
delete obj;
```

✅ **Use RAII:**
```cpp
// CORRECT
auto obj = std::make_unique<MyObject>();
// Automatically cleaned up
```

❌ **Creating threads:**
```cpp
// WRONG
std::thread t([](){ do_work(); });
```

✅ **Use event system:**
```cpp
// CORRECT
eventProcessor.schedule_imm(continuation, ET_CALL);
```

## Additional Resources

- Plugin API: `include/ts/ts.h`
- Event system: `include/iocore/eventsystem/`
- HTTP state machine: `src/proxy/http/HttpSM.cc`
- Documentation: `doc/developer-guide/`
