Compare commits
70 commits
Author | SHA1 | Date | |
---|---|---|---|
|
b1f7d607ee | ||
|
a271e08996 | ||
|
028223e46a | ||
|
4d46d86514 | ||
|
4c457c1dd3 | ||
|
3b178a142d | ||
|
c2f2c0c2da | ||
|
c434fbd160 | ||
|
86d3cd422e | ||
|
58a6240af9 | ||
|
7c6bd1e36b | ||
|
d6877b995c | ||
|
603ed1d72f | ||
|
f0961a247f | ||
|
c96c1db14c | ||
|
4cbcf6be3d | ||
|
615adc86ef | ||
|
e9636e642f | ||
|
e90434ba61 | ||
|
d09c4a0d76 | ||
|
e935335964 | ||
|
7fb89918f8 | ||
|
e914307a4d | ||
|
0bbca7bc27 | ||
|
7da26ca04d | ||
|
ba234206a2 | ||
|
6274997560 | ||
|
2dab592164 | ||
|
10302dd4b1 | ||
|
43a19d7c61 | ||
|
2a470ee856 | ||
|
0b8789ebbc | ||
|
4e281ddd08 | ||
|
fcb0cce437 | ||
|
f2d1a5aa83 | ||
|
5cb09b3708 | ||
|
29a68c8f55 | ||
|
b7f3d475e3 | ||
|
9a9c5ea1c3 | ||
|
cc8ff45cc1 | ||
|
bb488f7e82 | ||
|
78ce39b067 | ||
|
d57e026fbf | ||
|
48648fb6cd | ||
|
7159bd4641 | ||
|
364bc72a54 | ||
|
ee1cf1359c | ||
|
fa1084b45c | ||
|
50dbd5f765 | ||
|
68ca649688 | ||
|
edb7475318 | ||
|
877d71acaa | ||
|
4bb95063a9 | ||
|
fb56ba584a | ||
|
64fd480954 | ||
|
b11ecd51c5 | ||
|
38b7966a10 | ||
|
6f14f96982 | ||
|
4cddac37a3 | ||
|
d7a90c513d | ||
|
7574846553 | ||
|
5bc0d88bf1 | ||
|
36f4f4e1b8 | ||
|
483957077e | ||
|
7b1ed7a4a4 | ||
|
b29bbee5a1 | ||
|
ebc0e05b8b | ||
|
148523117b | ||
|
b68cb78ce1 | ||
|
c333fd7d78 |
23 changed files with 2848 additions and 0 deletions
78
.cproject
Normal file
78
.cproject
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.663343487">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.663343487" moduleId="org.eclipse.cdt.core.settings" name="Default">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration buildProperties="" id="cdt.managedbuild.toolchain.gnu.base.663343487" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
|
||||
<folderInfo id="cdt.managedbuild.toolchain.gnu.base.663343487.1554761701" name="/" resourcePath="">
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.base.1976366028" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.GNU_ELF" id="cdt.managedbuild.target.gnu.platform.base.790917044" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
|
||||
<builder id="cdt.managedbuild.target.gnu.builder.base.667198033" managedBuildOn="false" name="Gnu Make Builder.Default" superClass="cdt.managedbuild.target.gnu.builder.base"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.archiver.base.1340147019" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1587295855" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.548918774" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1621016424" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.c.linker.base.298540641" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base">
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.1326462310" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
|
||||
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
|
||||
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
|
||||
</inputType>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.107597551" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.assembler.base.1765741010" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1331876933" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="c-multiaddr.null.2082036538" name="c-multiaddr"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="refreshScope"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
|
||||
<buildTargets>
|
||||
<target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildTarget>all</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildTarget>clean</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="rebuild" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>rebuild</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
</buildTargets>
|
||||
</storageModule>
|
||||
</cproject>
|
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
*
|
||||
|
||||
!.gitignore
|
||||
!Makefile
|
||||
!**/
|
||||
|
||||
*.o
|
||||
*.a
|
||||
.settings/language.settings.xml
|
||||
test_multiaddr
|
||||
|
26
.project
Normal file
26
.project
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>c-multiaddr</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
24
LICENSE
Normal file
24
LICENSE
Normal file
|
@ -0,0 +1,24 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 AGORISE, LTD.
|
||||
An International Business Company, Cyprus Reg# ΗΕ375959
|
||||
|
||||
Contains works from BitShares Munich IVS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
33
Makefile
Normal file
33
Makefile
Normal file
|
@ -0,0 +1,33 @@
|
|||
CC = gcc
|
||||
CFLAGS = -O0 -I include -std=c99
|
||||
|
||||
DEBUG = true
|
||||
|
||||
|
||||
ifdef DEBUG
|
||||
CFLAGS += -g3
|
||||
endif
|
||||
|
||||
LFLAGS = -lm
|
||||
DEPS = include/multiaddr/base58.h include/multiaddr/endian.h include/multiaddr/multiaddr.h \
|
||||
include/multiaddr/protocols.h include/multiaddr/protoutils.h include/multiaddr/varhexutils.h \
|
||||
include/multiaddr/varint.h
|
||||
OBJS = base58.o varint.o varhexutils.o protoutils.o protocols.o multiaddr.o
|
||||
|
||||
%.o: %.c $(DEPS)
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
libmultiaddr.a: $(OBJS)
|
||||
ar rcs $@ $^
|
||||
|
||||
test_multiaddr: testing.o libmultiaddr.a
|
||||
$(CC) -o $@ $^ $(LFLAGS)
|
||||
|
||||
all: test_multiaddr
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f libmultiaddr.a
|
||||
rm -f test_multiaddr
|
||||
|
||||
rebuild: clean all
|
32
README.md
32
README.md
|
@ -1,2 +1,34 @@
|
|||
# c-multiaddr
|
||||
multiaddr for IPFS in C.
|
||||
|
||||
### Multiaddr provides easy networking protocols nesting, easy encapsulation of extra protocols, easy tunneling, etc.
|
||||
# Usage:
|
||||
#### All you need to include is multiaddr.h
|
||||
## Maddr struct:
|
||||
* char * string; // String that contains addresses such as /ip4/192.168.1.1/
|
||||
* uint8_t * bytes; // uint8_t * that contains the enecoded address
|
||||
* size_t bsize; //size_t that contains the real bytes size (Use it whenever using the bytes so you don't input trash!)
|
||||
|
||||
## New Multi Address From String(multiaddress_new_from_string)
|
||||
struct MultiAddress* a = multiaddress_new_from_string("/ip4/127.0.0.1/tcp/8080/");
|
||||
## Obtaining the byte buffer(.bytes, .bsize[0]):
|
||||
printf("TEST BYTES: %s\n",Var_To_Hex(a->bsize, a->bytes));
|
||||
Var_To_Hex = Byte Buffer to Hex String
|
||||
Hex_To_Var = Hex String to Byte Buffer
|
||||
## Encapsulation & Decapsulation(m_encapsulate, m_decapsulate)
|
||||
#### Remember, Decapsulation happens from right to left, never in reverse, if you have /ip4/udp/ipfs/ if you decapsulate "udp" you will also take out ipfs!
|
||||
* Now the string is: /ip4/192.168.1.1/
|
||||
* multiaddress_encapsulate(a,"/udp/3333/"); //Adds udp/3333/
|
||||
* Now the string is: /ip4/192.168.1.1/udp/3333/
|
||||
* multiaddress_decapsulate(a,"udp"); //Removes udp protocol and its address
|
||||
* Now the string is: /ip4/192.168.1.1/
|
||||
* multiaddress_encapsulate(a,"/tcp/8080");
|
||||
* Now the string is: /ip4/192.168.1.1/tcp/8080/
|
||||
|
||||
# Constructing a multiaddress from bytes:
|
||||
|
||||
* struct MultiAddress* beta;
|
||||
* beta = multiaddress_new_from_bytes(a->bytes,a->bsize); //This will already construct back to the string too!
|
||||
* printf("B STRING: %s\n",beta->string); //So after encapsulation and decapsulation atm this string would
|
||||
* contain: /ip4/192.168.1.1/tcp/8080/
|
||||
|
||||
|
|
15
STATUS.md
Normal file
15
STATUS.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# STATUS:
|
||||
* Compatibility: Windows/Mac/Linux/Openbsd based systems (probably more)
|
||||
* Finished Base58.h Encryption/Decryption Algorhytm
|
||||
* Finished Endian.h Library for automating compiling for Linux/Mac/Windows
|
||||
* Finished Varhexutils - Different conversion algorhytms between bytes and strings etc.
|
||||
* Finsihed Varint.h - Conversion from Hex
|
||||
* Finished Protocols.h - Library for loading protocols & manipulating them easily.
|
||||
* Finished: Multiaddr.h (easy library for developers)
|
||||
* Finished: Protoutils.h Converting from string to hex/binary, analizing strings/bin for validity,parsing ipv4,etc.
|
||||
* Finished: Readme - Documentation on how to use everything so any new developer can easily use all of this
|
||||
# Secondary things that might need to be implemented:
|
||||
* Protocols, everything except IP4,TCP,UDP,IPFS - These we actually need.
|
||||
* Few issues that are not urgent:
|
||||
- Decapsulation of tunneled protocols doesn't work, this will be fixed if needed in multiaddr.h/m_decapsulate
|
||||
- Endianness Check - protoutils.h/in protocols UDP,TCP
|
200
base58.c
Normal file
200
base58.c
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright 2012-2014 Luke Dashjr
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the standard MIT license. See COPYING for more details.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
|
||||
static const int8_t b58digits_map[] = {
|
||||
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
|
||||
-1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1,
|
||||
22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1,
|
||||
-1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46,
|
||||
47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,
|
||||
};
|
||||
|
||||
/**
|
||||
* convert a base58 encoded string into a binary array
|
||||
* @param b58 the base58 encoded string
|
||||
* @param base58_size the size of the encoded string
|
||||
* @param bin the results buffer
|
||||
* @param binszp the size of the results buffer
|
||||
* @returns true(1) on success
|
||||
*/
|
||||
int multiaddr_encoding_base58_decode(const char* b58, size_t base58_size, unsigned char** bin, size_t* binszp)
|
||||
{
|
||||
size_t binsz = *binszp;
|
||||
const unsigned char* b58u = (const void*)b58;
|
||||
unsigned char* binu = *bin;
|
||||
size_t outisz = (binsz + 3) / 4;
|
||||
uint32_t outi[outisz];
|
||||
uint64_t t;
|
||||
uint32_t c;
|
||||
size_t i, j;
|
||||
uint8_t bytesleft = binsz % 4;
|
||||
uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
|
||||
unsigned zerocount = 0;
|
||||
size_t b58sz;
|
||||
|
||||
b58sz = strlen(b58);
|
||||
|
||||
memset(outi, 0, outisz * sizeof(*outi));
|
||||
|
||||
// Leading zeros, just count
|
||||
for (i = 0; i < b58sz && !b58digits_map[b58u[i]]; ++i) {
|
||||
++zerocount;
|
||||
}
|
||||
|
||||
for (; i < b58sz; ++i) {
|
||||
if (b58u[i] & 0x80) {
|
||||
// High-bit set on invalid digit
|
||||
return 0;
|
||||
}
|
||||
if (b58digits_map[b58u[i]] == -1) {
|
||||
// Invalid base58 digit
|
||||
return 0;
|
||||
}
|
||||
c = (unsigned)b58digits_map[b58u[i]];
|
||||
for (j = outisz; j--;) {
|
||||
t = ((uint64_t)outi[j]) * 58 + c;
|
||||
c = (t & 0x3f00000000) >> 32;
|
||||
outi[j] = t & 0xffffffff;
|
||||
}
|
||||
if (c) {
|
||||
// Output number too big (carry to the next int32)
|
||||
memset(outi, 0, outisz * sizeof(*outi));
|
||||
return 0;
|
||||
}
|
||||
if (outi[0] & zeromask) {
|
||||
// Output number too big (last int32 filled too far)
|
||||
memset(outi, 0, outisz * sizeof(*outi));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
j = 0;
|
||||
switch (bytesleft) {
|
||||
case 3:
|
||||
*(binu++) = (outi[0] & 0xff0000) >> 16;
|
||||
case 2:
|
||||
*(binu++) = (outi[0] & 0xff00) >> 8;
|
||||
case 1:
|
||||
*(binu++) = (outi[0] & 0xff);
|
||||
++j;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (; j < outisz; ++j) {
|
||||
*(binu++) = (outi[j] >> 0x18) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0x10) & 0xff;
|
||||
*(binu++) = (outi[j] >> 8) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0) & 0xff;
|
||||
}
|
||||
|
||||
// Count canonical base58 byte count
|
||||
binu = *bin;
|
||||
for (i = 0; i < binsz; ++i) {
|
||||
if (binu[i]) {
|
||||
break;
|
||||
}
|
||||
--*binszp;
|
||||
}
|
||||
*binszp += zerocount;
|
||||
|
||||
memset(outi, 0, outisz * sizeof(*outi));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* encode an array of bytes into a base58 string
|
||||
* @param binary_data the data to be encoded
|
||||
* @param binary_data_size the size of the data to be encoded
|
||||
* @param base58 the results buffer
|
||||
* @param base58_size the size of the results buffer
|
||||
* @returns true(1) on success
|
||||
*/
|
||||
int multiaddr_encoding_base58_encode(const unsigned char* data, size_t binsz, unsigned char** b58, size_t* b58sz)
|
||||
{
|
||||
const uint8_t* bin = data;
|
||||
int carry;
|
||||
ssize_t i, j, high, zcount = 0;
|
||||
size_t size;
|
||||
|
||||
while (zcount < (ssize_t)binsz && !bin[zcount]) {
|
||||
++zcount;
|
||||
}
|
||||
|
||||
size = (binsz - zcount) * 138 / 100 + 1;
|
||||
uint8_t buf[size];
|
||||
memset(buf, 0, size);
|
||||
|
||||
for (i = zcount, high = size - 1; i < (ssize_t)binsz; ++i, high = j) {
|
||||
for (carry = bin[i], j = size - 1; (j > high) || carry; --j) {
|
||||
carry += 256 * buf[j];
|
||||
buf[j] = carry % 58;
|
||||
carry /= 58;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < (ssize_t)size && !buf[j]; ++j)
|
||||
;
|
||||
|
||||
if (*b58sz <= zcount + size - j) {
|
||||
*b58sz = zcount + size - j + 1;
|
||||
memset(buf, 0, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (zcount) {
|
||||
memset(b58, '1', zcount);
|
||||
}
|
||||
for (i = zcount; j < (ssize_t)size; ++i, ++j) {
|
||||
(*b58)[i] = b58digits_ordered[buf[j]];
|
||||
}
|
||||
(*b58)[i] = '\0';
|
||||
*b58sz = i + 1;
|
||||
|
||||
memset(buf, 0, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/***
|
||||
* calculate the size of the binary results based on an incoming base58 string
|
||||
* @param base58_string the string
|
||||
* @returns the size in bytes had the string been decoded
|
||||
*/
|
||||
size_t multiaddr_encoding_base58_decode_size(const unsigned char* base58_string) {
|
||||
size_t string_length = strlen((char*)base58_string);
|
||||
size_t decoded_length = 0;
|
||||
size_t radix = strlen(b58digits_ordered);
|
||||
double bits_per_digit = log2(radix);
|
||||
|
||||
decoded_length = floor(string_length * bits_per_digit / 8);
|
||||
return decoded_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate the max length in bytes of an encoding of n source bits
|
||||
* @param base58_string the string
|
||||
* @returns the maximum size in bytes had the string been decoded
|
||||
*/
|
||||
size_t multiaddr_encoding_base58_decode_max_size(const unsigned char* base58_string) {
|
||||
size_t string_length = strlen((char*)base58_string);
|
||||
size_t decoded_length = 0;
|
||||
size_t radix = strlen(b58digits_ordered);
|
||||
double bits_per_digit = log2(radix);
|
||||
|
||||
decoded_length = ceil(string_length * bits_per_digit / 8);
|
||||
return decoded_length;
|
||||
}
|
39
include/multiaddr/base58.h
Normal file
39
include/multiaddr/base58.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef base58_h
|
||||
#define base58_h
|
||||
#include "varint.h"
|
||||
/**
|
||||
* convert a base58 encoded string into a binary array
|
||||
* @param base58 the base58 encoded string
|
||||
* @param base58_size the size of the encoded string
|
||||
* @param binary_data the results buffer
|
||||
* @param binary_data_size the size of the results buffer
|
||||
* @returns true(1) on success
|
||||
*/
|
||||
int multiaddr_encoding_base58_decode(const char* base58, size_t base58_size, unsigned char** binary_data, size_t *binary_data_size);
|
||||
|
||||
/**
|
||||
* encode an array of bytes into a base58 string
|
||||
* @param binary_data the data to be encoded
|
||||
* @param binary_data_size the size of the data to be encoded
|
||||
* @param base58 the results buffer
|
||||
* @param base58_size the size of the results buffer
|
||||
* @returns true(1) on success
|
||||
*/
|
||||
int multiaddr_encoding_base58_encode(const unsigned char* binary_data, size_t binary_data_size, unsigned char** base58, size_t* base58_size);
|
||||
|
||||
/***
|
||||
* calculate the size of the binary results based on an incoming base58 string with no initial padding
|
||||
* @param base58_string the string
|
||||
* @returns the size in bytes had the string been decoded
|
||||
*/
|
||||
size_t multiaddr_encoding_base58_decode_size(const unsigned char* base58_string);
|
||||
|
||||
/**
|
||||
* calculate the max length in bytes of an encoding of n source bits
|
||||
* @param base58_string the string
|
||||
* @returns the maximum size in bytes had the string been decoded
|
||||
*/
|
||||
size_t multiaddr_encoding_base58_decode_max_size(const unsigned char* base58_string);
|
||||
|
||||
|
||||
#endif /* base58_h */
|
111
include/multiaddr/endian.h
Normal file
111
include/multiaddr/endian.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
#ifndef PORTABLE_ENDIAN_H__
|
||||
#define PORTABLE_ENDIAN_H__
|
||||
|
||||
#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
|
||||
|
||||
# define __WINDOWS__
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__CYGWIN__)
|
||||
|
||||
# include <endian.h>
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
# include <libkern/OSByteOrder.h>
|
||||
|
||||
# define htobe16(x) OSSwapHostToBigInt16(x)
|
||||
# define htole16(x) OSSwapHostToLittleInt16(x)
|
||||
# define be16toh(x) OSSwapBigToHostInt16(x)
|
||||
# define le16toh(x) OSSwapLittleToHostInt16(x)
|
||||
|
||||
# define htobe32(x) OSSwapHostToBigInt32(x)
|
||||
# define htole32(x) OSSwapHostToLittleInt32(x)
|
||||
# define be32toh(x) OSSwapBigToHostInt32(x)
|
||||
# define le32toh(x) OSSwapLittleToHostInt32(x)
|
||||
|
||||
# define htobe64(x) OSSwapHostToBigInt64(x)
|
||||
# define htole64(x) OSSwapHostToLittleInt64(x)
|
||||
# define be64toh(x) OSSwapBigToHostInt64(x)
|
||||
# define le64toh(x) OSSwapLittleToHostInt64(x)
|
||||
|
||||
# define __BYTE_ORDER BYTE_ORDER
|
||||
# define __BIG_ENDIAN BIG_ENDIAN
|
||||
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
# define __PDP_ENDIAN PDP_ENDIAN
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
|
||||
# include <sys/endian.h>
|
||||
|
||||
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
|
||||
# include <sys/endian.h>
|
||||
|
||||
# define be16toh(x) betoh16(x)
|
||||
# define le16toh(x) letoh16(x)
|
||||
|
||||
# define be32toh(x) betoh32(x)
|
||||
# define le32toh(x) letoh32(x)
|
||||
|
||||
# define be64toh(x) betoh64(x)
|
||||
# define le64toh(x) letoh64(x)
|
||||
|
||||
#elif defined(__WINDOWS__)
|
||||
|
||||
# include <winsock2.h>
|
||||
# include <sys/param.h>
|
||||
|
||||
# if BYTE_ORDER == LITTLE_ENDIAN
|
||||
|
||||
# define htobe16(x) htons(x)
|
||||
# define htole16(x) (x)
|
||||
# define be16toh(x) ntohs(x)
|
||||
# define le16toh(x) (x)
|
||||
|
||||
# define htobe32(x) htonl(x)
|
||||
# define htole32(x) (x)
|
||||
# define be32toh(x) ntohl(x)
|
||||
# define le32toh(x) (x)
|
||||
|
||||
# define htobe64(x) htonll(x)
|
||||
# define htole64(x) (x)
|
||||
# define be64toh(x) ntohll(x)
|
||||
# define le64toh(x) (x)
|
||||
|
||||
# elif BYTE_ORDER == BIG_ENDIAN
|
||||
|
||||
# define htobe16(x) (x)
|
||||
# define htole16(x) __builtin_bswap16(x)
|
||||
# define be16toh(x) (x)
|
||||
# define le16toh(x) __builtin_bswap16(x)
|
||||
|
||||
# define htobe32(x) (x)
|
||||
# define htole32(x) __builtin_bswap32(x)
|
||||
# define be32toh(x) (x)
|
||||
# define le32toh(x) __builtin_bswap32(x)
|
||||
|
||||
# define htobe64(x) (x)
|
||||
# define htole64(x) __builtin_bswap64(x)
|
||||
# define be64toh(x) (x)
|
||||
# define le64toh(x) __builtin_bswap64(x)
|
||||
|
||||
# else
|
||||
|
||||
# error byte order not supported
|
||||
|
||||
# endif
|
||||
|
||||
# define __BYTE_ORDER BYTE_ORDER
|
||||
# define __BIG_ENDIAN BIG_ENDIAN
|
||||
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
# define __PDP_ENDIAN PDP_ENDIAN
|
||||
|
||||
#else
|
||||
|
||||
# error platform not supported
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
106
include/multiaddr/multiaddr.h
Normal file
106
include/multiaddr/multiaddr.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
#ifndef MULTIADDR
|
||||
#define MULTIADDR
|
||||
#include <string.h>
|
||||
|
||||
#include "varhexutils.h"
|
||||
#include "varint.h"
|
||||
#include "protocols.h"
|
||||
#include "protoutils.h"
|
||||
|
||||
/**
|
||||
* Normally, addresses have been represented using string addresses, like:
|
||||
|
||||
tcp4://127.0.0.1:1234
|
||||
udp4://10.20.30.40:5060
|
||||
ws://1.2.3.4:5678
|
||||
tcp6://[1fff:0:a88:85a3::ac1f]:8001
|
||||
This isn't optimal. Instead, addresses should be formatted so:
|
||||
|
||||
Binary format:
|
||||
|
||||
(varint proto><n byte addr>)+
|
||||
<1 byte ipv4 code><4 byte ipv4 addr><1 byte udp code><2 byte udp port>
|
||||
<1 byte ipv6 code><16 byte ipv6 addr><1 byte tcp code><2 byte tcp port>
|
||||
|
||||
String format:
|
||||
|
||||
(/<addr str code>/<addr str rep>)+
|
||||
/ip4/<ipv4 str addr>/udp/<udp int port>
|
||||
/ip6/<ipv6 str addr>/tcp/<tcp int port>
|
||||
*/
|
||||
|
||||
struct MultiAddress
|
||||
{
|
||||
// A MultiAddress represented as a string
|
||||
char* string;
|
||||
// A MultiAddress represented as an array of bytes
|
||||
//<varint proto><n byte addr><1 byte protocol code><4 byte ipv4 address or 16 byte ipv6 address><1 byte tcp/udp code><2 byte port>
|
||||
uint8_t* bytes;
|
||||
size_t bsize;
|
||||
};
|
||||
|
||||
|
||||
int strpos(char *haystack, char *needle);
|
||||
|
||||
struct MultiAddress* multiaddress_new_from_bytes(const uint8_t* byteaddress, int size); //Construct new address from bytes
|
||||
|
||||
struct MultiAddress* multiaddress_new_from_string(const char* straddress); //Construct new address from string
|
||||
|
||||
void multiaddress_free(struct MultiAddress* in);
|
||||
|
||||
struct MultiAddress* multiaddress_copy(const struct MultiAddress* source);
|
||||
|
||||
// helpers to parse the MultiAddress struct
|
||||
|
||||
int multiaddress_encapsulate(struct MultiAddress * result, char * string);
|
||||
|
||||
int multiaddress_decapsulate(struct MultiAddress * result, char * srci);
|
||||
|
||||
int multiaddress_is_ip(const struct MultiAddress* in);
|
||||
|
||||
int multiaddress_is_ip4(const struct MultiAddress* in);
|
||||
|
||||
int multiaddress_is_ip6(const struct MultiAddress* in);
|
||||
|
||||
int multiaddress_get_ip_family(const struct MultiAddress* in);
|
||||
|
||||
/***
|
||||
* Pulls the textual representation of the IP address from a multihash
|
||||
* @param in the multihash to parse
|
||||
* @param ip where to put the ip address
|
||||
* @returns true(1) on success, otherwise 0
|
||||
*/
|
||||
int multiaddress_get_ip_address(const struct MultiAddress* in, char** ip);
|
||||
|
||||
/***
|
||||
* Pulls the IP port from a multiaddress
|
||||
* @param in the multiaddress
|
||||
* @param port where to put the port
|
||||
* @returns the port, or a negative number for an error
|
||||
*/
|
||||
int multiaddress_get_ip_port(const struct MultiAddress* in);
|
||||
|
||||
/**
|
||||
* Pulls the peer ID out of a multiaddress struct
|
||||
* @param in the MultiAddress
|
||||
* @returns the peer id string, or NULL NOTE: This allocates memory that needs to be freed
|
||||
*/
|
||||
char* multiaddress_get_peer_id(const struct MultiAddress* in);
|
||||
|
||||
/**
|
||||
* Check to see how these two addresses compare
|
||||
* @param a side A
|
||||
* @param b side B
|
||||
* @returns <0 if B > A; >0 if A > B; 0 if A == B
|
||||
*/
|
||||
int multiaddress_compare(const struct MultiAddress* a, const struct MultiAddress* b);
|
||||
|
||||
/**
|
||||
* Check to see how these two addresses compare, ignoring IP address, only looking at ID hash
|
||||
* @param a side A
|
||||
* @param b side B
|
||||
* @returns <0 if B > A; >0 if A > B; 0 if A == B
|
||||
*/
|
||||
int multiaddress_compare_id(const struct MultiAddress* a, const struct MultiAddress* b);
|
||||
|
||||
#endif
|
40
include/multiaddr/protocols.h
Normal file
40
include/multiaddr/protocols.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef PROTOCOLS
|
||||
#define PROTOCOLS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include "varhexutils.h"
|
||||
|
||||
struct Protocol
|
||||
{
|
||||
//char hexcode[21];
|
||||
int deccode;
|
||||
int size;
|
||||
char name[30];
|
||||
};
|
||||
|
||||
struct ProtocolListItem {
|
||||
struct Protocol* current;
|
||||
struct ProtocolListItem* next;
|
||||
};
|
||||
|
||||
int protocol_REMOVE_id(struct ProtocolListItem* head, int remid); //Function to remove & shift back all data, sort of like c++ vectors.
|
||||
|
||||
void unload_protocols(struct ProtocolListItem* head);
|
||||
|
||||
/**
|
||||
* load the available protocols into the global protocol_P
|
||||
* @returns True(1) on success, otherwise 0
|
||||
*/
|
||||
int load_protocols(struct ProtocolListItem** head);
|
||||
|
||||
struct Protocol * proto_with_name(const struct ProtocolListItem* head, const char* proto_w_name); //Search for protocol with inputted name
|
||||
|
||||
struct Protocol * proto_with_deccode(const struct ProtocolListItem* head, int proto_w_deccode); //Search for protocol with inputted deccode
|
||||
|
||||
void protocols_with_string(const struct ProtocolListItem* head, char * meee, int sizi); // NOT FINISHED, DO NOT USE!
|
||||
|
||||
#endif
|
55
include/multiaddr/protoutils.h
Normal file
55
include/multiaddr/protoutils.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
#ifndef PROTOUTILS
|
||||
#define PROTOUTILS
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
char ASCII2bits(char ch);
|
||||
|
||||
void hex2bin (char *dst, char *src, int len);
|
||||
|
||||
char bits2ASCII(char b);
|
||||
|
||||
void bin2hex (char *dst, char *src, int len);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//IPv4 VALIDATOR
|
||||
#define DELIM "."
|
||||
|
||||
/* return 1 if string contain only digits, else return 0 */
|
||||
int valid_digit(char *ip_str);
|
||||
|
||||
/* return 1 if IP string is valid, else return 0 */
|
||||
int is_valid_ipv4(char *ip_str);
|
||||
|
||||
//////////////IPv6 Validator
|
||||
#define MAX_HEX_NUMBER_COUNT 8
|
||||
|
||||
int ishexdigit(char ch);
|
||||
|
||||
int is_valid_ipv6(char *str);
|
||||
|
||||
uint64_t ip2int(const char * ipconvertint);
|
||||
|
||||
char * int2ip(int inputintip);
|
||||
|
||||
/**
|
||||
* Unserialize the bytes into a string
|
||||
* @param results where to put the resultant string
|
||||
* @param bytes the bytes to unserialize
|
||||
* @param bytes_size the length of the bytes array
|
||||
*/
|
||||
int bytes_to_string(char** results, const uint8_t* bytes, int bytes_size);
|
||||
|
||||
/**
|
||||
* Convert an address string to a byte representation
|
||||
* @param protocol the protocol to use
|
||||
* @param incoming the byte array
|
||||
* @param incoming_size the size of the byte array
|
||||
* @param results the results
|
||||
* @param results_size the size of the results
|
||||
* @returns the results array
|
||||
*/
|
||||
char * address_string_to_bytes(struct Protocol *protocol, const char *incoming, size_t incoming_size, char** results, int *results_size);
|
||||
|
||||
int string_to_bytes(uint8_t** finalbytes,size_t* realbbsize, const char * strx, size_t strsize);
|
||||
|
||||
#endif
|
60
include/multiaddr/varhexutils.h
Normal file
60
include/multiaddr/varhexutils.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#ifndef VARHEXUTILS
|
||||
#define VARHEXUTILS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "varint.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "endian.h"
|
||||
/*uint8_t * encode_big_endian_32(uint32_t ebex32)
|
||||
{
|
||||
uint8_t encbe[10] = {0};
|
||||
memcpy(encbe, htobe32(ebex32));
|
||||
return encbe;
|
||||
}*/
|
||||
int8_t Var_Bytes_Count(uint8_t * countbytesofthis);
|
||||
|
||||
uint8_t * Num_To_Varint_64(uint64_t TOV64INPUT); //UINT64_T TO VARINT
|
||||
|
||||
uint8_t * Num_To_Varint_32(uint32_t TOV32INPUT); // UINT32_T TO VARINT
|
||||
|
||||
uint64_t * Varint_To_Num_64(uint8_t TON64INPUT[60]); //VARINT TO UINT64_t
|
||||
|
||||
uint32_t * Varint_To_Num_32(uint8_t TON32INPUT[60]); //VARINT TO UINT32_t
|
||||
|
||||
//
|
||||
char * Int_To_Hex(uint64_t int2hex); //VAR[binformat] TO HEX
|
||||
|
||||
uint64_t Hex_To_Int(char * hax);
|
||||
|
||||
/**
|
||||
* Convert binary array to array of hex values
|
||||
* @param incoming the binary array
|
||||
* @param incoming_size the size of the incoming array
|
||||
* @returns the allocated array
|
||||
*/
|
||||
unsigned char *Var_To_Hex(const char *incoming, int incoming_size);
|
||||
|
||||
/**
|
||||
* Turn a hex string into a byte array
|
||||
* @param incoming a string of hex values
|
||||
* @param num_bytes the size of the result
|
||||
* @returns a pointer to the converted value
|
||||
*/
|
||||
unsigned char* Hex_To_Var(char * Hexstr, size_t* num_bytes);
|
||||
|
||||
//
|
||||
void convert(char * convert_result, uint8_t * buf); //Both of them read them properly.
|
||||
|
||||
char * Num_To_HexVar_64(uint64_t TOHVINPUT); //UINT64 TO HEXIFIED VAR
|
||||
|
||||
void convert2(char * convert_result2, uint8_t * bufhx);
|
||||
|
||||
char * Num_To_HexVar_32(uint32_t TOHVINPUT); //UINT32 TO HEXIFIED VAR
|
||||
|
||||
uint64_t HexVar_To_Num_64(char * theHEXstring); //HEXIFIED VAR TO UINT64_T
|
||||
|
||||
uint32_t HexVar_To_Num_32(char theHEXstring[]); //HEXIFIED VAR TO UINT32_T
|
||||
|
||||
#endif
|
51
include/multiaddr/varint.h
Normal file
51
include/multiaddr/varint.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#ifndef VARINT
|
||||
#define VARINT
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <stdint.h> /* uint8_t, uint64_t */
|
||||
|
||||
|
||||
#define DEFN_ENCODER(SIZE) \
|
||||
size_t \
|
||||
uvarint_encode##SIZE (uint##SIZE##_t val, uint8_t buf[], size_t bufsize) \
|
||||
{ \
|
||||
size_t i = 0; \
|
||||
for (; i < (SIZE/8) && i < bufsize; i++) { \
|
||||
buf[i] = (uint8_t) ((val & 0xFF) | 0x80); \
|
||||
val >>= 7; \
|
||||
if (!val) \
|
||||
return i + 1; \
|
||||
} \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
|
||||
#define DEFN_DECODER(SIZE) \
|
||||
size_t \
|
||||
uvarint_decode##SIZE (uint8_t buf[], size_t bufsize, uint##SIZE##_t *val) \
|
||||
{ \
|
||||
*val = 0; \
|
||||
size_t i = 0; \
|
||||
for (; i < (SIZE/8) && i < bufsize; i++) { \
|
||||
*val |= ((buf[i] & 0x7f) << (7 * i)); \
|
||||
if (!(buf[i] & 0x80)) \
|
||||
return i + 1; \
|
||||
} \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
|
||||
#define DECL_ENCODER(SIZE) \
|
||||
size_t \
|
||||
uvarint_encode##SIZE (uint##SIZE##_t val, uint8_t buf[], size_t bufsize);
|
||||
|
||||
#define DECL_DECODER(SIZE) \
|
||||
size_t \
|
||||
uvarint_decode##SIZE (uint8_t buf[], size_t bufsize, uint##SIZE##_t *val);
|
||||
|
||||
|
||||
DECL_ENCODER(32)
|
||||
DECL_DECODER(32)
|
||||
|
||||
DECL_ENCODER(64)
|
||||
DECL_DECODER(64)
|
||||
#endif
|
397
multiaddr.c
Normal file
397
multiaddr.c
Normal file
|
@ -0,0 +1,397 @@
|
|||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "multiaddr/varhexutils.h"
|
||||
#include "multiaddr/varint.h"
|
||||
#include "multiaddr/protocols.h"
|
||||
#include "multiaddr/protoutils.h"
|
||||
#include "multiaddr/multiaddr.h"
|
||||
|
||||
int strpos(char *haystack, char *needle)
|
||||
{
|
||||
char *p = strstr(haystack, needle);
|
||||
if (p)
|
||||
{
|
||||
return p - haystack;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1; // Not found = -1.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new MultiAddress struct
|
||||
* @returns an empty MultiAddress struct
|
||||
*/
|
||||
struct MultiAddress* multiaddress_new() {
|
||||
struct MultiAddress* out = (struct MultiAddress*)malloc(sizeof(struct MultiAddress));
|
||||
if (out != NULL) {
|
||||
out->bsize = 0;
|
||||
out->bytes = NULL;
|
||||
out->string = NULL;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* construct a new MultiAddress from bytes
|
||||
* @param byteaddress the byte array
|
||||
* @param size the size of the byte array
|
||||
* @returns a new MultiAddress struct filled in, or NULL on error
|
||||
*/
|
||||
struct MultiAddress* multiaddress_new_from_bytes(const uint8_t* byteaddress, int size)//Construct new address from bytes
|
||||
{
|
||||
struct MultiAddress* out = multiaddress_new();
|
||||
if (out != NULL) {
|
||||
if(byteaddress!=NULL)
|
||||
{
|
||||
out->bytes = malloc(size);
|
||||
if (out->bytes == NULL) {
|
||||
multiaddress_free(out);
|
||||
return NULL;
|
||||
}
|
||||
out->bsize = size;
|
||||
memcpy(out->bytes, byteaddress, size);
|
||||
if(!bytes_to_string(&out->string,byteaddress,size))
|
||||
{
|
||||
multiaddress_free(out);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
multiaddress_free(out);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
struct MultiAddress* multiaddress_new_from_string(const char* straddress)//Construct new address from string
|
||||
{
|
||||
struct MultiAddress* out = multiaddress_new();
|
||||
if (out != NULL) {
|
||||
out->string = malloc(strlen(straddress) + 1);
|
||||
if (out->string == NULL) {
|
||||
multiaddress_free(out);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(out->string, straddress);
|
||||
|
||||
if (string_to_bytes(&(out->bytes), &out->bsize, out->string, strlen(out->string)) == 0 )
|
||||
{
|
||||
multiaddress_free(out);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int multiaddress_is_ip(const struct MultiAddress* in) {
|
||||
if (in->bytes > 0) {
|
||||
int byte = in->bytes[0];
|
||||
|
||||
if (byte == 4 || byte == 41)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int multiaddress_is_ip4(const struct MultiAddress* in) {
|
||||
return in->bytes[0] == 4;
|
||||
}
|
||||
|
||||
int multiaddress_is_ip6(const struct MultiAddress* in) {
|
||||
return in->bytes[0] == 41;
|
||||
}
|
||||
|
||||
|
||||
int multiaddress_get_ip_family(const struct MultiAddress* in) {
|
||||
if (in->bytes[0] == 4)
|
||||
return AF_INET;
|
||||
if (in->bytes[0] == 41)
|
||||
return AF_INET6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***
|
||||
* Pulls the textual representation of the IP address from a multihash
|
||||
* @param in the multihash to parse
|
||||
* @param ip where to put the ip address
|
||||
* @returns true(1) on success, otherwise 0
|
||||
*/
|
||||
int multiaddress_get_ip_address(const struct MultiAddress* in, char** ip) {
|
||||
// the incoming address is not what was expected
|
||||
if (strncmp(in->string, "/ip4/", 5) != 0 && strncmp(in->string, "/ip6/", 5) != 0)
|
||||
return 0;
|
||||
if (strstr(in->string, "/tcp/") == NULL && strstr(in->string, "/udp/") == NULL)
|
||||
return 0;
|
||||
// ip
|
||||
char* str = malloc(strlen(in->string));
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
strcpy(str, &in->string[5]); // gets rid of /ip4/
|
||||
char* pos = strchr(str, '/');
|
||||
pos[0] = 0;
|
||||
*ip = malloc(strlen(str) + 1);
|
||||
strcpy(*ip, str);
|
||||
free(str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/***
|
||||
* Pulls the IP port from a multiaddress
|
||||
* @param in the multiaddress
|
||||
* @param port where to put the port
|
||||
* @returns the port, or a negative number for an error
|
||||
*/
|
||||
int multiaddress_get_ip_port(const struct MultiAddress* in) {
|
||||
char* ptr = strstr(in->string, "/tcp/");
|
||||
if (ptr == NULL)
|
||||
ptr = strstr(in->string, "/udp/");
|
||||
if (ptr == NULL)
|
||||
return -1;
|
||||
ptr += 5;
|
||||
char* end_ptr = strstr(ptr, "/");
|
||||
if (end_ptr == NULL) {
|
||||
return atoi(ptr);
|
||||
}
|
||||
char str[end_ptr - ptr + 1];
|
||||
memcpy(str, ptr, end_ptr - ptr);
|
||||
str[end_ptr-ptr] = '\0';
|
||||
return atoi(str);
|
||||
}
|
||||
|
||||
char* multiaddress_get_peer_id(const struct MultiAddress* in) {
|
||||
char* result = NULL;
|
||||
int str_len = 0;
|
||||
char* slash = NULL;
|
||||
char* ptr = NULL;
|
||||
|
||||
ptr = strstr(in->string, "/ipfs/");
|
||||
if (ptr != NULL && ptr[6] != 0) {
|
||||
ptr += 6;
|
||||
str_len = strlen(ptr);
|
||||
slash = strchr(ptr, '/');
|
||||
if (slash != NULL) {
|
||||
str_len = slash - ptr;
|
||||
}
|
||||
if (str_len > 0) {
|
||||
result = malloc(str_len + 1);
|
||||
if (result != NULL) {
|
||||
memset(result, 0, str_len + 1);
|
||||
memcpy(result, ptr, str_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void multiaddress_free(struct MultiAddress* in) {
|
||||
if (in != NULL) {
|
||||
if (in->bytes != NULL)
|
||||
free(in->bytes);
|
||||
if (in->string != NULL)
|
||||
free(in->string);
|
||||
free(in);
|
||||
in = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a multiaddress from one memory location to another
|
||||
* @param in the source
|
||||
* @returns the new struct MultiAddress or NULL if there was a problem (i.e. out of memory)
|
||||
*/
|
||||
struct MultiAddress* multiaddress_copy(const struct MultiAddress* in) {
|
||||
struct MultiAddress* out = NULL;
|
||||
if (in != NULL) {
|
||||
out = (struct MultiAddress*)malloc(sizeof(struct MultiAddress));
|
||||
if (out != NULL) {
|
||||
if (in->bsize > 0) {
|
||||
out->bytes = malloc(in->bsize);
|
||||
if (out->bytes == NULL) {
|
||||
free(out);
|
||||
return NULL;
|
||||
}
|
||||
out->bsize = in->bsize;
|
||||
memcpy(out->bytes, in->bytes, out->bsize);
|
||||
} // bytes need to be copied
|
||||
if (in->string != NULL) {
|
||||
out->string = malloc(strlen(in->string) + 1);
|
||||
if (out->string == NULL) {
|
||||
if (out->bsize > 0)
|
||||
free(out->bytes);
|
||||
free(out);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(out->string, in->string);
|
||||
} // string needs to be copied
|
||||
} // structure allocated
|
||||
} // good parameters
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a string into the MultiAddress and recalculate the bytes
|
||||
* @param result the struct
|
||||
* @param string the new string
|
||||
*/
|
||||
int multiaddress_encapsulate(struct MultiAddress* result, char* string)
|
||||
{
|
||||
if(result != NULL && string != NULL)
|
||||
{
|
||||
// remove the old values
|
||||
if (result->bytes != NULL)
|
||||
free(result->bytes);
|
||||
result->bytes = NULL;
|
||||
result->bsize = 0;
|
||||
char * exstr;
|
||||
if(string[0] == '/')
|
||||
{
|
||||
exstr = (char *) malloc(strlen(result->string)+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
exstr = (char *) malloc(strlen(result->string));
|
||||
}
|
||||
strcpy(exstr, result->string);
|
||||
free(result->string);
|
||||
// insert the new values
|
||||
result->string = malloc(strlen(string) + strlen(exstr) + 1);
|
||||
if (result->string == NULL) {
|
||||
multiaddress_free(result);
|
||||
return 0;
|
||||
}
|
||||
strcpy(result->string, exstr) |