@@ -2,13 +2,20 @@ package main
2
2
3
3
import (
4
4
"bytes"
5
+ "errors"
5
6
"flag"
6
7
"fmt"
7
8
"io/ioutil"
9
+ "log"
10
+ "net"
8
11
"net/http"
9
12
"net/http/httputil"
13
+ "os"
10
14
"path"
15
+ "runtime"
16
+ "strconv"
11
17
"strings"
18
+ "syscall"
12
19
13
20
"github.com/projectdiscovery/gologger"
14
21
"github.com/projectdiscovery/simplehttpserver/pkg/sslcert"
@@ -81,10 +88,12 @@ func main() {
81
88
}
82
89
layers = loglayer (basicauthlayer (http .FileServer (http .Dir (opts .Folder ))))
83
90
}
84
-
85
91
if opts .Upload {
86
- gologger .Print ().Msgf ( " Upload enabled" )
92
+ gologger .Print ().Msg ( "Starting service with Upload enabled" )
87
93
}
94
+ retry_listen:
95
+ gologger .Print ().Msgf ("Serving %s on http://%s/..." , opts .Folder , opts .ListenAddress )
96
+ var err error
88
97
if opts .HTTPS {
89
98
if opts .Certificate == "" || opts .Key == "" {
90
99
tlsOptions := sslcert .DefaultOptions
@@ -103,7 +112,19 @@ func main() {
103
112
gologger .Print ().Msgf ("%s\n " , http .ListenAndServeTLS (opts .ListenAddress , opts .Certificate , opts .Key , layers ))
104
113
}
105
114
} else {
106
- gologger .Print ().Msgf ("%s\n " , http .ListenAndServe (opts .ListenAddress , layers ))
115
+ err = http .ListenAndServe (opts .ListenAddress , layers )
116
+ }
117
+ if err != nil {
118
+ if isErrorAddressAlreadyInUse (err ) {
119
+ gologger .Print ().Msgf ("Can't listen on %s: %s - retrying with another port\n " , opts .ListenAddress , err )
120
+ newListenAddress , err := incPort (opts .ListenAddress )
121
+ if err != nil {
122
+ gologger .Fatal ().Msgf ("%s\n " , err )
123
+ }
124
+ opts .ListenAddress = newListenAddress
125
+ goto retry_listen
126
+ }
127
+ gologger .Print ().Msgf ("%s\n " , err )
107
128
}
108
129
}
109
130
@@ -175,3 +196,39 @@ func (lrw *loggingResponseWriter) WriteHeader(code int) {
175
196
func handleUpload (file string , data []byte ) error {
176
197
return ioutil .WriteFile (file , data , 0655 )
177
198
}
199
+
200
+ func isErrorAddressAlreadyInUse (err error ) bool {
201
+ var eOsSyscall * os.SyscallError
202
+ if ! errors .As (err , & eOsSyscall ) {
203
+ return false
204
+ }
205
+ var errErrno syscall.Errno // doesn't need a "*" (ptr) because it's already a ptr (uintptr)
206
+ if ! errors .As (eOsSyscall , & errErrno ) {
207
+ return false
208
+ }
209
+ if errErrno == syscall .EADDRINUSE {
210
+ return true
211
+ }
212
+ const WSAEADDRINUSE = 10048
213
+ if runtime .GOOS == "windows" && errErrno == WSAEADDRINUSE {
214
+ return true
215
+ }
216
+ return false
217
+ }
218
+
219
+ func incPort (address string ) (string , error ) {
220
+ addrOrig , portOrig , err := net .SplitHostPort (address )
221
+ if err != nil {
222
+ return address , err
223
+ }
224
+
225
+ // increment port
226
+ portNumber , err := strconv .Atoi (portOrig )
227
+ if err != nil {
228
+ return address , err
229
+ }
230
+ portNumber ++
231
+ newPort := strconv .FormatInt (int64 (portNumber ), 10 )
232
+
233
+ return net .JoinHostPort (addrOrig , newPort ), nil
234
+ }
0 commit comments