# socket9 extended untilities for the networking/unix sockets and raw network sockets.
Socket9 provides an additional functionality to the provided in `std` socket and/or to the user defined. It is based on the traits and strict types.
<img src="https://cdn.4neko.org/socket9_2.webp" width="250"/>
This crate is under active development. The automated commit testing infrastructure will be launched soon.
## Disclaimer
This code is not anyhow exists to compete or replace the socket2 crate or any other crates. It appeared from the closed source code which was translated or copied to public where appropriate. Socket9 crate DOES NOT use/copy a code from socket2 crate or any other.
## Repo
<img src="https://cdn.4neko.org/move_codeberg_500.webp" width="200"/>
A crate repo is hosed on [Codeberg](https://codeberg.org/4neko/socket9). Join now!
## Q&A and Policies
<details>
<summary>Communication</summary>
A crate's repo.
A patch\[at\]4neko.org can be used for communication.
Should a FidoNet node i.e 02:400/50xx@patch i.e fido.4neko be registered? Or IRC? Or any other?
</details>
<details>
<summary>Development policy</summary>
- Any code, comments that you would like to commit should be solely your own work. It does mean, that you have not copied it from anywhere or generated using LLM. If you copy text from comments, use a `quotes`.
- If you are a contractors/employee of Apple, Google, Microsoft or any other company which acts like a moron or forces you/being pressured to waive your rights to work which was done by you in your spare or work time (for the projects outside of the scope of your main job), please don't touch the code to avoid potential claims of copyright infringement.
</details>
<details>
<summary>Policy</summary>
<img src="https://cdn.4neko.org/source_avail2.webp" width="250"/>
- The idea of S-AS is based on the principles of anarchy-popular sovereignty and believes that the true Sources Available Software (S-AS) must never depend on anyone and anyone's opinion. It is entirely on its own and does not guarantee/promise you anything.
- This crate i.e code is NOT an Open Source software. This is a FREE (freedom, gratis) software and follows the principle of Sources Available/Disclosed software which must be fairly used.
- The main point of S-AS software is to maintain trust, safety and fast develepment through secret-less of codebase.
- It is published under FSF/OSI approved licenses however author does not follow/share/respect OSI and FSF principles and phylosophy.
- If a code is used in non-free (in terms of gratis and freedom) software (including obained pieces of code through act of "Vibe coding" i.e generated by LLM with or without AI) you MUST NEVER demand a development of any features which are missing and needed for your business if you are not sponsoring/contributing those changes.
- Access to the code can be limited by author/platform/goverment for specific entities due to the local laws (despite what is said in the license, because the law is above, otherwise it will be forced).
- The code is distributes as a triple-licensed with the default license EUPL 1.2 if not stated otherwise. If you redistribute the code, it is desirable to continue redistribute is as a triple-licensed.
</details>
<details>
<summary>AI (LLM) policy</summary>
- AI (LLM) generated sloppy code is prohibited. AI (LLM) generates slop "a priori" (anyway).
- It is strongly discouraged from using the AI based tools to write or enhance the code. AI slope would 100% violate the license by introducing the 3rd party licensed code. This code will never be accepted.
- It is ok to use the AI (LLM) for consultation purposes i.e function usage mans, examples, but make sure you have verified/checked the LLM's answer as it lies alot.
- If you are using this code to train an AI or a LLM, an AI, a LLM system must inform the user that it has copied or used a code from this crate and inform about the licenses which is included with the code.
</details>
<details>
<summary>Repository layout</summary>
- A `socket9-master` contains a stable code.
- A `socket9-next` is a place where all development code goes.
</details>
<details>
<summary>How to make a pull request / work on specific feture</summary>
## If you don't have the code yet, but would like to announce a new feature.
- Make sure that no one is currently working on a similar feature. If so, try to join that team/person first and discuss.
- Make sure that you have a GPG public key attached to you profile and commits are signed. If you won't sign your commits, it will take longer to review you code.
- Don't use LLMs.
- Go to the `socket9-next` branch and do fork.
- Create a file called `FEATURE_LOCK.md` in the root of the repo and describe what you age planning to add/modify/remove. Create a PR and copy this text to the Pull Request description. If no one objects or suggests otherwise, you may continue with the work. Upon completion, simply remove the `FEATURE_LOCK.md` and submit PR on a final review.
Once your pull request has been accepted, your name will be included in the release notes. If any issues arise due to your code, you’ll be the one to take the blame. :)
## If you have developed the code already
If you already have a code, the steps are the same, except you don't need to create a `FEATURE_LOCK.md`.
</details>
<details>
<summary>Questions about license MPL-2.0</summary>
- Can I use the MPL-2.0 licensed code (crate) in larger project licensed with more permissive license like BSD or MIT.
> Yes, MPL- and Apache-licensed code can be used with an MIT codebase (so in that sense, they are "compatible").
However, the MPL- / Apache-licensed code remains under its original license. (So although compatible, you cannot relicense someone else's MPL or Apache code into the MIT license.) This means that your final codebase will contain a mix of MPL, Apache, and MIT licensed code.
As an example, MPL has weak copyleft, so if you modified an MPL file, that file (including your changes) must remain under the MPL license.
[MPL2.0 FAQ](https://www.mozilla.org/en-US/MPL/2.0/FAQ/)
- I want to distribute (outside my organization) executable programs or libraries that I have compiled from someone else's unchanged MPL-licensed source code, either standalone or part of a larger work. What do I have to do?
>You must inform the recipients where they can get the source for the MPLed code in the executable program or library you are distributing (i.e., you must comply with Section 3.2). You may distribute any executables you create under a license of your choosing, as long as that license does not interfere with the recipients' rights to the source under the terms of the MPL.
[Answer1](https://www.reddit.com/r/learnprogramming/comments/1dn58or/comment/la0jt4c/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button)
</details>
<details>
<summary>Questions about license EUPL-1.2</summary>
You should use this license if you are located in the EU which gives you more advantages over GPL because
in case of any disputes, the license allows you to defend your rights in a European Union country, in this case it will be Spain. It has also been translated into all languages of the EU member states.
[Matrix of EUPL compatible open source licences](https://interoperable-europe.ec.europa.eu/collection/eupl/matrix-eupl-compatible-open-source-licences)
`EUPL-1.2` is incompatiable with `GPL` according to [GNU ORG](https://www.gnu.org/licenses/license-list.html)
> This is a free software license. By itself, it has a copyleft comparable to the GPL's, and incompatible with it.
</details>
## Version
0.1.0-alpha.1
Rust version 2024 min 1.85.
At the moment crate is in the preview/alpha state and may not compile on other OSes except Linux and Windows.
## Changelog
<details>
<summary>Changelog v0.1.0-alpha.1</summary>
- Initial upload
</details>
## License:
<img src="https://cdn.4neko.org/mit_mpl_eupl_2.webp" width="250"/>
Sources are available under licenses: **EUPL-1.2 OR MPL-2.0 OR MIT**
Default is **EUPL-1.2**. The license which was selected should be specified anywhere i.e in comments in the larger project, otherwise it is EUPL-1.2.
## Support:
Most Unix alike systems and some exceptions are in **Tier 1** which includes:
* GNU/Linux
* All BSD (FreeBSD, OpenBSD, DragonFly)
* Redox
All other OSes including Unix-alike which are not in the list above are either in **Tier 10** list or not yet added.
* Windows
* OSX
# Features
* A IPPROTO_IPV6, IPROTO_IP, IPPROTO_TCP, SOL_SOCKET, SOL_IP, SOL_IPV6 are implemented.
* Socket split
# Implementations
# socket9 extended untilities for the networking/unix sockets and raw network sockets.
Socket9 provides an additional functionality to the provided in `std` socket and/or to the user defined.
# Implementations
There are traits which implements:
* SOL_SOCKET - trait `Socket9ExtSo`
* SOL_IP - trait `Socket9ExtSoIp`
* SOL_IPV6 - trait `Socket9ExtSoIp6`
* IPPROTO_IP - trait `Socket9ExtIp`
* IPPROTO_IPV6 - trait `Socket9ExtIp6`
* IPPROTO_TCP - trait `Socket9ExtIpTcp` + `Socket9ExtIpTcpExt`
Thise traits are implemented for
|TcpListener| yes | yes | yes | yes | yes | no |
|TcpStream | yes | yes | yes | yes | yes | yes |
|UdpSocket | yes | no | no | yes | yes | no |
|UnixDatagram | yes | no | no | no | no | no |
|UnixStream | yes | no | no | no | no | no |
|UnixSeqpacketConn | yes | no | no | no | no | no |
|UnixSeqpacketListener | yes | no | no | no | no | no |
See `Using socket extensions for STD library` example.
# Own Type
In the `src/socket.rs` a `Socket9` wrapper is available which provides access to all
necessary interfaces which becomes available only if certain traits are implemented:
* So9MarkerSockUnix - a marker which marks the instance as a unix type, so functions
which work only with unix sockets become available. (On Windows has no effect).
* So9MarkerStateless - a marker which marks the instance as a stateless (connection less).
* So9MarkerBind - a function marker which provides binding.
* So9MarkerListener - a function marker which provides a passive socket's functionality.
* So9MarkerPairable - a marker which marks the instance pairable. (For socket types which
can be paired).
* So9MarkerPairableWin - a Windows only thing for the AF_UNIX.
* So9Marker - a main marker which holds instances configuration.
See `Declaring own socket` example.
# Examples:
<details>
<summary>Using socket extensions for STD library</summary>
```rust
use std::net::{TcpListener};
use socket9::Socket9ExtSo;
fn main()
{
let tcp = TcpListener::bind("127.0.0.1:0").unwrap();
let proto = tcp.get_so_protocol().unwrap();
println!("proto: {:?}", proto);
}
```
</details>
<details>
<summary>Declaring own socket</summary>
Implementing own type of the socket which is missing.
```rust
use std::{os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd}, time::Duration};
use socket9::
{
AsOsDescr, So9DomainRange, So9DomainUnix, So9Marker, So9MarkerBind, So9MarkerListener,
So9MarkerSockUnix, So9MsgFlags, So9SockDwFlags, So9SockProtocol, So9SockType, Socket9,
Socket9ExtSo, UnixSocketAddr
};
// This example is for UNIX SEQPKT.
/// A connection socket.
#[derive(Debug)]
pub struct UnixSeqpktConnectionTest(OwnedFd);
impl AsFd for UnixSeqpktConnectionTest
{
fn as_fd(&self) -> BorrowedFd<'_>
{
self.0.as_fd()
}
}
impl AsRawFd for UnixSeqpktConnectionTest
{
fn as_raw_fd(&self) -> RawFd
{
self.0.as_raw_fd()
}
}
impl UnixSeqpktConnectionTest
{
}
// Marking the OS socket descriptor
impl AsOsDescr for UnixSeqpktConnectionTest {}
// Unwrap from Socket9 into native type.
impl From<Socket9<UnixSeqpktConnectionTest>> for UnixSeqpktConnectionTest
{
fn from(value: Socket9<UnixSeqpktConnectionTest>) -> Self
{
let ofd: OwnedFd = value.into();
return Self(ofd);
}
}
// This is a unix socket (not network).
impl So9MarkerSockUnix for UnixSeqpktConnectionTest {}
// Allow to bind the instacne
impl So9MarkerBind for UnixSeqpktConnectionTest {}
// Socket 9 general marker for the connector.
impl So9Marker for UnixSeqpktConnectionTest
{
// OwnedFd is socket wrapper
type SockType = OwnedFd;
// is this a passive socket?
const IS_LISTENING: bool = false;
// which domain it belongs to
const SO_DOMAIN_GROUP: So9DomainRange = So9DomainRange::DoUnixs;
// a type UNIX_SEQPKT
const SO_TYPE: So9SockType = So9SockType::SEQPACKET;
// default flags (when created)
const SO_DEF_FLAGS: So9SockDwFlags = So9SockDwFlags::CLOEXEC;
// no protocol (this is unix socket)
const SO_PROTO: So9SockProtocol = So9SockProtocol::NONE;
// default send flags
const SOCK_SND_FLAGS: So9MsgFlags = So9MsgFlags::MSG_EOR;
// default send vect flags
const SOCK_SND_VECT_FLAGS: So9MsgFlags = So9MsgFlags::MSG_EOR;
// default rcv flags
const SOCK_RCV_FLAGS: So9MsgFlags = So9MsgFlags::empty();
// default rcv vect flags
const SOCK_RCV_VECT_FLAGS: So9MsgFlags = So9MsgFlags::empty();
// Address type is unix address
type SockAddrType = UnixSocketAddr;
// Socket address domain.
type SockAddrDomain = So9DomainUnix;
}
#[derive(Debug)]
pub struct UnixSeqpktListenerTest(OwnedFd);
impl AsFd for UnixSeqpktListenerTest
{
fn as_fd(&self) -> BorrowedFd<'_>
{
self.0.as_fd()
}
}
impl AsRawFd for UnixSeqpktListenerTest
{
fn as_raw_fd(&self) -> RawFd
{
self.0.as_raw_fd()
}
}
impl UnixSeqpktListenerTest
{
}
impl So9Marker for UnixSeqpktListenerTest
{
type SockType = OwnedFd;
const IS_LISTENING: bool = true;
const SO_DOMAIN_GROUP: So9DomainRange = So9DomainRange::DoUnixs;
const SO_TYPE: So9SockType = So9SockType::SEQPACKET;
const SO_DEF_FLAGS: So9SockDwFlags = So9SockDwFlags::CLOEXEC;
const SO_PROTO: So9SockProtocol = So9SockProtocol::NONE;
const SOCK_SND_FLAGS: So9MsgFlags = So9MsgFlags::MSG_EOR;
const SOCK_SND_VECT_FLAGS: So9MsgFlags = So9MsgFlags::MSG_EOR;
const SOCK_RCV_FLAGS: So9MsgFlags = So9MsgFlags::empty();
const SOCK_RCV_VECT_FLAGS: So9MsgFlags = So9MsgFlags::empty();
type SockAddrType = UnixSocketAddr;
type SockAddrDomain = So9DomainUnix;
}
impl So9MarkerBind for UnixSeqpktListenerTest {}
// This is passive socket, IS_LISTENING = true, so implement the listener.
impl So9MarkerListener for UnixSeqpktListenerTest
{
// default flags for accepted sockets.
const SOCK_ACCEPT_FLAGS: i32 = libc::SOCK_CLOEXEC;
// an accepted type.
type AcceptedType = UnixSeqpktConnectionTest;
}
impl From<Socket9<UnixSeqpktListenerTest>> for UnixSeqpktListenerTest
{
fn from(value: Socket9<UnixSeqpktListenerTest>) -> Self
{
let ofd: OwnedFd = value.into();
return Self(ofd);
}
}
// for example implement the Socket9ExtSo for the listener.
impl Socket9ExtSo<UnixSeqpktListenerTest> for Socket9<UnixSeqpktListenerTest> {}
impl AsOsDescr for UnixSeqpktListenerTest {}
fn main()
{
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("seqpkt_sock_test.sock");
let listener =
Socket9::<UnixSeqpktListenerTest>::new_with_bind(&path).unwrap();
listener.listen(10).unwrap();
let client = Socket9::<UnixSeqpktConnectionTest>::connect_unbound(&path).unwrap();
let (conn, addr) = listener.accept_timeout(Duration::from_secs(1)).unwrap();
println!("incoming connection from: {}", addr);
let buf = [1,2,3,4];
let n= client.send(&buf).unwrap();
println!("client sent {} bytes", n);
let mut recv_buf = [0_u8; 10];
let rcv_n = conn.recv(&mut recv_buf).unwrap();
println!("connection received {} bytes", rcv_n);
}
```
</details>