Compare commits
6 Commits
i2p-rs-1.1
...
master
Author | SHA1 | Date | |
---|---|---|---|
8f8948b89d | |||
0e8d8a2959 | |||
87b140e3b4 | |||
fbde12b629 | |||
286b06d2c4 | |||
1d4ce43a70 |
66
.github/workflows/sync.yaml
vendored
Normal file
66
.github/workflows/sync.yaml
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
# GitHub Actions workflow file to sync an external repository to this GitHub mirror.
|
||||
# This file was automatically generated by go-github-sync.
|
||||
#
|
||||
# The workflow does the following:
|
||||
# - Runs on a scheduled basis (and can also be triggered manually)
|
||||
# - Clones the GitHub mirror repository
|
||||
# - Fetches changes from the primary external repository
|
||||
# - Applies those changes to the mirror repository
|
||||
# - Pushes the updated content back to the GitHub mirror
|
||||
#
|
||||
# Authentication is handled by the GITHUB_TOKEN secret provided by GitHub Actions.
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Validate Github Actions Environment
|
||||
run: if [ "$GITHUB_ACTIONS" != "true" ]; then echo 'This script must be run in a GitHub Actions environment.'; exit 1; fi
|
||||
- name: Checkout GitHub Mirror
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Configure Git
|
||||
run: |-
|
||||
git config user.name 'GitHub Actions'
|
||||
git config user.email 'actions@github.com'
|
||||
- env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: Sync Primary Repository
|
||||
run: |-
|
||||
# Add the primary repository as a remote
|
||||
git remote add primary https://i2pgit.org/I2P_Developers/i2p-rs.git
|
||||
|
||||
# Fetch the latest changes from the primary repository
|
||||
git fetch primary
|
||||
|
||||
# Check if the primary branch exists in the primary repository
|
||||
if git ls-remote --heads primary master | grep -q master; then
|
||||
echo "Primary branch master found in primary repository"
|
||||
else
|
||||
echo "Error: Primary branch master not found in primary repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if we're already on the mirror branch
|
||||
if git rev-parse --verify --quiet master; then
|
||||
git checkout master
|
||||
else
|
||||
# Create the mirror branch if it doesn't exist
|
||||
git checkout -b master
|
||||
fi
|
||||
|
||||
|
||||
# Force-apply all changes from primary, overriding any conflicts
|
||||
echo "Performing force sync from primary/master to master"
|
||||
git reset --hard primary/master
|
||||
|
||||
|
||||
# Push changes back to the mirror repository
|
||||
git push origin master
|
||||
name: Sync Primary Repository to GitHub Mirror
|
||||
"on":
|
||||
push: {}
|
||||
schedule:
|
||||
- cron: 0 * * * *
|
||||
workflow_dispatch: {}
|
@ -3,6 +3,7 @@ use std::net::{SocketAddr, ToSocketAddrs};
|
||||
use crate::error::{Error, ErrorKind};
|
||||
use crate::net::{I2pSocketAddr, ToI2pSocketAddrs};
|
||||
use crate::sam::DEFAULT_API;
|
||||
use crate::sam_options::SAMOptions;
|
||||
|
||||
/// Unimplemented
|
||||
///
|
||||
@ -51,19 +52,21 @@ impl I2pDatagramSocket {
|
||||
/// let socket = I2pDatagramSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// ```
|
||||
pub fn bind<A: ToI2pSocketAddrs>(addr: A) -> Result<I2pDatagramSocket, Error> {
|
||||
I2pDatagramSocket::bind_via(DEFAULT_API, addr)
|
||||
I2pDatagramSocket::bind_via(DEFAULT_API, addr, SAMOptions::default())
|
||||
}
|
||||
|
||||
pub fn bind_via<A: ToSocketAddrs, B: ToI2pSocketAddrs>(
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
options: SAMOptions
|
||||
) -> Result<I2pDatagramSocket, Error> {
|
||||
super::each_i2p_addr(sam_addr, addr, I2pDatagramSocket::bind_addr).map_err(|e| e.into())
|
||||
super::each_i2p_addr(sam_addr, addr, options,I2pDatagramSocket::bind_addr).map_err(|e| e.into())
|
||||
}
|
||||
|
||||
fn bind_addr(
|
||||
_sam_addr: &SocketAddr,
|
||||
_addr: &I2pSocketAddr,
|
||||
_options: SAMOptions
|
||||
) -> Result<I2pDatagramSocket, Error> {
|
||||
unimplemented!();
|
||||
}
|
||||
@ -175,15 +178,16 @@ impl I2pDatagramSocket {
|
||||
/// socket.connect("127.0.0.1:8080").expect("connect function failed");
|
||||
/// ```
|
||||
pub fn connect<A: ToI2pSocketAddrs>(&self, addr: A) -> Result<(), Error> {
|
||||
self.connect_via(DEFAULT_API, addr)
|
||||
self.connect_via(DEFAULT_API, addr, SAMOptions::default())
|
||||
}
|
||||
|
||||
pub fn connect_via<A: ToSocketAddrs, B: ToI2pSocketAddrs>(
|
||||
&self,
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
options: SAMOptions,
|
||||
) -> Result<(), Error> {
|
||||
super::each_i2p_addr(sam_addr, addr, |_sam_addr, _addr| unimplemented!())
|
||||
super::each_i2p_addr(sam_addr, addr, options, |_sam_addr, _addr, _opts| unimplemented!())
|
||||
}
|
||||
|
||||
/// Sends data on the socket to the remote address to which it is connected.
|
||||
|
@ -1,10 +1,11 @@
|
||||
use crate::error::{Error, ErrorKind};
|
||||
use crate::sam_options::SAMOptions;
|
||||
use std::net::{SocketAddr, ToSocketAddrs};
|
||||
|
||||
pub use self::addr::{I2pSocketAddr, ToI2pSocketAddrs};
|
||||
pub use self::datagram::I2pDatagramSocket;
|
||||
pub use self::i2p::I2pAddr;
|
||||
pub use self::streaming::{I2pListener, I2pStream};
|
||||
pub use self::streaming::{I2pListenerBuilder, I2pListener, I2pStream};
|
||||
|
||||
mod addr;
|
||||
mod datagram;
|
||||
@ -16,15 +17,16 @@ mod test;
|
||||
fn each_i2p_addr<A: ToSocketAddrs, B: ToI2pSocketAddrs, F, T>(
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
opts: SAMOptions,
|
||||
mut f: F,
|
||||
) -> Result<T, Error>
|
||||
where
|
||||
F: FnMut(&SocketAddr, &I2pSocketAddr) -> Result<T, Error>,
|
||||
F: FnMut(&SocketAddr, &I2pSocketAddr, SAMOptions) -> Result<T, Error>,
|
||||
{
|
||||
let mut last_err = None;
|
||||
for addr in addr.to_socket_addrs()? {
|
||||
for sam_addr in sam_addr.to_socket_addrs()? {
|
||||
match f(&sam_addr, &addr) {
|
||||
match f(&sam_addr, &addr, opts.clone()) {
|
||||
Ok(l) => return Ok(l),
|
||||
Err(e) => last_err = Some(e),
|
||||
}
|
||||
@ -33,13 +35,13 @@ where
|
||||
Err(last_err.unwrap_or(ErrorKind::UnresolvableAddress.into()))
|
||||
}
|
||||
|
||||
fn each_addr<A: ToSocketAddrs, F, T>(sam_addr: A, mut f: F) -> Result<T, Error>
|
||||
fn each_addr<A: ToSocketAddrs, F, T>(sam_addr: A, opts: SAMOptions, mut f: F) -> Result<T, Error>
|
||||
where
|
||||
F: FnMut(&SocketAddr) -> Result<T, Error>,
|
||||
F: FnMut(&SocketAddr, SAMOptions) -> Result<T, Error>,
|
||||
{
|
||||
let mut last_err = None;
|
||||
for sam_addr in sam_addr.to_socket_addrs()? {
|
||||
match f(&sam_addr) {
|
||||
match f(&sam_addr, opts.clone()) {
|
||||
Ok(l) => return Ok(l),
|
||||
Err(e) => last_err = Some(e),
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use std::time::Duration;
|
||||
use crate::error::{Error, ErrorKind};
|
||||
use crate::net::{I2pAddr, I2pSocketAddr, ToI2pSocketAddrs};
|
||||
use crate::sam::{Session, StreamConnect, StreamForward, DEFAULT_API};
|
||||
use crate::sam_options::SAMOptions;
|
||||
|
||||
/// A structure which represents an I2P stream between a local socket and a
|
||||
/// remote socket.
|
||||
@ -74,7 +75,7 @@ impl I2pStream {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn connect<A: ToI2pSocketAddrs>(addr: A) -> Result<I2pStream, Error> {
|
||||
I2pStream::connect_via(DEFAULT_API, addr)
|
||||
I2pStream::connect_via(DEFAULT_API, addr, SAMOptions::default())
|
||||
}
|
||||
|
||||
/// Same as `connect` but reuses an existing SAM session.
|
||||
@ -92,12 +93,13 @@ impl I2pStream {
|
||||
pub fn connect_via<A: ToSocketAddrs, B: ToI2pSocketAddrs>(
|
||||
sam_addr: A,
|
||||
addr: B,
|
||||
options: SAMOptions,
|
||||
) -> Result<I2pStream, Error> {
|
||||
super::each_i2p_addr(sam_addr, addr, I2pStream::connect_addr).map_err(|e| e.into())
|
||||
super::each_i2p_addr(sam_addr, addr, options, I2pStream::connect_addr).map_err(|e| e.into())
|
||||
}
|
||||
|
||||
fn connect_addr(sam_addr: &SocketAddr, addr: &I2pSocketAddr) -> Result<I2pStream, Error> {
|
||||
let stream = StreamConnect::new(sam_addr, &addr.dest().string(), addr.port())?;
|
||||
fn connect_addr(sam_addr: &SocketAddr, addr: &I2pSocketAddr, options: SAMOptions) -> Result<I2pStream, Error> {
|
||||
let stream = StreamConnect::new(sam_addr, &addr.dest().string(), addr.port(), options)?;
|
||||
|
||||
Ok(I2pStream { inner: stream })
|
||||
}
|
||||
@ -295,11 +297,11 @@ impl I2pListener {
|
||||
}
|
||||
|
||||
pub fn bind_via<A: ToSocketAddrs>(sam_addr: A) -> Result<I2pListener, Error> {
|
||||
super::each_addr(sam_addr, I2pListener::bind_addr).map_err(|e| e.into())
|
||||
super::each_addr(sam_addr, SAMOptions::default(), I2pListener::bind_addr).map_err(|e| e.into())
|
||||
}
|
||||
|
||||
fn bind_addr(sam_addr: &SocketAddr) -> Result<I2pListener, Error> {
|
||||
let forward = StreamForward::new(sam_addr)?;
|
||||
fn bind_addr(sam_addr: &SocketAddr, options: SAMOptions) -> Result<I2pListener, Error> {
|
||||
let forward = StreamForward::new(sam_addr, options)?;
|
||||
Ok(I2pListener { forward })
|
||||
}
|
||||
|
||||
@ -397,3 +399,103 @@ impl<'a> Iterator for Incoming<'a> {
|
||||
Some(self.listener.accept().map(|p| p.0))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A helper struct for creating `I2pListener`s.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use i2p::net::{I2pListenerBuilder, I2pStream};
|
||||
///
|
||||
/// let listener = I2pListenerBuilder::new().build()?;
|
||||
///
|
||||
/// fn handle_client(stream: I2pStream) {
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// // accept connections and process them serially
|
||||
/// for stream in listener.incoming() {
|
||||
/// match stream {
|
||||
/// Ok(stream) => {
|
||||
/// handle_client(stream);
|
||||
/// }
|
||||
/// Err(e) => { /* connection failed */ }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub struct I2pListenerBuilder {
|
||||
session: Option<Session>,
|
||||
addrs: Vec<SocketAddr>,
|
||||
options: SAMOptions,
|
||||
}
|
||||
|
||||
impl Default for I2pListenerBuilder {
|
||||
fn default() -> Self {
|
||||
I2pListenerBuilder {
|
||||
session: None,
|
||||
addrs: vec![],
|
||||
options: Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl I2pListenerBuilder {
|
||||
|
||||
/// Build an `I2pListener` and bind to socket addresses using previously
|
||||
/// defined settings.
|
||||
///
|
||||
/// If none of `with_session`, `with_addr` or `with_addrs` were called, the
|
||||
/// listener will bind to `crate::sam::DEFAULT_API`.
|
||||
///
|
||||
/// If `with_options` was not called, defaults to `SAMOptions::default()`
|
||||
///
|
||||
/// If `with_session` was called, all other settings will be ignored.
|
||||
pub fn build(mut self) -> Result<I2pListener, Error> {
|
||||
if let Some(s) = self.session {
|
||||
Ok(I2pListener {
|
||||
forward: StreamForward::with_session(&s)?
|
||||
})
|
||||
}
|
||||
else {
|
||||
// Default to DEFAULT_API if no socket address has been set manually
|
||||
if self.addrs.len() == 0 {
|
||||
self.addrs.extend(ToSocketAddrs::to_socket_addrs(DEFAULT_API)?);
|
||||
}
|
||||
super::each_addr(
|
||||
self.addrs.as_slice(),
|
||||
self.options,
|
||||
I2pListener::bind_addr
|
||||
).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes this builder recreate an I2pListener from the specified session.
|
||||
/// According to the SAMv3 protocol, SAM options can only be set upon
|
||||
/// session creation. Therefore, `I2pListenerBuilder::build(...)` will
|
||||
/// ignore any options set using `with_options` if recreating a listener
|
||||
/// using a previous session.
|
||||
pub fn with_session(mut self, session: Session) -> Self {
|
||||
self.session = Some(session);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add `address` to the list of socket addresses to bind to
|
||||
pub fn with_addr(mut self, address: SocketAddr) -> Self {
|
||||
self.addrs.push(address);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add all addresses derived from `addresses` to the list of socket
|
||||
/// addresses to bind to
|
||||
pub fn with_addrs<A: ToSocketAddrs>(mut self, addresses: A) -> Result<Self, Error> {
|
||||
self.addrs.extend(addresses.to_socket_addrs()?);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Use the SAMOptions specified when building the `I2pListener`
|
||||
pub fn with_options(mut self, opts: SAMOptions) -> Self {
|
||||
self.options = opts;
|
||||
self
|
||||
}
|
||||
}
|
16
src/sam.rs
16
src/sam.rs
@ -207,25 +207,26 @@ impl Session {
|
||||
pub fn from_destination<A: ToSocketAddrs>(
|
||||
sam_addr: A,
|
||||
destination: &str,
|
||||
options: SAMOptions,
|
||||
) -> Result<Session, Error> {
|
||||
Self::create(
|
||||
sam_addr,
|
||||
destination,
|
||||
&nickname(),
|
||||
SessionStyle::Stream,
|
||||
SAMOptions::default(),
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
/// Convenience constructor to create a new transient session with an
|
||||
/// auto-generated nickname.
|
||||
pub fn transient<A: ToSocketAddrs>(sam_addr: A) -> Result<Session, Error> {
|
||||
pub fn transient<A: ToSocketAddrs>(sam_addr: A, options: SAMOptions) -> Result<Session, Error> {
|
||||
Self::create(
|
||||
sam_addr,
|
||||
"TRANSIENT",
|
||||
&nickname(),
|
||||
SessionStyle::Stream,
|
||||
SAMOptions::default(),
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
@ -260,8 +261,9 @@ impl StreamConnect {
|
||||
sam_addr: A,
|
||||
destination: &str,
|
||||
port: u16,
|
||||
options: SAMOptions,
|
||||
) -> Result<StreamConnect, Error> {
|
||||
let session = Session::transient(sam_addr)?;
|
||||
let session = Session::transient(sam_addr, options)?;
|
||||
Self::with_session(&session, destination, port)
|
||||
}
|
||||
|
||||
@ -272,7 +274,7 @@ impl StreamConnect {
|
||||
let dest = sam.naming_lookup(dest)?;
|
||||
|
||||
let mut stream_msg = format!(
|
||||
"STREAM CONNECT ID={nickname} DESTINATION={destination} SILENT=false\n",
|
||||
"STREAM CONNECT ID={nickname} DESTINATION={destination} SILENT=false",
|
||||
nickname = session.nickname,
|
||||
destination = dest,
|
||||
);
|
||||
@ -353,9 +355,9 @@ pub struct StreamForward {
|
||||
}
|
||||
|
||||
impl StreamForward {
|
||||
pub fn new<A: ToSocketAddrs>(sam_addr: A) -> Result<StreamForward, Error> {
|
||||
pub fn new<A: ToSocketAddrs>(sam_addr: A, options: SAMOptions) -> Result<StreamForward, Error> {
|
||||
Ok(StreamForward {
|
||||
session: Session::transient(sam_addr)?,
|
||||
session: Session::transient(sam_addr, options)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user