Compare commits

...

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);
free(exstr);
if(string[0] == '/')
{
strcat(result->string, string+1);
}
else
{
strcat(result->string, string);
}
if(string_to_bytes(&result->bytes, &result->bsize, result->string, strlen(result->string)+1) == 0)
{
multiaddress_free(result);
return 0;
}
} else {
return 0;
}
return 1;
}
/**
* Find scri and remove it from the resultant value
* (ie /ip4/127.0.0.1/tcp/4001 becomes ip4/127.0.0.1 when you call decapsulate(addr, "/tcp")
* @param result the address to work with
* @param srci the string to look for
*/
int multiaddress_decapsulate(struct MultiAddress * result, char * srci)
{
if(result!=NULL && srci!=NULL)
{
char * procstr = NULL;
procstr = result->string;
int i=0;
int sz=strlen(procstr);
char * src = NULL;
src=srci;
// change slash to space
for(i=0;i<sz;i++)
{
if(procstr[i] == '/')
{
procstr[i]=' ';
}
}
int pos=-1;
pos=strpos(procstr,src);
if(pos!=-1)
{
// fill rest with 0s
for(i=pos;i<sz;i++)
{
procstr[i] = '\0';
}
// replace space with slash
for(i=0;i<sz;i++)
{
if(procstr[i] == ' ')
{
procstr[i] = '/';
}
}
//Bytes update
if (result->bytes != NULL)
free(result->bytes);
result->bytes = NULL;
result->bsize = 0;
if(string_to_bytes(&result->bytes, &result->bsize, result->string, strlen(result->string)+1) == 0)
{
multiaddress_free(result);
return 0;
}
return 1;
}
else
{
return 0;
}
return 0;
}
else
{
return 0;
}
}
/**
* 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) {
if (a == NULL && b == NULL)
return 0;
if (a == NULL && b != NULL)
return -1;
if (a != NULL && b == NULL)
return 1;
int total = b->bsize - a->bsize;
if (total != 0)
return total;
for(size_t i = 0; i < b->bsize; i++) {
total = b->bytes[i] - a->bytes[i];
if (total != 0)
return total;
}
return 0;
}
/**
* Check to see how these two addresses compare, ignoring IP address,
* only looking at the first /ipfs/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) {
char* a_id = multiaddress_get_peer_id(a);
char* b_id = multiaddress_get_peer_id(b);
if (a_id == NULL && b_id == NULL)
return 0;
if (a_id == NULL && b_id != NULL)
return -1;
if (a_id != NULL && b_id == NULL)
return 1;
int retVal = strcmp(a_id, b_id);
if (a_id != NULL)
free(a_id);
if (b_id != NULL)
free(b_id);
return retVal;
}

15
proto-dat Normal file
View File

@ -0,0 +1,15 @@
hex-code dec-code size name
04 4 32 ip4
29 41 128 ip6
06 6 16 tcp
11 17 16 udp
21 33 16 dccp
84 132 16 sctp
12D 301 0 udt
12E 302 0 utp
2A 42 -1 ipfs
1E0 480 0 http
1BB 443 0 https
1DD 477 0 ws
1BC 444 10 onion
113 275 0 libp2p-webrtc-star

230
protocols.c Normal file
View File

@ -0,0 +1,230 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <errno.h>
#include "multiaddr/protocols.h"
#include "multiaddr/varhexutils.h"
/*
int protocol_REMOVE_id(struct ProtocolListItem* protocol_P, int remid)//Function to remove & shift back all data, sort of like c++ vectors.
{
if(remid < CNT_PROTOCOLNUM && remid >= 0&&CNT_PROTOCOLNUM!=0) //Checking to see if remid actually exists.
{
for(int i=remid; i<CNT_PROTOCOLNUM-1; ++i) //While i < num of registered protocols //Needs to be tested that -1 is for valgrind debugging
{
//strcpy((protocol_P+i)->hexcode, (protocol_P+i+1)->hexcode); //shift memory to the user we want to remove.
(protocol_P+i)->deccode = (protocol_P+i+1)->deccode; //Same as above
(protocol_P+i)->size = (protocol_P+i+1)->size; //Same as above
strcpy((protocol_P+i)->name, (protocol_P+i+1)->name); //Same as above
}//Overwriting user done. Time to get rid of that extra memory.
protocol_P = (struct Protocol*) realloc(protocol_P, (CNT_PROTOCOLNUM-1) * sizeof(struct Protocol));
//Memory erased,
CNT_PROTOCOLNUM--; //Since the record no longer exists, we should decrease the ammount of users.
return 1; //Purely for error checking, in case someone ever wants it/
} //1 = Success
else
{
if(CNT_PROTOCOLNUM == 0)
{
perror("ERROR: 0 PROTOCOLS... Did you load protocols?");
}
else
{
perror("ERROR: No such protocol!");
}
return 0;
}
}
*/
void unload_protocols(struct ProtocolListItem* head)
{
struct ProtocolListItem* current = head;
while (current != NULL) {
struct ProtocolListItem* next = current->next;
free(current->current);
free(current);
current = next;
}
}
/**
* load the available protocols into the global protocol_P
* @returns True(1) on success, otherwise 0
*/
int load_protocols(struct ProtocolListItem** head)
{
unload_protocols(*head);
int num_protocols = 14;
int dec_code[] = {4, 41, 6, 17, 33, 132, 301, 302, 42, 480, 443, 477, 444, 275};
int size[] = {32, 128, 16, 16, 16, 16, 0, 0, -1, 0, 0, 0, 10, 0 };
char* name[] = { "ip4", "ip6", "tcp", "udp", "dccp", "sctp", "udt", "utp", "ipfs", "http", "https", "ws", "onion", "libp2p-webrtc-star" };
struct ProtocolListItem* last = NULL;
for(int i = 0; i < num_protocols; i++) {
struct ProtocolListItem* current_item = (struct ProtocolListItem*)malloc(sizeof(struct ProtocolListItem));
current_item->current = (struct Protocol*)malloc(sizeof(struct Protocol));
current_item->next = NULL;
current_item->current->deccode = dec_code[i];
strcpy(current_item->current->name, name[i]);
current_item->current->size = size[i];
if (*head == NULL) {
*head = current_item;
} else {
last->next = current_item;
}
last = current_item;
}
return 1;
}
/*
void load_protocols_from_file(struct Protocol** in)
{
struct Protocol* protocol_P = *in;
FILE *FPROC_POINT; //File pointer.
FPROC_POINT = fopen("proto-dat", "r");//Opening proto-dat Or protocols.csv, I just formatted it to my liking.
if(FPROC_POINT != NULL) //While pointer is not null.
{
char W_BUFF[20] = "\0";//Char array to parse file.
for(int i=0; fscanf(FPROC_POINT, "%s", W_BUFF) != EOF; i++) // Scanning file and incrementing for processing.
{
switch(i)
{
case 0: //First word - HEXCODE
{
//ADD MEMORY FOR NEW PROTOCOL
if(CNT_PROTOCOLNUM==0) //If there are no registered protocols yet, allocate memory to pointer.
{
protocol_P = (struct Protocol*) malloc (sizeof(struct Protocol));
}
else //Reallocate memory to fit one more Protocol
{
protocol_P = (struct Protocol*) realloc(protocol_P, (CNT_PROTOCOLNUM+1) * sizeof(struct protocol));
}
//strcpy((protocol_P+CNT_PROTOCOLNUM)->hexcode, W_BUFF); //Copy word to structure at hexcode A hexcode is a string so we keep it as such
break;
}
case 1://Second word - DECCODE
{
(protocol_P+CNT_PROTOCOLNUM)->deccode= atoi(W_BUFF); //Copy word to structure at deccode after converting it to int.
break;
}
case 2://Third word - SIZE
{
(protocol_P+CNT_PROTOCOLNUM)->size= atoi(W_BUFF); //Copy word to structure at size after converting it to int.
break;
}
case 3://Fourth word - NAME
{
strcpy((protocol_P+CNT_PROTOCOLNUM)->name, W_BUFF); //Copy word to structure at name // String
i=-1;
CNT_PROTOCOLNUM++;
break;
}
default:
{
printf("HOUSTON WE HAVE A BIG PROBLEM!!!!\nPROTOCOLS.H-REACHED DEFAULT CASE IN READING FILE!\nREPORT TO SYSTEMS ADMIN!\n");
break;
}
}
}
fclose(FPROC_POINT);
protocol_REMOVE_id(protocol_P, 0);
}
else
{
perror("Fatal Error:");
}
}
*/
struct Protocol* proto_with_name(const struct ProtocolListItem* head, const char* proto_w_name) //Search for Protocol with inputted name
{
const struct ProtocolListItem* current = head;
while(current != NULL)
{
if (strcmp(proto_w_name, current->current->name) == 0) {
return current->current;
}
current = current->next;
}
return NULL;
}
struct Protocol* proto_with_deccode(const struct ProtocolListItem* head, int proto_w_deccode) //Search for Protocol with inputted deccode
{
const struct ProtocolListItem* current = head;
while(current != NULL)
{
if (current->current->deccode == proto_w_deccode) {
return current->current;
}
current = current->next;
}
return NULL;
}
void protocols_with_string(const struct ProtocolListItem* head, char* meee, int sizi) // NOT FINISHED, DO NOT USE!
{
int finalsize = 0;
if(!isalnum(meee[sizi-1]) && !isalnum(meee[sizi-1]))
{
//Everything is alright, it's nul terminated!;
finalsize = sizi;
}
else
{
//Well houston we have a problem.
finalsize = sizi+2;
}
char mestring[finalsize];
strcpy(mestring, meee);
if(sizi!=finalsize)
{
strcpy(mestring,"\0");
}
char * words[50] = { NULL };
int atword = 0;
int mem = 0;
for(int i=0; i<sizeof(mestring)-2; i++)
{
if(mestring[i] == '/')
{
printf("NEW WORD!\n");
atword++;
int currentsize = 0;
for(int j = i+1; mestring[j] != '/' && j < sizeof(mestring)-2; j++)
{
currentsize++;
}
char haay[20];
int lesbo = 0;
for(int x = i+1; x<sizeof(mestring)-2; x++)
{
if(mestring[x] == '/')
{
break;
}
haay[lesbo] = mestring[x];
lesbo++;
}
words[atword-1] = (char *) malloc(currentsize+2);
strcpy(words[atword-1], haay);
bzero(haay,20);
}
}
printf("Result:%s\n", words[0]);
for(int mm=0; mm < 50; mm++)
{
if(words[mm])
{
free(words[mm]);
}
}
}

