Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alternative to https://github.com/dom96/httpbeast/pull/50 using failOnExistingPort #52

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion httpbeast.nimble
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Package

version = "0.4.0"
version = "0.4.1"
author = "Dominik Picheta"
description = "A super-fast epoll-backed and parallel HTTP server."
license = "MIT"
Expand Down
27 changes: 18 additions & 9 deletions src/httpbeast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ type
numThreads: int
loggers: seq[Logger]
reusePort: bool
## controls whether to fail with "Address already in use".
## Setting this to false will raise when `threads` are on.
## controls whether to use `OptReusePort` for sockets
failOnExistingPort: bool
## Fail with "Address already in use" if port is in use, by attempting
## to bind to a temporary socket to fail early.

HttpBeastDefect* = ref object of Defect

Expand All @@ -67,14 +69,16 @@ proc initSettings*(port: Port = Port(8080),
bindAddr: string = "",
numThreads: int = 0,
domain = Domain.AF_INET,
reusePort = true): Settings =
reusePort = true,
failOnExistingPort = true): Settings =
Settings(
port: port,
bindAddr: bindAddr,
domain: domain,
numThreads: numThreads,
loggers: getHandlers(),
reusePort: reusePort,
failOnExistingPort: failOnExistingPort,
)

proc initData(fdKind: FdKind, ip = ""): Data =
Expand Down Expand Up @@ -311,6 +315,12 @@ proc updateDate(fd: AsyncFD): bool =
result = false # Returning true signifies we want timer to stop.
serverDate = now().utc().format("ddd, dd MMM yyyy HH:mm:ss 'GMT'")

proc newSocketAux(settings: Settings): owned(Socket) =
result = newSocket(settings.domain)
result.setSockOpt(OptReuseAddr, true)
result.setSockOpt(OptReusePort, settings.reusePort)
result.bindAddr(settings.port, settings.bindAddr)

proc eventLoop(params: (OnRequest, Settings)) =
let (onRequest, settings) = params

Expand All @@ -319,12 +329,7 @@ proc eventLoop(params: (OnRequest, Settings)) =

let selector = newSelector[Data]()

let server = newSocket(settings.domain)
server.setSockOpt(OptReuseAddr, true)
if compileOption("threads") and not settings.reusePort:
raise HttpBeastDefect(msg: "--threads:on requires reusePort to be enabled in settings")
server.setSockOpt(OptReusePort, settings.reusePort)
server.bindAddr(settings.port, settings.bindAddr)
let server = newSocketAux(settings)
server.listen()
server.getFd().setBlocking(false)
selector.registerHandle(server.getFd(), {Event.Read}, initData(Server))
Expand Down Expand Up @@ -475,6 +480,10 @@ proc run*(onRequest: OnRequest, settings: Settings) =
let numThreads = 1

echo("Starting ", numThreads, " threads")
if settings.failOnExistingPort:
var settings2 = settings
settings2.reusePort = false
close(newSocketAux(settings2)) # attempt to bind to a temporary socket
if numThreads > 1:
when compileOption("threads"):
var threads = newSeq[Thread[(OnRequest, Settings)]](numThreads)
Expand Down