- 协议: InitMessage 增加 ip6/prefix6/server_ip6 字段(omitempty,向后兼容) - TUN: Device 接口新增 ConfigureIPv6, macOS 用 ifconfig inet6, Linux 用 ip -6 addr add - 路由: full 模式自动添加 ::/1+8000::/1, v6 服务器旁路 /128, resolveHosts 双栈解析 - 会话: setupTUN 解析 v6 字段并配置 TUN+路由, connectOnce 传 v6 给 stats/日志 - 统计: SetConnected(ip,ip6), Snapshot.AssignedIP6 - DB: connection_logs 增加 assigned_ip6 列 + migrateV3 幂等迁移 - UI: 状态卡片新增独立 IPv6 行, 始终可见(未获取显示 IPv6: —) - 文档: 同步 client-development.md 至服务端 IPv6 版本
65 lines
1.9 KiB
Go
65 lines
1.9 KiB
Go
package db
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"lmvpn/internal/model"
|
|
)
|
|
|
|
// StartLog creates a connection log entry and returns its ID.
|
|
func (s *Store) StartLog(profileID int64) (int64, error) {
|
|
res, err := s.db.Exec(
|
|
`INSERT INTO connection_logs (profile_id, started_at, status)
|
|
VALUES (?, ?, 'connected')`,
|
|
profileID, time.Now())
|
|
if err != nil {
|
|
return 0, fmt.Errorf("start log: %w", err)
|
|
}
|
|
id, _ := res.LastInsertId()
|
|
return id, nil
|
|
}
|
|
|
|
// FinishLog finalises a connection log entry with final stats.
|
|
func (s *Store) FinishLog(id int64, status model.ConnectionStatus, assignedIP, assignedIP6 string, rxBytes, txBytes int64, errMsg string) error {
|
|
_, err := s.db.Exec(
|
|
`UPDATE connection_logs SET
|
|
ended_at = ?, assigned_ip = ?, assigned_ip6 = ?, rx_bytes = ?, tx_bytes = ?,
|
|
status = ?, error_msg = ?
|
|
WHERE id = ?`,
|
|
time.Now(), assignedIP, assignedIP6, rxBytes, txBytes, status, errMsg, id)
|
|
if err != nil {
|
|
return fmt.Errorf("finish log %d: %w", id, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// RecentLogs returns the most recent N connection logs for a profile.
|
|
func (s *Store) RecentLogs(profileID int64, limit int) ([]model.ConnectionLog, error) {
|
|
rows, err := s.db.Query(
|
|
`SELECT id, profile_id, started_at, ended_at, assigned_ip, assigned_ip6,
|
|
rx_bytes, tx_bytes, status, error_msg
|
|
FROM connection_logs WHERE profile_id = ?
|
|
ORDER BY started_at DESC LIMIT ?`,
|
|
profileID, limit)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("recent logs: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var out []model.ConnectionLog
|
|
for rows.Next() {
|
|
var l model.ConnectionLog
|
|
var ended interface{}
|
|
if err := rows.Scan(&l.ID, &l.ProfileID, &l.StartedAt, &ended,
|
|
&l.AssignedIP, &l.AssignedIP6, &l.RxBytes, &l.TxBytes, &l.Status, &l.ErrorMsg); err != nil {
|
|
return nil, err
|
|
}
|
|
if t, ok := ended.(time.Time); ok {
|
|
l.EndedAt = &t
|
|
}
|
|
out = append(out, l)
|
|
}
|
|
return out, rows.Err()
|
|
}
|