717
protoutils.c Normal file
View File

@ -0,0 +1,717 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <math.h>
#include <inttypes.h>
#include <ctype.h>
#include "multiaddr/base58.h"
#include "multiaddr/varhexutils.h"
#include "multiaddr/protocols.h"
#include "multiaddr/protoutils.h"
extern char *strtok_r(char *, const char *, char **);
//////////////////////////////////////////////////////////
char ASCII2bits(char ch) {
if (ch >= '0' && ch <= '9') {
return (ch - '0');
} else if (ch >= 'a' && ch <= 'z') {
return (ch - 'a') + 10;
} else if (ch >= 'A' && ch <= 'Z') {
return (ch - 'A') + 10;
}
return 0; // fail
}
void hex2bin (char *dst, char *src, int len)
{
while (len--) {
*dst = ASCII2bits(*src++) << 4; // higher bits
*dst++ |= ASCII2bits(*src++); // lower bits
}
}
char bits2ASCII(char b) {
if (b >= 0 && b < 10) {
return (b + '0');
} else if (b >= 10 && b <= 15) {
return (b - 10 + 'a');
}
return 0; // fail
}
void bin2hex (char *dst, char *src, int len)
{
while (len--) {
*dst++ = bits2ASCII((*src >> 4) & 0xf); // higher bits
*dst++ = bits2ASCII(*src++ & 0xf); // lower bits
}
*dst = '\0';
}
//////////////////////////////////////////////////////////
//IPv4 VALIDATOR
#define DELIM "."
/* return 1 if string contain only digits, else return 0 */
int valid_digit(char *ip_str)
{
int err = 0;
while (*ip_str) {
if (*ip_str >= '0' && *ip_str <= '9')
++ip_str;
else
return 0;
}
return 1;
}
/* return 1 if IP string is valid, else return 0 */
int is_valid_ipv4(char *ip_str)
{
int i, num, dots = 0;
char *ptr;
int err=0;
if (ip_str == NULL)
err = 1;
// See following link for strtok()
// http://pubs.opengroup.org/onlinepubs/009695399/functions/strtok_r.html
ptr = strtok(ip_str, DELIM);
if (ptr == NULL)
err = 1;
while (ptr)
{
/* after parsing string, it must contain only digits */
if (!valid_digit(ptr))
err = 1;
num = atoi(ptr);
/* check for valid IP */
if (num >= 0 && num <= 255) {
/* parse remaining string */
ptr = strtok(NULL, DELIM);
if (ptr != NULL)
++dots;
} else
err = 1;
}
/* valid IP string must contain 3 dots */
if (dots != 3)
{
err = 1;
}
if(err == 0)
{
return 1;
}
else
{
return 0;
}
}
//////////////IPv6 Validator
#define MAX_HEX_NUMBER_COUNT 8
int ishexdigit(char ch)
{
if((ch>='0'&&ch<='9')||(ch>='a'&&ch<='f')||(ch>='A'&&ch<='F'))
return(1);
return(0);
}
int is_valid_ipv6(char *str)
{
int hdcount=0;
int hncount=0;
int err=0;
int packed=0;
if(*str==':')
{
str++;
if(*str!=':')
return(0);
else
{
packed=1;
hncount=1;
str++;
if(*str==0)
return(1);
}
}
if(ishexdigit(*str)==0)
{
return(0);
}
hdcount=1;
hncount=1;
str++;
while(err==0&&*str!=0)
{
if(*str==':')
{
str++;
if(*str==':')
{
if(packed==1)
err=1;
else
{
str++;
if(ishexdigit(*str) || (*str==0 && hncount < MAX_HEX_NUMBER_COUNT ))
{
packed=1;
hncount++;
if(ishexdigit(*str))
{
if(hncount==MAX_HEX_NUMBER_COUNT)
{
err=1;
} else
{
hdcount=1;
hncount++;
str++;
}
}
} else
{
err=1;
}
}
}
else
{
if(!ishexdigit(*str))
{
err=1;
} else
{
if(hncount==MAX_HEX_NUMBER_COUNT)
{
err=1;
} else
{
hdcount=1;
hncount++;
str++;
}
}
}
}
else
{
if(ishexdigit(*str))
{
if(hdcount==4)
err=1;
else
{
hdcount++;
str++;
}
} else
err=1;
}
}
if(hncount<MAX_HEX_NUMBER_COUNT&&packed==0)
err=1;
return(err==0);
}
uint64_t ip2int(const char * ipconvertint)
{
uint64_t final_result =0;
char * iproc;
int ipat1=0;
int ipat2=0;
int ipat3=0;
int ipat4=0;
char ip[16];
strcpy(ip, ipconvertint);
iproc = strtok (ip,".");
for(int i=0; i<4;i++)
{
switch(i)
{
case 0:
{
ipat1 = atoi(iproc);
break;
}
case 1:
{
ipat2 = atoi(iproc);
break;
}
case 2:
{
ipat3 = atoi(iproc);
break;
}
case 3:
{
ipat4 = atoi(iproc);
break;
}
default:
{
printf("Somebody misplaced an int\n");
break;
}
}
iproc = strtok (NULL,".");
}
final_result = ((ipat1*pow(2,24))+(ipat2*pow(2,16))+(ipat3*pow(2,8))+ipat4*1);
return final_result;
}
char * int2ip(int inputintip)
{
uint32_t ipint = inputintip;
static char xxx_int2ip_result[16] = "\0";
bzero(xxx_int2ip_result,16);
uint32_t ipint0 = (ipint >> 8*3) % 256;
uint32_t ipint1 = (ipint >> 8*2) % 256;
uint32_t ipint2 = (ipint >> 8*1) % 256;
uint32_t ipint3 = (ipint >> 8*0) % 256;
sprintf(xxx_int2ip_result, "%d.%d.%d.%d", ipint0,ipint1,ipint2,ipint3);
return xxx_int2ip_result;
}
/**
* Unserialize the bytes into a string
* @param results where to put the resultant string
* @param in_bytes the bytes to unserialize
* @param in_bytes_size the length of the bytes array
* @returns 0 on error, otherwise 1
*/
int bytes_to_string(char** buffer, const uint8_t* in_bytes, int in_bytes_size)
{
uint8_t * bytes = NULL;
char *results = NULL;
int size = in_bytes_size;
struct ProtocolListItem* head = NULL;
char hex[(in_bytes_size*2)+1];
//Positioning for memory jump:
int lastpos = 0;
char pid[3];
// set up variables
load_protocols(&head);
memset(hex, 0, (in_bytes_size * 2) + 1);
char* tmp = (char*)Var_To_Hex((char*)in_bytes, size);
memcpy(hex, tmp, in_bytes_size * 2);
free(tmp);
pid[2] = 0;
// allocate memory for results
*buffer = malloc(800);
results = *buffer;
memset(results, 0, 800);
//Process Hex String
NAX:
//Stage 1 ID:
pid[0] = hex[lastpos];
pid[1] = hex[lastpos+1];
int protocol_int = Hex_To_Int(pid);
struct Protocol* protocol = proto_with_deccode(head, protocol_int);
if(protocol != NULL)
{
//////////Stage 2: Address
if(strcmp(protocol->name,"ipfs")!=0)
{
lastpos = lastpos+2;
char address[(protocol->size/4)+1];
memset(address, 0, (protocol->size / 4) + 1);
memcpy(address, &hex[lastpos], protocol->size / 4);
//////////Stage 3 Process it back to string
lastpos= lastpos+(protocol->size/4);
//////////Address:
//Keeping Valgrind happy
char name[30];
bzero(name,30);
strcpy(name, protocol->name);
//
strcat(results, "/");
strcat(results, name);
strcat(results, "/");
if(strcmp(name, "ip4")==0)
{
strcat(results,int2ip(Hex_To_Int(address)));
}
else if(strcmp(name, "tcp")==0)
{
char a[5];
sprintf(a,"%lu",Hex_To_Int(address));
strcat(results,a);
}
else if(strcmp(name, "udp")==0)
{
char a[5];
sprintf(a,"%lu",Hex_To_Int(address));
strcat(results,a);
}
/////////////Done processing this, move to next if there is more.
if(lastpos<size*2)
{
goto NAX;
}
}
else//IPFS CASE
{
lastpos = lastpos + 4;
//fetch the size of the address based on the varint prefix
char prefixedvarint[3];
memset(prefixedvarint, 0, 3);
memcpy(prefixedvarint, &hex[lastpos-2], 2);
int addrsize = HexVar_To_Num_32(prefixedvarint);
// get the ipfs address as hex values
unsigned char IPFS_ADDR[addrsize+1];
memset(IPFS_ADDR, 0, addrsize + 1);
memcpy(IPFS_ADDR, &hex[lastpos], addrsize);
// convert the address from hex values to a binary array
size_t num_bytes = 0;
unsigned char* addrbuf = Hex_To_Var((char*)IPFS_ADDR, &num_bytes);
size_t b58_size = strlen((char*)IPFS_ADDR);
unsigned char b58[b58_size];
memset(b58, 0, b58_size);
unsigned char *ptr_b58 = b58;
int returnstatus = multiaddr_encoding_base58_encode(addrbuf, num_bytes, &ptr_b58, &b58_size);
free(addrbuf);
if(returnstatus == 0)
{
fprintf(stderr, "Unable to base58 encode MultiAddress %s\n", IPFS_ADDR);
unload_protocols(head);
return 0;
}
strcat(results, "/");
strcat(results, protocol->name);
strcat(results, "/");
strcat(results, (char*)b58);
}
}
strcat(results, "/");
unload_protocols(head);
return 1;
}
//
/**
* 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)
{
static char astb__stringy[800] = "\0";
memset(astb__stringy, 0, 800);
int code = 0;
code = protocol->deccode;
switch(code)
{
case 4://IPv4
{
char testip[16] = "\0";
bzero(testip,16);
strcpy(testip,incoming);
if(is_valid_ipv4(testip)==1)
{
uint64_t iip = ip2int(incoming);
strcpy(astb__stringy,Int_To_Hex(iip));
protocol = NULL;
*results = malloc(strlen(astb__stringy));
memcpy(*results, astb__stringy, strlen(astb__stringy));
*results_size = strlen(astb__stringy);
return *results;
}
else
{
return "ERR";
}
break;
}
case 41://IPv6 Must be done
{
return "ERR";
break;
}
case 6: //Tcp
{
if(atoi(incoming)<65536&&atoi(incoming)>0)
{
static char himm_woot[5] = "\0";
bzero(himm_woot, 5);
strcpy(himm_woot, Int_To_Hex(atoi(incoming)));
if(himm_woot[2] == '\0')
{//manual switch
char swap0='0';
char swap1='0';
char swap2=himm_woot[0];
char swap3=himm_woot[1];
himm_woot[0] = swap0;
himm_woot[1] = swap1;
himm_woot[2] = swap2;
himm_woot[3] = swap3;
}
else if(himm_woot[3] == '\0')
{
char swap0='0';
char swap1=himm_woot[0];
char swap2=himm_woot[1];
char swap3=himm_woot[2];
himm_woot[0] = swap0;
himm_woot[1] = swap1;
himm_woot[2] = swap2;
himm_woot[3] = swap3;
}
himm_woot[4]='\0';
*results = malloc(5);
*results_size = 5;
memcpy(*results, himm_woot, 5);
return *results;
}
else
{
return "ERR";
}
break;
}
case 17: //Udp
{
if(atoi(incoming)<65536&&atoi(incoming)>0)
{
static char himm_woot2[5] = "\0";
bzero(himm_woot2, 5);
strcpy(himm_woot2, Int_To_Hex(atoi(incoming)));
if(himm_woot2[2] == '\0')
{//Manual Switch2be
char swap0='0';
char swap1='0';
char swap2=himm_woot2[0];
char swap3=himm_woot2[1];
himm_woot2[0] = swap0;
himm_woot2[1] = swap1;
himm_woot2[2] = swap2;
himm_woot2[3] = swap3;
}
else if(himm_woot2[3] == '\0')
{//Manual switch
char swap0='0';
char swap1=himm_woot2[0];
char swap2=himm_woot2[1];
char swap3=himm_woot2[2];
himm_woot2[0] = swap0;
himm_woot2[1] = swap1;
himm_woot2[2] = swap2;
himm_woot2[3] = swap3;
}
himm_woot2[4]='\0';
*results = malloc(5);
*results_size = 5;
memcpy(*results, himm_woot2, 5);
return *results;
}
else
{
return "ERR";
}
break;
}
case 33://dccp
{
return "ERR";
}
case 132://sctp
{
return "ERR";
}
case 301://udt
{
return "ERR";
}
case 302://utp
{
return "ERR";
}
case 42://IPFS - !!!
{
// decode the base58 to bytes
char * incoming_copy = NULL;
incoming_copy = (char*)incoming;
size_t incoming_copy_size = strlen(incoming_copy);
size_t result_buffer_length = multiaddr_encoding_base58_decode_max_size((unsigned char*)incoming_copy);
unsigned char result_buffer[result_buffer_length];
unsigned char* ptr_to_result = result_buffer;
memset(result_buffer, 0, result_buffer_length);
// now get the decoded address
int return_value = multiaddr_encoding_base58_decode(incoming_copy, incoming_copy_size, &ptr_to_result, &result_buffer_length);
if (return_value == 0)
{
return "ERR";
}
// throw everything in a hex string so we can debug the results
char addr_encoded[300];
memset(addr_encoded, 0, 300);
int ilen = 0;
for(int i = 0; i < result_buffer_length; i++)
{
// get the char so we can see it in the debugger
char miu[3];
sprintf(miu,"%02x", ptr_to_result[i]);
strcat(addr_encoded, miu);
}
ilen = strlen(addr_encoded);
char prefixed[3];
memset(prefixed, 0, 3);
strcpy(prefixed,Num_To_HexVar_32(ilen));
*results_size = ilen + 3;
*results = malloc(*results_size);
memset(*results, 0, *results_size);
strcat(*results, prefixed); // 2 bytes
strcat(*results, addr_encoded); // ilen bytes + null terminator
return *results;
}
case 480://http
{
return "ERR";
}
case 443://https
{
return "ERR";
}
case 477://ws
{
return "ERR";
}
case 444://onion
{
return "ERR";
}
case 275://libp2p-webrtc-star
{
return "ERR";
}
default:
{
printf("NO SUCH PROTOCOL!\n");
return "ERR";
}
}
}
/**
* convert a string address into bytes
* @param finalbytes the destination
* @param realbbsize the ultimate size of the destination
* @param strx the incoming string
* @param strsize the string length
*/
int string_to_bytes(uint8_t** finalbytes, size_t* realbbsize, const char* strx, size_t strsize)
{
if(strx[0] != '/')
{
fprintf(stderr, "multiaddr:string_to_bytes: Error, must start with '/' : [%s].\n", strx);
return 0;
}
//Initializing variables to store our processed HEX in:
int malf=0; //In case something goes wrong this will be 1.
char processed[800];//HEX CONTAINER
bzero(processed,800);
//Now Setting up variables for calculating which is the first
//and second word:
int firstorsecond = 1; //1=Protocol && 2 = Address
// copy input so as to not harm it
char pstring[strsize + 1];
strcpy(pstring,strx);
// load up the list of protocols
struct ProtocolListItem* head = NULL;
load_protocols(&head);
//Starting to extract words and process them:
char * wp;
char * end;
wp=strtok_r(pstring,"/",&end);
struct Protocol * protx;
while(wp)
{
if(firstorsecond==1)//This is the Protocol
{
protx = proto_with_name(head, wp);
if(protx != NULL)
{
strcat(processed, Int_To_Hex(protx->deccode));
firstorsecond=2;//Since the next word will be an address
}
else
{
printf("\nNo such protocol!\n\n");
malf=1;
break;
}
}
else//This is the address
{
char* s_to_b = NULL;
int s_to_b_size = 0;
if( strcmp(address_string_to_bytes(protx, wp,strlen(wp), &s_to_b, &s_to_b_size), "ERR") == 0)
{
malf = 1;
}
else
{
int temp_size = strlen(processed);
strncat(processed, s_to_b, s_to_b_size);
processed[temp_size + s_to_b_size] = 0;
free(s_to_b);
}
protx=NULL;//Since right now it doesn't need that assignment anymore.
firstorsecond=1;//Since the next word will be an protocol
}
wp=strtok_r(NULL,"/",&end);
}
protx=NULL;
unload_protocols(head);
if(malf==1)
{
return 0;
}
else
{
*finalbytes = Hex_To_Var(processed, realbbsize);
return 1;
}
}

