summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorflywind <43030857+xflywind@users.noreply.github.com>2020-09-09 18:47:22 +0800
committerGitHub <noreply@github.com>2020-09-09 12:47:22 +0200
commit8c82144ba507244084836b38689e4925de982626 (patch)
treea1f6839815344f6f5073ccda33ad4bc7155f18b9
parent7d4f0df107fdce5d1da93e26e54dd87526a0a74f (diff)
downloadNim-8c82144ba507244084836b38689e4925de982626.tar.gz
add getprotobyname (#15273)
* add getprotobyname

* tests, docs, changelog

* add since
-rw-r--r--changelog.md3
-rw-r--r--lib/pure/nativesockets.nim14
-rw-r--r--lib/windows/winlean.nim14
-rw-r--r--tests/stdlib/tgetprotobyname.nim25
4 files changed, 56 insertions, 0 deletions
diff --git a/changelog.md b/changelog.md
index 58efc42e6..2f7b584a3 100644
--- a/changelog.md
+++ b/changelog.md
@@ -168,6 +168,9 @@
   cannot be applied to every use case. The limitations and the (lack of) reliability
   of `round` are well documented.
 
+- Add `getprotobyname` to `winlean`. Add `getProtoByname` to `nativesockets` which returns a protocol code
+  from the database that matches the protocol `name`.
+
 
 
 ## Language changes
diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim
index e38dc2ecd..1f597f8eb 100644
--- a/lib/pure/nativesockets.nim
+++ b/lib/pure/nativesockets.nim
@@ -13,6 +13,8 @@
 # TODO: Clean up the exports a bit and everything else in general.
 
 import os, options
+import std/private/since
+
 
 when hostOS == "solaris":
   {.passl: "-lsocket -lnsl".}
@@ -199,6 +201,18 @@ proc toSockType*(protocol: Protocol): SockType =
   of IPPROTO_IP, IPPROTO_IPV6, IPPROTO_RAW, IPPROTO_ICMP, IPPROTO_ICMPV6:
     SOCK_RAW
 
+proc getProtoByName*(name: string): int {.since: (1, 3, 5).} =
+  ## Returns a protocol code from the database that matches the protocol ``name``.
+  when useWinVersion:
+    let protoent = winlean.getprotobyname(name.cstring)
+  else:
+    let protoent = posix.getprotobyname(name.cstring)
+  
+  if protoent == nil:
+    raise newException(OsError, "protocol not found")
+
+  result = protoent.p_proto.int
+
 proc close*(socket: SocketHandle) =
   ## Closes a socket.
   when useWinVersion:
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index c28700374..1334a85d5 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -96,6 +96,12 @@ type
     dwPlatformId*: DWORD
     szCSDVersion*: array[0..127, WinChar]
 
+  Protoent* = object
+    p_name*: cstring
+    p_aliases*: cstringArray
+    p_proto*: cshort
+
+
 const
   STARTF_USESHOWWINDOW* = 1'i32
   STARTF_USESTDHANDLES* = 256'i32
@@ -573,6 +579,14 @@ proc gethostbyname*(name: cstring): ptr Hostent {.
 proc gethostname*(hostname: cstring, len: cint): cint {.
   stdcall, importc: "gethostname", dynlib: ws2dll, sideEffect.}
 
+proc getprotobyname*(
+  name: cstring
+): ptr Protoent {.stdcall, importc: "getprotobyname", dynlib: ws2dll, sideEffect.}
+
+proc getprotobynumber*(
+  proto: cint
+): ptr Protoent {.stdcall, importc: "getprotobynumber", dynlib: ws2dll, sideEffect.}
+
 proc socket*(af, typ, protocol: cint): SocketHandle {.
   stdcall, importc: "socket", dynlib: ws2dll.}
 
diff --git a/tests/stdlib/tgetprotobyname.nim b/tests/stdlib/tgetprotobyname.nim
new file mode 100644
index 000000000..c3d8da0d8
--- /dev/null
+++ b/tests/stdlib/tgetprotobyname.nim
@@ -0,0 +1,25 @@
+discard """
+  cmd:      "nim c -r --styleCheck:hint --panics:on $options $file"
+  targets:  "c"
+  nimout:   ""
+  action:   "run"
+  exitcode: 0
+  timeout:  60.0
+"""
+
+import nativesockets
+
+
+doAssert getProtoByName("ip") == 0
+doAssert getProtoByName("ipv6") == 41
+doAssert getProtoByName("tcp") == 6
+doAssert getProtoByName("udp") == 17
+doAssert getProtoByName("icmp") == 1
+doAssert getProtoByName("ipv6-icmp") == 58
+
+when defined(windows):
+  doAssertRaises(OSError):
+    discard getProtoByName("raw")
+
+doAssertRaises(OSError):
+  discard getProtoByName("Error")