124 lines
3.2 KiB
Go
124 lines
3.2 KiB
Go
/*
|
|
* ============================================================================
|
|
* Projekt.....: rs2322tcp
|
|
* Datei.......: internal/client/connection.go
|
|
* Copyright (C) 2026 Dieter Lang
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*
|
|
* Beschreibung:
|
|
* Aufbau einer Verbindung zwischen einem lokalen virtuellen seriellen Port
|
|
* und dem zugehörigen entfernten Gerät.
|
|
*
|
|
* Die konfigurierte lokale virtuelle Schnittstelle wird dabei exakt
|
|
* übernommen.
|
|
* ============================================================================
|
|
*/
|
|
package client
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
|
|
"git.lang-dieter.de/rs2322tcp/internal/config"
|
|
"git.lang-dieter.de/rs2322tcp/internal/transport"
|
|
)
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Virtual port connection
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// connectVirtualPort opens the configured local virtual port and the
|
|
// corresponding remote TCP data connection and returns both endpoints.
|
|
//
|
|
// The caller owns the returned virtual port and TCP connection.
|
|
//
|
|
// The local virtual port is opened using exactly the port number specified
|
|
// in virtualPortConfig.Port. This preserves the user's configured mapping
|
|
// between local virtual interfaces and remote devices.
|
|
func connectVirtualPort(
|
|
c *Client,
|
|
manager *VirtualPortManager,
|
|
virtualPortConfig config.VirtualPortConfig,
|
|
devices []transport.RemoteDeviceInfo,
|
|
) (*ManagedVirtualPort, net.Conn, error) {
|
|
if c == nil || c.conn == nil {
|
|
return nil, nil, fmt.Errorf("client is not connected")
|
|
}
|
|
|
|
if manager == nil {
|
|
return nil, nil, fmt.Errorf("virtual port manager is nil")
|
|
}
|
|
|
|
device, err := findRemoteDevice(virtualPortConfig, devices)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
portNumber, err := virtualPortNumber(virtualPortConfig.Port)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
virtualPort, err := manager.OpenSpecific(portNumber)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf(
|
|
"open virtual port %q for %q: %w",
|
|
virtualPortConfig.Port,
|
|
virtualPortConfig.RemoteDevice,
|
|
err,
|
|
)
|
|
}
|
|
|
|
conn, err := c.OpenDataConnection(device)
|
|
if err != nil {
|
|
_ = virtualPort.Close()
|
|
|
|
return nil, nil, fmt.Errorf(
|
|
"open data connection for %q: %w",
|
|
device.ID,
|
|
err,
|
|
)
|
|
}
|
|
|
|
return virtualPort, conn, nil
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Bridge connection
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// connectBridge creates the local virtual port, opens the corresponding
|
|
// remote TCP data connection and creates the data bridge.
|
|
//
|
|
// The caller owns the returned bridge and its endpoints.
|
|
func connectBridge(
|
|
c *Client,
|
|
manager *VirtualPortManager,
|
|
virtualPortConfig config.VirtualPortConfig,
|
|
devices []transport.RemoteDeviceInfo,
|
|
) (*Bridge, *ManagedVirtualPort, net.Conn, error) {
|
|
virtualPort, conn, err := connectVirtualPort(
|
|
c,
|
|
manager,
|
|
virtualPortConfig,
|
|
devices,
|
|
)
|
|
if err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
bridge, err := NewBridge(virtualPort, conn)
|
|
if err != nil {
|
|
_ = conn.Close()
|
|
_ = virtualPort.Close()
|
|
|
|
return nil, nil, nil, fmt.Errorf(
|
|
"create bridge for %q: %w",
|
|
virtualPortConfig.RemoteDevice,
|
|
err,
|
|
)
|
|
}
|
|
|
|
return bridge, virtualPort, conn, nil
|
|
}
|