257
test_multiaddr.h Normal file
View File

@ -0,0 +1,257 @@
#pragma once
#include "multiaddr/multiaddr.h"
#include "multiaddr/varhexutils.h"
int test_new_like_libp2p() {
int retVal = 0;
char* ip = "10.211.55.2";
int port = 4001;
char str[strlen(ip) + 50];
sprintf(str, "/ip4/%s/tcp/%d/", ip, port);
struct MultiAddress* ma_string = multiaddress_new_from_string(str);
// convert to binary
struct MultiAddress* ma_binary = multiaddress_new_from_bytes(ma_string->bytes, ma_string->bsize);
if (strcmp(ma_string->string, ma_binary->string) != 0) {
fprintf(stderr, "%s does not equal %s\n", ma_string->string, ma_binary->string);
goto exit;
}
retVal = 1;
exit:
multiaddress_free(ma_string);
multiaddress_free(ma_binary);
return retVal;
}
int test_new_from_string() {
struct MultiAddress* a = multiaddress_new_from_string("/ip4/127.0.0.1/tcp/8080/");
printf("Number of Bytes: %lu, Bytes: ", a->bsize);
for(int i = 0; i < a->bsize; i++) {
printf("%02x ", a->bytes[i]);
}
printf(" End of bytes\n");
multiaddress_free(a);
return 1;
}
int test_full() {
char addrstr[100];
strcpy(addrstr,"/ip4/192.168.1.1/");
printf("INITIAL: %s\n",addrstr);
struct MultiAddress* a;
a= multiaddress_new_from_string(addrstr);
unsigned char* tmp = Var_To_Hex((char*)a->bytes, a->bsize);
printf("TEST BYTES: %s\n", tmp);
free(tmp);
//Remember, Decapsulation happens from right to left, never in reverse!
printf("A STRING:%s\n",a->string);
multiaddress_encapsulate(a,"/udp/3333/");
printf("A STRING ENCAPSULATED:%s\n",a->string);
tmp = Var_To_Hex((char*)a->bytes, a->bsize);
printf("TEST BYTES: %s\n", tmp);
free(tmp);
multiaddress_decapsulate(a,"udp");
printf("A STRING DECAPSULATED UDP:%s\n",a->string);
tmp = Var_To_Hex((char*)a->bytes, a->bsize);
printf("TEST BYTES: %s\n", tmp);
free(tmp);
multiaddress_encapsulate(a,"/udp/3333/");
printf("A STRING ENCAPSULATED UDP: %s\n",a->string);
multiaddress_encapsulate(a,"/ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG");
printf("A STRING ENCAPSULATED IPFS:%s\n",a->string);
tmp = Var_To_Hex((char*)a->bytes, a->bsize);
printf("TEST BYTES: %s\n", tmp);
free(tmp);
printf("TEST BYTE SIZE: %lu\n",a->bsize);
struct MultiAddress* beta;
beta = multiaddress_new_from_bytes(a->bytes,a->bsize);
printf("B STRING: %s\n",beta->string);
multiaddress_free(a);
multiaddress_free(beta);
return 1;
}
int test_hex_to_var() {
size_t d;
unsigned char* result = Hex_To_Var("04", &d);
if (d != 1)
return 0;
if (result[0] != 4)
return 0;
if (result != NULL)
free(result);
return 1;
}
int test_int_to_hex() {
int val = 2555351;
char* result = Int_To_Hex(val);
int retVal = Hex_To_Int(result);
if (retVal != val)
return 0;
return 1;
}
int test_multiaddr_utils() {
int retVal = 0;
struct MultiAddress* addr = multiaddress_new_from_string("/ip4/127.0.0.1/tcp/4001/");
if (!multiaddress_is_ip(addr)) {
fprintf(stderr, "The address should be an IP\n");
return 0;
}
char* ip = NULL;
multiaddress_get_ip_address(addr, &ip);
if (ip == NULL) {
fprintf(stderr, "get_ip_address returned NULL\n");
goto exit;
}
if(strcmp(ip, "127.0.0.1") != 0) {
fprintf(stderr, "ip addresses are not equal\n");
goto exit;
}
int port = multiaddress_get_ip_port(addr);
if (port != 4001) {
fprintf(stderr, "port incorrect. %d was returned instead of %d\n", port, 4001);
goto exit;
}
retVal = 1;
exit:
if (ip != NULL)
free(ip);
if (addr != NULL)
multiaddress_free(addr);
return retVal;
}
int test_multiaddr_peer_id() {
char* orig_address = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG";
char full_string[255];
char* result = NULL;
char* bytes = NULL;
int retVal = 0, port = 0;
struct MultiAddress *addr = NULL, *addr2 = NULL;
sprintf(full_string, "/ip4/127.0.0.1/tcp/4001/ipfs/%s/", orig_address);
addr = multiaddress_new_from_string(full_string);
result = multiaddress_get_peer_id(addr);
if (result == NULL || strcmp(result, orig_address) != 0)
goto exit;
free(result);
result = NULL;
// switch to bytes and back again to verify the peer id follows...
// 1. display the original bytes
result = (char*)Var_To_Hex((char*)addr->bytes, addr->bsize);
fprintf(stderr, "Original Bytes: %s\n", result);
free(result);
result = NULL;
// make a new MultiAddress from bytes
bytes = malloc(addr->bsize);
memcpy(bytes, addr->bytes, addr->bsize);
addr2 = multiaddress_new_from_bytes((unsigned char*)bytes, addr->bsize);
free(bytes);
bytes = NULL;
// 2. Display the resultant bytes
result = (char*)Var_To_Hex((char*)addr2->bytes, addr2->bsize);
fprintf(stderr, "New Bytes: %s\n", result);
free(result);
result = NULL;
if (strcmp(full_string, addr2->string) != 0) {
fprintf(stderr, "Original string was %s but new string is %s\n", full_string, addr2->string);
goto exit;
}
port = multiaddress_get_ip_port(addr2);
if (port != 4001) {
fprintf(stderr, "Original string had port 4001, but now reporting %d\n", port);
goto exit;
}
result = multiaddress_get_peer_id(addr2);
if (strcmp(result, orig_address) != 0) {
fprintf(stderr, "New peer id %s does not match %s", result, orig_address);
goto exit;
}
free(result);
result = NULL;
retVal = 1;
exit:
if (addr != NULL)
multiaddress_free(addr);
if (addr2 != NULL)
multiaddress_free(addr2);
if (result != NULL)
free(result);
if (bytes != NULL)
free(bytes);
return retVal;
}
int test_multiaddr_get_peer_id() {
const char* orig_address = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG";
char full_string[255] = "";
char* result = NULL;
int retVal = 0;
struct MultiAddress *addr = NULL;
sprintf(full_string, "/ip4/127.0.0.1/tcp/4001/ipfs/%s/", orig_address);
addr = multiaddress_new_from_string(full_string);
result = multiaddress_get_peer_id(addr);
if (result == NULL)
goto exit;
if (strcmp(orig_address, result) != 0)
goto exit;
retVal = 1;
exit:
multiaddress_free(addr);
free(result);
result = NULL;
return retVal;
}
int test_multiaddr_bytes() {
int retVal = 0;
char* orig_address = "/ip4/127.0.0.1/tcp/4001/";
struct MultiAddress *orig = NULL, *result = NULL;
orig = multiaddress_new_from_string(orig_address);
result = multiaddress_new_from_bytes(orig->bytes, orig->bsize);
if (strcmp(orig_address, result->string) != 0) {
fprintf(stderr, "%s does not equal %s\n", orig_address, result->string);
goto exit;
}
retVal = 1;
exit:
if (orig != NULL)
multiaddress_free(orig);
if (result != NULL)
multiaddress_free(result);
return retVal;
}

