@@ -2,14 +2,20 @@ package main
22
33import (
44 "bytes"
5+ "errors"
56 "flag"
67 "fmt"
78 "io/ioutil"
89 "log"
10+ "net"
911 "net/http"
1012 "net/http/httputil"
13+ "os"
1114 "path"
15+ "runtime"
16+ "strconv"
1217 "strings"
18+ "syscall"
1319
1420 "github.com/projectdiscovery/gologger"
1521)
@@ -47,7 +53,6 @@ func main() {
4753 opts .Folder = flag .Args ()[0 ]
4854 }
4955
50- gologger .Print ().Msgf ("Serving %s on http://%s/..." , opts .Folder , opts .ListenAddress )
5156 layers := loglayer (http .FileServer (http .Dir (opts .Folder )))
5257 if opts .BasicAuth != "" {
5358 baTokens := strings .SplitN (opts .BasicAuth , ":" , 2 )
@@ -59,17 +64,31 @@ func main() {
5964 }
6065 layers = loglayer (basicauthlayer (http .FileServer (http .Dir (opts .Folder ))))
6166 }
62-
6367 if opts .Upload {
64- gologger .Print ().Msgf ( " Upload enabled" )
68+ gologger .Print ().Msg ( "Starting service with Upload enabled" )
6569 }
70+ retry_listen:
71+ gologger .Print ().Msgf ("Serving %s on http://%s/..." , opts .Folder , opts .ListenAddress )
72+ var err error
6673 if opts .HTTPS {
6774 if opts .Certificate == "" || opts .Key == "" {
68- gologger .Fatal ().Msgf ("Certificate or Key file not specified" )
75+ gologger .Fatal ().Msg ("Certificate or Key file not specified" )
6976 }
70- gologger . Print (). Msgf ( "%s \n " , http .ListenAndServeTLS (opts .ListenAddress , opts .Certificate , opts .Key , layers ) )
77+ err = http .ListenAndServeTLS (opts .ListenAddress , opts .Certificate , opts .Key , layers )
7178 } else {
72- gologger .Print ().Msgf ("%s\n " , http .ListenAndServe (opts .ListenAddress , layers ))
79+ err = http .ListenAndServe (opts .ListenAddress , layers )
80+ }
81+ if err != nil {
82+ if isErrorAddressAlreadyInUse (err ) {
83+ gologger .Print ().Msgf ("Can't listen on %s: %s - retrying with another port\n " , opts .ListenAddress , err )
84+ newListenAddress , err := incPort (opts .ListenAddress )
85+ if err != nil {
86+ gologger .Fatal ().Msgf ("%s\n " , err )
87+ }
88+ opts .ListenAddress = newListenAddress
89+ goto retry_listen
90+ }
91+ gologger .Print ().Msgf ("%s\n " , err )
7392 }
7493}
7594
@@ -141,3 +160,39 @@ func (lrw *loggingResponseWriter) WriteHeader(code int) {
141160func handleUpload (file string , data []byte ) error {
142161 return ioutil .WriteFile (file , data , 0655 )
143162}
163+
164+ func isErrorAddressAlreadyInUse (err error ) bool {
165+ var eOsSyscall * os.SyscallError
166+ if ! errors .As (err , & eOsSyscall ) {
167+ return false
168+ }
169+ var errErrno syscall.Errno // doesn't need a "*" (ptr) because it's already a ptr (uintptr)
170+ if ! errors .As (eOsSyscall , & errErrno ) {
171+ return false
172+ }
173+ if errErrno == syscall .EADDRINUSE {
174+ return true
175+ }
176+ const WSAEADDRINUSE = 10048
177+ if runtime .GOOS == "windows" && errErrno == WSAEADDRINUSE {
178+ return true
179+ }
180+ return false
181+ }
182+
183+ func incPort (address string ) (string , error ) {
184+ addrOrig , portOrig , err := net .SplitHostPort (address )
185+ if err != nil {
186+ return address , err
187+ }
188+
189+ // increment port
190+ portNumber , err := strconv .Atoi (portOrig )
191+ if err != nil {
192+ return address , err
193+ }
194+ portNumber ++
195+ newPort := strconv .FormatInt (int64 (portNumber ), 10 )
196+
197+ return net .JoinHostPort (addrOrig , newPort ), nil
198+ }
0 commit comments