Skip to content

Commit

Permalink
io.socket: created socket(), defines and basic test
Browse files Browse the repository at this point in the history
  • Loading branch information
YoSTEALTH committed Jun 11, 2024
1 parent 3322369 commit a9f2c2b
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 0 deletions.
109 changes: 109 additions & 0 deletions src/shakti/io/socket.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
from libc.errno cimport ENFILE
from liburing.lib.socket cimport *
from liburing.socket cimport io_uring_prep_socket, io_uring_prep_socket_direct_alloc
from liburing.error cimport raise_error
from ..event.entry cimport SQE


# defines
cpdef enum SocketFamily:
AF_UNIX = __AF_UNIX
AF_INET = __AF_INET
AF_INET6 = __AF_INET6

cpdef enum SocketType:
SOCK_STREAM = __SOCK_STREAM
SOCK_DGRAM = __SOCK_DGRAM
SOCK_RAW = __SOCK_RAW
SOCK_RDM = __SOCK_RDM
SOCK_SEQPACKET = __SOCK_SEQPACKET
SOCK_DCCP = __SOCK_DCCP
SOCK_PACKET = __SOCK_PACKET
SOCK_CLOEXEC = __SOCK_CLOEXEC
SOCK_NONBLOCK = __SOCK_NONBLOCK

cpdef enum ShutdownHow:
SHUT_RD = __SHUT_RD
SHUT_WR = __SHUT_WR
SHUT_RDWR = __SHUT_RDWR

cpdef enum SocketProto:
IPPROTO_IP = __IPPROTO_IP
IPPROTO_ICMP = __IPPROTO_ICMP
IPPROTO_IGMP = __IPPROTO_IGMP
IPPROTO_IPIP = __IPPROTO_IPIP
IPPROTO_TCP = __IPPROTO_TCP
IPPROTO_EGP = __IPPROTO_EGP
IPPROTO_PUP = __IPPROTO_PUP
IPPROTO_UDP = __IPPROTO_UDP
IPPROTO_IDP = __IPPROTO_IDP
IPPROTO_TP = __IPPROTO_TP
IPPROTO_DCCP = __IPPROTO_DCCP
IPPROTO_IPV6 = __IPPROTO_IPV6
IPPROTO_RSVP = __IPPROTO_RSVP
IPPROTO_GRE = __IPPROTO_GRE
IPPROTO_ESP = __IPPROTO_ESP
IPPROTO_AH = __IPPROTO_AH
IPPROTO_MTP = __IPPROTO_MTP
IPPROTO_BEETPH = __IPPROTO_BEETPH
IPPROTO_ENCAP = __IPPROTO_ENCAP
IPPROTO_PIM = __IPPROTO_PIM
IPPROTO_COMP = __IPPROTO_COMP
# note: not supported
# IPPROTO_L2TP = __IPPROTO_L2TP
IPPROTO_SCTP = __IPPROTO_SCTP
IPPROTO_UDPLITE = __IPPROTO_UDPLITE
IPPROTO_MPLS = __IPPROTO_MPLS
IPPROTO_ETHERNET = __IPPROTO_ETHERNET
IPPROTO_RAW = __IPPROTO_RAW
IPPROTO_MPTCP = __IPPROTO_MPTCP

# setsockopt & getsockopt start >>>
cpdef enum __socket_define__:
SOL_SOCKET = __SOL_SOCKET
SO_DEBUG = __SO_DEBUG
SO_REUSEADDR = __SO_REUSEADDR
SO_TYPE = __SO_TYPE
SO_ERROR = __SO_ERROR
SO_DONTROUTE = __SO_DONTROUTE
SO_BROADCAST = __SO_BROADCAST
SO_SNDBUF = __SO_SNDBUF
SO_RCVBUF = __SO_RCVBUF
SO_SNDBUFFORCE = __SO_SNDBUFFORCE
SO_RCVBUFFORCE = __SO_RCVBUFFORCE
SO_KEEPALIVE = __SO_KEEPALIVE
SO_OOBINLINE = __SO_OOBINLINE
SO_NO_CHECK = __SO_NO_CHECK
SO_PRIORITY = __SO_PRIORITY
SO_LINGER = __SO_LINGER
SO_BSDCOMPAT = __SO_BSDCOMPAT
SO_REUSEPORT = __SO_REUSEPORT
SO_PASSCRED = __SO_PASSCRED
SO_PEERCRED = __SO_PEERCRED
SO_RCVLOWAT = __SO_RCVLOWAT
SO_SNDLOWAT = __SO_SNDLOWAT
SO_BINDTODEVICE = __SO_BINDTODEVICE

# Socket filtering
SO_ATTACH_FILTER = __SO_ATTACH_FILTER
SO_DETACH_FILTER = __SO_DETACH_FILTER
SO_GET_FILTER = __SO_GET_FILTER
SO_PEERNAME = __SO_PEERNAME
SO_ACCEPTCONN = __SO_ACCEPTCONN
SO_PEERSEC = __SO_PEERSEC
SO_PASSSEC = __SO_PASSSEC
SO_MARK = __SO_MARK
SO_PROTOCOL = __SO_PROTOCOL
SO_DOMAIN = __SO_DOMAIN
SO_RXQ_OVFL = __SO_RXQ_OVFL
SO_WIFI_STATUS = __SO_WIFI_STATUS
SCM_WIFI_STATUS = __SCM_WIFI_STATUS
SO_PEEK_OFF = __SO_PEEK_OFF

# not tested
SO_TIMESTAMP = __SO_TIMESTAMP
SO_TIMESTAMPNS = __SO_TIMESTAMPNS
SO_TIMESTAMPING = __SO_TIMESTAMPING
SO_RCVTIMEO = __SO_RCVTIMEO
SO_SNDTIMEO = __SO_SNDTIMEO
# setsockopt & getsockopt end <<<
23 changes: 23 additions & 0 deletions src/shakti/io/socket.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
async def socket(int family=__AF_INET, int type=__SOCK_STREAM, int protocol=0, unsigned int flags=0,
*, bint direct=False)-> int:
''' Create Socket
Example
>>> sock_fd = await socket(AF_INET, SOCK_STREAM)
Note
- Setting `direct=True` will return direct descriptor index.
'''
cdef SQE sqe = SQE(error=False)
if direct:
io_uring_prep_socket_direct_alloc(sqe, family, type, protocol, flags)
else:
io_uring_prep_socket(sqe, family, type, protocol, flags)
await sqe
if sqe.result > -1:
return sqe.result # `fd` or `index`
else:
if direct and sqe.result == -ENFILE:
raise_error(sqe.result, 'Either file table is full or register file not enabled!')
raise_error(sqe.result)

24 changes: 24 additions & 0 deletions test/io/socket_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import pytest
import shakti


def test_socket():
shakti.run(
socket()
)


async def socket():
# file descriptor
assert (sock_fd1 := await shakti.socket()) > 0 # shakti.AF_INET, shakti.SOCK_STREAM
assert (sock_fd2 := await shakti.socket(shakti.AF_UNIX, shakti.SOCK_DGRAM)) > sock_fd1
await shakti.close(sock_fd1)
await shakti.close(sock_fd2)

# direct descriptor without register
with pytest.raises(OSError, match='Either file table is full or register file not enabled!'):
assert await shakti.socket(direct=True)

# TODO: direct descriptor with register
# assert (sock_fd := await shakti.socket(direct=True)) == 0
# await shakti.close(sock_fd, True)

0 comments on commit a9f2c2b

Please sign in to comment.