84
testing.c Normal file
View File

@ -0,0 +1,84 @@
#include <stdio.h>
#include "test_multiaddr.h"
const char* names[] = {
"test_new_from_string",
"test_full",
"test_hex_to_var",
"test_int_to_hex",
"test_multiaddr_utils",
"test_multiaddr_peer_id",
"test_multiaddr_get_peer_id",
"test_multiaddr_bytes",
"test_new_like_libp2p"
};
int (*funcs[])(void) = {
test_new_from_string,
test_full,
test_hex_to_var,
test_int_to_hex,
test_multiaddr_utils,
test_multiaddr_peer_id,
test_multiaddr_get_peer_id,
test_multiaddr_bytes,
test_new_like_libp2p
};
int testit(const char* name, int (*func)(void)) {
printf("Testing %s...\n", name);
int retVal = func();
if (retVal)
printf("%s success!\n", name);
else
printf("** Uh oh! %s failed.**\n", name);
return retVal;
}
int main(int argc, char** argv) {
int counter = 0;
int tests_ran = 0;
char* test_wanted;
int only_one = 0;
if(argc > 1) {
only_one = 1;
if (argv[1][0] == '\'') { // some shells put quotes around arguments
argv[1][strlen(argv[1])-1] = 0;
test_wanted = &(argv[1][1]);
}
else
test_wanted = argv[1];
}
int array_length = sizeof(funcs) / sizeof(funcs[0]);
int array2_length = sizeof(names) / sizeof(names[0]);
if (array_length != array2_length) {
printf("Test arrays are not of the same length. Funcs: %d, Names: %d\n", array_length, array2_length);
}
for (int i = 0; i < array_length; i++) {
if (only_one) {
const char* currName = names[i];
if (strcmp(currName, test_wanted) == 0) {
tests_ran++;
counter += testit(names[i], funcs[i]);
}
}
else
if (!only_one) {
tests_ran++;
counter += testit(names[i], funcs[i]);
}
}
if (tests_ran == 0)
printf("***** No tests found *****\n");
else {
if (tests_ran - counter > 0) {
printf("***** There were %d failed test(s) (%d successful) *****\n", tests_ran - counter, counter);
} else {
printf("All %d tests passed\n", tests_ran);
}
}
return 1;
}

