Fixes socket problems on Windows and normalises some names.
Ref #2976. Ref #2003. See news.txt for details.
This commit is contained in:
parent
c16d153ff5
commit
615defb1a9
5 changed files with 78 additions and 55 deletions
|
|
@ -64,6 +64,9 @@ type
|
|||
sslPeekChar: char
|
||||
of false: nil
|
||||
lastError: OSErrorCode ## stores the last error on this socket
|
||||
domain: Domain
|
||||
sockType: SockType
|
||||
protocol: Protocol
|
||||
|
||||
Socket* = ref SocketImpl
|
||||
|
||||
|
|
@ -124,33 +127,39 @@ proc toOSFlags*(socketFlags: set[SocketFlag]): cint =
|
|||
result = result or MSG_PEEK
|
||||
of SocketFlag.SafeDisconn: continue
|
||||
|
||||
proc newSocket*(fd: SocketHandle, buffered = true): Socket =
|
||||
proc newSocket*(fd: SocketHandle, domain: Domain = AF_INET,
|
||||
sockType: SockType = SOCK_STREAM,
|
||||
protocol: Protocol = IPPROTO_TCP, buffered = true): Socket =
|
||||
## Creates a new socket as specified by the params.
|
||||
assert fd != osInvalidSocket
|
||||
new(result)
|
||||
result.fd = fd
|
||||
result.isBuffered = buffered
|
||||
result.domain = domain
|
||||
result.sockType = sockType
|
||||
result.protocol = protocol
|
||||
if buffered:
|
||||
result.currPos = 0
|
||||
|
||||
proc newSocket*(domain, typ, protocol: cint, buffered = true): Socket =
|
||||
proc newSocket*(domain, sockType, protocol: cint, buffered = true): Socket =
|
||||
## Creates a new socket.
|
||||
##
|
||||
## If an error occurs EOS will be raised.
|
||||
let fd = newRawSocket(domain, typ, protocol)
|
||||
let fd = newRawSocket(domain, sockType, protocol)
|
||||
if fd == osInvalidSocket:
|
||||
raiseOSError(osLastError())
|
||||
result = newSocket(fd, buffered)
|
||||
result = newSocket(fd, domain.Domain, sockType.SockType, protocol.Protocol,
|
||||
buffered)
|
||||
|
||||
proc newSocket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM,
|
||||
proc newSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM,
|
||||
protocol: Protocol = IPPROTO_TCP, buffered = true): Socket =
|
||||
## Creates a new socket.
|
||||
##
|
||||
## If an error occurs EOS will be raised.
|
||||
let fd = newRawSocket(domain, typ, protocol)
|
||||
let fd = newRawSocket(domain, sockType, protocol)
|
||||
if fd == osInvalidSocket:
|
||||
raiseOSError(osLastError())
|
||||
result = newSocket(fd, buffered)
|
||||
result = newSocket(fd, domain, sockType, protocol, buffered)
|
||||
|
||||
when defined(ssl):
|
||||
CRYPTO_malloc_init()
|
||||
|
|
@ -371,7 +380,7 @@ proc bindAddr*(socket: Socket, port = Port(0), address = "") {.
|
|||
sizeof(name).SockLen) < 0'i32:
|
||||
raiseOSError(osLastError())
|
||||
else:
|
||||
var aiList = getAddrInfo(address, port, AF_INET)
|
||||
var aiList = getAddrInfo(address, port, socket.domain)
|
||||
if bindAddr(socket.fd, aiList.ai_addr, aiList.ai_addrlen.SockLen) < 0'i32:
|
||||
dealloc(aiList)
|
||||
raiseOSError(osLastError())
|
||||
|
|
@ -532,15 +541,15 @@ proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) {
|
|||
var valuei = cint(if value: 1 else: 0)
|
||||
setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei)
|
||||
|
||||
proc connect*(socket: Socket, address: string, port = Port(0),
|
||||
af: Domain = AF_INET) {.tags: [ReadIOEffect].} =
|
||||
proc connect*(socket: Socket, address: string,
|
||||
port = Port(0)) {.tags: [ReadIOEffect].} =
|
||||
## Connects socket to ``address``:``port``. ``Address`` can be an IP address or a
|
||||
## host name. If ``address`` is a host name, this function will try each IP
|
||||
## of that host name. ``htons`` is already performed on ``port`` so you must
|
||||
## not do it.
|
||||
##
|
||||
## If ``socket`` is an SSL socket a handshake will be automatically performed.
|
||||
var aiList = getAddrInfo(address, port, af)
|
||||
var aiList = getAddrInfo(address, port, socket.domain)
|
||||
# try all possibilities:
|
||||
var success = false
|
||||
var lastError: OSErrorCode
|
||||
|
|
@ -992,15 +1001,15 @@ proc connectAsync(socket: Socket, name: string, port = Port(0),
|
|||
dealloc(aiList)
|
||||
if not success: raiseOSError(lastError)
|
||||
|
||||
proc connect*(socket: Socket, address: string, port = Port(0), timeout: int,
|
||||
af: Domain = AF_INET) {.tags: [ReadIOEffect, WriteIOEffect].} =
|
||||
proc connect*(socket: Socket, address: string, port = Port(0),
|
||||
timeout: int) {.tags: [ReadIOEffect, WriteIOEffect].} =
|
||||
## Connects to server as specified by ``address`` on port specified by ``port``.
|
||||
##
|
||||
## The ``timeout`` paremeter specifies the time in milliseconds to allow for
|
||||
## the connection to the server to be made.
|
||||
socket.fd.setBlocking(false)
|
||||
|
||||
socket.connectAsync(address, port, af)
|
||||
socket.connectAsync(address, port, socket.domain)
|
||||
var s = @[socket.fd]
|
||||
if selectWrite(s, timeout) != 1:
|
||||
raise newException(TimeoutError, "Call to 'connect' timed out.")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue