mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 22:10:33 +00:00
Improve net and ssl module docs.
This commit is contained in:
@@ -9,6 +9,9 @@
|
||||
|
||||
## This module provides an easy to use sockets-style
|
||||
## nim interface to the OpenSSL library.
|
||||
##
|
||||
## **Warning:** This module is deprecated, use the SSL procedures defined in
|
||||
## the ``net`` module instead.
|
||||
|
||||
{.deprecated.}
|
||||
|
||||
|
||||
@@ -8,19 +8,76 @@
|
||||
#
|
||||
|
||||
## This module implements a high-level cross-platform sockets interface.
|
||||
## The procedures implemented in this module are primarily for blocking sockets.
|
||||
## For asynchronous non-blocking sockets use the ``asyncnet`` module together
|
||||
## with the ``asyncdispatch`` module.
|
||||
##
|
||||
## The first thing you will always need to do in order to start using sockets,
|
||||
## is to create a new instance of the ``Socket`` type using the ``newSocket``
|
||||
## procedure.
|
||||
##
|
||||
## SSL
|
||||
## ====
|
||||
##
|
||||
## In order to use the SSL procedures defined in this module, you will need to
|
||||
## compile your application with the ``-d:ssl`` flag.
|
||||
##
|
||||
## Examples
|
||||
## ========
|
||||
##
|
||||
## Connecting to a server
|
||||
## ----------------------
|
||||
##
|
||||
## After you create a socket with the ``newSocket`` procedure, you can easily
|
||||
## connect it to a server running at a known hostname (or IP address) and port.
|
||||
## To do so over TCP, use the example below.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var socket = newSocket()
|
||||
## socket.connect("google.com", Port(80))
|
||||
##
|
||||
## UDP is a connectionless protocol, so UDP sockets don't have to explicitly
|
||||
## call the ``connect`` procedure. They can simply start sending data
|
||||
## immediately.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var socket = newSocket()
|
||||
## socket.sendTo("192.168.0.1", Port(27960), "status\n")
|
||||
##
|
||||
## Creating a server
|
||||
## -----------------
|
||||
##
|
||||
## After you create a socket with the ``newSocket`` procedure, you can create a
|
||||
## TCP server by calling the ``bindAddr`` and ``listen`` procedures.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var socket = newSocket()
|
||||
## socket.bindAddr(Port(1234))
|
||||
## socket.listen()
|
||||
##
|
||||
## You can then begin accepting connections using the ``accept`` procedure.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var client = newSocket()
|
||||
## var address = ""
|
||||
## while true:
|
||||
## socket.acceptAddr(client, address)
|
||||
## echo("Client connected from: ", address)
|
||||
##
|
||||
|
||||
{.deadCodeElim: on.}
|
||||
import nativesockets, os, strutils, parseutils, times
|
||||
export Port, `$`, `==`
|
||||
|
||||
const useWinVersion = defined(Windows) or defined(nimdoc)
|
||||
const defineSsl = defined(ssl) or defined(nimdoc)
|
||||
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
import openssl
|
||||
|
||||
# Note: The enumerations are mapped to Window's constants.
|
||||
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
type
|
||||
SslError* = object of Exception
|
||||
|
||||
@@ -54,7 +111,7 @@ type
|
||||
currPos: int # current index in buffer
|
||||
bufLen: int # current length of buffer
|
||||
of false: nil
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
case isSsl: bool
|
||||
of true:
|
||||
sslHandle: SSLPtr
|
||||
@@ -160,7 +217,7 @@ proc newSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM,
|
||||
raiseOSError(osLastError())
|
||||
result = newSocket(fd, domain, sockType, protocol, buffered)
|
||||
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
CRYPTO_malloc_init()
|
||||
SslLibraryInit()
|
||||
SslLoadErrorStrings()
|
||||
@@ -301,7 +358,7 @@ proc socketError*(socket: Socket, err: int = -1, async = false,
|
||||
## error was caused by no data being available to be read.
|
||||
##
|
||||
## If ``err`` is not lower than 0 no exception will be raised.
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if socket.isSSL:
|
||||
if err <= 0:
|
||||
var ret = SSLGetError(socket.sslHandle, err.cint)
|
||||
@@ -334,7 +391,7 @@ proc socketError*(socket: Socket, err: int = -1, async = false,
|
||||
raiseSSLError()
|
||||
else: raiseSSLError("Unknown Error")
|
||||
|
||||
if err == -1 and not (when defined(ssl): socket.isSSL else: false):
|
||||
if err == -1 and not (when defineSsl: socket.isSSL else: false):
|
||||
var lastE = if lastError.int == -1: getSocketError(socket) else: lastError
|
||||
if async:
|
||||
when useWinVersion:
|
||||
@@ -414,7 +471,7 @@ proc acceptAddr*(server: Socket, client: var Socket, address: var string,
|
||||
client.isBuffered = server.isBuffered
|
||||
|
||||
# Handle SSL.
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if server.isSSL:
|
||||
# We must wrap the client sock in a ssl context.
|
||||
|
||||
@@ -425,7 +482,7 @@ proc acceptAddr*(server: Socket, client: var Socket, address: var string,
|
||||
# Client socket is set above.
|
||||
address = $inet_ntoa(sockAddress.sin_addr)
|
||||
|
||||
when false: #defined(ssl):
|
||||
when false: #defineSsl:
|
||||
proc acceptAddrSSL*(server: Socket, client: var Socket,
|
||||
address: var string): SSLAcceptResult {.
|
||||
tags: [ReadIOEffect].} =
|
||||
@@ -444,7 +501,7 @@ when false: #defined(ssl):
|
||||
## ``AcceptNoClient`` will be returned when no client is currently attempting
|
||||
## to connect.
|
||||
template doHandshake(): stmt =
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if server.isSSL:
|
||||
client.setBlocking(false)
|
||||
# We must wrap the client sock in a ssl context.
|
||||
@@ -495,7 +552,7 @@ proc accept*(server: Socket, client: var Socket,
|
||||
proc close*(socket: Socket) =
|
||||
## Closes a socket.
|
||||
try:
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if socket.isSSL:
|
||||
ErrClearError()
|
||||
# As we are closing the underlying socket immediately afterwards,
|
||||
@@ -547,7 +604,7 @@ 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)
|
||||
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
proc handshake*(socket: Socket): bool {.tags: [ReadIOEffect, WriteIOEffect].} =
|
||||
## This proc needs to be called on a socket after it connects. This is
|
||||
## only applicable when using ``connectAsync``.
|
||||
@@ -594,7 +651,7 @@ proc hasDataBuffered*(s: Socket): bool =
|
||||
if s.isBuffered:
|
||||
result = s.bufLen > 0 and s.currPos != s.bufLen
|
||||
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if s.isSSL and not result:
|
||||
result = s.sslHasPeekChar
|
||||
|
||||
@@ -608,7 +665,7 @@ proc select(readfd: Socket, timeout = 500): int =
|
||||
|
||||
proc readIntoBuf(socket: Socket, flags: int32): int =
|
||||
result = 0
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if socket.isSSL:
|
||||
result = SSLRead(socket.sslHandle, addr(socket.buffer), int(socket.buffer.high))
|
||||
else:
|
||||
@@ -658,7 +715,7 @@ proc recv*(socket: Socket, data: pointer, size: int): int {.tags: [ReadIOEffect]
|
||||
|
||||
result = read
|
||||
else:
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if socket.isSSL:
|
||||
if socket.sslHasPeekChar:
|
||||
copyMem(data, addr(socket.sslPeekChar), 1)
|
||||
@@ -696,7 +753,7 @@ proc waitFor(socket: Socket, waited: var float, timeout, size: int,
|
||||
if timeout - int(waited * 1000.0) < 1:
|
||||
raise newException(TimeoutError, "Call to '" & funcName & "' timed out.")
|
||||
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if socket.isSSL:
|
||||
if socket.hasDataBuffered:
|
||||
# sslPeekChar is present.
|
||||
@@ -764,7 +821,7 @@ proc peekChar(socket: Socket, c: var char): int {.tags: [ReadIOEffect].} =
|
||||
|
||||
c = socket.buffer[socket.currPos]
|
||||
else:
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if socket.isSSL:
|
||||
if not socket.sslHasPeekChar:
|
||||
result = SSLRead(socket.sslHandle, addr(socket.sslPeekChar), 1)
|
||||
@@ -872,7 +929,7 @@ proc send*(socket: Socket, data: pointer, size: int): int {.
|
||||
##
|
||||
## **Note**: This is a low-level version of ``send``. You likely should use
|
||||
## the version below.
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if socket.isSSL:
|
||||
return SSLWrite(socket.sslHandle, cast[cstring](data), size)
|
||||
|
||||
@@ -943,7 +1000,7 @@ proc sendTo*(socket: Socket, address: string, port: Port,
|
||||
|
||||
proc isSsl*(socket: Socket): bool =
|
||||
## Determines whether ``socket`` is a SSL socket.
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
result = socket.isSSL
|
||||
else:
|
||||
result = false
|
||||
@@ -1253,7 +1310,7 @@ proc connect*(socket: Socket, address: string,
|
||||
dealloc(aiList)
|
||||
if not success: raiseOSError(lastError)
|
||||
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if socket.isSSL:
|
||||
# RFC3546 for SNI specifies that IP addresses are not allowed.
|
||||
if not isIpAddress(address):
|
||||
@@ -1314,7 +1371,7 @@ proc connect*(socket: Socket, address: string, port = Port(0),
|
||||
if selectWrite(s, timeout) != 1:
|
||||
raise newException(TimeoutError, "Call to 'connect' timed out.")
|
||||
else:
|
||||
when defined(ssl):
|
||||
when defineSsl:
|
||||
if socket.isSSL:
|
||||
socket.fd.setBlocking(true)
|
||||
doAssert socket.handshake()
|
||||
|
||||
Reference in New Issue
Block a user