handleConnection function executes the actual outgoing network call and captures/forwards the request and response messages.
(ctx context.Context, srcConn net.Conn)
| 1440 | |
| 1441 | // handleConnection function executes the actual outgoing network call and captures/forwards the request and response messages. |
| 1442 | func (p *Proxy) handleConnection(ctx context.Context, srcConn net.Conn) error { |
| 1443 | // activeConns.Add/Done are paired at the goroutine-spawn site |
| 1444 | // in the accept loop (see caller) to avoid the "Add concurrent |
| 1445 | // with Wait" race sync.WaitGroup documents as a misuse. |
| 1446 | //checking how much time proxy takes to execute the flow. |
| 1447 | start := time.Now() |
| 1448 | |
| 1449 | // making a new client connection id for each client connection |
| 1450 | clientConnID := util.GetNextID() |
| 1451 | defer func(start time.Time) { |
| 1452 | duration := time.Since(start) |
| 1453 | p.logger.Debug("time taken by proxy to execute the flow", zap.Any("Client ConnectionID", clientConnID), zap.Int64("Duration(ms)", duration.Milliseconds())) |
| 1454 | }(start) |
| 1455 | |
| 1456 | // dstConn stores conn with actual destination for the outgoing network call |
| 1457 | var dstConn net.Conn |
| 1458 | |
| 1459 | //Dialing for tls conn |
| 1460 | destConnID := util.GetNextID() |
| 1461 | |
| 1462 | remoteAddr := srcConn.RemoteAddr().(*net.TCPAddr) |
| 1463 | sourcePort := remoteAddr.Port |
| 1464 | |
| 1465 | // Claim this source port for the current connection (O7). The owner token |
| 1466 | // is this connection's unique destConnID; ClaimSrcPort overwrites any stale |
| 1467 | // owner left by a previous connection that reused this (recycled) port. |
| 1468 | pTls.ClaimSrcPort(sourcePort, destConnID) |
| 1469 | |
| 1470 | // Delete-on-close (O7): drop this source port's TLS dest mapping when the |
| 1471 | // connection finishes — but ONLY if this connection still owns the port. |
| 1472 | // The source port is released at the OS level when srcConn is closed (the |
| 1473 | // defer below), which runs BEFORE this one (LIFO), so a recycled port whose |
| 1474 | // NEW connection has already re-Stored its mapping must not be clobbered by |
| 1475 | // this older connection's cleanup. ReleaseSrcPortIfOwner's CompareAndDelete |
| 1476 | // on the owner token enforces that. It still bounds SrcPortToDstURL and, |
| 1477 | // critically for the multi-app agent, stops a recycled source port from |
| 1478 | // reading a previous (possibly different-app) connection's stale |
| 1479 | // destination when its ClientHello carries no SNI. Harmless for |
| 1480 | // non-CONNECT/non-TLS connections (the keys are simply absent). |
| 1481 | defer pTls.ReleaseSrcPortIfOwner(sourcePort, destConnID) |
| 1482 | |
| 1483 | probeProxy(p.logger, "accept", clientConnID, zap.Int("srcPort", sourcePort)) |
| 1484 | |
| 1485 | p.logger.Debug("Inside handleConnection of proxyServer", zap.Int("source port", sourcePort), zap.Int64("Time", time.Now().Unix())) |
| 1486 | destInfo, err := p.DestInfo.Get(ctx, uint16(sourcePort)) |
| 1487 | if err != nil { |
| 1488 | // Gracefully handle untracked connections (eBPF lookup failed) |
| 1489 | // This can happen when: |
| 1490 | // 1. A new connection was opened after test completion (e.g., driver health check) |
| 1491 | // 2. The eBPF hook didn't fire for this connection (race condition, bypass rule) |
| 1492 | // 3. The entry was already deleted before this lookup |
| 1493 | // |
| 1494 | // Instead of failing with an error (which causes the app to see a broken connection), |
| 1495 | // we close the connection gracefully. The client will see "connection refused" or EOF, |
| 1496 | // which is cleaner than a partial/broken connection that causes "already closed" errors. |
| 1497 | p.logger.Debug("Untracked connection (eBPF lookup failed), closing gracefully", |
| 1498 | zap.Int("Source port", sourcePort), zap.Error(err)) |
| 1499 | if srcConn != nil { |
no test coverage detected