Skip to content

Commit 8425b05

Browse files
authored
Merge pull request #14 from projectdiscovery/feature-port-auto-retry
Feature port auto retry
2 parents 9a1d1df + 86e2a7d commit 8425b05

File tree

1 file changed

+61
-6
lines changed

1 file changed

+61
-6
lines changed

simplehttpserver.go

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@ package main
22

33
import (
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) {
141160
func 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

Comments
 (0)