diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..838af7c
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,9 @@
+
+
+
+ enable
+ true
+ 10.0
+
+
+
diff --git a/src/Block.cs b/src/Block.cs
index a4cec47..ede6f07 100644
--- a/src/Block.cs
+++ b/src/Block.cs
@@ -1,33 +1,34 @@
-using System.IO;
+using System;
+using System.IO;
using System.Runtime.Serialization;
-
-namespace Ipfs.Http
-{
- ///
- [DataContract]
- public class Block : IDataBlock
- {
- long? size;
-
- ///
- [DataMember]
- public Cid Id { get; set; }
-
- ///
- [DataMember]
- public byte[] DataBytes { get; set; }
-
- ///
- public Stream DataStream
- {
- get
- {
- return new MemoryStream(DataBytes, false);
- }
+
+namespace Ipfs.Http
+{
+ ///
+ [DataContract]
+ public class Block : IDataBlock
+ {
+ private long? size;
+ private Cid? id;
+
+ ///
+ [DataMember]
+ public Cid Id
+ {
+ get => id ?? throw new InvalidDataException("Value must be initialized");
+
+ set => id = value;
}
- ///
- [DataMember]
+ ///
+ [DataMember]
+ public byte[] DataBytes { get; set; } = Array.Empty();
+
+ ///
+ public Stream DataStream => new MemoryStream(DataBytes, false);
+
+ ///
+ [DataMember]
public long Size
{
get
@@ -43,7 +44,5 @@ public long Size
size = value;
}
}
-
- }
-
-}
+ }
+}
diff --git a/src/CoreApi/BitswapApi.cs b/src/CoreApi/BitswapApi.cs
index dc3af6c..c97e2c0 100644
--- a/src/CoreApi/BitswapApi.cs
+++ b/src/CoreApi/BitswapApi.cs
@@ -1,58 +1,57 @@
using Ipfs.CoreApi;
-using Newtonsoft.Json.Linq;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
+using Newtonsoft.Json.Linq;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
-namespace Ipfs.Http
-{
- class BitswapApi : IBitswapApi
- {
- IpfsClient ipfs;
-
- internal BitswapApi(IpfsClient ipfs)
- {
- this.ipfs = ipfs;
+namespace Ipfs.Http
+{
+ class BitswapApi : IBitswapApi
+ {
+ private readonly IpfsClient ipfs;
+
+ internal BitswapApi(IpfsClient ipfs)
+ {
+ this.ipfs = ipfs;
}
- public Task GetAsync(Cid id, CancellationToken cancel = default(CancellationToken))
+ public Task GetAsync(Cid id, CancellationToken cancel = default)
{
return ipfs.Block.GetAsync(id, cancel);
}
- public async Task> WantsAsync(MultiHash peer = null, CancellationToken cancel = default(CancellationToken))
+ public async Task> WantsAsync(MultiHash? peer = null, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("bitswap/wantlist", cancel, peer?.ToString());
- var keys = (JArray)(JObject.Parse(json)["Keys"]);
- // https://github.com/ipfs/go-ipfs/issues/5077
- return keys
+ var keys = (JArray?)(JObject.Parse(json)["Keys"]);
+ // https://github.com/ipfs/go-ipfs/issues/5077
+ return keys
.Select(k =>
{
if (k.Type == JTokenType.String)
- return Cid.Decode(k.ToString());
+ return Cid.Decode(k.ToString());
var obj = (JObject)k;
- return Cid.Decode(obj["/"].ToString());
- });
+ return Cid.Decode(obj["/"]!.ToString());
+ });
}
-
- public async Task UnwantAsync(Cid id, CancellationToken cancel = default(CancellationToken))
+
+ public async Task UnwantAsync(Cid id, CancellationToken cancel = default)
{
await ipfs.DoCommandAsync("bitswap/unwant", cancel, id);
}
- public async Task LedgerAsync(Peer peer, CancellationToken cancel = default(CancellationToken))
+ public async Task LedgerAsync(Peer peer, CancellationToken cancel = default)
{
- var json = await ipfs.DoCommandAsync("bitswap/ledger", cancel, peer.Id.ToString());
+ var json = await ipfs.DoCommandAsync("bitswap/ledger", cancel, peer.Id?.ToString());
var o = JObject.Parse(json);
return new BitswapLedger
{
- Peer = (string)o["Peer"],
- DataReceived = (ulong)o["Sent"],
- DataSent = (ulong)o["Recv"],
- BlocksExchanged = (ulong)o["Exchanged"]
+ Peer = (string)o["Peer"]!,
+ DataReceived = (ulong?)o["Sent"] ?? 0,
+ DataSent = (ulong?)o["Recv"] ?? 0,
+ BlocksExchanged = (ulong?)o["Exchanged"] ?? 0,
};
}
- }
-
-}
+ }
+}
diff --git a/src/CoreApi/BlockApi.cs b/src/CoreApi/BlockApi.cs
index 7b1eb0b..dfed8f4 100644
--- a/src/CoreApi/BlockApi.cs
+++ b/src/CoreApi/BlockApi.cs
@@ -1,41 +1,41 @@
using Ipfs.CoreApi;
-using Newtonsoft.Json.Linq;
-using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
+using System.Collections.Generic;
using System.IO;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
-namespace Ipfs.Http
-{
- class BlockApi : IBlockApi
- {
- IpfsClient ipfs;
-
- internal BlockApi(IpfsClient ipfs)
- {
- this.ipfs = ipfs;
- }
-
- public async Task GetAsync(Cid id, CancellationToken cancel = default(CancellationToken))
- {
- var data = await ipfs.DownloadBytesAsync("block/get", cancel, id);
- return new Block
- {
- DataBytes = data,
- Id = id
- };
- }
-
- public async Task PutAsync(
+namespace Ipfs.Http
+{
+ class BlockApi : IBlockApi
+ {
+ private readonly IpfsClient ipfs;
+
+ internal BlockApi(IpfsClient ipfs)
+ {
+ this.ipfs = ipfs;
+ }
+
+ public async Task GetAsync(Cid id, CancellationToken cancel = default)
+ {
+ var data = await ipfs.DownloadBytesAsync("block/get", cancel, id);
+ return new Block
+ {
+ DataBytes = data,
+ Id = id
+ };
+ }
+
+ public async Task PutAsync(
byte[] data,
- string contentType = Cid.DefaultContentType,
- string multiHash = MultiHash.DefaultAlgorithmName,
- string encoding = MultiBase.DefaultAlgorithmName,
- bool pin = false,
- CancellationToken cancel = default(CancellationToken))
- {
- var options = new List();
+ string contentType = Cid.DefaultContentType,
+ string multiHash = MultiHash.DefaultAlgorithmName,
+ string encoding = MultiBase.DefaultAlgorithmName,
+ bool pin = false,
+ CancellationToken cancel = default)
+ {
+ var options = new List();
if (multiHash != MultiHash.DefaultAlgorithmName ||
contentType != Cid.DefaultContentType ||
encoding != MultiBase.DefaultAlgorithmName)
@@ -43,28 +43,28 @@ public async Task PutAsync(
options.Add($"mhtype={multiHash}");
options.Add($"format={contentType}");
options.Add($"cid-base={encoding}");
- }
+ }
var json = await ipfs.UploadAsync("block/put", cancel, data, options.ToArray());
var info = JObject.Parse(json);
- Cid cid = (string)info["Key"];
-
+ Cid cid = (string)info["Key"]!;
+
if (pin)
{
await ipfs.Pin.AddAsync(cid, recursive: false, cancel: cancel);
- }
-
- return cid;
- }
-
- public async Task PutAsync(
+ }
+
+ return cid;
+ }
+
+ public async Task PutAsync(
Stream data,
- string contentType = Cid.DefaultContentType,
- string multiHash = MultiHash.DefaultAlgorithmName,
- string encoding = MultiBase.DefaultAlgorithmName,
- bool pin = false,
- CancellationToken cancel = default(CancellationToken))
- {
- var options = new List();
+ string contentType = Cid.DefaultContentType,
+ string multiHash = MultiHash.DefaultAlgorithmName,
+ string encoding = MultiBase.DefaultAlgorithmName,
+ bool pin = false,
+ CancellationToken cancel = default)
+ {
+ var options = new List();
if (multiHash != MultiHash.DefaultAlgorithmName ||
contentType != Cid.DefaultContentType ||
encoding != MultiBase.DefaultAlgorithmName)
@@ -72,42 +72,40 @@ public async Task PutAsync(
options.Add($"mhtype={multiHash}");
options.Add($"format={contentType}");
options.Add($"cid-base={encoding}");
- }
- var json = await ipfs.UploadAsync("block/put", cancel, data, null, options.ToArray());
+ }
+ var json = await ipfs.UploadAsync("block/put", cancel, data, name: null, options.ToArray());
var info = JObject.Parse(json);
- Cid cid = (string)info["Key"];
-
+ Cid cid = (string)info["Key"]!;
+
if (pin)
{
await ipfs.Pin.AddAsync(cid, recursive: false, cancel: cancel);
- }
-
- return cid;
- }
-
- public async Task StatAsync(Cid id, CancellationToken cancel = default(CancellationToken))
- {
- var json = await ipfs.DoCommandAsync("block/stat", cancel, id);
+ }
+
+ return cid;
+ }
+
+ public async Task StatAsync(Cid id, CancellationToken cancel = default)
+ {
+ var json = await ipfs.DoCommandAsync("block/stat", cancel, id);
var info = JObject.Parse(json);
- return new Block
- {
- Size = (long)info["Size"],
- Id = (string)info["Key"]
- };
- }
-
- public async Task RemoveAsync(Cid id, bool ignoreNonexistent = false, CancellationToken cancel = default(CancellationToken))
- {
- var json = await ipfs.DoCommandAsync("block/rm", cancel, id, "force=" + ignoreNonexistent.ToString().ToLowerInvariant());
- if (json.Length == 0)
- return null;
- var result = JObject.Parse(json);
- var error = (string)result["Error"];
- if (error != null)
- throw new HttpRequestException(error);
- return (Cid)(string)result["Hash"];
+ return new Block
+ {
+ Size = (long?)info["Size"] ?? 0,
+ Id = (string)info["Key"]!
+ };
}
- }
-
-}
+ public async Task RemoveAsync(Cid id, bool ignoreNonexistent = false, CancellationToken cancel = default)
+ {
+ var json = await ipfs.DoCommandAsync("block/rm", cancel, id, "force=" + ignoreNonexistent.ToString().ToLowerInvariant());
+ if (json.Length == 0)
+ return null;
+ var result = JObject.Parse(json);
+ var error = (string?)result["Error"];
+ if (error is not null)
+ throw new HttpRequestException(error);
+ return (Cid)(string)result["Hash"]!;
+ }
+ }
+}
diff --git a/src/CoreApi/BlockRepositoryApi.cs b/src/CoreApi/BlockRepositoryApi.cs
index 2fa8803..f8745c2 100644
--- a/src/CoreApi/BlockRepositoryApi.cs
+++ b/src/CoreApi/BlockRepositoryApi.cs
@@ -1,39 +1,39 @@
using Ipfs.CoreApi;
-using Newtonsoft.Json.Linq;
-using System.Threading;
-using System.Threading.Tasks;
+using Newtonsoft.Json.Linq;
+using System.Threading;
+using System.Threading.Tasks;
-namespace Ipfs.Http
-{
- class BlockRepositoryApi : IBlockRepositoryApi
- {
- IpfsClient ipfs;
-
- internal BlockRepositoryApi(IpfsClient ipfs)
- {
- this.ipfs = ipfs;
+namespace Ipfs.Http
+{
+ class BlockRepositoryApi : IBlockRepositoryApi
+ {
+ private readonly IpfsClient ipfs;
+
+ internal BlockRepositoryApi(IpfsClient ipfs)
+ {
+ this.ipfs = ipfs;
}
- public async Task RemoveGarbageAsync(CancellationToken cancel = default(CancellationToken))
+ public async Task RemoveGarbageAsync(CancellationToken cancel = default)
{
await ipfs.DoCommandAsync("repo/gc", cancel);
}
- public Task StatisticsAsync(CancellationToken cancel = default(CancellationToken))
+ public Task StatisticsAsync(CancellationToken cancel = default)
{
return ipfs.DoCommandAsync("repo/stat", cancel);
}
- public async Task VerifyAsync(CancellationToken cancel = default(CancellationToken))
+ public async Task VerifyAsync(CancellationToken cancel = default)
{
await ipfs.DoCommandAsync("repo/verify", cancel);
}
- public async Task VersionAsync(CancellationToken cancel = default(CancellationToken))
+ public async Task VersionAsync(CancellationToken cancel = default)
{
- var json = await ipfs.DoCommandAsync("repo/version", cancel);
+ var json = await ipfs.DoCommandAsync("repo/version", cancel);
var info = JObject.Parse(json);
- return (string)info["Version"];
+ return (string)info["Version"]!;
}
- }
-}
+ }
+}
diff --git a/src/CoreApi/BootstrapApi.cs b/src/CoreApi/BootstrapApi.cs
index fea4bea..ef9ea9e 100644
--- a/src/CoreApi/BootstrapApi.cs
+++ b/src/CoreApi/BootstrapApi.cs
@@ -1,63 +1,74 @@
using Ipfs.CoreApi;
-using Newtonsoft.Json.Linq;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Ipfs.Http
-{
- class BootstrapApi : IBootstrapApi
- {
- IpfsClient ipfs;
-
- internal BootstrapApi(IpfsClient ipfs)
- {
- this.ipfs = ipfs;
+using Newtonsoft.Json.Linq;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Ipfs.Http
+{
+ class BootstrapApi : IBootstrapApi
+ {
+ private readonly IpfsClient ipfs;
+
+ internal BootstrapApi(IpfsClient ipfs)
+ {
+ this.ipfs = ipfs;
}
- public async Task AddAsync(MultiAddress address, CancellationToken cancel = default(CancellationToken))
+ public async Task AddAsync(MultiAddress address, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("bootstrap/add", cancel, address.ToString());
- var addrs = (JArray)(JObject.Parse(json)["Peers"]);
+ var addrs = (JArray?)(JObject.Parse(json)["Peers"]);
var a = addrs.FirstOrDefault();
- if (a == null)
+ if (a is null)
return null;
- return new MultiAddress((string)a);
+ return new MultiAddress((string)a!);
}
- public async Task> AddDefaultsAsync(CancellationToken cancel = default(CancellationToken))
+ public async Task> AddDefaultsAsync(CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("bootstrap/add/default", cancel);
- var addrs = (JArray)(JObject.Parse(json)["Peers"]);
+ var addrs = (JArray?)(JObject.Parse(json)["Peers"]);
+ if (addrs is null)
+ {
+ return Enumerable.Empty();
+ }
+
return addrs
- .Select(a => MultiAddress.TryCreate((string)a))
- .Where(ma => ma != null);
+ .Select(a => MultiAddress.TryCreate((string)a!))
+ .Where(ma => ma is not null)
+ .Cast();
}
- public async Task> ListAsync(CancellationToken cancel = default(CancellationToken))
+ public async Task> ListAsync(CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("bootstrap/list", cancel);
- var addrs = (JArray)(JObject.Parse(json)["Peers"]);
+ var addrs = (JArray?)(JObject.Parse(json)["Peers"]);
+ if (addrs is null)
+ {
+ return Enumerable.Empty();
+ }
+
return addrs
- .Select(a => MultiAddress.TryCreate((string)a))
- .Where(ma => ma != null);
+ .Select(a => MultiAddress.TryCreate((string)a!))
+ .Where(ma => ma is not null)
+ .Cast();
}
- public Task RemoveAllAsync(CancellationToken cancel = default(CancellationToken))
+ public Task RemoveAllAsync(CancellationToken cancel = default)
{
return ipfs.DoCommandAsync("bootstrap/rm/all", cancel);
}
- public async Task RemoveAsync(MultiAddress address, CancellationToken cancel = default(CancellationToken))
+ public async Task RemoveAsync(MultiAddress address, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("bootstrap/rm", cancel, address.ToString());
- var addrs = (JArray)(JObject.Parse(json)["Peers"]);
+ var addrs = (JArray?)(JObject.Parse(json)["Peers"]);
var a = addrs.FirstOrDefault();
- if (a == null)
+ if (a is null)
return null;
- return new MultiAddress((string)a);
+ return new MultiAddress((string)a!);
}
- }
-
-}
+ }
+}
diff --git a/src/CoreApi/ConfigApi.cs b/src/CoreApi/ConfigApi.cs
index 60da13f..723173a 100644
--- a/src/CoreApi/ConfigApi.cs
+++ b/src/CoreApi/ConfigApi.cs
@@ -9,46 +9,43 @@ namespace Ipfs.Http
{
class ConfigApi : IConfigApi
{
- IpfsClient ipfs;
+ private readonly IpfsClient ipfs;
internal ConfigApi(IpfsClient ipfs)
{
this.ipfs = ipfs;
}
- public async Task GetAsync(CancellationToken cancel = default(CancellationToken))
+ public async Task GetAsync(CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("config/show", cancel);
return JObject.Parse(json);
}
- public async Task GetAsync(string key, CancellationToken cancel = default(CancellationToken))
+ public async Task GetAsync(string key, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("config", cancel, key);
var r = JObject.Parse(json);
- return r["Value"];
+ return r["Value"]!;
}
- public async Task SetAsync(string key, string value, CancellationToken cancel = default(CancellationToken))
+ public Task SetAsync(string key, string value, CancellationToken cancel = default)
{
- var _ = await ipfs.DoCommandAsync("config", cancel, key, "arg=" + value);
- return;
+ return ipfs.DoCommandAsync("config", cancel, key, "arg=" + value);
}
- public async Task SetAsync(string key, JToken value, CancellationToken cancel = default(CancellationToken))
+ public Task SetAsync(string key, JToken value, CancellationToken cancel = default)
{
- var _ = await ipfs.DoCommandAsync("config", cancel,
+ return ipfs.DoCommandAsync("config", cancel,
key,
"arg=" + value.ToString(Formatting.None),
"json=true");
- return;
}
- public async Task ReplaceAsync(JObject config)
+ public Task ReplaceAsync(JObject config)
{
var data = Encoding.UTF8.GetBytes(config.ToString(Formatting.None));
- await ipfs.UploadAsync("config/replace", CancellationToken.None, data);
+ return ipfs.UploadAsync("config/replace", CancellationToken.None, data);
}
}
-
}
diff --git a/src/CoreApi/DagApi.cs b/src/CoreApi/DagApi.cs
index 6561c95..6c053af 100644
--- a/src/CoreApi/DagApi.cs
+++ b/src/CoreApi/DagApi.cs
@@ -1,31 +1,31 @@
-using Ipfs.CoreApi;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
+using Ipfs.CoreApi;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
using System.Globalization;
-using System.IO;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
-namespace Ipfs.Http
-{
- class DagApi : IDagApi
- {
- private IpfsClient ipfs;
-
- internal DagApi(IpfsClient ipfs)
- {
- this.ipfs = ipfs;
- }
-
- public async Task PutAsync(
+namespace Ipfs.Http
+{
+ class DagApi : IDagApi
+ {
+ private readonly IpfsClient ipfs;
+
+ internal DagApi(IpfsClient ipfs)
+ {
+ this.ipfs = ipfs;
+ }
+
+ public async Task PutAsync(
JObject data,
string contentType = "dag-cbor",
- string multiHash = MultiHash.DefaultAlgorithmName,
- string encoding = MultiBase.DefaultAlgorithmName,
- bool pin = true,
- CancellationToken cancel = default(CancellationToken))
- {
+ string multiHash = MultiHash.DefaultAlgorithmName,
+ string encoding = MultiBase.DefaultAlgorithmName,
+ bool pin = true,
+ CancellationToken cancel = default)
+ {
using (var ms = new MemoryStream())
{
using (var sw = new StreamWriter(ms, new UTF8Encoding(false), 4096, true) { AutoFlush = true })
@@ -45,10 +45,10 @@ public async Task PutAsync(
public async Task PutAsync(
object data,
string contentType = "dag-cbor",
- string multiHash = MultiHash.DefaultAlgorithmName,
- string encoding = MultiBase.DefaultAlgorithmName,
+ string multiHash = MultiHash.DefaultAlgorithmName,
+ string encoding = MultiBase.DefaultAlgorithmName,
bool pin = true,
- CancellationToken cancel = default(CancellationToken))
+ CancellationToken cancel = default)
{
using (var ms = new MemoryStream(
Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data)),
@@ -56,47 +56,43 @@ public async Task PutAsync(
{
return await PutAsync(ms, contentType, multiHash, encoding, pin, cancel);
}
- }
+ }
public async Task PutAsync(
Stream data,
string contentType = "dag-cbor",
- string multiHash = MultiHash.DefaultAlgorithmName,
- string encoding = MultiBase.DefaultAlgorithmName,
+ string multiHash = MultiHash.DefaultAlgorithmName,
+ string encoding = MultiBase.DefaultAlgorithmName,
bool pin = true,
- CancellationToken cancel = default(CancellationToken))
+ CancellationToken cancel = default)
{
var json = await ipfs.UploadAsync("dag/put", cancel,
- data, null,
+ data,
+ name: null,
$"format={contentType}",
$"pin={pin.ToString().ToLowerInvariant()}",
$"hash={multiHash}",
$"cid-base={encoding}");
var result = JObject.Parse(json);
- return (Cid)(string)result["Cid"]["/"];
+ return (Cid)(string)result["Cid"]!["/"]!;
}
- public async Task GetAsync(
- Cid id,
- CancellationToken cancel = default(CancellationToken))
+ public async Task GetAsync(Cid id, CancellationToken cancel = default)
{
- var json = await ipfs.DoCommandAsync("dag/get", cancel, id);
+ var json = await ipfs.DoCommandAsync("dag/get", cancel, id);
return JObject.Parse(json);
}
-
- public async Task GetAsync(
- string path,
- CancellationToken cancel = default(CancellationToken))
+ public async Task GetAsync(string path, CancellationToken cancel = default)
{
- var json = await ipfs.DoCommandAsync("dag/get", cancel, path);
+ var json = await ipfs.DoCommandAsync("dag/get", cancel, path);
return JToken.Parse(json);
}
- public async Task GetAsync(Cid id, CancellationToken cancel = default(CancellationToken))
+ public async Task GetAsync(Cid id, CancellationToken cancel = default)
{
- var json = await ipfs.DoCommandAsync("dag/get", cancel, id);
- return JsonConvert.DeserializeObject(json);
+ var json = await ipfs.DoCommandAsync("dag/get", cancel, id);
+ return JsonConvert.DeserializeObject(json);
}
- }
-}
+ }
+}
diff --git a/src/CoreApi/DhtApi.cs b/src/CoreApi/DhtApi.cs
index 55ff741..0757533 100644
--- a/src/CoreApi/DhtApi.cs
+++ b/src/CoreApi/DhtApi.cs
@@ -1,89 +1,88 @@
-using Ipfs.CoreApi;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Ipfs.Http
-{
- class DhtApi : IDhtApi
- {
- private IpfsClient ipfs;
-
- internal DhtApi(IpfsClient ipfs)
- {
- this.ipfs = ipfs;
- }
-
- public Task FindPeerAsync(MultiHash id, CancellationToken cancel = default(CancellationToken))
- {
- return ipfs.IdAsync(id, cancel);
- }
-
- public async Task> FindProvidersAsync(Cid id, int limit = 20, Action providerFound = null, CancellationToken cancel = default(CancellationToken))
+using Ipfs.CoreApi;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Ipfs.Http
+{
+ class DhtApi : IDhtApi
+ {
+ private readonly IpfsClient ipfs;
+
+ internal DhtApi(IpfsClient ipfs)
+ {
+ this.ipfs = ipfs;
+ }
+
+ public Task FindPeerAsync(MultiHash id, CancellationToken cancel = default)
+ {
+ return ipfs.IdAsync(id, cancel);
+ }
+
+ public async Task> FindProvidersAsync(Cid id, int limit = 20, Action? providerFound = null, CancellationToken cancel = default)
{
// TODO: providerFound action
- var stream = await ipfs.PostDownloadAsync("dht/findprovs", cancel, id, $"num-providers={limit}");
- return ProviderFromStream(stream, limit);
+ var stream = await ipfs.PostDownloadAsync("dht/findprovs", cancel, id, $"num-providers={limit}");
+ return ProviderFromStream(stream, limit);
}
- public Task GetAsync(byte[] key, CancellationToken cancel = default(CancellationToken))
+ public Task GetAsync(byte[] key, CancellationToken cancel = default)
{
throw new NotImplementedException();
}
- public Task ProvideAsync(Cid cid, bool advertise = true, CancellationToken cancel = default(CancellationToken))
+ public Task ProvideAsync(Cid cid, bool advertise = true, CancellationToken cancel = default)
{
throw new NotImplementedException();
}
- public Task PutAsync(byte[] key, out byte[] value, CancellationToken cancel = default(CancellationToken))
+ public Task PutAsync(byte[] key, out byte[] value, CancellationToken cancel = default)
{
throw new NotImplementedException();
}
- public Task TryGetAsync(byte[] key, out byte[] value, CancellationToken cancel = default(CancellationToken))
+ public Task TryGetAsync(byte[] key, out byte[] value, CancellationToken cancel = default)
{
throw new NotImplementedException();
}
- IEnumerable ProviderFromStream(Stream stream, int limit = int.MaxValue)
+ IEnumerable ProviderFromStream(Stream stream, int limit = int.MaxValue)
{
- using (var sr = new StreamReader(stream))
- {
- var n = 0;
- while (!sr.EndOfStream && n < limit)
- {
- var json = sr.ReadLine();
-
- var r = JObject.Parse(json);
- var id = (string)r["ID"];
- if (id != String.Empty)
+ using (var sr = new StreamReader(stream))
+ {
+ var n = 0;
+ while (!sr.EndOfStream && n < limit)
+ {
+ var json = sr.ReadLine();
+
+ var r = JObject.Parse(json);
+ var id = (string?)r["ID"];
+ if (!string.IsNullOrEmpty(id))
{
++n;
- yield return new Peer { Id = new MultiHash(id) };
- }
- else
- {
- var responses = (JArray)r["Responses"];
- if (responses != null)
- {
- foreach (var response in responses)
- {
- var rid = (string)response["ID"];
- if (rid != String.Empty)
+ yield return new Peer { Id = new MultiHash(id!) };
+ }
+ else
+ {
+ var responses = (JArray?)r["Responses"];
+ if (responses is not null)
+ {
+ foreach (var response in responses)
+ {
+ var rid = (string?)response["ID"];
+ if (!string.IsNullOrEmpty(rid))
{
- ++n;
- yield return new Peer { Id = new MultiHash(rid) };
- }
- }
- }
- }
- }
+ ++n;
+ yield return new Peer { Id = new MultiHash(rid!) };
+ }
+ }
+ }
+ }
+ }
}
- }
- }
-
-}
+ }
+ }
+}
diff --git a/src/CoreApi/DnsApi.cs b/src/CoreApi/DnsApi.cs
index bcc7c08..c3fd43c 100644
--- a/src/CoreApi/DnsApi.cs
+++ b/src/CoreApi/DnsApi.cs
@@ -1,26 +1,26 @@
using Ipfs.CoreApi;
-using Newtonsoft.Json.Linq;
-using System.Threading;
-using System.Threading.Tasks;
+using Newtonsoft.Json.Linq;
+using System.Threading;
+using System.Threading.Tasks;
-namespace Ipfs.Http
-{
- class DnsApi : IDnsApi
- {
- private IpfsClient ipfs;
-
- internal DnsApi(IpfsClient ipfs)
- {
- this.ipfs = ipfs;
+namespace Ipfs.Http
+{
+ class DnsApi : IDnsApi
+ {
+ private readonly IpfsClient ipfs;
+
+ internal DnsApi(IpfsClient ipfs)
+ {
+ this.ipfs = ipfs;
}
- public async Task ResolveAsync(string name, bool recursive = false, CancellationToken cancel = default(CancellationToken))
+ public async Task ResolveAsync(string name, bool recursive = false, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("dns", cancel,
name,
$"recursive={recursive.ToString().ToLowerInvariant()}");
- var path = (string)(JObject.Parse(json)["Path"]);
- return path;
+ var path = (string?)(JObject.Parse(json)["Path"]);
+ return path ?? string.Empty;
}
}
-}
+}
diff --git a/src/CoreApi/FileSystemApi.cs b/src/CoreApi/FileSystemApi.cs
index b94e702..3bec4a1 100644
--- a/src/CoreApi/FileSystemApi.cs
+++ b/src/CoreApi/FileSystemApi.cs
@@ -1,71 +1,70 @@
-using Ipfs.CoreApi;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Ipfs.Http
-{
- class FileSystemApi : IFileSystemApi
+using Ipfs.CoreApi;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Ipfs.Http
+{
+ class FileSystemApi : IFileSystemApi
{
- private IpfsClient ipfs;
- private Lazy emptyFolder;
-
- internal FileSystemApi(IpfsClient ipfs)
- {
- this.ipfs = ipfs;
- this.emptyFolder = new Lazy(() => ipfs.Object.NewDirectoryAsync().Result);
- }
-
- public async Task AddFileAsync(string path, AddFileOptions options = null, CancellationToken cancel = default(CancellationToken))
- {
- using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
- {
- var node = await AddAsync(stream, Path.GetFileName(path), options, cancel);
- return node;
- }
- }
-
- public Task AddTextAsync(string text, AddFileOptions options = null, CancellationToken cancel = default(CancellationToken))
- {
- return AddAsync(new MemoryStream(Encoding.UTF8.GetBytes(text), false), "", options, cancel);
- }
-
- public async Task AddAsync(Stream stream, string name = "", AddFileOptions options = null, CancellationToken cancel = default(CancellationToken))
- {
- if (options == null)
- options = new AddFileOptions();
- var opts = new List();
- if (!options.Pin)
- opts.Add("pin=false");
- if (options.Wrap)
- opts.Add("wrap-with-directory=true");
- if (options.RawLeaves)
- opts.Add("raw-leaves=true");
- if (options.OnlyHash)
- opts.Add("only-hash=true");
- if (options.Trickle)
- opts.Add("trickle=true");
- if (options.Progress != null)
- opts.Add("progress=true");
- if (options.Hash != MultiHash.DefaultAlgorithmName)
- opts.Add($"hash=${options.Hash}");
- if (options.Encoding != MultiBase.DefaultAlgorithmName)
- opts.Add($"cid-base=${options.Encoding}");
- if (!string.IsNullOrWhiteSpace(options.ProtectionKey))
- opts.Add($"protect={options.ProtectionKey}");
- opts.Add($"chunker=size-{options.ChunkSize}");
-
- var response = await ipfs.Upload2Async("add", cancel, stream, name, opts.ToArray());
-
- // The result is a stream of LDJSON objects.
- // See https://github.com/ipfs/go-ipfs/issues/4852
- FileSystemNode fsn = null;
+ private readonly IpfsClient ipfs;
+ private readonly Lazy emptyFolder;
+
+ internal FileSystemApi(IpfsClient ipfs)
+ {
+ this.ipfs = ipfs;
+ this.emptyFolder = new Lazy(() => ipfs.Object.NewDirectoryAsync().Result);
+ }
+
+ public async Task AddFileAsync(string path, AddFileOptions? options = null, CancellationToken cancel = default)
+ {
+ using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
+ {
+ var node = await AddAsync(stream, Path.GetFileName(path), options, cancel);
+ return node;
+ }
+ }
+
+ public Task AddTextAsync(string text, AddFileOptions? options = null, CancellationToken cancel = default)
+ {
+ return AddAsync(new MemoryStream(Encoding.UTF8.GetBytes(text), false), "", options, cancel);
+ }
+
+ public async Task AddAsync(Stream stream, string name = "", AddFileOptions? options = null, CancellationToken cancel = default)
+ {
+ options ??= new AddFileOptions();
+ var opts = new List();
+ if (!options.Pin)
+ opts.Add("pin=false");
+ if (options.Wrap)
+ opts.Add("wrap-with-directory=true");
+ if (options.RawLeaves)
+ opts.Add("raw-leaves=true");
+ if (options.OnlyHash)
+ opts.Add("only-hash=true");
+ if (options.Trickle)
+ opts.Add("trickle=true");
+ if (options.Progress is not null)
+ opts.Add("progress=true");
+ if (options.Hash != MultiHash.DefaultAlgorithmName)
+ opts.Add($"hash=${options.Hash}");
+ if (options.Encoding != MultiBase.DefaultAlgorithmName)
+ opts.Add($"cid-base=${options.Encoding}");
+ if (!string.IsNullOrWhiteSpace(options.ProtectionKey))
+ opts.Add($"protect={options.ProtectionKey}");
+ opts.Add($"chunker=size-{options.ChunkSize}");
+
+ var response = await ipfs.Upload2Async("add", cancel, stream, name, opts.ToArray());
+
+ // The result is a stream of LDJSON objects.
+ // See https://github.com/ipfs/go-ipfs/issues/4852
+ FileSystemNode? fsn = null;
using (var sr = new StreamReader(response))
using (var jr = new JsonTextReader(sr) { SupportMultipleContent = true })
{
@@ -78,8 +77,8 @@ internal FileSystemApi(IpfsClient ipfs)
{
options.Progress?.Report(new TransferProgress
{
- Name = (string)r["Name"],
- Bytes = (ulong)r["Bytes"]
+ Name = (string?)r["Name"],
+ Bytes = (ulong?)r["Bytes"] ?? 0
});
}
@@ -88,8 +87,8 @@ internal FileSystemApi(IpfsClient ipfs)
{
fsn = new FileSystemNode
{
- Id = (string)r["Hash"],
- Size = long.Parse((string)r["Size"]),
+ Id = (string)r["Hash"]!,
+ Size = long.Parse((string?)r["Size"]),
IsDirectory = false,
Name = name,
IpfsClient = ipfs
@@ -98,158 +97,163 @@ internal FileSystemApi(IpfsClient ipfs)
}
}
- fsn.IsDirectory = options.Wrap;
+ if (fsn is not null)
+ {
+ fsn.IsDirectory = options.Wrap;
+ }
+ else
+ {
+ throw new InvalidDataException("Returned JSON did not contain an added file record");
+ }
+
return fsn;
- }
-
- public async Task AddDirectoryAsync(string path, bool recursive = true, AddFileOptions options = null, CancellationToken cancel = default(CancellationToken))
- {
- if (options == null)
- options = new AddFileOptions();
+ }
+
+ public async Task AddDirectoryAsync(string path, bool recursive = true, AddFileOptions? options = null, CancellationToken cancel = default)
+ {
+ options ??= new AddFileOptions();
options.Wrap = false;
// Add the files and sub-directories.
- path = Path.GetFullPath(path);
- var files = Directory
- .EnumerateFiles(path)
- .Select(p => AddFileAsync(p, options, cancel));
- if (recursive)
- {
- var folders = Directory
- .EnumerateDirectories(path)
- .Select(dir => AddDirectoryAsync(dir, recursive, options, cancel));
- files = files.Union(folders);
+ path = Path.GetFullPath(path);
+ var files = Directory
+ .EnumerateFiles(path)
+ .Select(p => AddFileAsync(p, options, cancel));
+ if (recursive)
+ {
+ var folders = Directory
+ .EnumerateDirectories(path)
+ .Select(dir => AddDirectoryAsync(dir, recursive, options, cancel));
+ files = files.Union(folders);
}
// go-ipfs v0.4.14 sometimes fails when sending lots of 'add file'
// requests. It's happy with adding one file at a time.
-#if true
- var links = new List();
+#if true
+ var links = new List();
foreach (var file in files)
{
var node = await file;
links.Add(node.ToLink());
- }
-#else
+ }
+#else
var nodes = await Task.WhenAll(files);
- var links = nodes.Select(node => node.ToLink());
-#endif
+ var links = nodes.Select(node => node.ToLink());
+#endif
// Create the directory with links to the created files and sub-directories
- var folder = emptyFolder.Value.AddLinks(links);
+ var folder = emptyFolder.Value.AddLinks(links);
var directory = await ipfs.Object.PutAsync(folder, cancel);
- return new FileSystemNode
- {
- Id = directory.Id,
- Name = Path.GetFileName(path),
- Links = links,
- IsDirectory = true,
- Size = directory.Size,
- IpfsClient = ipfs
- };
-
- }
-
- ///
- /// Reads the content of an existing IPFS file as text.
- ///
- ///
- /// A path to an existing file, such as "QmXarR6rgkQ2fDSHjSY5nM2kuCXKYGViky5nohtwgF65Ec/about"
- /// or "QmZTR5bcpQD7cFgTorqxZDYaew1Wqgfbd2ud9QqGPAkK2V"
- ///
- ///
- /// Is used to stop the task. When cancelled, the is raised.
- ///
- ///
- /// The contents of the as a .
- ///
- public async Task ReadAllTextAsync(string path, CancellationToken cancel = default(CancellationToken))
- {
- using (var data = await ReadFileAsync(path, cancel))
- using (var text = new StreamReader(data))
- {
- return await text.ReadToEndAsync();
- }
- }
-
-
- ///
- /// Opens an existing IPFS file for reading.
- ///
- ///
- /// A path to an existing file, such as "QmXarR6rgkQ2fDSHjSY5nM2kuCXKYGViky5nohtwgF65Ec/about"
- /// or "QmZTR5bcpQD7cFgTorqxZDYaew1Wqgfbd2ud9QqGPAkK2V"
- ///
- ///
- /// Is used to stop the task. When cancelled, the is raised.
- ///
- ///
- /// A to the file contents.
- ///
- public Task ReadFileAsync(string path, CancellationToken cancel = default(CancellationToken))
- {
- return ipfs.PostDownloadAsync("cat", cancel, path);
- }
-
- public Task ReadFileAsync(string path, long offset, long length = 0, CancellationToken cancel = default(CancellationToken))
- {
- // https://github.com/ipfs/go-ipfs/issues/5380
- if (offset > int.MaxValue)
- throw new NotSupportedException("Only int offsets are currently supported.");
- if (length > int.MaxValue)
- throw new NotSupportedException("Only int lengths are currently supported.");
-
- if (length == 0)
- length = int.MaxValue; // go-ipfs only accepts int lengths
+ return new FileSystemNode
+ {
+ Id = directory.Id,
+ Name = Path.GetFileName(path),
+ Links = links,
+ IsDirectory = true,
+ Size = directory.Size,
+ IpfsClient = ipfs
+ };
+ }
+
+ ///
+ /// Reads the content of an existing IPFS file as text.
+ ///
+ ///
+ /// A path to an existing file, such as "QmXarR6rgkQ2fDSHjSY5nM2kuCXKYGViky5nohtwgF65Ec/about"
+ /// or "QmZTR5bcpQD7cFgTorqxZDYaew1Wqgfbd2ud9QqGPAkK2V"
+ ///
+ ///
+ /// Is used to stop the task. When cancelled, the is raised.
+ ///
+ ///
+ /// The contents of the as a .
+ ///
+ public async Task ReadAllTextAsync(string path, CancellationToken cancel = default)
+ {
+ using (var data = await ReadFileAsync(path, cancel))
+ using (var text = new StreamReader(data))
+ {
+ return await text.ReadToEndAsync();
+ }
+ }
+
+
+ ///
+ /// Opens an existing IPFS file for reading.
+ ///
+ ///
+ /// A path to an existing file, such as "QmXarR6rgkQ2fDSHjSY5nM2kuCXKYGViky5nohtwgF65Ec/about"
+ /// or "QmZTR5bcpQD7cFgTorqxZDYaew1Wqgfbd2ud9QqGPAkK2V"
+ ///
+ ///
+ /// Is used to stop the task. When cancelled, the is raised.
+ ///
+ ///
+ /// A to the file contents.
+ ///
+ public Task ReadFileAsync(string path, CancellationToken cancel = default)
+ {
+ return ipfs.PostDownloadAsync("cat", cancel, path);
+ }
+
+ public Task ReadFileAsync(string path, long offset, long length = 0, CancellationToken cancel = default)
+ {
+ // https://github.com/ipfs/go-ipfs/issues/5380
+ if (offset > int.MaxValue)
+ throw new NotSupportedException("Only int offsets are currently supported.");
+ if (length > int.MaxValue)
+ throw new NotSupportedException("Only int lengths are currently supported.");
+
+ if (length == 0)
+ length = int.MaxValue; // go-ipfs only accepts int lengths
return ipfs.PostDownloadAsync("cat", cancel, path,
- $"offset={offset}",
- $"length={length}");
- }
-
- ///
- /// Get information about the file or directory.
- ///
- ///
- /// A path to an existing file or directory, such as "QmXarR6rgkQ2fDSHjSY5nM2kuCXKYGViky5nohtwgF65Ec/about"
- /// or "QmZTR5bcpQD7cFgTorqxZDYaew1Wqgfbd2ud9QqGPAkK2V"
- ///
- ///
- /// Is used to stop the task. When cancelled, the is raised.
- ///
- ///
- public async Task ListFileAsync(string path, CancellationToken cancel = default(CancellationToken))
- {
- var json = await ipfs.DoCommandAsync("file/ls", cancel, path);
- var r = JObject.Parse(json);
- var hash = (string)r["Arguments"][path];
- var o = (JObject)r["Objects"][hash];
- var node = new FileSystemNode()
- {
- Id = (string)o["Hash"],
- Size = (long)o["Size"],
- IsDirectory = (string)o["Type"] == "Directory",
- Links = new FileSystemLink[0],
- IpfsClient = ipfs
- };
- var links = o["Links"] as JArray;
- if (links != null)
- {
- node.Links = links
- .Select(l => new FileSystemLink()
- {
- Name = (string)l["Name"],
- Id = (string)l["Hash"],
- Size = (long)l["Size"],
- })
- .ToArray();
- }
-
- return node;
+ $"offset={offset}",
+ $"length={length}");
+ }
+
+ ///
+ /// Get information about the file or directory.
+ ///
+ ///
+ /// A path to an existing file or directory, such as "QmXarR6rgkQ2fDSHjSY5nM2kuCXKYGViky5nohtwgF65Ec/about"
+ /// or "QmZTR5bcpQD7cFgTorqxZDYaew1Wqgfbd2ud9QqGPAkK2V"
+ ///
+ ///
+ /// Is used to stop the task. When cancelled, the is raised.
+ ///
+ /// A
+ public async Task ListFileAsync(string path, CancellationToken cancel = default)
+ {
+ var json = await ipfs.DoCommandAsync("file/ls", cancel, path);
+ var r = JObject.Parse(json);
+ var hash = (string)r["Arguments"]![path]!;
+ var o = (JObject)r["Objects"]![hash]!;
+ var node = new FileSystemNode
+ {
+ Id = (string)o["Hash"]!,
+ Size = (long?)o["Size"] ?? 0,
+ IsDirectory = (string?)o["Type"] == "Directory",
+ Links = new FileSystemLink[0],
+ IpfsClient = ipfs
+ };
+ var links = o["Links"] as JArray;
+ if (links is not null)
+ {
+ node.Links = links
+ .Select(l => new FileSystemLink((string)l["Hash"]!)
+ {
+ Name = (string?)l["Name"],
+ Size = (long?)l["Size"] ?? 0,
+ })
+ .ToArray();
+ }
+
+ return node;
}
- public Task GetAsync(string path, bool compress = false, CancellationToken cancel = default(CancellationToken))
+ public Task GetAsync(string path, bool compress = false, CancellationToken cancel = default)
{
- return ipfs.PostDownloadAsync("get", cancel, path, $"compress={compress}");
- }
- }
-}
+ return ipfs.PostDownloadAsync("get", cancel, path, $"compress={compress}");
+ }
+ }
+}
diff --git a/src/CoreApi/GenericApi.cs b/src/CoreApi/GenericApi.cs
index e6ca5d2..7fdb17a 100644
--- a/src/CoreApi/GenericApi.cs
+++ b/src/CoreApi/GenericApi.cs
@@ -1,82 +1,81 @@
-using Ipfs.CoreApi;
+using Ipfs.CoreApi;
using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
-namespace Ipfs.Http
-{
- public partial class IpfsClient : IGenericApi
- {
+namespace Ipfs.Http
+{
+ public partial class IpfsClient : IGenericApi
+ {
private const double TicksPerNanosecond = (double)TimeSpan.TicksPerMillisecond * 0.000001;
///
- public Task IdAsync(MultiHash peer = null, CancellationToken cancel = default(CancellationToken))
- {
- return DoCommandAsync("id", cancel, peer?.ToString());
+ public Task IdAsync(MultiHash? peer = null, CancellationToken cancel = default)
+ {
+ return DoCommandAsync("id", cancel, peer?.ToString());
}
///
- public async Task> PingAsync(MultiHash peer, int count = 10, CancellationToken cancel = default(CancellationToken))
+ public async Task> PingAsync(MultiHash peer, int count = 10, CancellationToken cancel = default)
{
- var stream = await PostDownloadAsync("ping", cancel,
- peer.ToString(),
- $"count={count.ToString(CultureInfo.InvariantCulture)}");
+ var stream = await PostDownloadAsync("ping", cancel,
+ peer.ToString(),
+ $"count={count.ToString(CultureInfo.InvariantCulture)}");
return PingResultFromStream(stream);
}
///
- public async Task> PingAsync(MultiAddress address, int count = 10, CancellationToken cancel = default(CancellationToken))
+ public async Task> PingAsync(MultiAddress address, int count = 10, CancellationToken cancel = default)
{
- var stream = await PostDownloadAsync("ping", cancel,
- address.ToString(),
- $"count={count.ToString(CultureInfo.InvariantCulture)}");
+ var stream = await PostDownloadAsync("ping", cancel,
+ address.ToString(),
+ $"count={count.ToString(CultureInfo.InvariantCulture)}");
return PingResultFromStream(stream);
}
IEnumerable PingResultFromStream(Stream stream)
{
- using (var sr = new StreamReader(stream))
- {
- while (!sr.EndOfStream)
- {
- var json = sr.ReadLine();
-
- var r = JObject.Parse(json);
+ using (var sr = new StreamReader(stream))
+ {
+ while (!sr.EndOfStream)
+ {
+ var json = sr.ReadLine();
+
+ var r = JObject.Parse(json);
yield return new PingResult
{
- Success = (bool)r["Success"],
- Text = (string)r["Text"],
- Time = TimeSpan.FromTicks((long)((long)r["Time"] * TicksPerNanosecond))
+ Success = (bool?)r["Success"] ?? false,
+ Text = (string?)r["Text"],
+ Time = TimeSpan.FromTicks((long)(((long?)r["Time"] ?? 0) * TicksPerNanosecond))
};
- }
- }
- }
+ }
+ }
+ }
///
- public async Task ResolveAsync(string name, bool recursive = true, CancellationToken cancel = default(CancellationToken))
+ public async Task ResolveAsync(string name, bool recursive = true, CancellationToken cancel = default)
{
var json = await DoCommandAsync("resolve", cancel,
name,
$"recursive={recursive.ToString().ToLowerInvariant()}");
- var path = (string)(JObject.Parse(json)["Path"]);
- return path;
+ var path = (string?)(JObject.Parse(json)["Path"]);
+ return path ?? string.Empty;
}
///
public async Task ShutdownAsync()
{
- await DoCommandAsync("shutdown", default(CancellationToken));
+ await DoCommandAsync("shutdown", default);
}
///
- public Task> VersionAsync(CancellationToken cancel = default(CancellationToken))
- {
- return DoCommandAsync>("version", cancel);
- }
-
- }
-}
+ public Task> VersionAsync(CancellationToken cancel = default)
+ {
+ return DoCommandAsync>("version", cancel);
+ }
+ }
+}
diff --git a/src/CoreApi/KeyApi.cs b/src/CoreApi/KeyApi.cs
index 003fa04..9e556ed 100644
--- a/src/CoreApi/KeyApi.cs
+++ b/src/CoreApi/KeyApi.cs
@@ -1,41 +1,47 @@
-using Ipfs.CoreApi;
-using Newtonsoft.Json.Linq;
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Ipfs.CoreApi;
+using Newtonsoft.Json.Linq;
namespace Ipfs.Http
{
- class KeyApi : IKeyApi
+ internal class KeyApi : IKeyApi
{
///
/// Information about a local key.
///
- public class KeyInfo : IKey
+ public sealed class KeyInfo : IKey
{
+ public KeyInfo(MultiHash id, string name)
+ {
+ Id = id;
+ Name = name;
+ }
+
///
- public MultiHash Id { get; set; }
+ public MultiHash Id { get; }
///
- public string Name { get; set; }
+ public string Name { get; }
///
public override string ToString()
{
- return Name;
+ return Name ?? string.Empty;
}
-
}
- IpfsClient ipfs;
+
+ private readonly IpfsClient ipfs;
internal KeyApi(IpfsClient ipfs)
{
this.ipfs = ipfs;
}
- public async Task CreateAsync(string name, string keyType, int size, CancellationToken cancel = default(CancellationToken))
+ public async Task CreateAsync(string name, string keyType, int size, CancellationToken cancel = default)
{
return await ipfs.DoCommandAsync("key/gen", cancel,
name,
@@ -43,49 +49,37 @@ internal KeyApi(IpfsClient ipfs)
$"size={size}");
}
- public async Task> ListAsync(CancellationToken cancel = default(CancellationToken))
+ public async Task> ListAsync(CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("key/list", cancel, null, "l=true");
- var keys = (JArray)(JObject.Parse(json)["Keys"]);
+ var keys = (JArray?)(JObject.Parse(json)["Keys"]);
return keys
- .Select(k => new KeyInfo
- {
- Id = (string)k["Id"],
- Name = (string)k["Name"]
- });
+ .Select(k => new KeyInfo((string)k["Id"]!, (string)k["Name"]!));
}
- public async Task RemoveAsync(string name, CancellationToken cancel = default(CancellationToken))
+ public async Task RemoveAsync(string name, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("key/rm", cancel, name);
var keys = JObject.Parse(json)["Keys"] as JArray;
return keys?
- .Select(k => new KeyInfo
- {
- Id = (string)k["Id"],
- Name = (string)k["Name"]
- })
+ .Select(k => new KeyInfo((string)k["Id"]!, (string)k["Name"]!))
.First();
}
- public async Task RenameAsync(string oldName, string newName, CancellationToken cancel = default(CancellationToken))
+ public async Task RenameAsync(string oldName, string newName, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("key/rename", cancel, oldName, $"arg={newName}");
var key = JObject.Parse(json);
- return new KeyInfo
- {
- Id = (string)key["Id"],
- Name = (string)key["Now"]
- };
+ return new KeyInfo((string)key["Id"]!, (string)key["Now"]!);
}
- public Task ExportAsync(string name, char[] password, CancellationToken cancel = default(CancellationToken))
+ public Task ExportAsync(string name, char[] password, CancellationToken cancel = default)
{
throw new NotImplementedException();
}
- public Task ImportAsync(string name, string pem, char[] password = null, CancellationToken cancel = default(CancellationToken))
+ public Task ImportAsync(string name, string pem, char[]? password = null, CancellationToken cancel = default)
{
throw new NotImplementedException();
}
diff --git a/src/CoreApi/NameApi.cs b/src/CoreApi/NameApi.cs
index 94d595e..922ddad 100644
--- a/src/CoreApi/NameApi.cs
+++ b/src/CoreApi/NameApi.cs
@@ -1,21 +1,21 @@
using Ipfs.CoreApi;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Threading;
-using System.Threading.Tasks;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
-namespace Ipfs.Http
-{
- class NameApi : INameApi
- {
- private IpfsClient ipfs;
-
- internal NameApi(IpfsClient ipfs)
- {
- this.ipfs = ipfs;
+namespace Ipfs.Http
+{
+ class NameApi : INameApi
+ {
+ private readonly IpfsClient ipfs;
+
+ internal NameApi(IpfsClient ipfs)
+ {
+ this.ipfs = ipfs;
}
- public async Task PublishAsync(string path, bool resolve = true, string key = "self", TimeSpan? lifetime = null, CancellationToken cancel = default(CancellationToken))
+ public async Task PublishAsync(string path, bool resolve = true, string key = "self", TimeSpan? lifetime = null, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("name/publish", cancel,
path,
@@ -26,12 +26,12 @@ internal NameApi(IpfsClient ipfs)
var info = JObject.Parse(json);
return new NamedContent
{
- NamePath = (string)info["Name"],
- ContentPath = (string)info["Value"]
+ NamePath = (string?)info["Name"],
+ ContentPath = (string?)info["Value"]
};
}
- public Task PublishAsync(Cid id, string key = "self", TimeSpan? lifetime = null, CancellationToken cancel = default(CancellationToken))
+ public Task PublishAsync(Cid id, string key = "self", TimeSpan? lifetime = null, CancellationToken cancel = default)
{
return PublishAsync("/ipfs/" + id.Encode(), false, key, lifetime, cancel);
}
@@ -42,8 +42,8 @@ internal NameApi(IpfsClient ipfs)
name,
$"recursive={recursive.ToString().ToLowerInvariant()}",
$"nocache={nocache.ToString().ToLowerInvariant()}");
- var path = (string)(JObject.Parse(json)["Path"]);
- return path;
+ var path = (string?)(JObject.Parse(json)["Path"]);
+ return path ?? string.Empty;
}
}
-}
+}
diff --git a/src/CoreApi/ObjectApi.cs b/src/CoreApi/ObjectApi.cs
index 8ea0210..e87547a 100644
--- a/src/CoreApi/ObjectApi.cs
+++ b/src/CoreApi/ObjectApi.cs
@@ -11,48 +11,48 @@ namespace Ipfs.Http
{
class ObjectApi : IObjectApi
{
- private IpfsClient ipfs;
+ private readonly IpfsClient ipfs;
internal ObjectApi(IpfsClient ipfs)
{
this.ipfs = ipfs;
}
- public Task NewDirectoryAsync(CancellationToken cancel = default(CancellationToken))
+ public Task NewDirectoryAsync(CancellationToken cancel = default)
{
return NewAsync("unixfs-dir", cancel);
}
- public async Task NewAsync(string template = null, CancellationToken cancel = default(CancellationToken))
+ public async Task NewAsync(string? template = null, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("object/new", cancel, template);
- var hash = (string)(JObject.Parse(json)["Hash"]);
- return await GetAsync(hash);
+ var hash = (string?)(JObject.Parse(json)["Hash"]);
+ return await GetAsync(hash!);
}
- public async Task GetAsync(Cid id, CancellationToken cancel = default(CancellationToken))
+ public async Task GetAsync(Cid id, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("object/get", cancel, id);
return GetDagFromJson(json);
}
- public Task PutAsync(byte[] data, IEnumerable links = null, CancellationToken cancel = default(CancellationToken))
+ public Task PutAsync(byte[] data, IEnumerable? links = null, CancellationToken cancel = default)
{
return PutAsync(new DagNode(data, links), cancel);
}
- public async Task PutAsync(DagNode node, CancellationToken cancel = default(CancellationToken))
+ public async Task PutAsync(DagNode node, CancellationToken cancel = default)
{
var json = await ipfs.UploadAsync("object/put", cancel, node.ToArray(), "inputenc=protobuf");
return node;
}
- public Task DataAsync(Cid id, CancellationToken cancel = default(CancellationToken))
+ public Task DataAsync(Cid id, CancellationToken cancel = default)
{
return ipfs.PostDownloadAsync("object/data", cancel, id);
}
- public async Task> LinksAsync(Cid id, CancellationToken cancel = default(CancellationToken))
+ public async Task> LinksAsync(Cid id, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("object/links", cancel, id);
return GetDagFromJson(json).Links;
@@ -63,30 +63,30 @@ internal ObjectApi(IpfsClient ipfs)
DagNode GetDagFromJson(string json)
{
var result = JObject.Parse(json);
- byte[] data = null;
- var stringData = (string)result["Data"];
- if (stringData != null)
+ byte[]? data = null;
+ var stringData = (string?)result["Data"];
+ if (stringData is not null)
data = Encoding.UTF8.GetBytes(stringData);
- var links = ((JArray)result["Links"])
+ var links = ((JArray?)result["Links"])
.Select(link => new DagLink(
- (string)link["Name"],
- (string)link["Hash"],
- (long)link["Size"]));
+ (string?)link["Name"],
+ (string)link["Hash"]!,
+ (long?)link["Size"] ?? 0));
return new DagNode(data, links);
}
- public async Task StatAsync(Cid id, CancellationToken cancel = default(CancellationToken))
+ public async Task StatAsync(Cid id, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("object/stat", cancel, id);
var r = JObject.Parse(json);
return new ObjectStat
{
- LinkCount = (int)r["NumLinks"],
- LinkSize = (long)r["LinksSize"],
- BlockSize = (long)r["BlockSize"],
- DataSize = (long)r["DataSize"],
- CumulativeSize = (long)r["CumulativeSize"]
+ LinkCount = (int?)r["NumLinks"] ?? 0,
+ LinkSize = (long?)r["LinksSize"] ?? 0,
+ BlockSize = (long?)r["BlockSize"] ?? 0,
+ DataSize = (long?)r["DataSize"] ?? 0,
+ CumulativeSize = (long?)r["CumulativeSize"] ?? 0,
};
}
}
diff --git a/src/CoreApi/PinApi.cs b/src/CoreApi/PinApi.cs
index 7f3bf2c..33e2c64 100644
--- a/src/CoreApi/PinApi.cs
+++ b/src/CoreApi/PinApi.cs
@@ -9,38 +9,41 @@ namespace Ipfs.Http
{
class PinApi : IPinApi
{
- private IpfsClient ipfs;
+ private readonly IpfsClient ipfs;
internal PinApi(IpfsClient ipfs)
{
this.ipfs = ipfs;
}
- public async Task> AddAsync(string path, bool recursive = true, CancellationToken cancel = default(CancellationToken))
+ public async Task> AddAsync(string path, bool recursive = true, CancellationToken cancel = default)
{
var opts = "recursive=" + recursive.ToString().ToLowerInvariant();
var json = await ipfs.DoCommandAsync("pin/add", cancel, path, opts);
- return ((JArray)JObject.Parse(json)["Pins"])
- .Select(p => (Cid)(string)p);
+ return ((JArray?)JObject.Parse(json)["Pins"])
+ .Select(p => (Cid)(string)p!);
}
- public async Task> ListAsync(CancellationToken cancel = default(CancellationToken))
+ public async Task> ListAsync(CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("pin/ls", cancel);
- var keys = (JObject)(JObject.Parse(json)["Keys"]);
+ var keys = (JObject?)(JObject.Parse(json)["Keys"]);
+ if (keys is null)
+ {
+ return Enumerable.Empty();
+ }
+
return keys
.Properties()
.Select(p => (Cid)p.Name);
}
- public async Task> RemoveAsync(Cid id, bool recursive = true, CancellationToken cancel = default(CancellationToken))
+ public async Task> RemoveAsync(Cid id, bool recursive = true, CancellationToken cancel = default)
{
var opts = "recursive=" + recursive.ToString().ToLowerInvariant();
var json = await ipfs.DoCommandAsync("pin/rm", cancel, id, opts);
- return ((JArray)JObject.Parse(json)["Pins"])
- .Select(p => (Cid)(string)p);
+ return ((JArray?)JObject.Parse(json)["Pins"])
+ .Select(p => (Cid)(string)p!);
}
-
}
-
}
diff --git a/src/CoreApi/PubSubApi.cs b/src/CoreApi/PubSubApi.cs
index f2c726d..c75336d 100644
--- a/src/CoreApi/PubSubApi.cs
+++ b/src/CoreApi/PubSubApi.cs
@@ -1,19 +1,19 @@
-using Ipfs.CoreApi;
-using Newtonsoft.Json.Linq;
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using Ipfs.CoreApi;
using Multiformats.Base;
+using Newtonsoft.Json.Linq;
namespace Ipfs.Http
{
class PubSubApi : IPubSubApi
{
- private IpfsClient ipfs;
+ private readonly IpfsClient ipfs;
internal PubSubApi(IpfsClient ipfs)
{
@@ -25,20 +25,22 @@ public async Task> SubscribedTopicsAsync(CancellationToken c
var json = await ipfs.DoCommandAsync("pubsub/ls", cancel);
var result = JObject.Parse(json);
var strings = result["Strings"] as JArray;
- if (strings == null) return new string[0];
- return strings.Select(s => (string)s);
+ if (strings is null) return Enumerable.Empty();
+ return strings.Select(s => (string)s!);
}
- public async Task> PeersAsync(string topic = null, CancellationToken cancel = default)
+ public async Task> PeersAsync(string? topic = null, CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("pubsub/peers", cancel, topic);
var result = JObject.Parse(json);
var strings = result["Strings"] as JArray;
- if (strings == null)
- return Array.Empty();
+ if (strings is null)
+ {
+ return Enumerable.Empty();
+ }
- return strings.Select(s => new Peer { Id = (string)s });
+ return strings.Select(s => new Peer { Id = (string)s! });
}
public Task PublishAsync(string topic, byte[] message, CancellationToken cancel = default)
@@ -76,10 +78,10 @@ public async Task SubscribeAsync(string topic, Action handler
var messageStream = await ipfs.PostDownloadAsync("pubsub/sub", cancellationToken, $"{Multibase.Encode(MultibaseEncoding.Base64Url, Encoding.UTF8.GetBytes(topic))}");
var sr = new StreamReader(messageStream);
- _ = Task.Run(() => ProcessMessages(topic, handler, sr, cancellationToken), cancellationToken);
+ _ = Task.Run(() => ProcessMessages(handler, sr, cancellationToken), cancellationToken);
}
- void ProcessMessages(string topic, Action handler, StreamReader sr, CancellationToken ct)
+ void ProcessMessages(Action handler, StreamReader sr, CancellationToken ct)
{
// .Net needs a ReadLine(CancellationToken)
// As a work-around, we register a function to close the stream
@@ -89,7 +91,7 @@ void ProcessMessages(string topic, Action handler, StreamReade
while (!sr.EndOfStream && !ct.IsCancellationRequested)
{
var json = sr.ReadLine();
- if (json == null)
+ if (json is null)
break;
// go-ipfs 0.4.13 and earlier always send empty JSON
@@ -112,7 +114,5 @@ void ProcessMessages(string topic, Action handler, StreamReade
sr.Dispose();
}
}
-
}
-
}
diff --git a/src/CoreApi/StatsApi.cs b/src/CoreApi/StatsApi.cs
index 1082730..1bfe29c 100644
--- a/src/CoreApi/StatsApi.cs
+++ b/src/CoreApi/StatsApi.cs
@@ -9,41 +9,39 @@ namespace Ipfs.Http
class StatApi : IStatsApi
{
- private IpfsClient ipfs;
+ private readonly IpfsClient ipfs;
internal StatApi(IpfsClient ipfs)
{
this.ipfs = ipfs;
}
- public Task BandwidthAsync(CancellationToken cancel = default(CancellationToken))
+ public Task BandwidthAsync(CancellationToken cancel = default)
{
return ipfs.DoCommandAsync("stats/bw", cancel);
}
- public async Task BitswapAsync(CancellationToken cancel = default(CancellationToken))
+ public async Task BitswapAsync(CancellationToken cancel = default)
{
var json = await ipfs.DoCommandAsync("stats/bitswap", cancel);
var stat = JObject.Parse(json);
return new BitswapData
{
- BlocksReceived = (ulong)stat["BlocksReceived"],
- DataReceived = (ulong)stat["DataReceived"],
- BlocksSent = (ulong)stat["BlocksSent"],
- DataSent = (ulong)stat["DataSent"],
- DupBlksReceived = (ulong)stat["DupBlksReceived"],
- DupDataReceived = (ulong)stat["DupDataReceived"],
- ProvideBufLen = (int)stat["ProvideBufLen"],
- Peers = ((JArray)stat["Peers"]).Select(s => new MultiHash((string)s)),
- Wantlist = ((JArray)stat["Wantlist"]).Select(o => Cid.Decode(o["/"].ToString()))
+ BlocksReceived = (ulong?)stat["BlocksReceived"] ?? 0,
+ DataReceived = (ulong?)stat["DataReceived"] ?? 0,
+ BlocksSent = (ulong?)stat["BlocksSent"] ?? 0,
+ DataSent = (ulong?)stat["DataSent"] ?? 0,
+ DupBlksReceived = (ulong?)stat["DupBlksReceived"] ?? 0,
+ DupDataReceived = (ulong?)stat["DupDataReceived"] ?? 0,
+ ProvideBufLen = (int?)stat["ProvideBufLen"] ?? 0,
+ Peers = ((JArray?)stat["Peers"]).Select(s => new MultiHash((string)s!)).ToList(),
+ Wantlist = ((JArray?)stat["Wantlist"]).Select(o => Cid.Decode(o["/"]?.ToString() ?? string.Empty))
};
}
- public Task RepositoryAsync(CancellationToken cancel = default(CancellationToken))
+ public Task RepositoryAsync(CancellationToken cancel = default)
{
return ipfs.DoCommandAsync("stats/repo", cancel);
}
-
-
}
}
diff --git a/src/CoreApi/SwarmApi.cs b/src/CoreApi/SwarmApi.cs
index fc83326..488d1ae 100644
--- a/src/CoreApi/SwarmApi.cs
+++ b/src/CoreApi/SwarmApi.cs
@@ -1,99 +1,112 @@
-using Ipfs.CoreApi;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Ipfs.Http
-{
- class SwarmApi : ISwarmApi
- {
- private IpfsClient ipfs;
-
- internal SwarmApi(IpfsClient ipfs)
- {
- this.ipfs = ipfs;
- }
-
- public async Task> AddressesAsync(CancellationToken cancel = default(CancellationToken))
- {
- var json = await ipfs.DoCommandAsync("swarm/addrs", cancel);
- return ((JObject)JObject.Parse(json)["Addrs"])
- .Properties()
+using Ipfs.CoreApi;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Ipfs.Http
+{
+ class SwarmApi : ISwarmApi
+ {
+ private readonly IpfsClient ipfs;
+
+ internal SwarmApi(IpfsClient ipfs)
+ {
+ this.ipfs = ipfs;
+ }
+
+ public async Task> AddressesAsync(CancellationToken cancel = default)
+ {
+ var json = await ipfs.DoCommandAsync("swarm/addrs", cancel);
+ var obj = (JObject?)JObject.Parse(json);
+ if (obj is null)
+ {
+ return Enumerable.Empty();
+ }
+
+ var addrs = (JObject?)obj["Addrs"];
+ if (addrs is null)
+ {
+ return Enumerable.Empty();
+ }
+
+ return addrs
+ .Properties()
.Select(p => new Peer
- {
- Id = p.Name,
- Addresses = ((JArray)p.Value)
- .Select(a => MultiAddress.TryCreate((string)a))
- .Where(ma => ma != null)
- });
- }
-
- public async Task> PeersAsync(CancellationToken cancel = default(CancellationToken))
- {
- var json = await ipfs.DoCommandAsync("swarm/peers", cancel, null, "verbose=true");
- var result = JObject.Parse(json);
-
- // Older servers return an array of strings
- var strings = (JArray)result["Strings"];
- if (strings != null)
- {
- return strings
- .Select(s =>
- {
- var parts = ((string)s).Split(' ');
- var address = new MultiAddress(parts[0]);
- return new Peer
- {
- Id = address.PeerId,
- ConnectedAddress = parts[0],
- Latency = Duration.Parse(parts[1])
- };
- });
- }
-
- // Current servers return JSON
- var peers = (JArray)result["Peers"];
- if (peers != null)
- {
- return peers.Select(p => new Peer
- {
- Id = (string)p["Peer"],
- ConnectedAddress = new MultiAddress((string)p["Addr"] + "/ipfs/" + (string)p["Peer"]),
- Latency = Duration.Parse((string)p["Latency"])
- });
+ {
+ Id = p.Name,
+ Addresses = ((JArray)p.Value)
+ .Select(a => MultiAddress.TryCreate((string)a!))
+ .Where(ma => ma is not null)
+ .Cast()
+ });
+ }
+
+ public async Task> PeersAsync(CancellationToken cancel = default)
+ {
+ var json = await ipfs.DoCommandAsync("swarm/peers", cancel, null, "verbose=true");
+ var result = JObject.Parse(json);
+
+ // Older servers return an array of strings
+ var strings = (JArray?)result["Strings"];
+ if (strings is not null)
+ {
+ return strings
+ .Select(s =>
+ {
+ var parts = ((string)s)!.Split(' ');
+ var address = new MultiAddress(parts[0]);
+ return new Peer
+ {
+ Id = address.PeerId,
+ ConnectedAddress = parts[0],
+ Latency = Duration.Parse(parts[1])
+ };
+ });
+ }
+
+ // Current servers return JSON
+ var peers = (JArray?)result["Peers"];
+ if (peers is not null)
+ {
+ return peers.Select(p => new Peer
+ {
+ Id = (string)p["Peer"]!,
+ ConnectedAddress = new MultiAddress((string?)p["Addr"] + "/ipfs/" + (string?)p["Peer"]),
+ Latency = Duration.Parse((string?)p["Latency"] ?? "0")
+ });
}
// Hmmm. Another change we can handle
- throw new FormatException("Unknown response from 'swarm/peers");
- }
-
- public async Task ConnectAsync(MultiAddress address, CancellationToken cancel = default(CancellationToken))
- {
- await ipfs.DoCommandAsync("swarm/connect", cancel, address.ToString());
- }
-
- public async Task DisconnectAsync(MultiAddress address, CancellationToken cancel = default(CancellationToken))
- {
- await ipfs.DoCommandAsync("swarm/disconnect", cancel, address.ToString());
+ throw new FormatException("Unknown response from 'swarm/peers");
+ }
+
+ public async Task ConnectAsync(MultiAddress address, CancellationToken cancel = default)
+ {
+ await ipfs.DoCommandAsync("swarm/connect", cancel, address.ToString());
+ }
+
+ public async Task DisconnectAsync(MultiAddress address, CancellationToken cancel = default)
+ {
+ await ipfs.DoCommandAsync("swarm/disconnect", cancel, address.ToString());
}
- public async Task AddAddressFilterAsync(MultiAddress address, bool persist = false, CancellationToken cancel = default(CancellationToken))
+ public async Task AddAddressFilterAsync(MultiAddress address, bool persist = false, CancellationToken cancel = default)
{
// go-ipfs always does persist, https://github.com/ipfs/go-ipfs/issues/4605
var json = await ipfs.DoCommandAsync("swarm/filters/add", cancel, address.ToString());
- var addrs = (JArray)(JObject.Parse(json)["Strings"]);
+ var addrs = (JArray?)(JObject.Parse(json)["Strings"]);
var a = addrs.FirstOrDefault();
- if (a == null)
+ if (a is null)
return null;
- return new MultiAddress((string)a);
+ return new MultiAddress((string)a!);
}
- public async Task> ListAddressFiltersAsync(bool persist = false, CancellationToken cancel = default(CancellationToken))
+ public async Task> ListAddressFiltersAsync(bool persist = false, CancellationToken cancel = default)
{
- JArray addrs;
+ JArray? addrs;
if (persist)
{
addrs = await ipfs.Config.GetAsync("Swarm.AddrFilters", cancel) as JArray;
@@ -104,23 +117,23 @@ internal SwarmApi(IpfsClient ipfs)
addrs = (JObject.Parse(json)["Strings"]) as JArray;
}
- if (addrs == null)
- return new MultiAddress[0];
+ if (addrs is null)
+ return Enumerable.Empty();
return addrs
- .Select(a => MultiAddress.TryCreate((string)a))
- .Where(ma => ma != null);
+ .Select(a => MultiAddress.TryCreate((string)a!))
+ .Where(ma => ma is not null)
+ .Cast();
}
- public async Task RemoveAddressFilterAsync(MultiAddress address, bool persist = false, CancellationToken cancel = default(CancellationToken))
+ public async Task RemoveAddressFilterAsync(MultiAddress address, bool persist = false, CancellationToken cancel = default)
{
// go-ipfs always does persist, https://github.com/ipfs/go-ipfs/issues/4605
var json = await ipfs.DoCommandAsync("swarm/filters/rm", cancel, address.ToString());
- var addrs = (JArray)(JObject.Parse(json)["Strings"]);
+ var addrs = (JArray?)(JObject.Parse(json)["Strings"]);
var a = addrs.FirstOrDefault();
- if (a == null)
+ if (a is null)
return null;
- return new MultiAddress((string)a);
+ return new MultiAddress((string)a!);
}
- }
-
-}
+ }
+}
diff --git a/src/FileSystemLink.cs b/src/FileSystemLink.cs
index 3315569..77e7162 100644
--- a/src/FileSystemLink.cs
+++ b/src/FileSystemLink.cs
@@ -5,8 +5,17 @@
///
public class FileSystemLink : IFileSystemLink
{
+ ///
+ /// Creates a new instance of .
+ ///
+ ///
+ public FileSystemLink(Cid id)
+ {
+ Id = id;
+ }
+
///
- public string Name { get; set; }
+ public string? Name { get; set; }
///
public Cid Id { get; set; }
diff --git a/src/FileSystemNode.cs b/src/FileSystemNode.cs
index 07bd148..3285548 100644
--- a/src/FileSystemNode.cs
+++ b/src/FileSystemNode.cs
@@ -1,157 +1,156 @@
-using System.Collections.Generic;
-using System.IO;
+using System;
+using System.Collections.Generic;
+using System.IO;
using System.Runtime.Serialization;
-
-namespace Ipfs.Http
-{
- ///
- [DataContract]
- public class FileSystemNode : IFileSystemNode
- {
- IpfsClient ipfsClient;
- IEnumerable links;
- long? size;
- bool? isDirectory;
-
- ///
- public byte[] DataBytes
- {
- get
- {
+
+namespace Ipfs.Http
+{
+ ///
+ [DataContract]
+ public class FileSystemNode : IFileSystemNode
+ {
+ private IpfsClient? ipfsClient;
+ private IEnumerable? links;
+ private long? size;
+ private bool? isDirectory;
+ private Cid? id;
+
+ ///
+ public byte[] DataBytes
+ {
+ get
+ {
using (var stream = DataStream)
{
- if (DataStream == null)
- return null;
+ if (stream is null)
+ return Array.Empty();
using (var data = new MemoryStream())
{
stream.CopyTo(data);
return data.ToArray();
- }
- }
- }
- }
-
- ///
- public Stream DataStream
- {
- get
- {
- return IpfsClient?.FileSystem.ReadFileAsync(Id).Result;
- }
- }
-
- ///
- [DataMember]
- public Cid Id { get; set; }
-
- ///
- [DataMember]
+ }
+ }
+ }
+ }
+
+ ///
+ public Stream DataStream => IpfsClient.FileSystem.ReadFileAsync(Id).GetAwaiter().GetResult();
+
+ ///
+ [DataMember]
+ public Cid Id
+ {
+ get => id ?? throw new InvalidDataException("Field mus be initialized");
+ set => id = value;
+ }
+
+ ///
+ [DataMember]
public IEnumerable Links
- {
- get
- {
- if (links == null) GetInfo();
- return links;
- }
- set
- {
- links = value;
- }
- }
-
- ///
- /// Size of the file contents.
- ///
- ///
- /// This is the size of the file not the raw encoded contents
- /// of the block.
- ///
- [DataMember]
- public long Size
- {
- get
- {
- if (!size.HasValue) GetInfo();
- return size.Value;
- }
- set
- {
- size = value;
- }
- }
-
- ///
- /// Determines if the link is a directory (folder).
- ///
- ///
- /// true if the link is a directory; Otherwise false,
- /// the link is some type of a file.
- ///
- [DataMember]
- public bool IsDirectory
- {
- get
- {
- if (!isDirectory.HasValue) GetInfo();
- return isDirectory.Value;
- }
- set
- {
- isDirectory = value;
- }
- }
-
- ///
- /// The file name of the IPFS node.
- ///
- [DataMember]
- public string Name { get; set; }
-
- ///
- public IFileSystemLink ToLink(string name = "")
- {
- var link = new FileSystemLink
- {
- Name = string.IsNullOrWhiteSpace(name) ? Name : name,
- Id = Id,
- Size = Size,
- };
- return link;
- }
-
+ {
+ get
+ {
+ if (links is null) GetInfo();
+ return links!;
+ }
+ set
+ {
+ links = value;
+ }
+ }
+
+ ///
+ /// Size of the file contents.
+ ///
+ ///
+ /// This is the size of the file not the raw encoded contents
+ /// of the block.
+ ///
+ [DataMember]
+ public long Size
+ {
+ get
+ {
+ if (!size.HasValue) GetInfo();
+ return size!.Value;
+ }
+ set
+ {
+ size = value;
+ }
+ }
+
+ ///
+ /// Determines if the link is a directory (folder).
+ ///
+ ///
+ /// true if the link is a directory; Otherwise false,
+ /// the link is some type of a file.
+ ///
+ [DataMember]
+ public bool IsDirectory
+ {
+ get
+ {
+ if (!isDirectory.HasValue) GetInfo();
+ return isDirectory!.Value;
+ }
+ set
+ {
+ isDirectory = value;
+ }
+ }
+
+ ///
+ /// The file name of the IPFS node.
+ ///
+ [DataMember]
+ public string? Name { get; set; }
+
+ ///
+ public IFileSystemLink ToLink(string name = "")
+ {
+ var link = new FileSystemLink(Id)
+ {
+ Name = string.IsNullOrWhiteSpace(name) ? Name : name,
+ Id = Id,
+ Size = Size,
+ };
+ return link;
+ }
+
///
/// The client to IPFS.
- ///
- ///
- /// Used to fetch additional information on the node.
- ///
- public IpfsClient IpfsClient
- {
- get
- {
- if (ipfsClient == null)
- {
- lock (this)
- {
- ipfsClient = new IpfsClient();
- }
- }
- return ipfsClient;
- }
- set
- {
- ipfsClient = value;
- }
- }
-
- void GetInfo()
- {
- var node = IpfsClient.FileSystem.ListFileAsync(Id).Result;
- this.IsDirectory = node.IsDirectory;
- this.Links = node.Links;
- this.Size = node.Size;
- }
-
- }
-}
+ ///
+ ///
+ /// Used to fetch additional information on the node.
+ ///
+ public IpfsClient IpfsClient
+ {
+ get
+ {
+ if (ipfsClient is null)
+ {
+ lock (this)
+ {
+ ipfsClient ??= new IpfsClient();
+ }
+ }
+ return ipfsClient;
+ }
+ set
+ {
+ ipfsClient = value;
+ }
+ }
+
+ void GetInfo()
+ {
+ var node = IpfsClient.FileSystem.ListFileAsync(Id).Result;
+ this.IsDirectory = node.IsDirectory;
+ this.Links = node.Links;
+ this.Size = node.Size;
+ }
+ }
+}
diff --git a/src/IpfsClient.cs b/src/IpfsClient.cs
index 2d4194e..7ff7304 100644
--- a/src/IpfsClient.cs
+++ b/src/IpfsClient.cs
@@ -26,10 +26,10 @@ namespace Ipfs.Http
///
public partial class IpfsClient : ICoreApi
{
- const string unknownFilename = "unknown";
+ private const string unknownFilename = "unknown";
- static object safe = new object();
- static HttpClient api = null;
+ private static readonly object safe = new object();
+ private static HttpClient? api;
///
/// The default URL to the IPFS HTTP API server.
@@ -42,7 +42,7 @@ public partial class IpfsClient : ICoreApi
///
public static Uri DefaultApiUri = new Uri(
Environment.GetEnvironmentVariable("IpfsHttpApi")
- ?? "http://localhost:5001");
+ ?? "http://localhost:1206");
///
/// Creates a new instance of the class and sets the
@@ -168,12 +168,12 @@ public IpfsClient(string host)
///
public IKeyApi Key { get; private set; }
- Uri BuildCommand(string command, string arg = null, params string[] options)
+ Uri BuildCommand(string command, string? arg = null, params string[] options)
{
var url = "/api/v0/" + command;
var q = new StringBuilder();
- if (arg != null)
+ if (arg is not null)
{
q.Append("&arg=");
q.Append(WebUtility.UrlEncode(arg));
@@ -206,21 +206,21 @@ Uri BuildCommand(string command, string arg = null, params string[] options)
}
///
- /// Get the IPFS API.
+ /// Get the IPFS API singleton.
///
///
/// A .
///
///
- /// Only one client is needed. Its thread safe.
+ /// Only one client is needed. It is thread safe.
///
HttpClient Api()
{
- if (api == null)
+ if (api is null)
{
lock (safe)
{
- if (api == null)
+ if (api is null)
{
if (HttpMessageHandler is HttpClientHandler handler && handler.SupportsAutomaticDecompression)
{
@@ -267,7 +267,7 @@ HttpClient Api()
///
/// When the IPFS server indicates an error.
///
- public async Task DoCommandAsync(string command, CancellationToken cancel, string arg = null, params string[] options)
+ public async Task DoCommandAsync(string command, CancellationToken cancel, string? arg = null, params string[] options)
{
var url = BuildCommand(command, arg, options);
@@ -304,7 +304,6 @@ internal async Task DoCommandAsync(Uri url, HttpContent content, CancellationTok
}
}
-
///
/// Perform an IPFS API command returning
/// a specific .
@@ -335,10 +334,13 @@ internal async Task DoCommandAsync(Uri url, HttpContent content, CancellationTok
///
/// When the IPFS server indicates an error.
///
- public async Task DoCommandAsync(string command, CancellationToken cancel, string arg = null, params string[] options)
+ ///
+ /// When the response body returned from the request cannot be parsed as valid JSON.
+ ///
+ public async Task DoCommandAsync(string command, CancellationToken cancel, string? arg = null, params string[] options)
{
var json = await DoCommandAsync(command, cancel, arg, options);
- return JsonConvert.DeserializeObject(json);
+ return JsonConvert.DeserializeObject(json) ?? throw new InvalidDataException($"String could not be decoded as JSON: {json}");
}
///
@@ -363,7 +365,7 @@ public async Task DoCommandAsync(string command, CancellationToken cancel,
///
/// When the IPFS server indicates an error.
///
- public async Task PostDownloadAsync(string command, CancellationToken cancel, string arg = null, params string[] options)
+ public async Task PostDownloadAsync(string command, CancellationToken cancel, string? arg = null, params string[] options)
{
var url = BuildCommand(command, arg, options);
@@ -398,7 +400,7 @@ public async Task PostDownloadAsync(string command, CancellationToken ca
///
/// When the IPFS server indicates an error.
///
- public async Task DownloadAsync(string command, CancellationToken cancel, string arg = null, params string[] options)
+ public async Task DownloadAsync(string command, CancellationToken cancel, string? arg = null, params string[] options)
{
var url = BuildCommand(command, arg, options);
@@ -431,7 +433,7 @@ public async Task DownloadAsync(string command, CancellationToken cancel
///
/// When the IPFS server indicates an error.
///
- public async Task DownloadBytesAsync(string command, CancellationToken cancel, string arg = null, params string[] options)
+ public async Task DownloadBytesAsync(string command, CancellationToken cancel, string? arg = null, params string[] options)
{
var url = BuildCommand(command, arg, options);
@@ -469,7 +471,7 @@ public async Task DownloadBytesAsync(string command, CancellationToken c
///
/// When the IPFS server indicates an error.
///
- public async Task UploadAsync(string command, CancellationToken cancel, Stream data, string name, params string[] options)
+ public async Task UploadAsync(string command, CancellationToken cancel, Stream data, string? name, params string[] options)
{
var content = new MultipartFormDataContent();
var streamContent = new StreamContent(data);
@@ -491,6 +493,7 @@ public async Task UploadAsync(string command, CancellationToken cancel,
return json;
}
}
+
///
/// Perform an IPFS API command that
/// requires uploading of a "file".
@@ -519,7 +522,7 @@ public async Task UploadAsync(string command, CancellationToken cancel,
///
/// When the IPFS server indicates an error.
///
- public async Task Upload2Async(string command, CancellationToken cancel, Stream data, string name, params string[] options)
+ public async Task Upload2Async(string command, CancellationToken cancel, Stream data, string? name, params string[] options)
{
var content = new MultipartFormDataContent();
var streamContent = new StreamContent(data);
@@ -589,7 +592,10 @@ async Task ThrowOnErrorAsync(HttpResponseMessage response)
try
{
var res = JsonConvert.DeserializeObject(body);
- message = (string)res.Message;
+ if (res is not null)
+ {
+ message = (string)res.Message;
+ }
}
catch { }
diff --git a/src/IpfsHttpClient.csproj b/src/IpfsHttpClient.csproj
index 1472560..2b053cc 100644
--- a/src/IpfsHttpClient.csproj
+++ b/src/IpfsHttpClient.csproj
@@ -6,10 +6,9 @@
Ipfs.Http
bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml
full
- true
- 0.0.6
+ 0.0.7
$(Version)
@@ -46,7 +45,7 @@
-
+
diff --git a/src/MerkleNode.cs b/src/MerkleNode.cs
index 33332e1..2d1c39c 100644
--- a/src/MerkleNode.cs
+++ b/src/MerkleNode.cs
@@ -1,4 +1,5 @@
-using System;
+using Org.BouncyCastle.Bcpg.OpenPgp;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
@@ -16,9 +17,9 @@ public class MerkleNode : IMerkleNode, IEquatable
{
bool hasBlockStats;
long blockSize;
- string name;
- IEnumerable links;
- IpfsClient ipfsClient;
+ string name = string.Empty;
+ IEnumerable? links;
+ IpfsClient? ipfsClient;
///
/// Creates a new instance of the with the specified
@@ -28,13 +29,10 @@ public class MerkleNode : IMerkleNode, IEquatable
/// The of the node.
///
/// A name for the node.
- public MerkleNode(Cid id, string name = null)
+ public MerkleNode(Cid id, string? name = null)
{
- if (id == null)
- throw new ArgumentNullException("id");
-
Id = id;
- Name = name;
+ Name = name ?? string.Empty;
}
///
@@ -45,7 +43,7 @@ public MerkleNode(Cid id, string name = null)
/// The string representation of a of the node or "/ipfs/cid".
///
/// A name for the node.
- public MerkleNode(string path, string name = null)
+ public MerkleNode(string path, string? name = null)
{
if (string.IsNullOrWhiteSpace(path))
throw new ArgumentNullException("path");
@@ -54,7 +52,7 @@ public MerkleNode(string path, string name = null)
path = path.Substring(6);
Id = Cid.Decode(path);
- Name = name;
+ Name = name ?? string.Empty;
}
///
@@ -65,7 +63,7 @@ public MerkleNode(string path, string name = null)
public MerkleNode(IMerkleLink link)
{
Id = link.Id;
- Name = link.Name;
+ Name = link.Name ?? string.Empty;
blockSize = link.Size;
hasBlockStats = true;
}
@@ -74,7 +72,7 @@ internal IpfsClient IpfsClient
{
get
{
- if (ipfsClient == null)
+ if (ipfsClient is null)
{
lock (this)
{
@@ -134,11 +132,7 @@ public IEnumerable Links
{
get
{
- if (links == null)
- {
- links = IpfsClient.Object.LinksAsync(Id).Result;
- }
-
+ links ??= IpfsClient.Object.LinksAsync(Id).GetAwaiter().GetResult();
return links;
}
}
@@ -163,7 +157,7 @@ public Stream DataStream
}
///
- public IMerkleLink ToLink(string name = null)
+ public IMerkleLink ToLink(string? name = null)
{
return new DagLink(name ?? Name, Id, BlockSize);
}
@@ -192,26 +186,26 @@ public override int GetHashCode()
}
///
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
{
var that = obj as MerkleNode;
- return that != null && this.Id == that.Id;
+ return that is not null && this.Id == that.Id;
}
///
- public bool Equals(MerkleNode that)
+ public bool Equals(MerkleNode? that)
{
- return that != null && this.Id == that.Id;
+ return that is not null && this.Id == that.Id;
}
///
/// TODO
///
- public static bool operator ==(MerkleNode a, MerkleNode b)
+ public static bool operator ==(MerkleNode? a, MerkleNode? b)
{
if (object.ReferenceEquals(a, b)) return true;
- if (object.ReferenceEquals(a, null)) return false;
- if (object.ReferenceEquals(b, null)) return false;
+ if (a is null) return false;
+ if (b is null) return false;
return a.Equals(b);
}
@@ -219,13 +213,9 @@ public bool Equals(MerkleNode that)
///
/// TODO
///
- public static bool operator !=(MerkleNode a, MerkleNode b)
+ public static bool operator !=(MerkleNode? a, MerkleNode? b)
{
- if (object.ReferenceEquals(a, b)) return false;
- if (object.ReferenceEquals(a, null)) return true;
- if (object.ReferenceEquals(b, null)) return true;
-
- return !a.Equals(b);
+ return !(a == b);
}
///
diff --git a/src/PublishedMessage.cs b/src/PublishedMessage.cs
index ca257ca..9dbb933 100644
--- a/src/PublishedMessage.cs
+++ b/src/PublishedMessage.cs
@@ -29,12 +29,12 @@ public PublishedMessage(string json)
{
var o = JObject.Parse(json);
- this.Sender = (string)o["from"];
- this.SequenceNumber = Multibase.Decode((string)o["seqno"], out MultibaseEncoding _);
- this.DataBytes = Multibase.Decode((string)o["data"], out MultibaseEncoding _);
+ this.Sender = (string)o["from"]!;
+ this.SequenceNumber = Multibase.Decode((string?)o["seqno"], out MultibaseEncoding _);
+ this.DataBytes = Multibase.Decode((string?)o["data"], out MultibaseEncoding _);
- var topics = (JArray) (o["topicIDs"]);
- this.Topics = topics.Select(t => Encoding.UTF8.GetString(Multibase.Decode((string)t, out MultibaseEncoding _)));
+ var topics = (JArray?) (o["topicIDs"]);
+ this.Topics = topics.Select(t => Encoding.UTF8.GetString(Multibase.Decode((string?)t, out MultibaseEncoding _)));
}
///
diff --git a/src/TrustedPeerCollection.cs b/src/TrustedPeerCollection.cs
index 61e6e88..45dc2ac 100644
--- a/src/TrustedPeerCollection.cs
+++ b/src/TrustedPeerCollection.cs
@@ -21,11 +21,11 @@ public class TrustedPeerCollection : ICollection
{
class BootstrapListResponse
{
- public MultiAddress[] Peers { get; set; }
+ public MultiAddress[] Peers { get; set; } = Array.Empty();
}
- IpfsClient ipfs;
- MultiAddress[] peers;
+ private readonly IpfsClient ipfs;
+ MultiAddress[]? peers;
internal TrustedPeerCollection(IpfsClient ipfs)
{
@@ -35,10 +35,7 @@ internal TrustedPeerCollection(IpfsClient ipfs)
///
public void Add(MultiAddress peer)
{
- if (peer == null)
- throw new ArgumentNullException();
-
- ipfs.DoCommandAsync("bootstrap/add", default(CancellationToken), peer.ToString()).Wait();
+ ipfs.DoCommandAsync("bootstrap/add", CancellationToken.None, peer.ToString()).Wait();
peers = null;
}
@@ -50,7 +47,7 @@ public void Add(MultiAddress peer)
///
public void AddDefaultNodes()
{
- ipfs.DoCommandAsync("bootstrap/add", default(CancellationToken), null, "default=true").Wait();
+ ipfs.DoCommandAsync("bootstrap/add", CancellationToken.None, arg: null, "default=true").Wait();
peers = null;
}
@@ -62,7 +59,7 @@ public void AddDefaultNodes()
///
public void Clear()
{
- ipfs.DoCommandAsync("bootstrap/rm", default(CancellationToken), null, "all=true").Wait();
+ ipfs.DoCommandAsync("bootstrap/rm", CancellationToken.None, arg: null, "all=true").Wait();
peers = null;
}
@@ -77,7 +74,7 @@ public bool Contains(MultiAddress item)
public void CopyTo(MultiAddress[] array, int index)
{
Fetch();
- peers.CopyTo(array, index);
+ peers!.CopyTo(array, index);
}
///
@@ -85,7 +82,7 @@ public int Count
{
get
{
- if (peers == null)
+ if (peers is null)
Fetch();
return peers.Count();
}
@@ -105,10 +102,7 @@ public bool IsReadOnly
///
public bool Remove(MultiAddress peer)
{
- if (peer == null)
- throw new ArgumentNullException();
-
- ipfs.DoCommandAsync("bootstrap/rm", default(CancellationToken), peer.ToString()).Wait();
+ ipfs.DoCommandAsync("bootstrap/rm", CancellationToken.None, peer.ToString()).Wait();
peers = null;
return true;
}
@@ -117,19 +111,19 @@ public bool Remove(MultiAddress peer)
public IEnumerator GetEnumerator()
{
Fetch();
- return ((IEnumerable)peers).GetEnumerator();
+ return ((IEnumerable)peers!).GetEnumerator();
}
///
IEnumerator IEnumerable.GetEnumerator()
{
Fetch();
- return peers.GetEnumerator();
+ return peers!.GetEnumerator();
}
void Fetch()
{
- peers = ipfs.DoCommandAsync("bootstrap/list", default(CancellationToken)).Result.Peers;
+ peers = ipfs.DoCommandAsync("bootstrap/list", CancellationToken.None).GetAwaiter().GetResult().Peers;
}
}
}
diff --git a/test/BlockTest.cs b/test/BlockTest.cs
index 8db34c8..f04eeb7 100644
--- a/test/BlockTest.cs
+++ b/test/BlockTest.cs
@@ -30,6 +30,5 @@ public void DataStream()
Assert.AreEqual(3, stream.ReadByte());
Assert.AreEqual(-1, stream.ReadByte(), "at eof");
}
-
}
}
diff --git a/test/CoreApi/BitswapApiTest.cs b/test/CoreApi/BitswapApiTest.cs
index 1561aaa..ebf0720 100644
--- a/test/CoreApi/BitswapApiTest.cs
+++ b/test/CoreApi/BitswapApiTest.cs
@@ -1,34 +1,37 @@
-using Ipfs.Http;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using System.IO;
+using System;
using System.Linq;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Ipfs.Http
{
[TestClass]
- public class BitswapApiTest
+ public sealed class BitswapApiTest
{
- private IpfsClient ipfs = TestFixture.Ipfs;
+ private readonly IpfsClient ipfs = TestFixture.Ipfs;
[TestMethod]
public async Task Wants()
{
var block = new DagNode(Encoding.UTF8.GetBytes("BitswapApiTest unknown block"));
-#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
- Task.Run(() => ipfs.Bitswap.GetAsync(block.Id).Wait());
-
- var endTime = DateTime.Now.AddSeconds(10);
- while (DateTime.Now < endTime)
- {
- await Task.Delay(100);
- var wants = await ipfs.Bitswap.WantsAsync();
- if (wants.Contains(block.Id))
- return;
- }
- Assert.Fail("wanted block is missing");
+ await RunAsyncTaskAndTestAsync(
+ ct => ipfs.Bitswap.GetAsync(block.Id, ct),
+ async () =>
+ {
+ var endTime = DateTime.Now.AddSeconds(10);
+ while (DateTime.Now < endTime)
+ {
+ await Task.Delay(100);
+ var wants = await ipfs.Bitswap.WantsAsync();
+ if (wants.Contains(block.Id))
+ {
+ return;
+ }
+ }
+ Assert.Fail("wanted block is missing");
+ });
}
[TestMethod]
@@ -36,31 +39,33 @@ public async Task Wants()
public async Task Unwant()
{
var block = new DagNode(Encoding.UTF8.GetBytes("BitswapApiTest unknown block 2"));
-#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
- Task.Run(() => ipfs.Bitswap.GetAsync(block.Id).Wait());
-
- var endTime = DateTime.Now.AddSeconds(10);
- while (true)
- {
- if (DateTime.Now > endTime)
- Assert.Fail("wanted block is missing");
- await Task.Delay(100);
- var wants = await ipfs.Bitswap.WantsAsync();
- if (wants.Contains(block.Id))
- break;
- }
+ await RunAsyncTaskAndTestAsync(
+ ct => ipfs.Bitswap.GetAsync(block.Id, ct),
+ async () =>
+ {
+ var endTime = DateTime.Now.AddSeconds(10);
+ while (true)
+ {
+ if (DateTime.Now > endTime)
+ Assert.Fail("wanted block is missing");
+ await Task.Delay(100);
+ var wants = await ipfs.Bitswap.WantsAsync();
+ if (wants.Contains(block.Id))
+ break;
+ }
- await ipfs.Bitswap.UnwantAsync(block.Id);
- endTime = DateTime.Now.AddSeconds(10);
- while (true)
- {
- if (DateTime.Now > endTime)
- Assert.Fail("unwanted block is present");
- await Task.Delay(100);
- var wants = await ipfs.Bitswap.WantsAsync();
- if (!wants.Contains(block.Id))
- break;
- }
+ await ipfs.Bitswap.UnwantAsync(block.Id);
+ endTime = DateTime.Now.AddSeconds(10);
+ while (true)
+ {
+ if (DateTime.Now > endTime)
+ Assert.Fail("unwanted block is present");
+ await Task.Delay(100);
+ var wants = await ipfs.Bitswap.WantsAsync();
+ if (!wants.Contains(block.Id))
+ break;
+ }
+ });
}
[TestMethod]
@@ -69,7 +74,29 @@ public async Task Ledger()
var peer = new Peer { Id = "QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3" };
var ledger = await ipfs.Bitswap.LedgerAsync(peer);
Assert.IsNotNull(ledger);
- Assert.AreEqual(peer.Id, ledger.Peer.Id);
+ Assert.IsNotNull(ledger.Peer);
+ Assert.AreEqual(peer.Id, ledger.Peer!.Id);
+ }
+
+ private static async Task RunAsyncTaskAndTestAsync(Func asyncTaskWork, Func testWork)
+ {
+ var cts = new CancellationTokenSource();
+ var asyncTask = Task.Run(async () => await asyncTaskWork(cts.Token));
+ try
+ {
+ await testWork();
+ }
+ finally
+ {
+ cts.Cancel();
+ try
+ {
+ await asyncTask;
+ }
+ catch
+ {
+ }
+ }
}
}
}
diff --git a/test/CoreApi/BlockApiTest.cs b/test/CoreApi/BlockApiTest.cs
index 5f5c232..c2e3aac 100644
--- a/test/CoreApi/BlockApiTest.cs
+++ b/test/CoreApi/BlockApiTest.cs
@@ -1,5 +1,4 @@
-using Ipfs.Http;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Linq;
@@ -11,109 +10,109 @@ namespace Ipfs.Http
[TestClass]
public class BlockApiTest
{
- private IpfsClient ipfs = TestFixture.Ipfs;
- private string id = "QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ";
- private byte[] blob = Encoding.UTF8.GetBytes("blorb");
+ private readonly IpfsClient ipfs = TestFixture.Ipfs;
+ private const string id = "bafkreiaxnnnb7qz2focittuqq3ya25q7rcv3bqynnczfzako47346wosmu";
+ private readonly byte[] blob = Encoding.UTF8.GetBytes("blorb");
[TestMethod]
- public void Put_Bytes()
+ public async Task Put_Bytes()
{
- var cid = ipfs.Block.PutAsync(blob).Result;
+ var cid = await ipfs.Block.PutAsync(blob);
Assert.AreEqual(id, (string)cid);
- var data = ipfs.Block.GetAsync(cid).Result;
+ var data = await ipfs.Block.GetAsync(cid);
Assert.AreEqual(blob.Length, data.Size);
CollectionAssert.AreEqual(blob, data.DataBytes);
}
[TestMethod]
- public void Put_Bytes_ContentType()
+ public async Task Put_Bytes_ContentType()
{
- var cid = ipfs.Block.PutAsync(blob, contentType: "raw").Result;
+ var cid = await ipfs.Block.PutAsync(blob, contentType: "raw");
Assert.AreEqual("bafkreiaxnnnb7qz2focittuqq3ya25q7rcv3bqynnczfzako47346wosmu", (string)cid);
- var data = ipfs.Block.GetAsync(cid).Result;
+ var data = await ipfs.Block.GetAsync(cid);
Assert.AreEqual(blob.Length, data.Size);
CollectionAssert.AreEqual(blob, data.DataBytes);
}
[TestMethod]
- public void Put_Bytes_Hash()
+ public async Task Put_Bytes_Hash()
{
- var cid = ipfs.Block.PutAsync(blob, "raw", "sha2-512").Result;
+ var cid = await ipfs.Block.PutAsync(blob, "raw", "sha2-512");
Assert.AreEqual("bafkrgqelljziv4qfg5mefz36m2y3h6voaralnw6lwb4f53xcnrf4mlsykkn7vt6eno547tw5ygcz62kxrle45wnbmpbofo5tvu57jvuaf7k7e", (string)cid);
- var data = ipfs.Block.GetAsync(cid).Result;
+ var data = await ipfs.Block.GetAsync(cid);
Assert.AreEqual(blob.Length, data.Size);
CollectionAssert.AreEqual(blob, data.DataBytes);
}
[TestMethod]
- public void Put_Bytes_Pinned()
+ public async Task Put_Bytes_Pinned()
{
var data1 = new byte[] { 23, 24, 127 };
- var cid1 = ipfs.Block.PutAsync(data1, contentType: "raw", pin: true).Result;
- var pins = ipfs.Pin.ListAsync().Result;
+ var cid1 = await ipfs.Block.PutAsync(data1, contentType: "raw", pin: true);
+ var pins = await ipfs.Pin.ListAsync();
Assert.IsTrue(pins.Any(pin => pin == cid1));
var data2 = new byte[] { 123, 124, 27 };
- var cid2 = ipfs.Block.PutAsync(data2, contentType: "raw", pin: false).Result;
- pins = ipfs.Pin.ListAsync().Result;
+ var cid2 = await ipfs.Block.PutAsync(data2, contentType: "raw", pin: false);
+ pins = await ipfs.Pin.ListAsync();
Assert.IsFalse(pins.Any(pin => pin == cid2));
}
[TestMethod]
- public void Put_Stream()
+ public async Task Put_Stream()
{
- var cid = ipfs.Block.PutAsync(new MemoryStream(blob)).Result;
+ var cid = await ipfs.Block.PutAsync(new MemoryStream(blob));
Assert.AreEqual(id, (string)cid);
- var data = ipfs.Block.GetAsync(cid).Result;
+ var data = await ipfs.Block.GetAsync(cid);
Assert.AreEqual(blob.Length, data.Size);
CollectionAssert.AreEqual(blob, data.DataBytes);
}
[TestMethod]
- public void Put_Stream_ContentType()
+ public async Task Put_Stream_ContentType()
{
- var cid = ipfs.Block.PutAsync(new MemoryStream(blob), contentType: "raw").Result;
+ var cid = await ipfs.Block.PutAsync(new MemoryStream(blob), contentType: "raw");
Assert.AreEqual("bafkreiaxnnnb7qz2focittuqq3ya25q7rcv3bqynnczfzako47346wosmu", (string)cid);
- var data = ipfs.Block.GetAsync(cid).Result;
+ var data = await ipfs.Block.GetAsync(cid);
Assert.AreEqual(blob.Length, data.Size);
CollectionAssert.AreEqual(blob, data.DataBytes);
}
[TestMethod]
- public void Put_Stream_Hash()
+ public async Task Put_Stream_Hash()
{
- var cid = ipfs.Block.PutAsync(new MemoryStream(blob), "raw", "sha2-512").Result;
+ var cid = await ipfs.Block.PutAsync(new MemoryStream(blob), "raw", "sha2-512");
Assert.AreEqual("bafkrgqelljziv4qfg5mefz36m2y3h6voaralnw6lwb4f53xcnrf4mlsykkn7vt6eno547tw5ygcz62kxrle45wnbmpbofo5tvu57jvuaf7k7e", (string)cid);
- var data = ipfs.Block.GetAsync(cid).Result;
+ var data = await ipfs.Block.GetAsync(cid);
Assert.AreEqual(blob.Length, data.Size);
CollectionAssert.AreEqual(blob, data.DataBytes);
}
[TestMethod]
- public void Put_Stream_Pinned()
+ public async Task Put_Stream_Pinned()
{
var data1 = new MemoryStream(new byte[] { 23, 24, 127 });
- var cid1 = ipfs.Block.PutAsync(data1, contentType: "raw", pin: true).Result;
- var pins = ipfs.Pin.ListAsync().Result;
+ var cid1 = await ipfs.Block.PutAsync(data1, contentType: "raw", pin: true);
+ var pins = await ipfs.Pin.ListAsync();
Assert.IsTrue(pins.Any(pin => pin == cid1));
var data2 = new MemoryStream(new byte[] { 123, 124, 27 });
- var cid2 = ipfs.Block.PutAsync(data2, contentType: "raw", pin: false).Result;
- pins = ipfs.Pin.ListAsync().Result;
+ var cid2 = await ipfs.Block.PutAsync(data2, contentType: "raw", pin: false);
+ pins = await ipfs.Pin.ListAsync();
Assert.IsFalse(pins.Any(pin => pin == cid2));
}
[TestMethod]
- public void Get()
+ public async Task Get()
{
- var _ = ipfs.Block.PutAsync(blob).Result;
- var block = ipfs.Block.GetAsync(id).Result;
+ var _ = await ipfs.Block.PutAsync(blob);
+ var block = await ipfs.Block.GetAsync(id);
Assert.AreEqual(id, (string)block.Id);
CollectionAssert.AreEqual(blob, block.DataBytes);
var blob1 = new byte[blob.Length];
@@ -122,10 +121,10 @@ public void Get()
}
[TestMethod]
- public void Stat()
+ public async Task Stat()
{
- var _ = ipfs.Block.PutAsync(blob).Result;
- var info = ipfs.Block.StatAsync(id).Result;
+ var _ = await ipfs.Block.PutAsync(blob);
+ var info = await ipfs.Block.StatAsync(id);
Assert.AreEqual(id, (string)info.Id);
Assert.AreEqual(5, info.Size);
}
@@ -133,22 +132,23 @@ public void Stat()
[TestMethod]
public async Task Remove()
{
- var _ = ipfs.Block.PutAsync(blob).Result;
+ var _ = await ipfs.Block.PutAsync(blob);
var cid = await ipfs.Block.RemoveAsync(id);
- Assert.AreEqual(id, (string)cid);
+ Assert.IsNotNull(cid);
+ Assert.AreEqual(id, (string)cid!);
}
[TestMethod]
public void Remove_Unknown()
{
- ExceptionAssert.Throws(() => { var _ = ipfs.Block.RemoveAsync("QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rFF").Result; });
+ ExceptionAssert.Throws(() => { var _ = ipfs.Block.RemoveAsync("QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rFF").GetAwaiter().GetResult(); });
}
[TestMethod]
public async Task Remove_Unknown_OK()
{
- var cid = await ipfs.Block.RemoveAsync("QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rFF", true);
+ var cid = await ipfs.Block.RemoveAsync("QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rFF", ignoreNonexistent: true);
+ Assert.IsNull(cid);
}
-
}
}
diff --git a/test/CoreApi/BlockRepositoryTest.cs b/test/CoreApi/BlockRepositoryTest.cs
index b28bb1d..5848eb8 100644
--- a/test/CoreApi/BlockRepositoryTest.cs
+++ b/test/CoreApi/BlockRepositoryTest.cs
@@ -21,6 +21,5 @@ public async Task Version()
var version = await ipfs.BlockRepository.VersionAsync();
Assert.IsFalse(string.IsNullOrWhiteSpace(version));
}
-
}
}
diff --git a/test/CoreApi/BootstrapTest.cs b/test/CoreApi/BootstrapTest.cs
index 702a801..1d16a13 100644
--- a/test/CoreApi/BootstrapTest.cs
+++ b/test/CoreApi/BootstrapTest.cs
@@ -7,8 +7,8 @@ namespace Ipfs.Http
[TestClass]
public class BootstapApiTest
{
- IpfsClient ipfs = TestFixture.Ipfs;
- MultiAddress somewhere = "/ip4/127.0.0.1/tcp/4009/ipfs/QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ";
+ private readonly IpfsClient ipfs = TestFixture.Ipfs;
+ private readonly MultiAddress somewhere = "/ip4/127.0.0.1/tcp/4009/ipfs/QmPv52ekjS75L4JmHpXVeuJ5uX2ecSfSZo88NSyxwA3rAQ";
[TestMethod]
public async Task Add_Remove()
diff --git a/test/CoreApi/ConfigApiTest.cs b/test/CoreApi/ConfigApiTest.cs
index 0fb20c6..869e8d6 100644
--- a/test/CoreApi/ConfigApiTest.cs
+++ b/test/CoreApi/ConfigApiTest.cs
@@ -16,7 +16,7 @@ public void Get_Entire_Config()
{
IpfsClient ipfs = TestFixture.Ipfs;
var config = ipfs.Config.GetAsync().Result;
- StringAssert.StartsWith(config["Addresses"]["API"].Value(), apiAddress);
+ StringAssert.StartsWith(config["Addresses"]!["API"]!.Value(), apiAddress);
}
[TestMethod]
@@ -32,8 +32,8 @@ public void Get_Object_Key_Value()
{
IpfsClient ipfs = TestFixture.Ipfs;
var addresses = ipfs.Config.GetAsync("Addresses").Result;
- StringAssert.StartsWith(addresses["API"].Value(), apiAddress);
- StringAssert.StartsWith(addresses["Gateway"].Value(), gatewayAddress);
+ StringAssert.StartsWith(addresses["API"]!.Value(), apiAddress);
+ StringAssert.StartsWith(addresses["Gateway"]!.Value