Skip to content
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.5.0"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
version = "0.5.0"
version = "0.4.0"

author = "Dominik Picheta"
description = "A super-fast epoll-backed and parallel HTTP server."
license = "MIT"
Expand Down
28 changes: 17 additions & 11 deletions src/httpbeast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ type
domain*: Domain
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.
failOnExistingPort: bool
## Fail with "Address already in use" if port is in use, by attempting
## to bind to a temporary socket to fail early if `numThreads>1`, or
## not setting `OptReusePort` if `numThreads==1`.

HttpBeastDefect* = ref object of Defect

Expand All @@ -67,14 +68,14 @@ proc initSettings*(port: Port = Port(8080),
bindAddr: string = "",
numThreads: int = 0,
domain = Domain.AF_INET,
reusePort = true): Settings =
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 +312,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, not settings.failOnExistingPort)
result.bindAddr(settings.port, settings.bindAddr)

Comment on lines +315 to +320
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
proc newSocketAux(settings: Settings): owned(Socket) =
result = newSocket(settings.domain)
result.setSockOpt(OptReuseAddr, true)
result.setSockOpt(OptReusePort, not settings.failOnExistingPort)
result.bindAddr(settings.port, settings.bindAddr)
proc bindOnExistingTest(settings: Settings) =
let sock = newSocket(settings.domain)
sock.setSockOpt(OptReuseAddr, true)
sock.bindAddr(settings.port, settings.bindAddr)

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

Expand All @@ -319,12 +326,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)
Comment on lines -322 to -327
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert this.

let server = newSocketAux(settings)
server.listen()
server.getFd().setBlocking(false)
selector.registerHandle(server.getFd(), {Event.Read}, initData(Server))
Expand Down Expand Up @@ -476,6 +478,10 @@ proc run*(onRequest: OnRequest, settings: Settings) =

echo("Starting ", numThreads, " threads")
if numThreads > 1:
if settings.failOnExistingPort:
close(newSocketAux(settings)) # attempt to bind to a temporary socket
var settings = settings
settings.failOnExistingPort = false
Comment on lines +481 to +484
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if settings.failOnExistingPort:
close(newSocketAux(settings)) # attempt to bind to a temporary socket
var settings = settings
settings.failOnExistingPort = false
if settings.failOnExistingPort:
bindOnExistingTest(settings)

when compileOption("threads"):
var threads = newSeq[Thread[(OnRequest, Settings)]](numThreads)
for i in 0 ..< numThreads:
Expand Down