mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2026-09-22 15:29:03 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53996050a2 | ||
|
|
f5d77a1bc2 | ||
|
|
93a7eef2a5 | ||
|
|
67acba4bc9 | ||
|
|
9979474f1e | ||
|
|
6c53891b44 | ||
|
|
95a23dc7ec | ||
|
|
7c3a446499 | ||
|
|
6a24ac4f00 | ||
|
|
3af55f4423 | ||
|
|
95c0790a88 | ||
|
|
5cabb60a6f | ||
|
|
86056fdbd9 | ||
|
|
8a46452a70 | ||
|
|
20f8668c28 | ||
|
|
7015992b84 | ||
|
|
4be890c171 | ||
|
|
e98fd3dba0 | ||
|
|
f5717f4427 | ||
|
|
5f8a3f4a7f | ||
|
|
499ac2699f | ||
|
|
b342f56bec | ||
|
|
28a73b620e | ||
|
|
e73c4cb68b | ||
|
|
c9c63074bb | ||
|
|
70f368fdc3 | ||
|
|
a7c4cbe53a | ||
|
|
3368330b77 | ||
|
|
b9aeec9f29 | ||
|
|
bf5c07f79a | ||
|
|
63fa4a684d | ||
|
|
3635a940f9 | ||
|
|
71b1eb9d52 | ||
|
|
58c9e90b49 | ||
|
|
d415c61c67 | ||
|
|
2e373f6400 | ||
|
|
421a04b35f | ||
|
|
80d8b7d0ae | ||
|
|
f823fd05ac | ||
|
|
2a6b74746e | ||
|
|
741642ba53 | ||
|
|
8d30d51cf3 | ||
|
|
ee9a811b81 | ||
|
|
f260c2839c | ||
|
|
2ba97fb46b | ||
|
|
9df88a3933 | ||
|
|
3daea24d50 | ||
|
|
7e156b2622 | ||
|
|
e4c5ad9f43 | ||
|
|
439e602d5a | ||
|
|
a53cfc9096 | ||
|
|
e7b515c86c | ||
|
|
304ed641fe | ||
|
|
7a17f6ca80 | ||
|
|
d35d322890 | ||
|
|
dd203f0065 | ||
|
|
fb975ead23 | ||
|
|
a816f56426 | ||
|
|
e6e825da70 | ||
|
|
917b95a1d6 | ||
|
|
b0a83093ce | ||
|
|
57d8730f1b | ||
|
|
af8fcac0fc | ||
|
|
9cf734b74a | ||
|
|
083ae2d097 | ||
|
|
668c428051 | ||
|
|
10fc164fcb | ||
|
|
0c7f8e247c | ||
|
|
b8e9a79d00 | ||
|
|
e4e517e9c3 | ||
|
|
5f4eb1ebc6 | ||
|
|
c345c699fd | ||
|
|
a677597b44 | ||
|
|
1fce55fab1 | ||
|
|
2e85cf18c1 | ||
|
|
76bc9968ff | ||
|
|
557cc359b3 | ||
|
|
102b0865cb | ||
|
|
a793dc2b29 | ||
|
|
a6f4de8172 | ||
|
|
1d36ea8ddf | ||
|
|
ca83f07b54 | ||
|
|
195ded4608 | ||
|
|
97cbd98bc5 | ||
|
|
3e49337d9a | ||
|
|
c6dd5b239f | ||
|
|
aa59c1de10 | ||
|
|
a004878546 | ||
|
|
086050686f | ||
|
|
f934b81703 | ||
|
|
77fd78d5c9 | ||
|
|
a86e1cdb88 | ||
|
|
2510f594e5 | ||
|
|
339b2314ea | ||
|
|
fd2b383c3e | ||
|
|
ae93c95151 | ||
|
|
ffad0b2780 | ||
|
|
bcd079b70e | ||
|
|
9f8069434a | ||
|
|
9e28bbfbb2 | ||
|
|
47f611e7b8 | ||
|
|
b14856da50 | ||
|
|
1111d11be1 | ||
|
|
51295e77d0 | ||
|
|
a20b540fb0 | ||
|
|
ef3e319c64 | ||
|
|
41cd980bf7 |
No files matched your search
@@ -16,12 +16,6 @@ ZeroTier One includes or links with the following third party software:
|
||||
* LZ4 compression algorithm by Yann Collet (BSD license)
|
||||
http://code.google.com/p/lz4/
|
||||
|
||||
* JsonCPP by Baptiste Lepilleur (public domain)
|
||||
http://jsoncpp.sourceforge.net
|
||||
|
||||
* http-parser, a simple C http parser library (MIT license)
|
||||
https://github.com/joyent/http-parser
|
||||
|
||||
* OpenSSL libcrypto (BSD-style OpenSSL license)
|
||||
http://www.openssl.org/
|
||||
|
||||
|
||||
+10
-10
@@ -6,12 +6,12 @@ ARCH=$(shell uname -m)
|
||||
DEFS=-DZT_ARCH="$(ARCH)" -DZT_OSNAME="linux" -DZT_TRACE
|
||||
|
||||
# Uncomment for a release optimized build
|
||||
CFLAGS=-Wall -O3 -fno-unroll-loops -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
STRIP=strip --strip-all
|
||||
#CFLAGS=-Wall -O3 -fno-unroll-loops -fstack-protector -pthread $(INCLUDES) -DNDEBUG $(DEFS)
|
||||
#STRIP=strip --strip-all
|
||||
|
||||
# Uncomment for a debug build
|
||||
#CFLAGS=-Wall -g -pthread $(INCLUDES) -DZT_TRACE -DZT_LOG_STDOUT $(DEFS)
|
||||
#STRIP=echo
|
||||
CFLAGS=-Wall -g -pthread $(INCLUDES) -DZT_TRACE $(DEFS)
|
||||
STRIP=echo
|
||||
|
||||
CXXFLAGS=$(CFLAGS) -fno-rtti
|
||||
|
||||
@@ -20,16 +20,20 @@ CXXFLAGS=$(CFLAGS) -fno-rtti
|
||||
# separate binaries for the RedHat and Debian universes to distribute via
|
||||
# auto-update. This way we get one Linux binary for all systems of a given
|
||||
# architecture.
|
||||
LIBS=ext/bin/libcrypto/linux-$(ARCH)/libcrypto.a
|
||||
LIBS=ext/bin/libcrypto/linux-$(ARCH)/libcrypto.a -lm -ldl
|
||||
|
||||
include objects.mk
|
||||
|
||||
all: one launcher
|
||||
all: one cli launcher
|
||||
|
||||
one: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-one main.cpp $(OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-one
|
||||
|
||||
cli: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-cli cli.cpp $(OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-cli
|
||||
|
||||
selftest: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.cpp $(OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-selftest
|
||||
@@ -38,10 +42,6 @@ idtool: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-idtool idtool.cpp $(OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-idtool
|
||||
|
||||
packtool: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-packtool packtool.cpp $(OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-packtool
|
||||
|
||||
launcher:
|
||||
$(CC) -Os -o zerotier-launcher launcher.c
|
||||
$(STRIP) zerotier-launcher
|
||||
|
||||
+10
-10
@@ -5,7 +5,7 @@ INCLUDES=-Iext/bin/libcrypto/include -Iext/jsoncpp/include
|
||||
DEFS=-DZT_ARCH="x86_combined" -DZT_OSNAME="mac" -DZT_TRACE
|
||||
|
||||
# Uncomment for a release optimized universal binary build
|
||||
CFLAGS=-arch i386 -arch x86_64 -Wall -O3 -ftree-vectorize -pthread -mmacosx-version-min=10.6 -DNDEBUG $(INCLUDES) $(DEFS)
|
||||
CFLAGS=-arch i386 -arch x86_64 -Wall -O3 -ftree-vectorize -fstack-protector -pthread -mmacosx-version-min=10.6 -DNDEBUG $(INCLUDES) $(DEFS)
|
||||
STRIP=strip
|
||||
|
||||
# Uncomment for a debug build
|
||||
@@ -13,19 +13,20 @@ STRIP=strip
|
||||
#STRIP=echo
|
||||
|
||||
CXXFLAGS=$(CFLAGS) -fno-rtti
|
||||
|
||||
# We statically link against libcrypto since Apple has apparently decided
|
||||
# to deprecate it and may remove it in future OS releases.
|
||||
LIBS=ext/bin/libcrypto/mac-x86_combined/libcrypto.a
|
||||
LIBS=-lcrypto -lm
|
||||
|
||||
include objects.mk
|
||||
|
||||
all: one launcher mac-tap
|
||||
all: one cli launcher mac-tap
|
||||
|
||||
one: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-one main.cpp $(OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-one
|
||||
|
||||
cli: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-cli cli.cpp $(OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-cli
|
||||
|
||||
selftest: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.cpp $(OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-selftest
|
||||
@@ -34,10 +35,6 @@ idtool: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-idtool idtool.cpp $(OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-idtool
|
||||
|
||||
packtool: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-packtool packtool.cpp $(OBJS) $(LIBS)
|
||||
$(STRIP) zerotier-packtool
|
||||
|
||||
mac-tap: FORCE
|
||||
cd mac-tap/tuntap ; make tap.kext
|
||||
|
||||
@@ -55,6 +52,9 @@ launcher-fakebin:
|
||||
$(CC) $(CFLAGS) -DZEROTIER_FAKE_VERSION_MAJOR=1 -DZEROTIER_FAKE_VERSION_MINOR=2 -DZEROTIER_FAKE_VERSION_REV
|
||||
$(CC) $(CFLAGS) -DZEROTIER_FAKE_VERSION_MAJOR=1 -DZEROTIER_FAKE_VERSION_MINOR=2 -DZEROTIER_FAKE_VERSION_REV
|
||||
|
||||
makekeypair: $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -o zerotier-makekeypair makekeypair.cpp $(OBJS) $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -rf *.dSYM
|
||||
rm -f $(OBJS) zerotier-*
|
||||
|
||||
@@ -50,9 +50,6 @@ Check out the [blog](http://blog.zerotier.com/) for announcements, in-depth arti
|
||||
**Q:** What about privacy? Does this hide my location on the network?
|
||||
**A:** ZeroTier is not a connection anonymizer. Other than encryption, it doesn't do anything special to hide your identity or network location. If you want strong privacy protection there are already very advanced tools like [Tor](https://www.torproject.org) for that, and this isn't trying to duplicate their functionality. At the same time, ZT does not do anything special to harm your privacy either. It's not spyware or snoop-ware.
|
||||
|
||||
**Q:** You say "almost unlimited size." Isn't multicast and broadcast traffic eventually going to be too much? What happens then?
|
||||
**A:** ZeroTier One uses an algorithm called *implicit social switching*. The overall maximum number of recipients for a multicast is limited, so if there are too many listeners to a given multicast address then obviously not everyone will receive every message. So who does? Social switching causes multicasts to propagate in the direction of peers to whom you have recently communicated. As a result, multicasts tend to propagate along lines of association. The people most likely to get your service announcements are those with whom you frequently connect.
|
||||
|
||||
**Q:** Is this designed to replace IP, BGP, IPv6, routers, etc.?
|
||||
**A:** No. Its purpose is to act as a collaboration tool, a VPN alternative, a network mobility tool, a testbed for the development of software that takes advantage of fully open networking, a virtual LAN party for gamers, and so on, but it's not intended (or able) to replace the core of the Internet.
|
||||
|
||||
@@ -92,6 +89,7 @@ Check out the [blog](http://blog.zerotier.com/) for announcements, in-depth arti
|
||||
|
||||
----
|
||||
|
||||
<a href="http://flattr.com/thing/1611614/ZeroTier-Networks" target="_blank"><img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>
|
||||
<a href="http://flattr.com/thing/1611614/ZeroTier-Networks" target="_blank"><img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" /></a>
|
||||
[](http://githalytics.com/zerotier/ZeroTierOne)
|
||||
|
||||
(c)2012-2013 [ZeroTier Networks LLC](https://www.zerotier.com/)
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* ZeroTier One - Global Peer to Peer Ethernet
|
||||
* Copyright (C) 2012-2013 ZeroTier Networks LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which
|
||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*
|
||||
* If you would like to embed ZeroTier into a commercial application or
|
||||
* redistribute it in a modified binary form, please contact ZeroTier Networks
|
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef __WINDOWS__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "node/Node.hpp"
|
||||
#include "node/Constants.hpp"
|
||||
#include "node/Utils.hpp"
|
||||
#include "node/Thread.hpp"
|
||||
#include "node/Condition.hpp"
|
||||
|
||||
using namespace ZeroTier;
|
||||
|
||||
static void printHelp(FILE *out,const char *exename)
|
||||
{
|
||||
fprintf(out,"Usage: %s [-switches] <command>"ZT_EOL_S,exename);
|
||||
fprintf(out,ZT_EOL_S);
|
||||
fprintf(out,"Switches:"ZT_EOL_S);
|
||||
fprintf(out," -t<token> - Specify token on command line"ZT_EOL_S);
|
||||
fprintf(out," -T<file> - Read token from file"ZT_EOL_S);
|
||||
fprintf(out,ZT_EOL_S);
|
||||
fprintf(out,"Use the 'help' command to get help from ZeroTier One itself."ZT_EOL_S);
|
||||
}
|
||||
|
||||
static volatile unsigned int numResults = 0;
|
||||
static Condition doneCondition;
|
||||
|
||||
static void resultHandler(void *arg,unsigned long id,const char *line)
|
||||
{
|
||||
++numResults;
|
||||
if (strlen(line))
|
||||
fprintf(stdout,"%s"ZT_EOL_S,line);
|
||||
else doneCondition.signal();
|
||||
}
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
if (argc <= 1) {
|
||||
printHelp(stdout,argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string authToken;
|
||||
std::string command;
|
||||
bool pastSwitches = false;
|
||||
for(int i=1;i<argc;++i) {
|
||||
if ((argv[i][0] == '-')&&(!pastSwitches)) {
|
||||
if (strlen(argv[i]) <= 1) {
|
||||
printHelp(stdout,argv[0]);
|
||||
return -1;
|
||||
}
|
||||
switch(argv[i][1]) {
|
||||
case 't':
|
||||
authToken.assign(argv[i] + 2);
|
||||
break;
|
||||
case 'T':
|
||||
if (!Utils::readFile(argv[i] + 2,authToken)) {
|
||||
fprintf(stdout,"FATAL ERROR: unable to read token from '%s'"ZT_EOL_S,argv[i] + 2);
|
||||
return -2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
pastSwitches = true;
|
||||
if (command.length())
|
||||
command.push_back(' ');
|
||||
command.append(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!authToken.length()) {
|
||||
const char *home = getenv("HOME");
|
||||
if (home) {
|
||||
std::string dotZeroTierAuthToken(home);
|
||||
dotZeroTierAuthToken.push_back(ZT_PATH_SEPARATOR);
|
||||
dotZeroTierAuthToken.append(".zerotierOneAuthToken");
|
||||
if (!Utils::readFile(dotZeroTierAuthToken.c_str(),authToken)) {
|
||||
#ifndef __WINDOWS__
|
||||
#ifdef __APPLE__
|
||||
const char *systemAuthTokenPath = "/Library/Application Support/ZeroTier/One/authtoken.secret";
|
||||
#else
|
||||
const char *systemAuthTokenPath = "/var/lib/zerotier-one/authtoken.secret";
|
||||
#endif
|
||||
if (!Utils::readFile(systemAuthTokenPath,authToken)) {
|
||||
fprintf(stdout,"FATAL ERROR: no token specified on command line and could not read '%s' or '%s'"ZT_EOL_S,dotZeroTierAuthToken.c_str(),systemAuthTokenPath);
|
||||
return -2;
|
||||
}
|
||||
#else // __WINDOWS__
|
||||
fprintf(stdout,"FATAL ERROR: no token specified on command line and could not read '%s'"ZT_EOL_S,dotZeroTierAuthToken.c_str());
|
||||
return -2;
|
||||
#endif // __WINDOWS__
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!authToken.length()) {
|
||||
fprintf(stdout,"FATAL ERROR: could not find auth token"ZT_EOL_S);
|
||||
return -2;
|
||||
}
|
||||
|
||||
Node::LocalClient client(authToken.c_str(),&resultHandler,(void *)0);
|
||||
client.send(command.c_str());
|
||||
|
||||
doneCondition.wait(1000);
|
||||
|
||||
if (!numResults) {
|
||||
fprintf(stdout,"ERROR: no results received. Is ZeroTier One running?"ZT_EOL_S);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
Symlink
+1
@@ -0,0 +1 @@
|
||||
linux-armv4/
|
||||
@@ -0,0 +1,4 @@
|
||||
make clean
|
||||
./Configure no-sock no-ssl2 no-ssl3 no-err no-krb5 no-engine no-hw no-tlsext no-jpake no-capieng no-idea no-camellia no-seed no-bf no-cast no-des no-rc2 no-rc4 no-rc5 no-md2 no-md4 no-ripemd no-mdc2 no-rsa no-dsa no-dh no-shared no-zlib no-dso no-cms no-ocsp no-txt_db no-pem no-mdc2 no-ui no-ts linux-armv4
|
||||
make depend
|
||||
make build_crypto
|
||||
@@ -1,41 +0,0 @@
|
||||
# Authors ordered by first contribution.
|
||||
Ryan Dahl <ry@tinyclouds.org>
|
||||
Jeremy Hinegardner <jeremy@hinegardner.org>
|
||||
Sergey Shepelev <temotor@gmail.com>
|
||||
Joe Damato <ice799@gmail.com>
|
||||
tomika <tomika_nospam@freemail.hu>
|
||||
Phoenix Sol <phoenix@burninglabs.com>
|
||||
Cliff Frey <cliff@meraki.com>
|
||||
Ewen Cheslack-Postava <ewencp@cs.stanford.edu>
|
||||
Santiago Gala <sgala@apache.org>
|
||||
Tim Becker <tim.becker@syngenio.de>
|
||||
Jeff Terrace <jterrace@gmail.com>
|
||||
Ben Noordhuis <info@bnoordhuis.nl>
|
||||
Nathan Rajlich <nathan@tootallnate.net>
|
||||
Mark Nottingham <mnot@mnot.net>
|
||||
Aman Gupta <aman@tmm1.net>
|
||||
Tim Becker <tim.becker@kuriositaet.de>
|
||||
Sean Cunningham <sean.cunningham@mandiant.com>
|
||||
Peter Griess <pg@std.in>
|
||||
Salman Haq <salman.haq@asti-usa.com>
|
||||
Cliff Frey <clifffrey@gmail.com>
|
||||
Jon Kolb <jon@b0g.us>
|
||||
Fouad Mardini <f.mardini@gmail.com>
|
||||
Paul Querna <pquerna@apache.org>
|
||||
Felix Geisendörfer <felix@debuggable.com>
|
||||
koichik <koichik@improvement.jp>
|
||||
Andre Caron <andre.l.caron@gmail.com>
|
||||
Ivo Raisr <ivosh@ivosh.net>
|
||||
James McLaughlin <jamie@lacewing-project.org>
|
||||
David Gwynne <loki@animata.net>
|
||||
Thomas LE ROUX <thomas@november-eleven.fr>
|
||||
Randy Rizun <rrizun@ortivawireless.com>
|
||||
Andre Louis Caron <andre.louis.caron@usherbrooke.ca>
|
||||
Simon Zimmermann <simonz05@gmail.com>
|
||||
Erik Dubbelboer <erik@dubbelboer.com>
|
||||
Martell Malone <martellmalone@gmail.com>
|
||||
Bertrand Paquet <bpaquet@octo.com>
|
||||
BogDan Vatra <bogdan@kde.org>
|
||||
Peter Faiman <peter@thepicard.org>
|
||||
Corey Richardson <corey@octayn.net>
|
||||
Tóth Tamás <tomika_nospam@freemail.hu>
|
||||
@@ -1,4 +0,0 @@
|
||||
Contributors must agree to the Contributor License Agreement before patches
|
||||
can be accepted.
|
||||
|
||||
http://spreadsheets2.google.com/viewform?hl=en&formkey=dDJXOGUwbzlYaWM4cHN1MERwQS1CSnc6MQ
|
||||
@@ -1,23 +0,0 @@
|
||||
http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright
|
||||
Igor Sysoev.
|
||||
|
||||
Additional changes are licensed under the same terms as NGINX and
|
||||
copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
||||
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.
|
||||
@@ -1,180 +0,0 @@
|
||||
HTTP Parser
|
||||
===========
|
||||
|
||||
[](https://travis-ci.org/joyent/http-parser)
|
||||
|
||||
This is a parser for HTTP messages written in C. It parses both requests and
|
||||
responses. The parser is designed to be used in performance HTTP
|
||||
applications. It does not make any syscalls nor allocations, it does not
|
||||
buffer data, it can be interrupted at anytime. Depending on your
|
||||
architecture, it only requires about 40 bytes of data per message
|
||||
stream (in a web server that is per connection).
|
||||
|
||||
Features:
|
||||
|
||||
* No dependencies
|
||||
* Handles persistent streams (keep-alive).
|
||||
* Decodes chunked encoding.
|
||||
* Upgrade support
|
||||
* Defends against buffer overflow attacks.
|
||||
|
||||
The parser extracts the following information from HTTP messages:
|
||||
|
||||
* Header fields and values
|
||||
* Content-Length
|
||||
* Request method
|
||||
* Response status code
|
||||
* Transfer-Encoding
|
||||
* HTTP version
|
||||
* Request URL
|
||||
* Message body
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
One `http_parser` object is used per TCP connection. Initialize the struct
|
||||
using `http_parser_init()` and set the callbacks. That might look something
|
||||
like this for a request parser:
|
||||
|
||||
http_parser_settings settings;
|
||||
settings.on_url = my_url_callback;
|
||||
settings.on_header_field = my_header_field_callback;
|
||||
/* ... */
|
||||
|
||||
http_parser *parser = malloc(sizeof(http_parser));
|
||||
http_parser_init(parser, HTTP_REQUEST);
|
||||
parser->data = my_socket;
|
||||
|
||||
When data is received on the socket execute the parser and check for errors.
|
||||
|
||||
size_t len = 80*1024, nparsed;
|
||||
char buf[len];
|
||||
ssize_t recved;
|
||||
|
||||
recved = recv(fd, buf, len, 0);
|
||||
|
||||
if (recved < 0) {
|
||||
/* Handle error. */
|
||||
}
|
||||
|
||||
/* Start up / continue the parser.
|
||||
* Note we pass recved==0 to signal that EOF has been recieved.
|
||||
*/
|
||||
nparsed = http_parser_execute(parser, &settings, buf, recved);
|
||||
|
||||
if (parser->upgrade) {
|
||||
/* handle new protocol */
|
||||
} else if (nparsed != recved) {
|
||||
/* Handle error. Usually just close the connection. */
|
||||
}
|
||||
|
||||
HTTP needs to know where the end of the stream is. For example, sometimes
|
||||
servers send responses without Content-Length and expect the client to
|
||||
consume input (for the body) until EOF. To tell http_parser about EOF, give
|
||||
`0` as the forth parameter to `http_parser_execute()`. Callbacks and errors
|
||||
can still be encountered during an EOF, so one must still be prepared
|
||||
to receive them.
|
||||
|
||||
Scalar valued message information such as `status_code`, `method`, and the
|
||||
HTTP version are stored in the parser structure. This data is only
|
||||
temporally stored in `http_parser` and gets reset on each new message. If
|
||||
this information is needed later, copy it out of the structure during the
|
||||
`headers_complete` callback.
|
||||
|
||||
The parser decodes the transfer-encoding for both requests and responses
|
||||
transparently. That is, a chunked encoding is decoded before being sent to
|
||||
the on_body callback.
|
||||
|
||||
|
||||
The Special Problem of Upgrade
|
||||
------------------------------
|
||||
|
||||
HTTP supports upgrading the connection to a different protocol. An
|
||||
increasingly common example of this is the Web Socket protocol which sends
|
||||
a request like
|
||||
|
||||
GET /demo HTTP/1.1
|
||||
Upgrade: WebSocket
|
||||
Connection: Upgrade
|
||||
Host: example.com
|
||||
Origin: http://example.com
|
||||
WebSocket-Protocol: sample
|
||||
|
||||
followed by non-HTTP data.
|
||||
|
||||
(See http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 for more
|
||||
information the Web Socket protocol.)
|
||||
|
||||
To support this, the parser will treat this as a normal HTTP message without a
|
||||
body. Issuing both on_headers_complete and on_message_complete callbacks. However
|
||||
http_parser_execute() will stop parsing at the end of the headers and return.
|
||||
|
||||
The user is expected to check if `parser->upgrade` has been set to 1 after
|
||||
`http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied
|
||||
offset by the return value of `http_parser_execute()`.
|
||||
|
||||
|
||||
Callbacks
|
||||
---------
|
||||
|
||||
During the `http_parser_execute()` call, the callbacks set in
|
||||
`http_parser_settings` will be executed. The parser maintains state and
|
||||
never looks behind, so buffering the data is not necessary. If you need to
|
||||
save certain data for later usage, you can do that from the callbacks.
|
||||
|
||||
There are two types of callbacks:
|
||||
|
||||
* notification `typedef int (*http_cb) (http_parser*);`
|
||||
Callbacks: on_message_begin, on_headers_complete, on_message_complete.
|
||||
* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);`
|
||||
Callbacks: (requests only) on_uri,
|
||||
(common) on_header_field, on_header_value, on_body;
|
||||
|
||||
Callbacks must return 0 on success. Returning a non-zero value indicates
|
||||
error to the parser, making it exit immediately.
|
||||
|
||||
In case you parse HTTP message in chunks (i.e. `read()` request line
|
||||
from socket, parse, read half headers, parse, etc) your data callbacks
|
||||
may be called more than once. Http-parser guarantees that data pointer is only
|
||||
valid for the lifetime of callback. You can also `read()` into a heap allocated
|
||||
buffer to avoid copying memory around if this fits your application.
|
||||
|
||||
Reading headers may be a tricky task if you read/parse headers partially.
|
||||
Basically, you need to remember whether last header callback was field or value
|
||||
and apply following logic:
|
||||
|
||||
(on_header_field and on_header_value shortened to on_h_*)
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| State (prev. callback) | Callback | Description/action |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| nothing (first call) | on_h_field | Allocate new buffer and copy callback data |
|
||||
| | | into it |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| value | on_h_field | New header started. |
|
||||
| | | Copy current name,value buffers to headers |
|
||||
| | | list and allocate new buffer for new name |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| field | on_h_field | Previous name continues. Reallocate name |
|
||||
| | | buffer and append callback data to it |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| field | on_h_value | Value for current header started. Allocate |
|
||||
| | | new buffer and copy callback data to it |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
| value | on_h_value | Value continues. Reallocate value buffer |
|
||||
| | | and append callback data to it |
|
||||
------------------------ ------------ --------------------------------------------
|
||||
|
||||
|
||||
Parsing URLs
|
||||
------------
|
||||
|
||||
A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`.
|
||||
Users of this library may wish to use it to parse URLs constructed from
|
||||
consecutive `on_url` callbacks.
|
||||
|
||||
See examples of reading in headers:
|
||||
|
||||
* [partial example](http://gist.github.com/155877) in C
|
||||
* [from http-parser tests](http://github.com/joyent/http-parser/blob/37a0ff8/test.c#L403) in C
|
||||
* [from Node library](http://github.com/joyent/node/blob/842eaf4/src/http.js#L284) in Javascript
|
||||
@@ -1,156 +0,0 @@
|
||||
/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
|
||||
*
|
||||
* Additional changes are licensed under the same terms as NGINX and
|
||||
* copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Dump what the parser finds to stdout as it happen */
|
||||
|
||||
#include "http_parser.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int on_message_begin(http_parser* _) {
|
||||
(void)_;
|
||||
printf("\n***MESSAGE BEGIN***\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_headers_complete(http_parser* _) {
|
||||
(void)_;
|
||||
printf("\n***HEADERS COMPLETE***\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_message_complete(http_parser* _) {
|
||||
(void)_;
|
||||
printf("\n***MESSAGE COMPLETE***\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_url(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Url: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_header_field(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Header field: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_header_value(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Header value: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int on_body(http_parser* _, const char* at, size_t length) {
|
||||
(void)_;
|
||||
printf("Body: %.*s\n", (int)length, at);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usage(const char* name) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s $type $filename\n"
|
||||
" type: -x, where x is one of {r,b,q}\n"
|
||||
" parses file as a Response, reQuest, or Both\n",
|
||||
name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
enum http_parser_type file_type;
|
||||
|
||||
if (argc != 3) {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
char* type = argv[1];
|
||||
if (type[0] != '-') {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
switch (type[1]) {
|
||||
/* in the case of "-", type[1] will be NUL */
|
||||
case 'r':
|
||||
file_type = HTTP_RESPONSE;
|
||||
break;
|
||||
case 'q':
|
||||
file_type = HTTP_REQUEST;
|
||||
break;
|
||||
case 'b':
|
||||
file_type = HTTP_BOTH;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
char* filename = argv[2];
|
||||
FILE* file = fopen(filename, "r");
|
||||
if (file == NULL) {
|
||||
perror("fopen");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long file_length = ftell(file);
|
||||
if (file_length == -1) {
|
||||
perror("ftell");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
char* data = malloc(file_length);
|
||||
if (fread(data, 1, file_length, file) != (size_t)file_length) {
|
||||
fprintf(stderr, "couldn't read entire file\n");
|
||||
free(data);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
http_parser_settings settings;
|
||||
memset(&settings, 0, sizeof(settings));
|
||||
settings.on_message_begin = on_message_begin;
|
||||
settings.on_url = on_url;
|
||||
settings.on_header_field = on_header_field;
|
||||
settings.on_header_value = on_header_value;
|
||||
settings.on_headers_complete = on_headers_complete;
|
||||
settings.on_body = on_body;
|
||||
settings.on_message_complete = on_message_complete;
|
||||
|
||||
http_parser parser;
|
||||
http_parser_init(&parser, file_type);
|
||||
size_t nparsed = http_parser_execute(&parser, &settings, data, file_length);
|
||||
free(data);
|
||||
|
||||
if (nparsed != (size_t)file_length) {
|
||||
fprintf(stderr,
|
||||
"Error: %s (%s)\n",
|
||||
http_errno_description(HTTP_PARSER_ERRNO(&parser)),
|
||||
http_errno_name(HTTP_PARSER_ERRNO(&parser)));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
#include "http_parser.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void
|
||||
dump_url (const char *url, const struct http_parser_url *u)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port);
|
||||
for (i = 0; i < UF_MAX; i++) {
|
||||
if ((u->field_set & (1 << i)) == 0) {
|
||||
printf("\tfield_data[%u]: unset\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n",
|
||||
i,
|
||||
u->field_data[i].off,
|
||||
u->field_data[i].len,
|
||||
u->field_data[i].len,
|
||||
url + u->field_data[i].off);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
if (argc != 3) {
|
||||
printf("Syntax : %s connect|get url\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
struct http_parser_url u;
|
||||
int len = strlen(argv[2]);
|
||||
int connect = strcmp("connect", argv[1]) == 0 ? 1 : 0;
|
||||
printf("Parsing %s, connect %d\n", argv[2], connect);
|
||||
|
||||
int result = http_parser_parse_url(argv[2], len, connect, &u);
|
||||
if (result != 0) {
|
||||
printf("Parse error : %d\n", result);
|
||||
return result;
|
||||
}
|
||||
printf("Parse ok, result : \n");
|
||||
dump_url(argv[2], &u);
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,111 +0,0 @@
|
||||
# This file is used with the GYP meta build system.
|
||||
# http://code.google.com/p/gyp/
|
||||
# To build try this:
|
||||
# svn co http://gyp.googlecode.com/svn/trunk gyp
|
||||
# ./gyp/gyp -f make --depth=`pwd` http_parser.gyp
|
||||
# ./out/Debug/test
|
||||
{
|
||||
'target_defaults': {
|
||||
'default_configuration': 'Debug',
|
||||
'configurations': {
|
||||
# TODO: hoist these out and put them somewhere common, because
|
||||
# RuntimeLibrary MUST MATCH across the entire project
|
||||
'Debug': {
|
||||
'defines': [ 'DEBUG', '_DEBUG' ],
|
||||
'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'RuntimeLibrary': 1, # static debug
|
||||
},
|
||||
},
|
||||
},
|
||||
'Release': {
|
||||
'defines': [ 'NDEBUG' ],
|
||||
'cflags': [ '-Wall', '-Wextra', '-O3' ],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'RuntimeLibrary': 0, # static release
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
},
|
||||
'VCLibrarianTool': {
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'GenerateDebugInformation': 'true',
|
||||
},
|
||||
},
|
||||
'conditions': [
|
||||
['OS == "win"', {
|
||||
'defines': [
|
||||
'WIN32'
|
||||
],
|
||||
}]
|
||||
],
|
||||
},
|
||||
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'http_parser',
|
||||
'type': 'static_library',
|
||||
'include_dirs': [ '.' ],
|
||||
'direct_dependent_settings': {
|
||||
'defines': [ 'HTTP_PARSER_STRICT=0' ],
|
||||
'include_dirs': [ '.' ],
|
||||
},
|
||||
'defines': [ 'HTTP_PARSER_STRICT=0' ],
|
||||
'sources': [ './http_parser.c', ],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
# Compile as C++. http_parser.c is actually C99, but C++ is
|
||||
# close enough in this case.
|
||||
'CompileAs': 2,
|
||||
},
|
||||
},
|
||||
}]
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
'target_name': 'http_parser_strict',
|
||||
'type': 'static_library',
|
||||
'include_dirs': [ '.' ],
|
||||
'direct_dependent_settings': {
|
||||
'defines': [ 'HTTP_PARSER_STRICT=1' ],
|
||||
'include_dirs': [ '.' ],
|
||||
},
|
||||
'defines': [ 'HTTP_PARSER_STRICT=1' ],
|
||||
'sources': [ './http_parser.c', ],
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
# Compile as C++. http_parser.c is actually C99, but C++ is
|
||||
# close enough in this case.
|
||||
'CompileAs': 2,
|
||||
},
|
||||
},
|
||||
}]
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
'target_name': 'test-nonstrict',
|
||||
'type': 'executable',
|
||||
'dependencies': [ 'http_parser' ],
|
||||
'sources': [ 'test.c' ]
|
||||
},
|
||||
|
||||
{
|
||||
'target_name': 'test-strict',
|
||||
'type': 'executable',
|
||||
'dependencies': [ 'http_parser_strict' ],
|
||||
'sources': [ 'test.c' ]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,304 +0,0 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef http_parser_h
|
||||
#define http_parser_h
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define HTTP_PARSER_VERSION_MAJOR 2
|
||||
#define HTTP_PARSER_VERSION_MINOR 0
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)
|
||||
#include <BaseTsd.h>
|
||||
#include <stddef.h>
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
|
||||
* faster
|
||||
*/
|
||||
#ifndef HTTP_PARSER_STRICT
|
||||
# define HTTP_PARSER_STRICT 1
|
||||
#endif
|
||||
|
||||
/* Maximium header size allowed */
|
||||
#define HTTP_MAX_HEADER_SIZE (80*1024)
|
||||
|
||||
|
||||
typedef struct http_parser http_parser;
|
||||
typedef struct http_parser_settings http_parser_settings;
|
||||
|
||||
|
||||
/* Callbacks should return non-zero to indicate an error. The parser will
|
||||
* then halt execution.
|
||||
*
|
||||
* The one exception is on_headers_complete. In a HTTP_RESPONSE parser
|
||||
* returning '1' from on_headers_complete will tell the parser that it
|
||||
* should not expect a body. This is used when receiving a response to a
|
||||
* HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
|
||||
* chunked' headers that indicate the presence of a body.
|
||||
*
|
||||
* http_data_cb does not return data chunks. It will be call arbitrarally
|
||||
* many times for each string. E.G. you might get 10 callbacks for "on_url"
|
||||
* each providing just a few characters more data.
|
||||
*/
|
||||
typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
|
||||
typedef int (*http_cb) (http_parser*);
|
||||
|
||||
|
||||
/* Request Methods */
|
||||
#define HTTP_METHOD_MAP(XX) \
|
||||
XX(0, DELETE, DELETE) \
|
||||
XX(1, GET, GET) \
|
||||
XX(2, HEAD, HEAD) \
|
||||
XX(3, POST, POST) \
|
||||
XX(4, PUT, PUT) \
|
||||
/* pathological */ \
|
||||
XX(5, CONNECT, CONNECT) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(7, TRACE, TRACE) \
|
||||
/* webdav */ \
|
||||
XX(8, COPY, COPY) \
|
||||
XX(9, LOCK, LOCK) \
|
||||
XX(10, MKCOL, MKCOL) \
|
||||
XX(11, MOVE, MOVE) \
|
||||
XX(12, PROPFIND, PROPFIND) \
|
||||
XX(13, PROPPATCH, PROPPATCH) \
|
||||
XX(14, SEARCH, SEARCH) \
|
||||
XX(15, UNLOCK, UNLOCK) \
|
||||
/* subversion */ \
|
||||
XX(16, REPORT, REPORT) \
|
||||
XX(17, MKACTIVITY, MKACTIVITY) \
|
||||
XX(18, CHECKOUT, CHECKOUT) \
|
||||
XX(19, MERGE, MERGE) \
|
||||
/* upnp */ \
|
||||
XX(20, MSEARCH, M-SEARCH) \
|
||||
XX(21, NOTIFY, NOTIFY) \
|
||||
XX(22, SUBSCRIBE, SUBSCRIBE) \
|
||||
XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||
/* RFC-5789 */ \
|
||||
XX(24, PATCH, PATCH) \
|
||||
XX(25, PURGE, PURGE) \
|
||||
|
||||
enum http_method
|
||||
{
|
||||
#define XX(num, name, string) HTTP_##name = num,
|
||||
HTTP_METHOD_MAP(XX)
|
||||
#undef XX
|
||||
};
|
||||
|
||||
|
||||
enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
|
||||
|
||||
|
||||
/* Flag values for http_parser.flags field */
|
||||
enum flags
|
||||
{ F_CHUNKED = 1 << 0
|
||||
, F_CONNECTION_KEEP_ALIVE = 1 << 1
|
||||
, F_CONNECTION_CLOSE = 1 << 2
|
||||
, F_TRAILING = 1 << 3
|
||||
, F_UPGRADE = 1 << 4
|
||||
, F_SKIPBODY = 1 << 5
|
||||
};
|
||||
|
||||
|
||||
/* Map for errno-related constants
|
||||
*
|
||||
* The provided argument should be a macro that takes 2 arguments.
|
||||
*/
|
||||
#define HTTP_ERRNO_MAP(XX) \
|
||||
/* No error */ \
|
||||
XX(OK, "success") \
|
||||
\
|
||||
/* Callback-related errors */ \
|
||||
XX(CB_message_begin, "the on_message_begin callback failed") \
|
||||
XX(CB_status_complete, "the on_status_complete callback failed") \
|
||||
XX(CB_url, "the on_url callback failed") \
|
||||
XX(CB_header_field, "the on_header_field callback failed") \
|
||||
XX(CB_header_value, "the on_header_value callback failed") \
|
||||
XX(CB_headers_complete, "the on_headers_complete callback failed") \
|
||||
XX(CB_body, "the on_body callback failed") \
|
||||
XX(CB_message_complete, "the on_message_complete callback failed") \
|
||||
\
|
||||
/* Parsing-related errors */ \
|
||||
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
|
||||
XX(HEADER_OVERFLOW, \
|
||||
"too many header bytes seen; overflow detected") \
|
||||
XX(CLOSED_CONNECTION, \
|
||||
"data received after completed connection: close message") \
|
||||
XX(INVALID_VERSION, "invalid HTTP version") \
|
||||
XX(INVALID_STATUS, "invalid HTTP status code") \
|
||||
XX(INVALID_METHOD, "invalid HTTP method") \
|
||||
XX(INVALID_URL, "invalid URL") \
|
||||
XX(INVALID_HOST, "invalid host") \
|
||||
XX(INVALID_PORT, "invalid port") \
|
||||
XX(INVALID_PATH, "invalid path") \
|
||||
XX(INVALID_QUERY_STRING, "invalid query string") \
|
||||
XX(INVALID_FRAGMENT, "invalid fragment") \
|
||||
XX(LF_EXPECTED, "LF character expected") \
|
||||
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
|
||||
XX(INVALID_CONTENT_LENGTH, \
|
||||
"invalid character in content-length header") \
|
||||
XX(INVALID_CHUNK_SIZE, \
|
||||
"invalid character in chunk size header") \
|
||||
XX(INVALID_CONSTANT, "invalid constant string") \
|
||||
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
|
||||
XX(STRICT, "strict mode assertion failed") \
|
||||
XX(PAUSED, "parser is paused") \
|
||||
XX(UNKNOWN, "an unknown error occurred")
|
||||
|
||||
|
||||
/* Define HPE_* values for each errno value above */
|
||||
#define HTTP_ERRNO_GEN(n, s) HPE_##n,
|
||||
enum http_errno {
|
||||
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
|
||||
};
|
||||
#undef HTTP_ERRNO_GEN
|
||||
|
||||
|
||||
/* Get an http_errno value from an http_parser */
|
||||
#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
|
||||
|
||||
|
||||
struct http_parser {
|
||||
/** PRIVATE **/
|
||||
unsigned char type : 2; /* enum http_parser_type */
|
||||
unsigned char flags : 6; /* F_* values from 'flags' enum; semi-public */
|
||||
unsigned char state; /* enum state from http_parser.c */
|
||||
unsigned char header_state; /* enum header_state from http_parser.c */
|
||||
unsigned char index; /* index into current matcher */
|
||||
|
||||
uint32_t nread; /* # bytes read in various scenarios */
|
||||
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
|
||||
|
||||
/** READ-ONLY **/
|
||||
unsigned short http_major;
|
||||
unsigned short http_minor;
|
||||
unsigned short status_code; /* responses only */
|
||||
unsigned char method; /* requests only */
|
||||
unsigned char http_errno : 7;
|
||||
|
||||
/* 1 = Upgrade header was present and the parser has exited because of that.
|
||||
* 0 = No upgrade header present.
|
||||
* Should be checked when http_parser_execute() returns in addition to
|
||||
* error checking.
|
||||
*/
|
||||
unsigned char upgrade : 1;
|
||||
|
||||
/** PUBLIC **/
|
||||
void *data; /* A pointer to get hook to the "connection" or "socket" object */
|
||||
};
|
||||
|
||||
|
||||
struct http_parser_settings {
|
||||
http_cb on_message_begin;
|
||||
http_data_cb on_url;
|
||||
http_cb on_status_complete;
|
||||
http_data_cb on_header_field;
|
||||
http_data_cb on_header_value;
|
||||
http_cb on_headers_complete;
|
||||
http_data_cb on_body;
|
||||
http_cb on_message_complete;
|
||||
};
|
||||
|
||||
|
||||
enum http_parser_url_fields
|
||||
{ UF_SCHEMA = 0
|
||||
, UF_HOST = 1
|
||||
, UF_PORT = 2
|
||||
, UF_PATH = 3
|
||||
, UF_QUERY = 4
|
||||
, UF_FRAGMENT = 5
|
||||
, UF_USERINFO = 6
|
||||
, UF_MAX = 7
|
||||
};
|
||||
|
||||
|
||||
/* Result structure for http_parser_parse_url().
|
||||
*
|
||||
* Callers should index into field_data[] with UF_* values iff field_set
|
||||
* has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
|
||||
* because we probably have padding left over), we convert any port to
|
||||
* a uint16_t.
|
||||
*/
|
||||
struct http_parser_url {
|
||||
uint16_t field_set; /* Bitmask of (1 << UF_*) values */
|
||||
uint16_t port; /* Converted UF_PORT string */
|
||||
|
||||
struct {
|
||||
uint16_t off; /* Offset into buffer in which field starts */
|
||||
uint16_t len; /* Length of run in buffer */
|
||||
} field_data[UF_MAX];
|
||||
};
|
||||
|
||||
|
||||
void http_parser_init(http_parser *parser, enum http_parser_type type);
|
||||
|
||||
|
||||
size_t http_parser_execute(http_parser *parser,
|
||||
const http_parser_settings *settings,
|
||||
const char *data,
|
||||
size_t len);
|
||||
|
||||
|
||||
/* If http_should_keep_alive() in the on_headers_complete or
|
||||
* on_message_complete callback returns 0, then this should be
|
||||
* the last message on the connection.
|
||||
* If you are the server, respond with the "Connection: close" header.
|
||||
* If you are the client, close the connection.
|
||||
*/
|
||||
int http_should_keep_alive(const http_parser *parser);
|
||||
|
||||
/* Returns a string version of the HTTP method. */
|
||||
const char *http_method_str(enum http_method m);
|
||||
|
||||
/* Return a string name of the given error */
|
||||
const char *http_errno_name(enum http_errno err);
|
||||
|
||||
/* Return a string description of the given error */
|
||||
const char *http_errno_description(enum http_errno err);
|
||||
|
||||
/* Parse a URL; return nonzero on failure */
|
||||
int http_parser_parse_url(const char *buf, size_t buflen,
|
||||
int is_connect,
|
||||
struct http_parser_url *u);
|
||||
|
||||
/* Pause or un-pause the parser; a nonzero value pauses */
|
||||
void http_parser_pause(http_parser *parser, int paused);
|
||||
|
||||
/* Checks if this is the final chunk of the body. */
|
||||
int http_body_is_final(const http_parser *parser);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,252 +0,0 @@
|
||||
/*
|
||||
* Huffandpuff minimal Huffman coder
|
||||
*
|
||||
* (c)2013 Adam Ierymenko <adam.ierymenko@zerotier.com>
|
||||
* This code is in the public domain and is distributed with NO WARRANTY.
|
||||
*/
|
||||
|
||||
#include "huffman.h"
|
||||
|
||||
struct _huffman_node
|
||||
{
|
||||
struct _huffman_node *lr[2];
|
||||
struct _huffman_node *qprev,*qnext;
|
||||
double prob;
|
||||
unsigned long c;
|
||||
};
|
||||
|
||||
struct _huffman_encode_table
|
||||
{
|
||||
unsigned long code;
|
||||
unsigned long bits;
|
||||
};
|
||||
|
||||
static void _huffman_write_tree_and_make_encode_table(unsigned char *out,unsigned long *outbitctr,unsigned long outlen,struct _huffman_encode_table *et,unsigned long code,unsigned int bits,struct _huffman_node *t)
|
||||
{
|
||||
struct _huffman_encode_table *eti;
|
||||
unsigned int i;
|
||||
unsigned long byte_index;
|
||||
|
||||
byte_index = (*outbitctr)++ >> 3;
|
||||
byte_index *= (byte_index < outlen);
|
||||
if (t->lr[0]) {
|
||||
out[byte_index] <<= 1;
|
||||
_huffman_write_tree_and_make_encode_table(out,outbitctr,outlen,et,code,bits + 1,t->lr[0]);
|
||||
_huffman_write_tree_and_make_encode_table(out,outbitctr,outlen,et,code | (1 << bits),bits + 1,t->lr[1]);
|
||||
} else {
|
||||
out[byte_index] = (out[byte_index] << 1) | 1;
|
||||
for(i=0;i<9;++i) {
|
||||
byte_index = (*outbitctr)++ >> 3;
|
||||
if (byte_index >= outlen) return;
|
||||
out[byte_index] = (out[byte_index] << 1) | ((unsigned char)((t->c >> i) & 1));
|
||||
}
|
||||
eti = &(et[t->c]);
|
||||
eti->code = code;
|
||||
eti->bits = bits;
|
||||
}
|
||||
}
|
||||
|
||||
static struct _huffman_node *_huffman_read_tree(const unsigned char *in,unsigned long *inbitctr,unsigned long inlen,unsigned char **heapptr,unsigned char *heapend)
|
||||
{
|
||||
struct _huffman_node *n;
|
||||
unsigned int i;
|
||||
unsigned long byte_index;
|
||||
|
||||
n = (struct _huffman_node *)(*heapptr);
|
||||
*heapptr += sizeof(struct _huffman_node);
|
||||
if (*heapptr > heapend) return (struct _huffman_node *)0;
|
||||
|
||||
byte_index = *inbitctr >> 3;
|
||||
byte_index *= (byte_index < inlen);
|
||||
if (((in[byte_index] >> (~((*inbitctr)++) & 7)) & 1)) {
|
||||
n->lr[0] = (struct _huffman_node *)0;
|
||||
n->lr[1] = (struct _huffman_node *)0;
|
||||
n->c = 0;
|
||||
for(i=0;i<9;++i) {
|
||||
byte_index = *inbitctr >> 3;
|
||||
if (byte_index >= inlen) return (struct _huffman_node *)0;
|
||||
n->c |= (((unsigned int)(in[byte_index] >> (~((*inbitctr)++) & 7))) & 1) << i;
|
||||
}
|
||||
} else {
|
||||
n->lr[0] = _huffman_read_tree(in,inbitctr,inlen,heapptr,heapend);
|
||||
n->lr[1] = _huffman_read_tree(in,inbitctr,inlen,heapptr,heapend);
|
||||
if (!((n->lr[0])&&(n->lr[1])))
|
||||
return (struct _huffman_node *)0;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
unsigned long huffman_compress(const unsigned char *in,unsigned long inlen,unsigned char *out,unsigned long outlen,void *huffheap)
|
||||
{
|
||||
struct _huffman_encode_table *et,*eti;
|
||||
struct _huffman_node *t,*n;
|
||||
struct _huffman_node *pair[2];
|
||||
unsigned char *heapptr = (unsigned char *)huffheap;
|
||||
unsigned long i,code,byte_index,outbitctr;
|
||||
unsigned int bits,b;
|
||||
double *counts,lowest_prob,total_symbols;
|
||||
|
||||
counts = (double *)heapptr;
|
||||
heapptr += (sizeof(double) * 257);
|
||||
for(i=0;i<256;++i)
|
||||
counts[i] = 0.0;
|
||||
counts[256] = 1.0; /* one stop code at end */
|
||||
for(i=0;i<inlen;++i)
|
||||
counts[(unsigned long)in[i]] += 1.0;
|
||||
|
||||
t = (struct _huffman_node *)0;
|
||||
total_symbols = (double)(inlen + 1);
|
||||
for(i=0;i<=256;++i) {
|
||||
if (counts[i] > 0.0) {
|
||||
n = (struct _huffman_node *)heapptr;
|
||||
heapptr += sizeof(struct _huffman_node);
|
||||
if (t)
|
||||
t->qprev = n;
|
||||
n->qprev = (struct _huffman_node *)0;
|
||||
n->qnext = t;
|
||||
n->lr[0] = (struct _huffman_node *)0;
|
||||
n->lr[1] = (struct _huffman_node *)0;
|
||||
n->prob = counts[i] / total_symbols;
|
||||
n->c = (unsigned int)i;
|
||||
t = n;
|
||||
}
|
||||
}
|
||||
|
||||
while (t->qnext) {
|
||||
for(i=0;i<2;++i) {
|
||||
lowest_prob = 1.0;
|
||||
pair[i] = (struct _huffman_node *)0;
|
||||
n = t;
|
||||
while (n) {
|
||||
if (n->prob <= lowest_prob) {
|
||||
lowest_prob = n->prob;
|
||||
pair[i] = n;
|
||||
}
|
||||
n = n->qnext;
|
||||
}
|
||||
if (pair[i]->qprev)
|
||||
pair[i]->qprev->qnext = pair[i]->qnext;
|
||||
else t = pair[i]->qnext;
|
||||
if (pair[i]->qnext)
|
||||
pair[i]->qnext->qprev = pair[i]->qprev;
|
||||
}
|
||||
n = (struct _huffman_node *)heapptr;
|
||||
heapptr += sizeof(struct _huffman_node);
|
||||
n->lr[0] = pair[0];
|
||||
n->lr[1] = pair[1];
|
||||
n->prob = pair[0]->prob + pair[1]->prob;
|
||||
if (t)
|
||||
t->qprev = n;
|
||||
n->qprev = (struct _huffman_node *)0;
|
||||
n->qnext = t;
|
||||
t = n;
|
||||
}
|
||||
|
||||
et = (struct _huffman_encode_table *)heapptr;
|
||||
heapptr += (sizeof(struct _huffman_encode_table) * 257);
|
||||
outbitctr = 0;
|
||||
_huffman_write_tree_and_make_encode_table(out,&outbitctr,outlen,et,0,0,t);
|
||||
|
||||
for(i=0;i<inlen;++i) {
|
||||
eti = &(et[(unsigned long)in[i]]);
|
||||
code = eti->code;
|
||||
bits = eti->bits;
|
||||
for(b=0;b<bits;++b) {
|
||||
byte_index = outbitctr++ >> 3;
|
||||
if (byte_index >= outlen) return 0;
|
||||
out[byte_index] = (out[byte_index] << 1) | (unsigned char)(code & 1);
|
||||
code >>= 1;
|
||||
}
|
||||
}
|
||||
code = et[256].code;
|
||||
bits = et[256].bits;
|
||||
for(b=0;b<bits;++b) {
|
||||
byte_index = outbitctr++ >> 3;
|
||||
if (byte_index >= outlen) return 0;
|
||||
out[byte_index] = (out[byte_index] << 1) | (unsigned char)(code & 1);
|
||||
code >>= 1;
|
||||
}
|
||||
|
||||
if (outbitctr > (outlen << 3))
|
||||
return 0;
|
||||
else if ((outbitctr & 7)) {
|
||||
out[i = (outbitctr >> 3)] <<= 8 - (outbitctr & 7);
|
||||
return (i + 1);
|
||||
} else return (outbitctr >> 3);
|
||||
}
|
||||
|
||||
unsigned long huffman_decompress(const unsigned char *in,unsigned long inlen,unsigned char *out,unsigned long outlen,void *huffheap)
|
||||
{
|
||||
struct _huffman_node *t,*n;
|
||||
unsigned char *heapptr = (unsigned char *)huffheap;
|
||||
unsigned long inbitctr,outptr,byte_index = 0;
|
||||
|
||||
inbitctr = 0;
|
||||
t = _huffman_read_tree(in,&inbitctr,inlen,&heapptr,heapptr + HUFFHEAP_SIZE);
|
||||
if (!t) return 0;
|
||||
outptr = 0;
|
||||
for(;;) {
|
||||
n = t;
|
||||
while (n->lr[0]) {
|
||||
byte_index = inbitctr >> 3;
|
||||
if (byte_index >= inlen) return 0;
|
||||
n = n->lr[((unsigned long)(in[byte_index] >> (~(inbitctr++) & 7))) & 1];
|
||||
}
|
||||
if (n->c == 256) return outptr;
|
||||
if (outptr == outlen) return 0;
|
||||
out[outptr++] = (unsigned char)n->c;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HUFFANDPUFF_TEST
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define HUFFANDPUFF_TEST_MAXLEN 1048576
|
||||
#define HUFFANDPUFF_TEST_ITER 1024
|
||||
|
||||
static unsigned char testin[HUFFANDPUFF_TEST_MAXLEN];
|
||||
static unsigned char testout[HUFFANDPUFF_TEST_MAXLEN * 2];
|
||||
static unsigned char testver[HUFFANDPUFF_TEST_MAXLEN];
|
||||
static unsigned char huffbuf[HUFFHEAP_SIZE];
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
unsigned long i,k,l,cl,dcl;
|
||||
int v;
|
||||
unsigned char mask;
|
||||
|
||||
srand(time(0));
|
||||
|
||||
for(k=0;k<HUFFANDPUFF_TEST_ITER;++k) {
|
||||
l = (rand() % HUFFANDPUFF_TEST_MAXLEN) + 1;
|
||||
mask = (rand() & 0xff);
|
||||
for(i=0;i<l;++i)
|
||||
testin[i] = (unsigned char)(rand() & 0xff) & mask;
|
||||
cl = huffman_compress(testin,l,testout,sizeof(testout),huffbuf);
|
||||
if (cl) {
|
||||
memset(testver,0,sizeof(testver));
|
||||
dcl = huffman_decompress(testout,cl,testver,sizeof(testver),huffbuf);
|
||||
v = ((dcl)&&(!memcmp(testver,testin,l)));
|
||||
printf("[%d] in: %d, out: %d, verified: %s\n",(int)k,(int)l,(int)cl,(v) ? "OK" : "FAIL");
|
||||
} else printf("[%d] in: %d, out: FAIL\n",(int)k,(int)l);
|
||||
}
|
||||
|
||||
printf("\nFuzzing decompress function...\n");
|
||||
for(;;) {
|
||||
l = (rand() % HUFFANDPUFF_TEST_MAXLEN) + 1;
|
||||
mask = (rand() & 0xff);
|
||||
for(i=0;i<l;++i)
|
||||
testin[i] = (unsigned char)(rand() & 0xff) & mask;
|
||||
huffman_decompress(testin,l,testver,sizeof(testver),huffbuf);
|
||||
printf("."); fflush(stdout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Huffandpuff minimal Huffman coder
|
||||
*
|
||||
* (c)2013 Adam Ierymenko <adam.ierymenko@zerotier.com>
|
||||
* This code is in the public domain and is distributed with NO WARRANTY.
|
||||
*/
|
||||
|
||||
#ifndef ____HUFFMAN_H
|
||||
#define ____HUFFMAN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Required size of huffheap parameter to compress and decompress
|
||||
*
|
||||
* Note: if you change any of the data types in the _huffman_node
|
||||
* or _huffman_encode_table structs in huffman.c, this also must be
|
||||
* changed.
|
||||
*/
|
||||
#define HUFFHEAP_SIZE ((sizeof(double) * 257) + (((sizeof(void *) * 4) + sizeof(double) + sizeof(unsigned long)) * (257 * 3)) + ((sizeof(unsigned long) + sizeof(unsigned long)) * 257))
|
||||
|
||||
/**
|
||||
* Huffman encode a block of data
|
||||
*
|
||||
* @param in Input data
|
||||
* @param inlen Input data length
|
||||
* @param out Output buffer
|
||||
* @param outlen Output buffer length
|
||||
* @param huffheap Heap memory to use for compression (must be HUFFHEAP_SIZE in size)
|
||||
* @return Size of encoded result or 0 on out buffer overrun
|
||||
*/
|
||||
extern unsigned long huffman_compress(const unsigned char *in,unsigned long inlen,unsigned char *out,unsigned long outlen,void *huffheap);
|
||||
|
||||
/**
|
||||
* Huffman decode a block of data
|
||||
*
|
||||
* @param in Input data
|
||||
* @param inlen Length of input data
|
||||
* @param out Output buffer
|
||||
* @param outlen Length of output buffer
|
||||
* @param huffheap Heap memory to use for decompression (must be HUFFHEAP_SIZE in size)
|
||||
* @return Size of decoded result or 0 on out buffer overrun or corrupt input data
|
||||
*/
|
||||
extern unsigned long huffman_decompress(const unsigned char *in,unsigned long inlen,unsigned char *out,unsigned long outlen,void *huffheap);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Loaded 20 of 100 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user