-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
150 lines (138 loc) · 4.56 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package main
import (
"flag"
"net"
"fmt"
"strconv"
"strings"
log "github.com/sirupsen/logrus"
)
type stringMapVar struct {
contents map[string]int
}
func (s stringMapVar) String() string {
return fmt.Sprint(s.contents)
}
func (s stringMapVar) Set(value string) error {
iface := strings.Split(value, ",")
bandwidth, err := strconv.Atoi(iface[1])
if err != nil {
log.WithError(err).Fatal("Could not parse iface arguments! Uh-oh!")
panic(err)
}
s.contents[iface[0]] = bandwidth
return nil
}
var flagServerDestination string
var flagClientListenPort int
var flagServerListenPort int
var flagListenMode bool
var flagAddress string
var flagIfacePoll int
var flagRedundant bool
var flagRedundantDownload bool
var flagRedundantUpload bool
var flagRandReorder bool
var (
flagInterfaces = stringMapVar{
contents: make(map[string]int),
}
)
func init() {
log.SetFormatter(&log.TextFormatter{})
log.SetLevel(log.DebugLevel)
flag.StringVar(&flagServerDestination, "lp", "localhost:22", "(server only parameter) Where to forward the connection")
flag.IntVar(&flagClientListenPort, "cp", 5021, "(client only parameter) What port to listen on for the application")
flag.IntVar(&flagServerListenPort, "sp", 5022, "(server only parameter) What port to listen on for the application")
flag.BoolVar(&flagRedundant, "r", false, "(client only parameter) Send packets on every interface instead of just one? (Improves reliability)")
flag.BoolVar(&flagRedundantDownload, "rd", false, "(client only parameter) Redundant mode only for downloads")
flag.BoolVar(&flagRedundantUpload, "ru", false, "(client only parameter) Redundant mode only for uploads")
flag.BoolVar(&flagListenMode, "l", false, "(determines client or server behavior) Should listen?")
flag.StringVar(&flagAddress, "address", "localhost:5022", "(client only parameter) Address of the server")
flag.IntVar(&flagIfacePoll, "poll", 5, "(client only parameter) How fast we should poll for new interfaces (seconds)")
flag.BoolVar(&flagRandReorder, "randreorder", false, "Enable this to purposefully split up data into smaller chunks and randomly reorder them before sending. Useful to test the reassembler, has a huge negative impact on performance.")
flag.Var(flagInterfaces, "iface", "(client only parameter) (deprecated) Specifies which interfaces will be used for connections, as well as the bandwidth for each interface.\n"+
"Bandwidth is in KB/s. For unrestricted bandwidth, specify 0.\n"+
"Usage: fusion -iface=<interface name>,<bandwidth>"+
"Example: fusion -iface=en0,50")
//flag.Var(flagUDPInterfaces, "udp-interface", "The name of the interface you wish to use as UDP instead of TCP (This is not recommended for a single interface, as retrying on UDP will not be attempted")
//flag.Var(flagUDPInterfaces, "ui", "Shorthand for the 'udp-interface' parameter. See 'udp-interface' for usage")
//flag.Memes
}
func main() {
flag.Parse()
log.Debug(flagInterfaces)
if flagListenMode {
if flagRedundant || flagRedundantUpload || flagRedundantDownload {
log.WithFields(log.Fields{
"redundant": flagRedundant,
"redundant-up": flagRedundantUpload,
"redundant-down": flagRedundantDownload,
}).Warning("While in listen mode, the redundant flags will have no effect.")
return
}
err := Server()
if err != nil {
panic(err)
}
} else {
err := Client(flagAddress)
if err != nil {
panic(err)
}
}
}
func Client(serverAddr string) error {
log.WithFields(log.Fields{
"port": flagClientListenPort,
"red": flagRedundant,
"red-up": flagRedundantUpload,
"red-dl": flagRedundantDownload,
"listen": flagListenMode,
"addr": flagAddress,
"poll": flagIfacePoll,
}).Info("Starting client...")
ln, err := net.Listen("tcp", ":"+strconv.Itoa(flagClientListenPort))
if err != nil {
return err
}
for {
conn, err := ln.Accept()
if err != nil {
return err
}
go func() {
sessionID := ClientReceivedSSHConnection(conn)
err := SetupInterfaces(sessionID, serverAddr)
if err != nil {
log.Errorln(err)
}
}()
}
}
func Server() error {
log.WithFields(log.Fields{
"listen": flagListenMode,
"forward": flagServerDestination,
"poll": flagIfacePoll,
}).Info("Starting server...")
ln, err := net.Listen("tcp", ":"+strconv.Itoa(flagServerListenPort))
if err != nil {
return err
}
for {
conn, err := ln.Accept()
if err != nil {
return err
}
go func() {
err := ServerReceivedClientConnection(conn)
if err != nil {
// TODO: Add in and then utilize per-connection logging contexts
log.WithFields(log.Fields{
"conn": conn,
}).Errorln(err)
}
}()
}
}