# What Is tcp.go in the Croc Relay Server? A Deep Dive into the TCP Implementation

> Explore tcp.go in the croc relay server. Understand its role in TCP implementation, connection handling, PAKE authentication, and bidirectional data transfer between peers.

- Repository: [Zack/croc](https://github.com/schollz/croc)
- Tags: deep-dive
- Published: 2026-07-26

---

**[`tcp.go`](https://github.com/schollz/croc/blob/main/tcp.go) implements the entire TCP-based relay server for croc, handling connection acceptance, PAKE authentication, room pairing, and bidirectional data piping between peers.**

In the `schollz/croc` secure file transfer tool, [`tcp.go`](https://github.com/schollz/croc/blob/main/tcp.go) serves as the central nervous system of the relay server component. This single file contains the complete implementation of the TCP listener, cryptographic handshake logic, and room management system that enables secure peer-to-peer transfers without requiring port forwarding. Understanding the role of [`tcp.go`](https://github.com/schollz/croc/blob/main/tcp.go) in the croc relay server reveals how the tool establishes encrypted bridges between machines behind NAT firewalls.

## Core Responsibilities of tcp.go in the Croc Relay Server

The [`src/tcp/tcp.go`](https://github.com/schollz/croc/blob/main/src/tcp/tcp.go) file defines a `server` struct that encapsulates all relay functionality, including configuration (host, port, password, banner), room state management, and a stop handler for graceful shutdown.

### Listening for Inbound TCP Connections

The `run()` method creates the network backbone of the relay. According to the source at `src/tcp/tcp.go#L19-L27`, this function initializes a `net.ListenConfig`, binds to the configured address, and enters an acceptance loop that hands off new connections to handler goroutines. This design allows the relay to manage thousands of concurrent connection attempts.

### Secure Handshake Using PAKE

Every incoming connection undergoes password-authenticated key exchange (PAKE) within `clientCommunication()`. As implemented in `src/tcp/tcp.go#L78-L87`, this function derives a strong encryption key from the shared password before any file data traverses the network. This ensures that even if the relay server is compromised, it cannot decrypt the transferred content.

### Room Creation and Peer Pairing

The server implements a virtual "room" abstraction to pair participants. When the first client connects, [`tcp.go`](https://github.com/schollz/croc/blob/main/tcp.go) creates a room identified by a random string. As shown in `src/tcp/tcp.go#L64-L71` and `src/tcp/tcp.go#L84-L92`, the second client joining the same room triggers the server to staple the two connections together, establishing the peer-to-peer bridge.

### Bidirectional Data Piping

Once paired, the `pipe()` function (lines 87-95) spawns two goroutines that continuously copy bytes between sockets. This full-duplex channel remains active for the file transfer duration, with each goroutine handling one direction of traffic to maximize throughput.

### Lifecycle Management and Health Checks

A background goroutine named `deleteOldRooms` (defined at `src/tcp/tcp.go#L30-L38`) enforces TTL policies to reclaim resources from abandoned transfers. Additionally, the `pingRoom` constant and `PingServer` function (lines 48-51 and 14-22) provide external monitoring tools a lightweight way to verify server health without interfering with active transfers.

## Client-Side Connection Helpers

Beyond server logic, [`tcp.go`](https://github.com/schollz/croc/blob/main/tcp.go) exposes utilities that croc clients use to connect to relays.

### Connecting to the Relay

The `ConnectToTCPServer` function (lines 37-46) abstracts the client-side PAKE exchange, banner retrieval, and room joining. Clients call this function to establish an encrypted channel to the other peer through the relay.

### Health Monitoring

`PingServer` allows clients or external monitors to check relay availability. This function connects to the special `pingRoom` endpoint, validates the server banner, and returns the remote IP address, as documented in `src/tcp/tcp.go#L48-L51`.

## Code Example: Starting the Croc Relay Server

To launch a relay instance programmatically, invoke the `Run()` function. This chains through `RunWithOptionsAsync()` → `newDefaultServer()` → `server.start()` → `server.run()`:

```go
// Host, port, and password are supplied via CLI flags
err := tcp.Run(debugLevel, host, port, password, banner)
if err != nil {
    log.Fatal(err)
}

```

This call initializes the TCP listener at `src/tcp/tcp.go#L19-L27` and begins the acceptance loop that waits for peer connections.

## Code Example: Connecting a Client to the Relay

Clients use `ConnectToTCPServer` to perform the PAKE handshake and join a room:

```go
c, banner, ip, err := tcp.ConnectToTCPServer(
    "relay.example.com:4000",
    "myPassword",
    "randomRoomID",
)
if err != nil {
    log.Fatal(err)
}
defer c.Close()
// c now carries an encrypted channel to the other peer

```

This call executes the PAKE protocol defined at lines 78-87, transmits the password, receives the server banner and remote address, and finally joins the specified room to await the paired connection.

## How tcp.go Integrates with the Croc Architecture

The relay implementation in [`src/tcp/tcp.go`](https://github.com/schollz/croc/blob/main/src/tcp/tcp.go) does not operate in isolation. It relies on:

- **[`src/comm/comm.go`](https://github.com/schollz/croc/blob/main/src/comm/comm.go)**: Provides the `Send` and `Receive` wrappers around `net.Conn` used during the PAKE handshake and room negotiation.
- **[`src/crypt/crypt.go`](https://github.com/schollz/croc/blob/main/src/crypt/crypt.go)**: Supplies symmetric encryption functions (`Encrypt`, `Decrypt`) that protect the data streams established by `pipe()`.
- **[`src/models/models.go`](https://github.com/schollz/croc/blob/main/src/models/models.go)**: Defines constants such as `TCP_BUFFER_SIZE` referenced in channel creation routines.
- **[`src/croc/croc.go`](https://github.com/schollz/croc/blob/main/src/croc/croc.go)**: Serves as the CLI entry point that parses user flags and ultimately invokes `tcp.Run` to start the relay service.

Together, these files form a complete relay-server stack where [`tcp.go`](https://github.com/schollz/croc/blob/main/tcp.go) manages the transport layer while delegating cryptography and message framing to specialized modules.

## Summary

- **[`tcp.go`](https://github.com/schollz/croc/blob/main/tcp.go)** implements the complete TCP relay server in `schollz/croc`, from socket creation to data forwarding.
- The file handles **PAKE-based authentication** to derive encryption keys without transmitting passwords over the wire.
- It manages **room-based peer pairing**, connecting two clients who share the same room ID through a temporary virtual channel.
- **Bidirectional piping** via the `pipe()` function creates full-duplex data streams between paired sockets.
- **Automatic cleanup** via `deleteOldRooms` prevents resource leaks from abandoned transfers.
- **Client helpers** like `ConnectToTCPServer` and `PingServer` provide convenient APIs for establishing connections and monitoring relay health.

## Frequently Asked Questions

### What is the exact role of tcp.go in the croc relay server implementation?

[`tcp.go`](https://github.com/schollz/croc/blob/main/tcp.go) serves as the core engine that accepts inbound TCP connections, authenticates them using PAKE, pairs two participants in a temporary room, and pipes encrypted data between them. It implements both the server-side listener and client-side connection utilities required for the relay to function.

### How does tcp.go secure connections between peers who have never met?

The file implements password-authenticated key exchange (PAKE) in the `clientCommunication()` function (lines 78-87). Both sides derive the same strong encryption key from a shared password without actually transmitting that password over the network, preventing man-in-the-middle attacks even against a malicious relay operator.

### What happens if a client disconnects before pairing with another peer?

The `deleteOldRooms` goroutine (lines 30-38) periodically scans active rooms and removes those that exceed their time-to-live (TTL). This cleanup process reclaims memory and socket resources when a transfer abandons or fails before the second peer connects.

### Can tcp.go handle multiple simultaneous file transfers?

Yes. The `run()` function spawns a new goroutine for every incoming connection (lines 19-27), and room state is maintained in a thread-safe map structure. This architecture allows the relay to manage hundreds of concurrent rooms, each isolated from the others, while the `pipe()` function handles bidirectional copying for each paired connection independently.