Compare commits

...
Sign in to create a new pull request.

70 commits

Author SHA1 Message Date
Agorise
b1f7d607ee
Update LICENSE 2019-01-01 10:36:34 -06:00
Agorise
a271e08996
Update LICENSE 2018-06-17 16:31:04 +03:00
Agorise
028223e46a
Update LICENSE 2017-11-15 13:24:45 +02:00
Agorise
4d46d86514 Update LICENSE 2017-10-16 13:53:40 +03:00
jmjatlanta
4c457c1dd3 Better error reporting 2017-09-21 09:45:26 -05:00
jmjatlanta
3b178a142d Added helper method to compare ipfs address without IP address 2017-08-24 14:36:03 -05:00
John Jones
c2f2c0c2da Added a compare method 2017-07-26 07:36:45 -05:00
jmjatlanta
c434fbd160 Fixed warnings 2017-07-17 16:13:53 -05:00
John Jones
86d3cd422e Fixed memory leak and most compiler warnings 2017-07-17 15:11:08 -05:00
John Jones
58a6240af9 Fixed bug on odd byte ip addresses
IP addresses that when converted to an integer ended up as a string with
an odd number of bytes would result in a memory read into invalid
memory. Zero filled the text string representation of the bytes to avoid
this issue.
2017-07-13 18:29:02 -05:00
John Jones
7c6bd1e36b Added sanity check 2017-04-27 11:09:18 -05:00
John Jones
d6877b995c Fixed initialization bug 2017-04-17 14:36:16 -05:00
John Jones
603ed1d72f Fixed multiaddress_get_peer_id to return allocated memory
Returing in place causes problems with continuations i.e. ending
slashes. Therefore it is better to return allocated memory.
2017-04-17 11:56:36 -05:00
John Jones
f0961a247f Multiaddress stability fixes 2017-04-16 23:46:07 -05:00
John Jones
c96c1db14c Now handling zeros in address correctly 2017-04-13 09:29:44 -05:00
John Jones
4cbcf6be3d Test that proves MultiAddress not handling 0s properly 2017-04-03 22:01:46 -05:00
John Jones
615adc86ef Added ability to parse out peer id 2017-04-03 11:54:15 -05:00
John Jones
e9636e642f Fixed udp bug 2017-03-24 16:49:12 -05:00
John Jones
e90434ba61 strtok_r only by declaration 2017-03-21 13:36:06 -05:00
John Jones
d09c4a0d76 added string tokenizer for c99 2017-03-21 13:04:44 -05:00
John Jones
e935335964 c99 2017-03-21 14:57:41 +00:00
John Jones
7fb89918f8 Parsing of IP adresses is now easier 2017-03-09 18:48:00 -05:00
John Jones
e914307a4d Added some utility methods to make parsing easier 2017-03-09 18:20:56 -05:00
John Jones
0bbca7bc27 Small comment change 2017-02-27 12:26:38 -05:00
John Jones
7da26ca04d Minor tweak to get rid of compiler warning 2017-02-22 10:54:16 -05:00
John M. Jones
ba234206a2 Merge pull request #6 from xethyrion/master
Misc fixes
2017-02-22 00:50:24 -05:00
xethyrion
6274997560 Fixed everything.. as far as I can tell.. 2017-02-22 07:17:09 +02:00
xethyrion
2dab592164 How it should be used 2017-02-21 21:05:20 +02:00
xethyrion
10302dd4b1 Update README.md 2017-02-21 21:04:06 +02:00
xethyrion
43a19d7c61 Updated to current version 2017-02-21 21:02:42 +02:00
xethyrion
2a470ee856 Fixed encapsulation
Now working properly.
2017-02-21 20:55:28 +02:00
John Jones
0b8789ebbc Bug fixes 2017-02-20 17:45:48 -05:00
John Jones
4e281ddd08 Added testing framework 2017-02-20 15:58:19 -05:00
John Jones
fcb0cce437 Minor fixes to the conversion from bytes to MultiAddress 2017-02-20 08:15:16 -05:00
John Jones
f2d1a5aa83 added a helpful comment 2017-02-16 23:13:58 -05:00
John M. Jones
5cb09b3708 Merge pull request #4 from jmjatlanta/master
Multiple fixes to code
2017-02-15 12:14:04 -05:00
John Jones
29a68c8f55 Multiple fixes to code 2017-02-15 10:42:06 -05:00
ken Code
b7f3d475e3 Merge pull request #3 from jmjatlanta/master
Various changes to align with other ipfs projects
2017-02-14 11:42:52 +01:00
John Jones
9a9c5ea1c3 More cleanup 2017-02-13 17:49:20 -05:00
John Jones
cc8ff45cc1 Added a method to copy MultiAddresses 2017-02-13 14:28:06 -05:00
John Jones
bb488f7e82 More in line with existing code. Refactored naming. 2017-02-13 14:12:32 -05:00
John Jones
78ce39b067 renamed struct maddr to MultiAddress 2017-02-13 13:30:22 -05:00
John Jones
d57e026fbf Moved functionality from headers to c files so that we can compile 2017-02-13 13:25:43 -05:00
ken Code
48648fb6cd Update LICENSE 2017-01-31 17:11:29 +01:00
ken Code
7159bd4641 Merge pull request #2 from jmjatlanta/master
Removed copyright notice
2016-12-05 14:31:57 +01:00
jmjatlanta
364bc72a54 Merge remote-tracking branch 'upstream/master' 2016-12-05 07:25:55 -05:00
John Jones
ee1cf1359c Small changes to allow compile 2016-12-05 06:56:09 -05:00
John Jones
fa1084b45c added Eclipse project files 2016-11-17 16:35:50 -05:00
xethyrion
50dbd5f765 Merge pull request #1 from jmjatlanta/master
Directory structure changes
2016-11-14 11:03:10 -08:00
John Jones
68ca649688 Directory structure changes
Made an include directory to avoid naming conflicts with other projects.
Also added a Makefile to help with building the library and testing
application. Note: This does not build due to what appears to be a
missing codec.h file.
2016-11-14 08:03:48 -05:00
xethyrion
edb7475318 Update STATUS.md 2016-11-10 13:38:23 +02:00
xethyrion
877d71acaa Update and rename STATUS to STATUS.md 2016-11-10 13:19:34 +02:00
xethyrion
4bb95063a9 Update README.md 2016-11-10 13:07:23 +02:00
xethyrion
fb56ba584a Update README.md 2016-11-10 10:27:58 +02:00
xethyrion
64fd480954 Update README.md 2016-11-10 10:26:10 +02:00
xethyrion
b11ecd51c5 Update README.md 2016-11-10 10:24:23 +02:00
xethyrion
38b7966a10 Update README.md 2016-11-10 10:19:07 +02:00
xethyrion
6f14f96982 Update README.md 2016-11-10 10:18:36 +02:00
xethyrion
4cddac37a3 Update README.md 2016-11-10 10:15:13 +02:00
xethyrion
d7a90c513d added ipfs support with proper base58 2016-11-10 00:53:11 +02:00
xethyrion
7574846553 Not needed after all 2016-11-09 01:12:29 +02:00
xethyrion
5bc0d88bf1 Added more space for proxies
Fixed a bug in protoutils.h->string_to_bytes where an extra NULL caused memory errors.
2016-11-08 18:01:10 +02:00
xethyrion
36f4f4e1b8 additional notes 2016-11-08 14:57:13 +02:00
xethyrion
483957077e Update 2016-11-08 13:02:45 +02:00
xethyrion
7b1ed7a4a4 Update STATUS 2016-11-08 12:59:03 +02:00
xethyrion
b29bbee5a1 Update STATUS 2016-11-06 04:13:50 +02:00
xethyrion
ebc0e05b8b Add files via upload 2016-11-06 03:57:36 +02:00
xethyrion
148523117b Delete base58.h 2016-11-06 03:55:29 +02:00
ken Code
b68cb78ce1 Create LICENSE 2016-11-04 12:27:08 +01:00
xethyrion
c333fd7d78 Add files via upload 2016-11-02 18:27:58 +02:00
23 changed files with 2848 additions and 0 deletions

78
.cproject Normal file
View 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
View file

@ -0,0 +1,11 @@
*
!.gitignore
!Makefile
!**/
*.o
*.a
.settings/language.settings.xml
test_multiaddr

26
.project Normal file
View 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
View 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
View 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

View file

@ -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
View 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
View 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;
}

View 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
View 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

View 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

View 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

View 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

View 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

View 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
View 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)