diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-12-20 00:56:45 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-12-20 00:56:45 (GMT) |
commit | 0388c7ac478187ff8d264b6e0275a4c4a43796b9 (patch) | |
tree | 7e62439ebf72b6369ee7b1daa370e6251c06b7e0 /contrib | |
parent | 22e22bfd0965e01fea041e053873d352387805f6 (diff) | |
download | uscxml-0388c7ac478187ff8d264b6e0275a4c4a43796b9.zip uscxml-0388c7ac478187ff8d264b6e0275a4c4a43796b9.tar.gz uscxml-0388c7ac478187ff8d264b6e0275a4c4a43796b9.tar.bz2 |
Performance and bugfix for WebSockets
Diffstat (limited to 'contrib')
-rwxr-xr-x | contrib/build-scripts/build-arabica-macosx.sh | 5 | ||||
-rwxr-xr-x | contrib/build-scripts/build-v8-mac.sh | 8 | ||||
-rw-r--r-- | contrib/dom/scripts/CodeGeneratorArabicaV8.pm.new | 1018 | ||||
-rwxr-xr-x | contrib/local/compress_and_upload_deps.sh | 1 | ||||
-rw-r--r-- | contrib/src/evws/evws.c | 112 |
5 files changed, 1091 insertions, 53 deletions
diff --git a/contrib/build-scripts/build-arabica-macosx.sh b/contrib/build-scripts/build-arabica-macosx.sh index 8489815..c5a4bb9 100755 --- a/contrib/build-scripts/build-arabica-macosx.sh +++ b/contrib/build-scripts/build-arabica-macosx.sh @@ -1,8 +1,9 @@ #!/bin/bash # -# build libevent for MacOSX +# build arabica for MacOSX # +# ./configure --with-boost=/opt/local/include/ --with-libxml2=`xcrun --show-sdk-path`/usr --with-parser=libxml2 # exit on error set -e @@ -12,6 +13,7 @@ DIR="$( cd "$( dirname "$0" )" && pwd )" MACOSX_VER=`/usr/bin/sw_vers -productVersion` MACOSX_COMP=(`echo $MACOSX_VER | tr '.' ' '`) DEST_DIR="${DIR}/../prebuilt/darwin-i386/${MACOSX_COMP[0]}.${MACOSX_COMP[1]}/gnu" +SYSROOT=`xcrun --show-sdk-path` if [ ! -f src/arabica.cpp ]; then echo @@ -63,6 +65,7 @@ LDFLAGS="${MACOSX_VERSION_MIN} -arch x86_64" \ --disable-dependency-tracking \ --with-pic + make cp ./src/.libs/libarabica.a ./libarabica.x86_64.a make clean diff --git a/contrib/build-scripts/build-v8-mac.sh b/contrib/build-scripts/build-v8-mac.sh index 4d5aa62..e979c4d 100755 --- a/contrib/build-scripts/build-v8-mac.sh +++ b/contrib/build-scripts/build-v8-mac.sh @@ -37,6 +37,14 @@ fi DEPOT_PATH="${PWD}/../depot_tools" export PATH="${DEPOT_PATH}:${PATH}" +if [ ${MACOSX_COMP[1]} -lt 9 ]; then + CXXFLAGS="-mmacosx-version-min=10.6 -stdlib=libstdc++" + LDFLAGS="-stdlib=libstdc++" +else + CXXFLAGS="-mmacosx-version-min=10.7 -stdlib=libc++" + LDFLAGS="-stdlib=libc++" +fi + make dependencies make ia32.release diff --git a/contrib/dom/scripts/CodeGeneratorArabicaV8.pm.new b/contrib/dom/scripts/CodeGeneratorArabicaV8.pm.new new file mode 100644 index 0000000..cbe33e8 --- /dev/null +++ b/contrib/dom/scripts/CodeGeneratorArabicaV8.pm.new @@ -0,0 +1,1018 @@ +# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> +# Copyright (C) 2006 Anders Carlsson <andersca@mac.com> +# Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> +# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> +# Copyright (C) 2006 Apple Computer, Inc. +# Copyright (C) 2007, 2008, 2009, 2012 Google Inc. +# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> +# Copyright (C) Research In Motion Limited 2010. All rights reserved. +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) +# Copyright (C) 2012 Ericsson AB. All rights reserved. +# Copyright (C) 2013 Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +package CodeGeneratorArabicaV8; + +use strict; +use Data::Dumper; +use Carp qw/longmess cluck confess/; + +use constant FileNamePrefix => "V8"; + +my $codeGenerator; + + +my @headerContent = (); +my @implContentHeader = (); +my @implContent = (); +my @implContentDecls = (); +my %implIncludes = (); +my %headerIncludes = (); + +# Default .h template +my $headerTemplate = << 'EOF'; +/** + * @file + * @author This file has been generated by generate-bindings.pl. DO NOT MODIFY! + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * 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. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +EOF + +# Default constructor +sub new +{ + my $object = shift; + my $reference = { }; + + $codeGenerator = shift; + + bless($reference, $object); + return $reference; +} + +sub GenerateInterface +{ + my $object = shift; + my $interface = shift; + +# print Dumper($interface); + + # Start actual generation + if ($interface->extendedAttributes->{"Callback"}) { + die(); + $object->GenerateCallbackHeader($interface); + $object->GenerateCallbackImplementation($interface); + } else { + $object->GenerateHeader($interface); + $object->GenerateImplementation($interface); + } +} + +sub AddToImplIncludes +{ + my $header = shift; + my $conditional = shift; + + if ($header eq "V8bool.h") { + confess(); + } + + if (not $conditional) { + $implIncludes{$header} = 1; + } elsif (not exists($implIncludes{$header})) { + $implIncludes{$header} = $conditional; + } else { + my $oldValue = $implIncludes{$header}; + if ($oldValue ne 1) { + my %newValue = (); + $newValue{$conditional} = 1; + foreach my $condition (split(/\|/, $oldValue)) { + $newValue{$condition} = 1; + } + $implIncludes{$header} = join("|", sort keys %newValue); + } + } +} + +sub GenerateHeader +{ + my $object = shift; + my $interface = shift; + my $interfaceName = $interface->name; + my $extensions = $interface->extendedAttributes; +# print Dumper($extensions); + + # Copy contents of parent interfaces except the first parent. + my @parents; + $codeGenerator->AddMethodsConstantsAndAttributesFromParentInterfaces($interface, \@parents, 1); + $codeGenerator->LinkOverloadedFunctions($interface); + + # - Add default header template + push(@headerContent, GenerateHeaderContentHeader($interface)); + + $headerIncludes{"string"} = 1; + $headerIncludes{"uscxml/plugins/datamodel/ecmascript/v8/V8DOM.h"} = 1; + $headerIncludes{"DOM/Node.hpp"} = 1; + $headerIncludes{"v8.h"} = 1; + + if ($interfaceName =~ /.*Array$/ or $interfaceName =~ /^ArrayBuffer.*/) { + $headerIncludes{"../../TypedArray.h"} = 1; + } + + foreach (@{$interface->parents}) { + my $parent = $_; + $headerIncludes{"V8${parent}.h"} = 1; + } + + push(@headerContent, "#include \<string\>\n"); + foreach my $headerInclude (sort keys(%headerIncludes)) { + if ($headerInclude =~ /wtf|v8\.h/) { + push(@headerContent, "#include \<${headerInclude}\>\n"); + } else { + push(@headerContent, "#include \"${headerInclude}\"\n"); + } + } + + push(@headerContent, ""); + push(@headerContent, "\nnamespace Arabica {"); + push(@headerContent, "\nnamespace DOM {\n"); + + push(@headerContent, "\nclass V8${interfaceName} {"); + push(@headerContent, "\npublic:"); + + my $wrapperType = IdlToWrapperType($interfaceName); + push(@headerContent, <<END); + + struct V8${interfaceName}Private { + V8DOM* dom; + ${wrapperType}* nativeObj; + }; +END + + if ($extensions->{'DontDestroyWrapped'}) { + push(@headerContent, "\n V8_DESTRUCTOR_KEEP_WRAPPED(V8${interfaceName}Private);"); + } else { + push(@headerContent, "\n V8_DESTRUCTOR(V8${interfaceName}Private);"); + } + push(@headerContent, "\n static bool hasInstance(v8::Handle<v8::Value>);"); + push(@headerContent, "\n"); + + # callbacks for actual functions + my %generated; + foreach my $function (@{$interface->functions}) { + my $name = $function->signature->name; + my $attrExt = $function->signature->extendedAttributes; + my $custom = ($attrExt->{'Custom'} ? "Custom" : ""); + next if (exists $generated{"${name}${custom}Callback"}); + push(@headerContent, "\n static void ${name}${custom}Callback(const v8::FunctionCallbackInfo<v8::Value>&);"); + $generated{"${name}${custom}Callback"} = 1; + } + push(@headerContent, "\n"); + + # attribute getter and setters + foreach my $attribute (@{$interface->attributes}) { + my $name = $attribute->signature->name; + my $attrExt = $attribute->signature->extendedAttributes; + my $customGetter = ($attrExt->{'CustomGetter'} ? "Custom" : ""); + my $customSetter = ($attrExt->{'CustomSetter'} ? "Custom" : ""); + push(@headerContent, "\n static void ${name}${customGetter}AttrGetter(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info);"); + if (!IsReadonly($attribute)) { + push(@headerContent, "\n static void ${name}${customSetter}AttrSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info);"); + } + } + + if ($extensions->{'CustomIndexedGetter'}) { + push(@headerContent, "\n static void indexedPropertyCustomGetter(uint32_t, const v8::AccessorInfo&);"); + } + if ($extensions->{'CustomIndexedSetter'}) { + push(@headerContent, "\n static void indexedPropertyCustomSetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);"); + } + push(@headerContent, "\n"); + + GenerateClassPrototypeHeader($interface); + + push(@headerContent, "\n};\n\n}\n}\n\n"); + push(@headerContent, "#endif // V8${interfaceName}" . "_h\n"); + +} + +# +# Write class template prototype constructor +# +sub GenerateClassPrototypeHeader +{ + my $interface = shift; + my $interfaceName = $interface->name; + my $extensions = $interface->extendedAttributes; + + if ($extensions->{'Constructors'}) { + + push(@headerContent, "\n"); + push(@headerContent, " static void constructor(const v8::FunctionCallbackInfo<v8::Value>&);\n"); + push(@headerContent, <<END); + static v8::Handle<v8::FunctionTemplate> getConstructor(v8::Isolate* isolate) { + return v8::FunctionTemplate::New(isolate, constructor); + } +END + } + + push(@headerContent, <<END); + static v8::Handle<v8::FunctionTemplate> getTmpl(v8::Isolate* isolate) { + v8::Handle<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(); + tmpl->SetClassName(v8::String::NewFromUtf8(isolate, "${interfaceName}")); + tmpl->ReadOnlyPrototype(); + + v8::Local<v8::ObjectTemplate> instance = tmpl->InstanceTemplate(); + v8::Local<v8::ObjectTemplate> prototype = tmpl->PrototypeTemplate(); + (void)prototype; // surpress unused warnings + + instance->SetInternalFieldCount(1); +END + + push(@headerContent, "\n"); + foreach my $attribute (@{$interface->attributes}) { + my $name = $attribute->signature->name; + my $attrExt = $attribute->signature->extendedAttributes; + my $customGetter = ($attrExt->{'CustomGetter'} ? "Custom" : ""); + my $customSetter = ($attrExt->{'CustomSetter'} ? "Custom" : ""); + my $getter = "V8${interfaceName}::${name}${customGetter}AttrGetter"; + my $setter = (IsReadonly($attribute) ? "0" : "V8${interfaceName}::${name}${customSetter}AttrSetter"); + push(@headerContent, <<END); + instance->SetAccessor(v8::String::NewFromUtf8(isolate, "${name}"), ${getter}, ${setter}, + v8::External::New(isolate, 0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None)); +END + } + + if ($extensions->{'CustomIndexedGetter'} || $extensions->{'CustomIndexedSetter'}) { + my $indexedGetter = ($extensions->{'CustomIndexedGetter'} ? "V8${interfaceName}::indexedPropertyCustomGetter" : 0); + my $indexedSetter = ($extensions->{'CustomIndexedSetter'} ? "V8${interfaceName}::indexedPropertyCustomSetter" : 0); + push(@headerContent, "\n instance->SetIndexedPropertyHandler(${indexedGetter}, ${indexedSetter});"); + } + + push(@headerContent, "\n"); + my %generated; + foreach my $function (@{$interface->functions}) { + my $name = $function->signature->name; + my $attrExt = $function->signature->extendedAttributes; + my $custom = ($attrExt->{'Custom'} ? "Custom" : ""); + next if (exists $generated{"${name}"}); + $generated{"${name}"} = 1; + push(@headerContent, <<END); + prototype->Set(v8::String::NewFromUtf8(isolate, "${name}"), + v8::FunctionTemplate::New(isolate, V8${interfaceName}::${name}${custom}Callback, v8::Undefined(isolate)), static_cast<v8::PropertyAttribute>(v8::DontDelete)); +END + } + + push(@headerContent, "\n"); + foreach my $constant (@{$interface->constants}) { + my $name = $constant->name; + my $value = $constant->value; + my $type = IdlToV8Type($constant->type); + push(@headerContent, <<END); + tmpl->Set(v8::String::NewFromUtf8(isolate, "${name}"), ${type}::New(${value}), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum)); + prototype->Set(v8::String::NewFromUtf8(isolate, "${name}"), ${type}::New(${value}), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum)); +END + } + + push(@headerContent, "\n"); + if (@{$interface->parents}) { + my $parent = @{$interface->parents}[0]; + push(@headerContent, " tmpl->Inherit(V8${parent}::getTmpl());\n"); + } + push(@headerContent, <<END); + return tmpl; + } + +END + +} + +sub GenerateImplementationAttributes +{ + my $interface = shift; + my $interfaceName = $interface->name; + my $extensions = $interface->extendedAttributes; + + # Generate property accessors for attributes. + for (my $index = 0; $index < @{$interface->attributes}; $index++) { + my $attribute = @{$interface->attributes}[$index]; + my $attrType = $attribute->signature->type; + my $attrName = $attribute->signature->name; + my $attrExt = $attribute->signature->extendedAttributes; + + my $wrapperRetType = IdlToWrapperType($attrType); + my $wrapperType = IdlToWrapperType($interfaceName); + my $wrapperGetter; + + if ($attrExt->{'AttributeIsPublic'} || $extensions->{'AttributesArePublic'}) { + $wrapperGetter = $attrName; + } else { + $wrapperGetter = IdlToWrapperAttrGetter($interface, $attribute)."()"; + + } + + # getter + if (!$attrExt->{'CustomGetter'}) { + push(@implContent, <<END); + + void V8${interfaceName}::${attrName}AttrGetter(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) { + v8::Isolate* isolate = args.GetIsolate(); + v8::Local<v8::Object> self = info.Holder(); + struct V8${interfaceName}Private* privData = V8DOM::toClassPtr<V8${interfaceName}Private >(self->GetInternalField(0)); +END + if (IsWrapperType($attrType)) { + AddToImplIncludes("V8".$attrType.".h"); + push(@implContent, "\n ".GenerateConditionalUndefReturn($interface, $attribute, "privData->nativeObj->${wrapperGetter}")); + + push(@implContent, <<END); + + ${wrapperRetType}* arbaicaRet = new ${wrapperRetType}(privData->nativeObj->${wrapperGetter}); + + v8::Handle<v8::Function> arbaicaRetCtor = V8${attrType}::getTmpl(isolate)->GetFunction(); + v8::Persistent<v8::Object> arbaicaRetObj = v8::Persistent<v8::Object>::New(arbaicaRetCtor->NewInstance()); + + struct V8${attrType}::V8${attrType}Private* retPrivData = new V8${attrType}::V8${attrType}Private(); + retPrivData->dom = privData->dom; + retPrivData->nativeObj = arbaicaRet; + + arbaicaRetObj->SetInternalField(0, V8DOM::toExternal(retPrivData)); + arbaicaRetObj.MakeWeak(0, V8${attrType}::jsDestructor); + return arbaicaRetObj; +END + } else { + my $v8Type = IdlToV8Type($attrType); + if ($attrType eq "DOMString") { + if ($attrExt->{'EmptyAsNull'}) { + push(@implContent, "\n if (privData->nativeObj->${wrapperGetter}.length() == 0)"); + push(@implContent, "\n return v8::Undefined(isolate);"); + } + push(@implContent, "\n return ${v8Type}::New(privData->nativeObj->${wrapperGetter}.c_str());"); + } else { + push(@implContent, "\n return ${v8Type}::New(privData->nativeObj->${wrapperGetter});"); + } + } + push(@implContent, "\n }\n"); + } + + if (!$attrExt->{'CustomSetter'}) { + # setter + if (!IsReadonly($attribute)) { + my $wrapperSetter = IdlToWrapperAttrSetter($attrName); + push(@implContent, "\n void V8${interfaceName}::${attrName}AttrSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {"); + push(@implContent, "\n v8::Isolate* isolate = args.GetIsolate();"); + push(@implContent, "\n v8::Local<v8::Object> self = info.Holder();"); + push(@implContent, "\n struct V8${interfaceName}Private* privData = V8DOM::toClassPtr<V8${interfaceName}Private >(self->GetInternalField(0));"); + + my ($handle, $deref) = IdlToArgHandle($attribute->signature->type, "local".ucfirst($attribute->signature->name), "value", $interfaceName); + + push(@implContent, "\n $handle"); + push(@implContent, "\n privData->nativeObj->${wrapperSetter}(${deref});"); + push(@implContent, "\n }\n"); + + } + } + } +} + +sub GenerateConditionalUndefReturn +{ + my $interface = shift; + my $attribute = shift; + my $getterExpression = shift; + + return "" if ($attribute->signature->type eq "NamedNodeMap"); + return "" if ($attribute->signature->type eq "NodeList"); + return "if (!$getterExpression) return v8::Undefined(isolate);"; +} + +sub GenerateConstructor +{ + my $interface = shift; + my $interfaceName = $interface->name; + my $wrapperType = IdlToWrapperType($interfaceName); + my $extensions = $interface->extendedAttributes; + + if ($extensions->{'Constructors'}) { + + push(@implContent, "\n void V8${interfaceName}::constructor(const v8::FunctionCallbackInfo<v8::Value>& args) {"); + push(@implContent, <<END); + + v8::Isolate* isolate = args.GetIsolate(); + if (!args.IsConstructCall()) { + isolate->ThrowException(v8::String::NewFromUtf8(isolate, "Cannot call constructor as function")); + return; + } +END + + push(@implContent, "\n ".IdlToWrapperType($interfaceName)."* localInstance = NULL;"); + # dispatch the actual constructor + push(@implContent, "\n if (false) {\n}"); + my @variants; + foreach my $fullCons (@{$extensions->{'Constructors'}}) { + push (@variants, $fullCons); + + for (my $i = @{$fullCons}; $i > 0; $i--) { + my $variant = @{$fullCons}[$i]; + if ($variant->{'domSignature::isOptional'}) { + my $slice; + for (my $j = 0; $j < $i; $j++) { + push(@{$slice}, @{$fullCons}[$j]); + } + push (@variants, $slice); + } + } + + # sort to put most determinate signatures first + @variants = sort { + if (@{$b} != @{$a}) { + # more arguments are more determinant + @{$b} <=> @{$a}; + } else { + my @aWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$a}); + my @bWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$b}); + @bWrap <=> @aWrap; + } + } @variants; + } + foreach my $constructor (@variants) { + push(@implContent, " else if (args.Length() == " . @{$constructor}); + + for (my $i = 0; $i < @{$constructor}; $i++) { + my $type = $constructor->[$i]->{'domSignature::type'}; + AddToImplIncludes("V8".$type.".h") if (IsWrapperType($type)); + push(@implContent, " &&\n " . IdlToTypeChecker($type, "args[$i]")); + + } + push(@implContent, ") {\n"); + my $constructorArgs; + my $constructorSep = ""; + for (my $i = 0; $i < @{$constructor}; $i++) { + my $type = $constructor->[$i]->{'domSignature::type'}; + my $name = $constructor->[$i]->{'domSignature::name'}; + my ($handle, $deref) = IdlToArgHandle($type, "local".ucfirst($name), "args[$i]", $interfaceName); + $constructorArgs .= ${constructorSep}.${deref}; + $constructorSep = ", "; + push(@implContent, "\n $handle"); + + } + push(@implContent, "\n localInstance = new ".IdlToWrapperType($interfaceName)."(${constructorArgs});"); + push(@implContent, "\n\n }"); + } + push(@implContent, "\n"); + + push(@implContent, <<END); + if (!localInstance) { + throw V8Exception("Parameter mismatch while calling constructor for ${interfaceName}"); + } + + v8::Handle<v8::Function> retCtor = V8${interfaceName}::getTmpl(isolate)->GetFunction(); + v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance()); + + struct V8${interfaceName}::V8${interfaceName}Private* retPrivData = new V8${interfaceName}::V8${interfaceName}Private(); + retPrivData->nativeObj = localInstance; + + retObj->SetInternalField(0, V8DOM::toExternal(retPrivData)); + retObj.MakeWeak(0, V8${interfaceName}::jsDestructor); + + args.GetReturnValue().Set(retObj); + return; + } +END + } + +} + +sub GenerateImplementationFunctionCallbacks +{ + my $interface = shift; + my $interfaceName = $interface->name; + my $wrapperType = IdlToWrapperType($interfaceName); + my $extensions = $interface->extendedAttributes; + + + # Generate methods for functions. + my %generated; + foreach my $function (@{$interface->functions}) { + my $name = $function->signature->name; + my $attrExt = $function->signature->extendedAttributes; + my $retType = $function->signature->type; + my $wrapperRetType = IdlToWrapperType($retType); + + next if ($attrExt->{'Custom'}); + next if (exists $generated{"${name}Callback"}); + $generated{"${name}Callback"} = 1; + + # get all functions with this name + my @sameFunctions = grep($_->signature->name eq $name, @{$interface->functions}); + + # signature + push(@implContent, <<END); + + void V8${interfaceName}::${name}Callback(const v8::FunctionCallbackInfo<v8::Value>& args) { + v8::Isolate* isolate = args.GetIsolate(); +END + + # get this + push(@implContent, "\n v8::Local<v8::Object> self = args.Holder();"); + push(@implContent, "\n struct V8${interfaceName}Private* privData = V8DOM::toClassPtr<V8${interfaceName}Private >(self->GetInternalField(0));"); + + # establish all variants + my @variants; + foreach my $functionVar (@sameFunctions) { + push (@variants, $functionVar->parameters); + + for (my $i = @{$functionVar->parameters}; $i > 0; $i--) { + my $variant = @{$functionVar->parameters}[$i]; + if ($variant->{'domSignature::isOptional'}) { + my $slice; + for (my $j = 0; $j < $i; $j++) { + push(@{$slice}, @{$functionVar->parameters}[$j]); + } + push (@variants, $slice); + } + } + } + + # arguments to local handles + push(@implContent, "\n if (false) {"); + + # sort to put most determinate signatures first + @variants = sort { + if (@{$b} != @{$a}) { + # more arguments are more determinant + @{$b} <=> @{$a}; + } else { + my @aWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$a}); + my @bWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$b}); + @bWrap <=> @aWrap; + } + } @variants; + + foreach my $variant (@variants) { + my $parameterIndex = 0; + my @argList; + + push(@implContent, "\n } else if (args.Length() == " . @{$variant}); + for (my $i = 0; $i < @{$variant}; $i++) { + my $type = $variant->[$i]->{'domSignature::type'}; + push(@implContent, " &&\n " . IdlToTypeChecker($type, "args[$i]")); + } + push(@implContent, ")\n {"); + foreach my $parameter (@{$variant}) { + my $value = "args[$parameterIndex]"; + my $type = $parameter->type; + AddToImplIncludes("V8".$type.".h") if (IsWrapperType($type)); + + my ($handle, $deref) = IdlToArgHandle($parameter->type, "local".ucfirst($parameter->name), "args[${parameterIndex}]", $interfaceName); + push(@implContent, "\n ${handle}"); + push(@argList, $deref); + $parameterIndex++; + } + + # invoke native function with argument handles + my $retNativeType = IdlToNativeType($retType); + my $wrapperFunctionName = IdlToWrapperFunction($interface, $function); + if (IsWrapperType($retType)) { + push(@implContent, "\n\n ${retNativeType}* retVal = new $wrapperRetType(privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . "));\n"); + } elsif ($retNativeType eq "void") { + push(@implContent, "\n\n privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); + } else { + push(@implContent, "\n\n ${retNativeType} retVal = privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); + } + + # wrap return type if needed + if (IsWrapperType($retType)) { + AddToImplIncludes("V8".$retType.".h"); + + push(@implContent, <<END); + v8::Handle<v8::Function> retCtor = V8${retType}::getTmpl(isolate)->GetFunction(); + v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance()); + + struct V8${retType}::V8${retType}Private* retPrivData = new V8${retType}::V8${retType}Private(); + retPrivData->dom = privData->dom; + retPrivData->nativeObj = retVal; + + retObj->SetInternalField(0, V8DOM::toExternal(retPrivData)); + + retObj.MakeWeak(0, V8${retType}::jsDestructor); + return retObj; +END + } else { + my $toHandleString = NativeToHandle($retNativeType, "retVal"); + push(@implContent, "\n return ${toHandleString};"); + } + } + push(@implContent, <<END); + + } + throw V8Exception("Parameter mismatch while calling ${name}"); + return v8::Undefined(isolate); + } +END + } + +} + +sub GenerateImplementation +{ + my $object = shift; + my $interface = shift; + my $interfaceName = $interface->name; + my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface); + my $v8InterfaceName = "V8$interfaceName"; + my $wrapperType = IdlToWrapperType($interfaceName); + my $extensions = $interface->extendedAttributes; + + AddToImplIncludes("V8${interfaceName}.h"); + + # Find the super descriptor. + my $parentClass = ""; + my $parentClassTemplate = ""; + foreach (@{$interface->parents}) { + my $parent = $_; + AddToImplIncludes("V8${parent}.h"); + $parentClass = "V8" . $parent; + last; + } + + push(@implContent, "namespace Arabica {\n"); + push(@implContent, "namespace DOM {\n\n"); + + if ($extensions->{'Constructors'}) { + GenerateConstructor($interface); + } + + GenerateImplementationAttributes($interface); + GenerateImplementationFunctionCallbacks($interface); + + + push(@implContent, <<END); + bool V8${interfaceName}::hasInstance(v8::Handle<v8::Value> value) { + return getTmpl()->HasInstance(value); + } + +} +} +END + + # We've already added the header for this file in implContentHeader, so remove + # it from implIncludes to ensure we don't #include it twice. +# delete $implIncludes{"${v8InterfaceName}.h"}; +} + +sub WriteData +{ + my $object = shift; + my $interface = shift; + my $outputDir = shift; + my $outputHeadersDir = shift; + + my $name = $interface->name; + my $prefix = FileNamePrefix; + my $headerFileName = "$outputHeadersDir/$prefix$name.h"; + my $implFileName = "$outputDir/$prefix$name.cpp"; + + # print "WriteData\n"; + # print Dumper($interface); + # exit(); + + # Update a .cpp file if the contents are changed. + my $contents = $headerTemplate; + $contents .= join "", @implContentHeader; + + my @includes = (); + my %implIncludeConditions = (); + foreach my $include (keys %implIncludes) { + my $condition = $implIncludes{$include}; + my $checkType = $include; + $checkType =~ s/\.h//; + next if $codeGenerator->IsSVGAnimatedType($checkType); + + if ($include =~ /wtf/) { + $include = "\<$include\>"; + } else { + $include = "\"$include\""; + } + + if ($condition eq 1) { + push @includes, $include; + } else { + push @{$implIncludeConditions{$condition}}, $include; + } + } + foreach my $include (sort @includes) { + $contents .= "#include $include\n"; + } + foreach my $condition (sort keys %implIncludeConditions) { + $contents .= "\n#if " . $codeGenerator->GenerateConditionalStringFromAttributeValue($condition) . "\n"; + foreach my $include (sort @{$implIncludeConditions{$condition}}) { + $contents .= "#include $include\n"; + } + $contents .= "#endif\n"; + } + + $contents .= "\n"; + $contents .= join "", @implContentDecls, @implContent; + $codeGenerator->UpdateFile($implFileName, $contents); + + %implIncludes = (); + @implContentHeader = (); + @implContentDecls = (); + @implContent = (); + + # Update a .h file if the contents are changed. + $contents = join "", @headerContent; + $codeGenerator->UpdateFile($headerFileName, $contents); + + @headerContent = (); +} + +sub IdlToV8Type +{ + my $idlType = shift; + return "v8::Integer" if ($idlType eq "unsigned short"); + return "v8::Integer" if ($idlType eq "short"); + return "v8::Integer" if ($idlType eq "unsigned long"); + return "v8::Integer" if ($idlType eq "long"); + return "v8::String" if ($idlType eq "DOMString"); + return "v8::Boolean" if ($idlType eq "boolean"); + return "v8::Number" if ($idlType eq "double"); + die($idlType); +} + +sub IdlToNativeType +{ + my $idlType = shift; + + return IdlToWrapperType($idlType) if (IsWrapperType($idlType)); + + return "std::string" if ($idlType eq "DOMString"); + return "bool" if ($idlType eq "boolean"); + return "short" if ($idlType eq "short"); + return "long" if ($idlType eq "long"); + return "unsigned short" if ($idlType eq "unsigned short"); + return "unsigned long" if ($idlType eq "unsigned long"); + return "void" if ($idlType eq "void"); + return "char" if ($idlType eq "byte"); + return "unsigned char" if ($idlType eq "octet"); + return "double" if ($idlType eq "double"); + return "float" if ($idlType eq "float"); + die(${idlType}); +} + +sub NativeToHandle +{ + my $nativeType = shift; + my $nativeName = shift; + + return ("v8::Boolean::New(${nativeName})") if ($nativeType eq "bool"); + return ("v8::Number::New(${nativeName})") if ($nativeType eq "double"); + return ("v8::Number::New(${nativeName})") if ($nativeType eq "double"); + return ("v8::Number::New(${nativeName})") if ($nativeType eq "float"); + return ("v8::Number::New(${nativeName})") if ($nativeType eq "short"); + return ("v8::Number::New(${nativeName})") if ($nativeType eq "char"); + return ("v8::Number::New(${nativeName})") if ($nativeType eq "unsigned short"); + return ("v8::Number::New(${nativeName})") if ($nativeType eq "unsigned long"); + return ("v8::Number::New(${nativeName})") if ($nativeType eq "unsigned char"); + return ("v8::Number::New(${nativeName})") if ($nativeType eq "long"); + return ("v8::String::NewFromUtf8(isolate, ${nativeName}.c_str())") if ($nativeType eq "std::string"); + return ("v8::Undefined(isolate)") if ($nativeType eq "void"); + + die($nativeType); +} + +sub IdlToWrapperType +{ + my $idlType = shift; + return "Arabica::XPath::XPathValue<std::string>" if ($idlType eq "XPathResult"); + return "Arabica::XPath::NodeSet<std::string>" if ($idlType eq "NodeSet"); + return "Arabica::DOM::Node<std::string>" if ($idlType eq "Node"); + return "Arabica::DOM::Element<std::string>" if ($idlType eq "Element"); + return "uscxml::Event" if ($idlType eq "SCXMLEvent"); + return "uscxml::Storage" if ($idlType eq "Storage"); + return "uscxml::ArrayBuffer" if ($idlType eq "ArrayBuffer"); + return "uscxml::ArrayBufferView" if ($idlType eq "ArrayBufferView"); + return "uscxml::Int8Array" if ($idlType eq "Int8Array"); + return "uscxml::Uint8Array" if ($idlType eq "Uint8Array"); + return "uscxml::Uint8ClampedArray" if ($idlType eq "Uint8ClampedArray"); + return "uscxml::Int16Array" if ($idlType eq "Int16Array"); + return "uscxml::Uint16Array" if ($idlType eq "Uint16Array"); + return "uscxml::Int32Array" if ($idlType eq "Int32Array"); + return "uscxml::Uint32Array" if ($idlType eq "Uint32Array"); + return "uscxml::Float32Array" if ($idlType eq "Float32Array"); + return "uscxml::Float64Array" if ($idlType eq "Float64Array"); + return "uscxml::DataView" if ($idlType eq "DataView"); + return "Arabica::DOM::${idlType}<std::string>"; +} + +sub IdlToArgHandle +{ + my $type = shift; + my $localName = shift; + my $paramName = shift; + my $thisType = shift; + + return ("v8::String::AsciiValue ${localName}(${paramName});", "*${localName}") if ($type eq "DOMString"); + return ("unsigned long ${localName} = ${paramName}->ToNumber()->Uint32Value();", ${localName}) if ($type eq "unsigned long"); + return ("long ${localName} = ${paramName}->ToNumber()->Int32Value();", ${localName}) if ($type eq "long"); + return ("double ${localName} = ${paramName}->ToNumber()->Value();", ${localName}) if ($type eq "double"); + return ("float ${localName} = ${paramName}->ToNumber()->Value();", ${localName}) if ($type eq "float"); + return ("unsigned short ${localName} = ${paramName}->ToNumber()->Uint32Value();", ${localName}) if ($type eq "unsigned short"); + return ("bool ${localName} = ${paramName}->ToBoolean()->BooleanValue();", ${localName}) if ($type eq "boolean"); + return ("char ${localName} = ${paramName}->ToNumber()->Int32Value();", ${localName}) if ($type eq "byte"); + return ("short ${localName} = ${paramName}->ToNumber()->Int32Value();", ${localName}) if ($type eq "short"); + return ("unsigned char ${localName} = ${paramName}->ToNumber()->Uint32Value();", ${localName}) if ($type eq "octet"); + return ("void* ${localName} = v8::External::Unwrap(${paramName}->ToObject()->GetInternalField(0));", ${localName}) if ($type eq "any"); + return ("std::vector<long> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToInteger()->Value());\n}", "${localName}") if ($type eq "long[]"); + return ("std::vector<float> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToNumber()->Value());\n}", "${localName}") if ($type eq "float[]"); + return ("std::vector<double> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToNumber()->Value());\n}", "${localName}") if ($type eq "double[]"); + return ("std::vector<char> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToInt32()->Value());\n}", "${localName}") if ($type eq "byte[]"); + return ("std::vector<short> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToInt32()->Value());\n}", "${localName}") if ($type eq "short[]"); + return ("std::vector<unsigned short> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "unsigned short[]"); + return ("std::vector<unsigned long> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "unsigned long[]"); + return ("std::vector<unsigned char> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "octet[]"); + + if (IsWrapperType($type)) { + my $wrapperType = IdlToWrapperType($type); + if ($type =~ /.*Array$/ or $type =~ /^ArrayBuffer.*/) { + return ("${wrapperType}* ${localName} = V8DOM::toClassPtr<V8${type}::V8${type}Private >(${paramName}->ToObject()->GetInternalField(0))->nativeObj;", "${localName}"); + } + + return ("${wrapperType}* ${localName} = V8DOM::toClassPtr<V8${type}::V8${type}Private >(${paramName}->ToObject()->GetInternalField(0))->nativeObj;", "*${localName}"); + } + + print $type."\n"; + die(); +} + +sub IdlToTypeChecker +{ + my $idlType = shift; + my $attr = shift; + + return $attr."->IsString()" if ($idlType eq "DOMString"); + return $attr."->IsBoolean()" if ($idlType eq "boolean"); + return $attr."->IsInt32()" if ($idlType eq "short"); + return $attr."->IsInt32()" if ($idlType eq "long"); + return $attr."->IsArray()" if ($idlType eq "long[]"); + return $attr."->IsUint32()" if ($idlType eq "unsigned short"); + return $attr."->IsUint32()" if ($idlType eq "unsigned long"); + return $attr."->IsInt32()" if ($idlType eq "byte"); + return $attr."->IsUint32()" if ($idlType eq "octet"); + return $attr."->IsNumber()" if ($idlType eq "double"); + return $attr."->IsArray()" if ($idlType eq "double[]"); + return $attr."->IsNumber()" if ($idlType eq "float"); + return $attr."->IsArray()" if ($idlType eq "float[]"); + return $attr."->IsArray()" if ($idlType eq "short[]"); + return $attr."->IsArray()" if ($idlType eq "unsigned short[]"); + return $attr."->IsArray()" if ($idlType eq "unsigned long[]"); + return $attr."->IsArray()" if ($idlType eq "byte[]"); + return $attr."->IsArray()" if ($idlType eq "octet[]"); + return "true" if ($idlType eq "any"); + + return $attr."->IsObject() && V8".$idlType."::hasInstance(".$attr.")" if (IsWrapperType($idlType)); + + print $idlType."\n"; + die(); + +} + +sub IdlToWrapperAttrGetter +{ + my $interface = shift; + my $attribute = shift; + + return $attribute->signature->name if ($interface->name eq "NodeSet" && $attribute->signature->name eq "size"); + return $attribute->signature->name if ($interface->name eq "NodeSet" && $attribute->signature->name eq "empty"); + return "asString" if ($interface->name eq "XPathResult" && $attribute->signature->name eq "stringValue"); + return "asBool" if ($interface->name eq "XPathResult" && $attribute->signature->name eq "booleanValue"); + return "asNumber" if ($interface->name eq "XPathResult" && $attribute->signature->name eq "numberValue"); + + return "get" . ucfirst($attribute->signature->name); +} + +sub IdlToWrapperFunction +{ + my $interface = shift; + my $function = shift; + + # if ($interface->name eq "NodeSet" && $function->signature->name eq "toDocumentOrder") { + # print Dumper($interface); + # print Dumper($function); + # } + + return "to_document_order" if ($interface->name eq "NodeSet" && $function->signature->name eq "toDocumentOrder"); + + return $function->signature->name; + +} + +sub IdlToWrapperAttrSetter +{ + my $idlAttr = shift; + return "set" . ucfirst($idlAttr); +} + + +sub IsReadonly +{ + my $attribute = shift; + my $attrExt = $attribute->signature->extendedAttributes; + return ($attribute->type =~ /readonly/ || $attrExt->{"V8ReadOnly"}) && !$attrExt->{"Replaceable"}; +} + + +my %non_wrapper_types = ( + 'CompareHow' => 1, + 'DOMObject' => 1, + 'DOMString' => 1, + 'DOMString[]' => 1, + 'DOMTimeStamp' => 1, + 'Date' => 1, + 'Dictionary' => 1, + 'EventListener' => 1, + # FIXME: When EventTarget is an interface and not a mixin, fix this so that + # EventTarget is treated as a wrapper type. + 'EventTarget' => 1, + 'IDBKey' => 1, + 'JSObject' => 1, + 'MediaQueryListListener' => 1, + 'NodeFilter' => 1, + 'any' => 1, + 'boolean' => 1, + 'double' => 1, + 'float' => 1, + 'int' => 1, + 'long long' => 1, + 'long' => 1, + 'long[]' => 1, + 'short' => 1, + 'short[]' => 1, + 'void' => 1, + 'byte' => 1, + 'byte[]' => 1, + 'octet' => 1, + 'char' => 1, + 'float[]' => 1, + 'float' => 1, + 'double[]' => 1, + 'octet[]' => 1, + 'double' => 1, + 'unsigned int' => 1, + 'unsigned long long' => 1, + 'unsigned long' => 1, + 'unsigned long[]' => 1, + 'unsigned short' => 1, + 'unsigned short[]' => 1 +); + +sub IsWrapperType +{ + my $type = shift; + return !($non_wrapper_types{$type}); +} + +sub GenerateHeaderContentHeader +{ + my $interface = shift; + my $v8InterfaceName = "V8" . $interface->name; + my $conditionalString = $codeGenerator->GenerateConditionalString($interface); + + my @headerContentHeader = split("\r", $headerTemplate); + + push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString; + push(@headerContentHeader, "\n#ifndef ${v8InterfaceName}" . "_h"); + push(@headerContentHeader, "\n#define ${v8InterfaceName}" . "_h\n\n"); + return @headerContentHeader; +} + +1; diff --git a/contrib/local/compress_and_upload_deps.sh b/contrib/local/compress_and_upload_deps.sh index 90a398d..6fcffde 100755 --- a/contrib/local/compress_and_upload_deps.sh +++ b/contrib/local/compress_and_upload_deps.sh @@ -32,6 +32,7 @@ ssh ${USCXML_PREBUILT_HOST} mkdir -p ${USCXML_PREBUILT_PATH}/${VERSION} PLATFORMS=`find . -maxdepth 1 -type d -regex ./[^\.].*` #PLATFORMS="linux-x86_64" +PLATFORMS="darwin-i386" for FILE in ${PLATFORMS}; do PLATFORM=`basename $FILE` echo $FILE diff --git a/contrib/src/evws/evws.c b/contrib/src/evws/evws.c index b39bc03..5dbd8e9 100644 --- a/contrib/src/evws/evws.c +++ b/contrib/src/evws/evws.c @@ -66,11 +66,11 @@ struct evws *evws_new(struct event_base *base) { ret_obj->base = base; ret_obj->listener = NULL; - ret_obj->connections.tqh_first = NULL; - ret_obj->connections.tqh_last = &(ret_obj->connections.tqh_first); - - ret_obj->callbacks.tqh_first = NULL; - ret_obj->callbacks.tqh_last = &(ret_obj->callbacks.tqh_first); + (&ret_obj->connections)->tqh_first = NULL; + (&ret_obj->connections)->tqh_last = &((&ret_obj->connections)->tqh_first); + + (&ret_obj->callbacks)->tqh_first = NULL; + (&ret_obj->callbacks)->tqh_last = &((&ret_obj->callbacks)->tqh_first); return ret_obj; } @@ -89,16 +89,22 @@ evutil_socket_t evws_bind_socket(struct evws * ws, unsigned short port) { sin.sin_addr.s_addr = htonl(0); sin.sin_port = htons(port); - if(!(ws->listener = evconnlistener_new_bind(ws->base, cb_accept, ws, LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE|LEV_OPT_THREADSAFE, -1, (struct sockaddr*)&sin, sizeof(sin)))) { + if(!(ws->listener = evconnlistener_new_bind(ws->base, + cb_accept, + ws, + LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE|LEV_OPT_THREADSAFE, + -1, + (struct sockaddr*)&sin, sizeof(sin))) + ) { return 0; } return evconnlistener_get_fd(ws->listener); } int evws_set_cb(struct evws * ws, const char * uri, cb_frame_type message_cb, cb_type connect_cb, void * arg) { - struct evws_cb *ws_cb; + struct evws_cb *ws_cb = NULL; - for (ws_cb = ws->callbacks.tqh_first; ws_cb; ws_cb = ws_cb->next.tqe_next) { + for (ws_cb = (&ws->callbacks)->tqh_first; ws_cb; ws_cb = ws_cb->next.tqe_next) { if (strcmp(ws_cb->uri, uri) == 0) return (-1); } @@ -114,9 +120,9 @@ int evws_set_cb(struct evws * ws, const char * uri, cb_frame_type message_cb, cb // TAILQ_INSERT_TAIL ws_cb->next.tqe_next = NULL; - ws_cb->next.tqe_prev = ws->callbacks.tqh_last; - ws->callbacks.tqh_last = &ws_cb; - ws->callbacks.tqh_last = &ws_cb->next.tqe_next; + ws_cb->next.tqe_prev = (&ws->callbacks)->tqh_last; + *(&ws->callbacks)->tqh_last = ws_cb; + (&ws->callbacks)->tqh_last = &(ws_cb->next.tqe_next); return (0); } @@ -131,7 +137,7 @@ cb_frame_type evws_set_gencb(struct evws *ws, cb_frame_type cb, void * arg) { // Broadcast data to all buffers associated with pattern void evws_broadcast(struct evws *ws, const char *uri, enum evws_opcode opcode, const char *data, uint64_t length) { struct evws_connection *ws_connection; - for (ws_connection = ws->connections.tqh_first; ws_connection; ws_connection = ws_connection->next.tqe_next) { + for ((ws_connection) = (&ws->connections)->tqh_first; ws_connection; ws_connection = ws_connection->next.tqe_next) { if (strcmp(ws_connection->uri, uri) == 0) evws_send_data(ws_connection, opcode, data, length); } @@ -140,15 +146,12 @@ void evws_broadcast(struct evws *ws, const char *uri, enum evws_opcode opcode, c // Error callback static void cb_error(struct bufferevent *bev, short what, void *ctx) { struct evws_connection *conn = ctx; - - //TAILQ_REMOVE - if (conn->next.tqe_next != NULL) + if (conn->next.tqe_next != NULL) { conn->next.tqe_next->next.tqe_prev = conn->next.tqe_prev; - else { - conn->ws->connections.tqh_last = conn->next.tqe_prev; + } else { + (&(conn->ws->connections))->tqh_last = conn->next.tqe_prev; } - conn->next.tqe_prev = &conn->next.tqe_next; - + *(conn)->next.tqe_prev = conn->next.tqe_next; evws_connection_free(conn); } @@ -224,11 +227,12 @@ void cb_read_handshake(struct bufferevent *bev, void *arg) { origin = strdup(svalue); } header = evws_header_new(skey, svalue); - //TAILQ_INSERT_TAIL + + // TAILQ_INSERT_TAIL header->next.tqe_next = NULL; - header->next.tqe_prev = ws_conn->headers.tqh_last; - ws_conn->headers.tqh_last = &header; - ws_conn->headers.tqh_last = &header->next.tqe_next; + header->next.tqe_prev = (&ws_conn->headers)->tqh_last; + *(&ws_conn->headers)->tqh_last = header; + (&ws_conn->headers)->tqh_last = &(header->next.tqe_next); free(line); } @@ -236,6 +240,9 @@ void cb_read_handshake(struct bufferevent *bev, void *arg) { break; }; + if (key == NULL) + return; + // -- SHA1 SHA1Reset(&sha1); @@ -280,24 +287,24 @@ void cb_read_handshake(struct bufferevent *bev, void *arg) { "\r\n", chksumBase64 ); - bufferevent_setcb(ws_conn->bufev, cb_read_frame, NULL, cb_error, ws_conn); - - //TAILQ_INSERT_TAIL(&(ws_conn->ws->connections), ws_conn, next); + bufferevent_setcb(ws_conn->bufev, cb_read_frame, ((void*)0), cb_error, ws_conn); + ws_conn->next.tqe_next = NULL; - ws_conn->next.tqe_prev = ws_conn->ws->connections.tqh_last; - ws_conn->ws->connections.tqh_last = &ws_conn; - ws_conn->ws->connections.tqh_last = &ws_conn->next.tqe_next; + ws_conn->next.tqe_prev = (&(ws_conn->ws->connections))->tqh_last; + *(&(ws_conn->ws->connections))->tqh_last = ws_conn; + (&(ws_conn->ws->connections))->tqh_last = &(ws_conn->next.tqe_next); { struct evws_cb *ws_cb; - for (ws_cb = ws_conn->ws->callbacks.tqh_first; ws_cb; ws_cb = ws_cb->next.tqe_next) { + for (ws_cb = ((&ws_conn->ws->callbacks))->tqh_first; ws_cb; ws_cb = ws_cb->next.tqe_next) { if (strcmp(ws_cb->uri, ws_conn->uri) == 0) { - if(ws_cb->conn_cb != NULL) - ws_cb->conn_cb(ws_conn, NULL, 0, ws_cb->cb_arg); + if(ws_cb->conn_cb != ((void*)0)) + ws_cb->conn_cb(ws_conn, ((void*)0), 0, ws_cb->cb_arg); return; } } } + } int evws_parse_header_line(char *line, char **skey, char **svalue) @@ -317,7 +324,7 @@ void cb_read_frame(struct bufferevent *bev, void *arg) { struct evws_connection *conn = arg; struct evws *ws = conn->ws; - char readbuf[1024]; + char readbuf[2048]; // make sure a MTU fits int size = 0; struct evbuffer *buffer = bufferevent_get_input(bev); while ((size = evbuffer_remove(buffer, readbuf, sizeof(readbuf))) > 0) { @@ -414,11 +421,12 @@ NEXT_FRAME: if (conn->frame->payload_read == conn->frame->size) { // done reading this frame - invoke callbacks struct evws_cb *ws_cb; - for (ws_cb = ws->callbacks.tqh_first; ws_cb; ws_cb = ws_cb->next.tqe_next) { + // TAILQ_FOREACH + for (ws_cb = ((&ws->callbacks))->tqh_first; ws_cb; ws_cb = (ws_cb->next.tqe_next)) { if (strcmp(ws_cb->uri, conn->uri) == 0) { - if(ws_cb->msg_cb != NULL) + if(ws_cb->msg_cb != ((void*)0)) ws_cb->msg_cb(conn, conn->frame, ws_cb->cb_arg); - continue; + return; } } ws->gencb(conn, conn->frame, ws->gencb_arg); @@ -484,27 +492,28 @@ struct evws_connection* evws_connection_new(struct evws *ws, evutil_socket_t fd) struct evws_connection* conn = calloc(1, sizeof(struct evws_connection)); conn->ws = ws; conn->fd = fd; - conn->uri = NULL; - + conn->uri = ((void*)0); + conn->bufev = bufferevent_socket_new(ws->base, fd, BEV_OPT_CLOSE_ON_FREE); conn->state = 0; - conn->frame = NULL; + conn->frame = ((void*)0); + + (&conn->headers)->tqh_first = NULL; + (&conn->headers)->tqh_last = &(((&conn->headers))->tqh_first); - conn->headers.tqh_first = NULL; - conn->headers.tqh_last = &(conn->headers.tqh_first); - return conn; } void evws_connection_free(struct evws_connection *conn) { struct evws_header *header; bufferevent_free(conn->bufev); - if(conn->uri != NULL) + if(conn->uri != ((void*)0)) free(conn->uri); - - for (header = conn->headers.tqh_first; header; header = header->next.tqe_next) { + + for (header = (&conn->headers)->tqh_first; header; header = header->next.tqe_next) { evws_header_free(header); } + free(conn); } @@ -530,19 +539,18 @@ struct evws_header *evws_header_new(char *key, char *value) void evws_header_free(struct evws_header *header) { if(header->key != NULL) free(header->key); - // @Note: segfault when freeing value, some strange value if(header->value != NULL) free(header->value); free(header); } char *evws_find_header(const struct wsheadersq *q, const char *key) { - struct evws_header *header; - char * ret = NULL; - for (header = q->tqh_first; header; header = header->next.tqe_next) { - - if(strcmp(header->key, key) == 0) { - ret = header->value; + struct evws_header *hdr; + char * ret = ((void*)0); + + for (hdr = q->tqh_first; hdr; hdr = hdr->next.tqe_next) { + if(strcmp(hdr->key, key) == 0) { + ret = hdr->value; break; } } |