Fixes socket problems on Windows and normalises some names.

Ref #2976. Ref #2003. See news.txt for details.
This commit is contained in:
Dominik Picheta 2015-06-29 20:11:21 +01:00
commit 615defb1a9
5 changed files with 78 additions and 55 deletions

View file

@ -85,35 +85,44 @@ type
bioIn: BIO
bioOut: BIO
of false: nil
domain: Domain
sockType: SockType
protocol: Protocol
AsyncSocket* = ref AsyncSocketDesc
{.deprecated: [PAsyncSocket: AsyncSocket].}
# TODO: Save AF, domain etc info and reuse it in procs which need it like connect.
proc newAsyncSocket*(fd: AsyncFD, buffered = true): AsyncSocket =
proc newAsyncSocket*(fd: AsyncFD, domain: Domain = AF_INET,
sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP, buffered = true): AsyncSocket =
## Creates a new ``AsyncSocket`` based on the supplied params.
assert fd != osInvalidSocket.AsyncFD
new(result)
result.fd = fd.SocketHandle
result.isBuffered = buffered
result.domain = domain
result.sockType = sockType
result.protocol = protocol
if buffered:
result.currPos = 0
proc newAsyncSocket*(domain: Domain = AF_INET6, typ: SockType = SOCK_STREAM,
proc newAsyncSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP, buffered = true): AsyncSocket =
## Creates a new asynchronous socket.
##
## This procedure will also create a brand new file descriptor for
## this socket.
result = newAsyncSocket(newAsyncRawSocket(domain, typ, protocol), buffered)
result = newAsyncSocket(newAsyncRawSocket(domain, sockType, protocol), domain,
sockType, protocol, buffered)
proc newAsyncSocket*(domain, typ, protocol: cint, buffered = true): AsyncSocket =
proc newAsyncSocket*(domain, sockType, protocol: cint,
buffered = true): AsyncSocket =
## Creates a new asynchronous socket.
##
## This procedure will also create a brand new file descriptor for
## this socket.
result = newAsyncSocket(newAsyncRawSocket(domain, typ, protocol), buffered)
result = newAsyncSocket(newAsyncRawSocket(domain, sockType, protocol),
Domain(domain), SockType(sockType), Protocol(protocol), buffered)
when defined(ssl):
proc getSslError(handle: SslPtr, err: cint): cint =
@ -169,13 +178,12 @@ when defined(ssl):
let err = getSslError(socket.sslHandle, opResult.cint)
yield appeaseSsl(socket, flags, err.cint)
proc connect*(socket: AsyncSocket, address: string, port: Port,
af = AF_INET) {.async.} =
proc connect*(socket: AsyncSocket, address: string, port: Port) {.async.} =
## Connects ``socket`` to server at ``address:port``.
##
## Returns a ``Future`` which will complete when the connection succeeds
## or an error occurs.
await connect(socket.fd.AsyncFD, address, port, af)
await connect(socket.fd.AsyncFD, address, port, socket.domain)
if socket.isSsl:
when defined(ssl):
let flags = {SocketFlag.SafeDisconn}
@ -287,7 +295,8 @@ proc acceptAddr*(socket: AsyncSocket, flags = {SocketFlag.SafeDisconn}):
retFuture.fail(future.readError)
else:
let resultTup = (future.read.address,
newAsyncSocket(future.read.client, socket.isBuffered))
newAsyncSocket(future.read.client, socket.domain,
socket.sockType, socket.protocol, socket.isBuffered))
retFuture.complete(resultTup)
return retFuture
@ -423,17 +432,15 @@ proc bindAddr*(socket: AsyncSocket, port = Port(0), address = "") {.
## Binds ``address``:``port`` to the socket.
##
## If ``address`` is "" then ADDR_ANY will be bound.
var sockDomain = getSockDomain(socket.fd)
var realaddr = address
if realaddr == "":
case sockDomain
case socket.domain
of AF_INET6: realaddr = "::"
of AF_INET: realaddr = "0.0.0.0"
else:
raiseOSError("Unknown socket address family and no address specified to bindAddr")
var aiList = getAddrInfo(realaddr, port, sockDomain)
var aiList = getAddrInfo(realaddr, port, socket.domain)
if bindAddr(socket.fd, aiList.ai_addr, aiList.ai_addrlen.Socklen) < 0'i32:
dealloc(aiList)
raiseOSError(osLastError())