259
varhexutils.c Normal file
View File

@ -0,0 +1,259 @@
#ifndef VARHEXUTILS
#define VARHEXUTILS
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <inttypes.h>
#include "multiaddr/varint.h"
#include "multiaddr/varhexutils.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)
{
static int8_t xrzk_bytescnt = 0;
for(int8_t i=0; i<10; i++)
{
if(countbytesofthis[i] != 0)
{
xrzk_bytescnt++;
}
}
return xrzk_bytescnt;
}
uint8_t * Num_To_Varint_64(uint64_t TOV64INPUT) //UINT64_T TO VARINT
{
static uint8_t buffy_001[60] = {0};
uvarint_encode64(TOV64INPUT, buffy_001, 60);
return buffy_001;
}
uint8_t * Num_To_Varint_32(uint32_t TOV32INPUT) // UINT32_T TO VARINT
{
static uint8_t buffy_032[60] = {0};
uvarint_encode32(TOV32INPUT, buffy_032, 60);
return buffy_032;
}
uint64_t * Varint_To_Num_64(uint8_t TON64INPUT[60]) //VARINT TO UINT64_t
{
static uint64_t varintdecode_001 = 0;
uvarint_decode64(TON64INPUT, 60, &varintdecode_001);
return &varintdecode_001;
}
uint32_t * Varint_To_Num_32(uint8_t TON32INPUT[60]) //VARINT TO UINT32_t
{
static uint32_t varintdecode_032 = 0;
uvarint_decode32(TON32INPUT, 60, &varintdecode_032);
return &varintdecode_032;
}
/**
* Converts a 64 bit integer into a hex string
* @param int2hex the 64 bit integer
* @returns a hex representation as a string (leading zero if necessary)
*/
char * Int_To_Hex(uint64_t int2hex) //VAR[binformat] TO HEX
{
static char result[50];
memset(result, 0, 50);
sprintf(result, "%02lX", int2hex);
int slen = strlen(result);
if (slen % 2 != 0) {
for(int i = slen; i >= 0; --i) {
result[i+1] = result[i];
}
result[0] = '0';
}
return result;
}
uint64_t Hex_To_Int(char * hax)
{
char * hex = NULL;
hex=hax;
uint64_t val = 0;
while (*hex)
{
// get current character then increment
uint8_t byte = *hex++;
// transform hex character to the 4bit equivalent number, using the ascii table indexes
if (byte >= '0' && byte <= '9') byte = byte - '0';
else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10;
else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10;
// shift 4 to make space for new digit, and add the 4 bits of the new digit
val = (val << 4) | (byte & 0xF);
}
return val;
}
/**
* Convert a byte array into a hex byte array
* @param in the incoming byte array
* @param in_size the size of in
* @param out the resultant array of hex bytes
*/
void vthconvert(const unsigned char* in, int in_size, unsigned char** out)
{
*out = (unsigned char*)malloc( (in_size * 2) + 1);
memset(*out, 0, (in_size * 2) + 1);
unsigned char *ptr = *out;
for (int i = 0; i < in_size; i++) {
sprintf((char*)&ptr[i * 2], "%02x", in[i]);
}
}
/**
* 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 unsigned char *incoming, int incoming_size)
{
if(incoming != NULL)
{
unsigned char* retVal = NULL;
// this does the real work
vthconvert(incoming, incoming_size, &retVal);
// we can't return an array that will be deallocated!
return retVal;
}
return NULL;
}
/**
* 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(const char* incoming, size_t* num_bytes) //HEX TO VAR[BINFORMAT]
{
// the return value
unsigned char* retVal = NULL;
int incoming_size = strlen(incoming);
*num_bytes = incoming_size / 2;
retVal = (unsigned char*)malloc(*num_bytes);
char code[3];
code[2]='\0';
int pos = 0;
for(int i=0; i < incoming_size; i += 2)
{
code[0] = incoming[i];
code[1] = incoming[i+1];
uint64_t lu = strtol(code, NULL, 16);
retVal[pos] = (unsigned int)lu;
pos++;
}
return retVal;
}
//
void convert(char * convert_result, uint8_t * buf) //Both of them read them properly.
{
char conv_proc[800]="\0";
bzero(conv_proc,800);
int i;
for(i=0; i < 10; i++)
{
sprintf (conv_proc, "%02X", buf[i]);
//printf("%d:%d\n",i, buf[i]);
strcat(convert_result, conv_proc);
}
}
char * Num_To_HexVar_64(uint64_t TOHVINPUT) //UINT64 TO HEXIFIED VAR
{ //Code to varint - py
static char convert_result[800]="\0";//Note that the hex resulted from this will differ from py
bzero(convert_result,800);
memset(convert_result,0,sizeof(convert_result));//But if you make sure the string is always 20 chars in size
uint8_t buf[400] = {0};
bzero(buf,400);
uvarint_encode64(TOHVINPUT, buf, 800);
convert(convert_result,buf);
return convert_result;
}
void convert2(char * convert_result2, uint8_t * bufhx)
{
uint8_t * buf = NULL;
buf = bufhx;
char conv_proc[4]="\0";
conv_proc[3] = '\0';
bzero(conv_proc, 3);
int i;
for(i=0; i == 0; i++)
{
sprintf (conv_proc, "%02X", buf[i]);
//printf("aaaaaaaaaaah%d:%d\n",i, buf[i]);
strcat(convert_result2, conv_proc);
}
buf = NULL;
}
char * Num_To_HexVar_32(uint32_t TOHVINPUT) //UINT32 TO HEXIFIED VAR
{ //Code to varint - py
static char convert_result2[3]="\0";
bzero(convert_result2,3);
convert_result2[2] = '\0';
memset(convert_result2,0,sizeof(convert_result2));
uint8_t buf[1] = {0};
bzero(buf,1);
uvarint_encode32(TOHVINPUT, buf, 1);
convert2(convert_result2,buf);
return convert_result2;
}
uint64_t HexVar_To_Num_64(char * theHEXstring) //HEXIFIED VAR TO UINT64_T
{ //Varint to code - py
uint8_t buffy[400] = {0};
char codo[800] = "\0";
bzero(codo,800);
strcpy(codo, theHEXstring);
char code[3] = "\0";
int x = 0;
for(int i= 0;i<399;i++)
{
strncpy(&code[0],&codo[i],1);
strncpy(&code[1],&codo[i+1],1);
char *ck = NULL;
uint64_t lu = 0;
lu=strtoul(code, &ck, 16);
buffy[x] = lu;
i++;
x++;
}
static uint64_t decoded;
uvarint_decode64 (buffy, 400, &decoded);
return decoded;
}
uint32_t HexVar_To_Num_32(char theHEXstring[]) //HEXIFIED VAR TO UINT32_T
{ //Varint to code py
uint8_t buffy[400] = {0};
bzero(buffy,400);
char codo[800] = "\0";
bzero(codo,800);
strcpy(codo, theHEXstring);
char code[4] = "\0";
bzero(code,3);
code[3] = '\0';
int x = 0;
for(int i= 0;i<399;i++)
{
strncpy(&code[0],&codo[i],1);
strncpy(&code[1],&codo[i+1],1);
char *ck = NULL;
uint32_t lu = {0};
lu=strtoul(code, &ck, 16);
buffy[x] = lu;
i++;
x++;
}
static uint32_t decoded;
uvarint_decode32 (buffy, 10, &decoded);
return decoded;
}
#endif

8
varint.c Normal file
View File

@ -0,0 +1,8 @@
#include "multiaddr/varint.h"
DEFN_ENCODER(32)
DEFN_DECODER(32)
DEFN_ENCODER(64)
DEFN_DECODER(64)