@@ -2,13 +2,20 @@ package main
22
33import (
44 "bytes"
5+ "errors"
56 "flag"
67 "fmt"
78 "io/ioutil"
9+ "log"
10+ "net"
811 "net/http"
912 "net/http/httputil"
13+ "os"
1014 "path"
15+ "runtime"
16+ "strconv"
1117 "strings"
18+ "syscall"
1219
1320 "github.com/projectdiscovery/gologger"
1421 "github.com/projectdiscovery/simplehttpserver/pkg/sslcert"
@@ -81,10 +88,12 @@ func main() {
8188 }
8289 layers = loglayer (basicauthlayer (http .FileServer (http .Dir (opts .Folder ))))
8390 }
84-
8591 if opts .Upload {
86- gologger .Print ().Msgf ( " Upload enabled" )
92+ gologger .Print ().Msg ( "Starting service with Upload enabled" )
8793 }
94+ retry_listen:
95+ gologger .Print ().Msgf ("Serving %s on http://%s/..." , opts .Folder , opts .ListenAddress )
96+ var err error
8897 if opts .HTTPS {
8998 if opts .Certificate == "" || opts .Key == "" {
9099 tlsOptions := sslcert .DefaultOptions
@@ -103,7 +112,19 @@ func main() {
103112 gologger .Print ().Msgf ("%s\n " , http .ListenAndServeTLS (opts .ListenAddress , opts .Certificate , opts .Key , layers ))
104113 }
105114 } 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 )
107128 }
108129}
109130
@@ -175,3 +196,39 @@ func (lrw *loggingResponseWriter) WriteHeader(code int) {
175196func handleUpload (file string , data []byte ) error {
176197 return ioutil .WriteFile (file , data , 0655 )
177198}
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