qpid-proton-0.10/0000775000000000000000000000000012562450203010575 5ustar qpid-proton-0.10/version.txt0000664000000000000000000000000512562450203013016 0ustar 0.10 qpid-proton-0.10/tools/0000775000000000000000000000000012562450203011735 5ustar qpid-proton-0.10/tools/cmake/0000775000000000000000000000000012562450203013015 5ustar qpid-proton-0.10/tools/cmake/Modules/0000775000000000000000000000000012562450203014425 5ustar qpid-proton-0.10/tools/cmake/Modules/WindowsC99SymbolCheck.py0000664000000000000000000000405712562450203021050 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Stop cmake build if pn_i_xxx substitute functions aren't used for # the dangererous non-complying [v]snprintf family. A source of # painful bug-hunting. # # Each obj must be checked instead of just the dll since Visual Studio # sometimes inserts references to vsnprintf in DllMainCRTStartup, # causing false positives. # # bad: vsnprintf, __vsnprintf, _imp__vsnprintf, ..., same for snprintf # OK: vsnprintf_s, pn_i_vsnprintf # import sys import os import subprocess import glob import re def symcheck(objfile): symfile = objfile.replace('.obj', '.sym') cmd = ['dumpbin.exe', '/SYMBOLS', objfile, '/OUT:' + symfile] # /dev/null standin junk = open('junk', 'w') p = subprocess.Popen(cmd, stdout=junk) n = p.wait() if n != 0 : raise Exception("dumpbin call failure") f = open(symfile, 'r') for line in f : m = re.search(r'UNDEF.*\b([a-zA-Z_]*snprintf)\b', line) if m : sym = m.group(1) if re.match(r'_*pn_i_v?snprintf', sym) is None : raise Exception('Unsafe use of C99 violating function in ' + objfile + ' : ' + sym) def main(): os.chdir(sys.argv[1]) objs = glob.glob('*.obj') for obj in glob.glob('*.obj'): symcheck(obj) if __name__ == "__main__": sys.exit(main()) qpid-proton-0.10/tools/cmake/Modules/WindowsC99CheckDef.cmake0000664000000000000000000000241112562450203020721 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Check qpid-proton.dll after linking for dangerous calls to # Windows functions that suggest but deviate from C99 behavior: # _snprintf, vsnprintf, _vsnprintf # See platform.h for safe wrapper calls. # set(obj_dir ${CMAKE_CURRENT_BINARY_DIR}/qpid-proton.dir/${CMAKE_CFG_INTDIR}) add_custom_command(TARGET qpid-proton PRE_LINK COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_MODULE_PATH}WindowsC99SymbolCheck.py ${obj_dir} COMMENT "Checking for dangerous use of C99-violating functions") qpid-proton-0.10/tools/cmake/Modules/UseJavaSymlinks.cmake0000664000000000000000000000213512562450203020520 0ustar # # Helper script for UseJava.cmake # #============================================================================= # Copyright 2010-2011 Andreas schneider # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) if (UNIX AND _JAVA_TARGET_OUTPUT_LINK) if (_JAVA_TARGET_OUTPUT_NAME) find_program(LN_EXECUTABLE NAMES ln ) execute_process( COMMAND ${LN_EXECUTABLE} -sf "${_JAVA_TARGET_OUTPUT_NAME}" "${_JAVA_TARGET_OUTPUT_LINK}" WORKING_DIRECTORY ${_JAVA_TARGET_DIR} ) else () message(SEND_ERROR "FATAL: Can't find _JAVA_TARGET_OUTPUT_NAME") endif () endif () qpid-proton-0.10/tools/cmake/Modules/UseJavaClassFilelist.cmake0000664000000000000000000000421012562450203021444 0ustar # # This script create a list of compiled Java class files to be added to a # jar file. This avoids including cmake files which get created in the # binary directory. # #============================================================================= # Copyright 2010-2011 Andreas schneider # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) if (CMAKE_JAVA_CLASS_OUTPUT_PATH) if (EXISTS "${CMAKE_JAVA_CLASS_OUTPUT_PATH}") set(_JAVA_GLOBBED_FILES) if (CMAKE_JAR_CLASSES_PREFIX) foreach(JAR_CLASS_PREFIX ${CMAKE_JAR_CLASSES_PREFIX}) message(STATUS "JAR_CLASS_PREFIX: ${JAR_CLASS_PREFIX}") file(GLOB_RECURSE _JAVA_GLOBBED_TMP_FILES "${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${JAR_CLASS_PREFIX}/*.class") if (_JAVA_GLOBBED_TMP_FILES) list(APPEND _JAVA_GLOBBED_FILES ${_JAVA_GLOBBED_TMP_FILES}) endif () endforeach() else() file(GLOB_RECURSE _JAVA_GLOBBED_FILES "${CMAKE_JAVA_CLASS_OUTPUT_PATH}/*.class") endif () set(_JAVA_CLASS_FILES) # file(GLOB_RECURSE foo RELATIVE) is broken so we need this. foreach(_JAVA_GLOBBED_FILE ${_JAVA_GLOBBED_FILES}) file(RELATIVE_PATH _JAVA_CLASS_FILE ${CMAKE_JAVA_CLASS_OUTPUT_PATH} ${_JAVA_GLOBBED_FILE}) set(_JAVA_CLASS_FILES ${_JAVA_CLASS_FILES}${_JAVA_CLASS_FILE}\n) endforeach() # write to file file(WRITE ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist ${_JAVA_CLASS_FILES}) else () message(SEND_ERROR "FATAL: Java class output path doesn't exist") endif () else () message(SEND_ERROR "FATAL: Can't find CMAKE_JAVA_CLASS_OUTPUT_PATH") endif () qpid-proton-0.10/tools/cmake/Modules/UseJava.cmake0000664000000000000000000011270112562450203016767 0ustar # - Use Module for Java # This file provides functions for Java. It is assumed that FindJava.cmake # has already been loaded. See FindJava.cmake for information on how to # load Java into your CMake project. # # add_jar(TARGET_NAME SRC1 SRC2 .. SRCN RCS1 RCS2 .. RCSN) # # This command creates a .jar. It compiles the given source # files (SRC) and adds the given resource files (RCS) to the jar file. # If only resource files are given then just a jar file is created. # # Additional instructions: # To add compile flags to the target you can set these flags with # the following variable: # # set(CMAKE_JAVA_COMPILE_FLAGS -nowarn) # # To add a path or a jar file to the class path you can do this # with the CMAKE_JAVA_INCLUDE_PATH variable. # # set(CMAKE_JAVA_INCLUDE_PATH /usr/share/java/shibboleet.jar) # # To use a different output name for the target you can set it with: # # set(CMAKE_JAVA_TARGET_OUTPUT_NAME shibboleet.jar) # add_jar(foobar foobar.java) # # To use a different output directory than CMAKE_CURRENT_BINARY_DIR # you can set it with: # # set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${PROJECT_BINARY_DIR}/bin) # # To define an entry point in your jar you can set it with: # # set(CMAKE_JAVA_JAR_ENTRY_POINT com/examples/MyProject/Main) # # To add a VERSION to the target output name you can set it using # CMAKE_JAVA_TARGET_VERSION. This will create a jar file with the name # shibboleet-1.0.0.jar and will create a symlink shibboleet.jar # pointing to the jar with the version information. # # set(CMAKE_JAVA_TARGET_VERSION 1.2.0) # add_jar(shibboleet shibbotleet.java) # # If the target is a JNI library, utilize the following commands to # create a JNI symbolic link: # # set(CMAKE_JNI_TARGET TRUE) # set(CMAKE_JAVA_TARGET_VERSION 1.2.0) # add_jar(shibboleet shibbotleet.java) # install_jar(shibboleet ${LIB_INSTALL_DIR}/shibboleet) # install_jni_symlink(shibboleet ${JAVA_LIB_INSTALL_DIR}) # # If a single target needs to produce more than one jar from its # java source code, to prevent the accumulation of duplicate class # files in subsequent jars, set/reset CMAKE_JAR_CLASSES_PREFIX prior # to calling the add_jar() function: # # set(CMAKE_JAR_CLASSES_PREFIX com/redhat/foo) # add_jar(foo foo.java) # # set(CMAKE_JAR_CLASSES_PREFIX com/redhat/bar) # add_jar(bar bar.java) # # Target Properties: # The add_jar() functions sets some target properties. You can get these # properties with the # get_property(TARGET PROPERTY ) # command. # # INSTALL_FILES The files which should be installed. This is used by # install_jar(). # JNI_SYMLINK The JNI symlink which should be installed. # This is used by install_jni_symlink(). # JAR_FILE The location of the jar file so that you can include # it. # CLASS_DIR The directory where the class files can be found. For # example to use them with javah. # # find_jar( # name | NAMES name1 [name2 ...] # [PATHS path1 [path2 ... ENV var]] # [VERSIONS version1 [version2]] # [DOC "cache documentation string"] # ) # # This command is used to find a full path to the named jar. A cache # entry named by is created to stor the result of this command. If # the full path to a jar is found the result is stored in the variable # and the search will not repeated unless the variable is cleared. If # nothing is found, the result will be -NOTFOUND, and the search # will be attempted again next time find_jar is invoked with the same # variable. # The name of the full path to a file that is searched for is specified # by the names listed after NAMES argument. Additional search locations # can be specified after the PATHS argument. If you require special a # version of a jar file you can specify it with the VERSIONS argument. # The argument after DOC will be used for the documentation string in # the cache. # # install_jar(TARGET_NAME DESTINATION) # # This command installs the TARGET_NAME files to the given DESTINATION. # It should be called in the same scope as add_jar() or it will fail. # # install_jni_symlink(TARGET_NAME DESTINATION) # # This command installs the TARGET_NAME JNI symlinks to the given # DESTINATION. It should be called in the same scope as add_jar() # or it will fail. # # create_javadoc( # PACKAGES pkg1 [pkg2 ...] # [SOURCEPATH ] # [CLASSPATH ] # [INSTALLPATH ] # [DOCTITLE "the documentation title"] # [WINDOWTITLE "the title of the document"] # [AUTHOR TRUE|FALSE] # [USE TRUE|FALSE] # [VERSION TRUE|FALSE] # ) # # Create java documentation based on files or packages. For more # details please read the javadoc manpage. # # There are two main signatures for create_javadoc. The first # signature works with package names on a path with source files: # # Example: # create_javadoc(my_example_doc # PACKAGES com.exmaple.foo com.example.bar # SOURCEPATH "${CMAKE_CURRENT_SOURCE_DIR}" # CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH} # WINDOWTITLE "My example" # DOCTITLE "

My example

" # AUTHOR TRUE # USE TRUE # VERSION TRUE # ) # # The second signature for create_javadoc works on a given list of # files. # # create_javadoc( # FILES file1 [file2 ...] # [CLASSPATH ] # [INSTALLPATH ] # [DOCTITLE "the documentation title"] # [WINDOWTITLE "the title of the document"] # [AUTHOR TRUE|FALSE] # [USE TRUE|FALSE] # [VERSION TRUE|FALSE] # ) # # Example: # create_javadoc(my_example_doc # FILES ${example_SRCS} # CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH} # WINDOWTITLE "My example" # DOCTITLE "

My example

" # AUTHOR TRUE # USE TRUE # VERSION TRUE # ) # # Both signatures share most of the options. These options are the # same as what you can find in the javadoc manpage. Please look at # the manpage for CLASSPATH, DOCTITLE, WINDOWTITLE, AUTHOR, USE and # VERSION. # # The documentation will be by default installed to # # ${CMAKE_INSTALL_PREFIX}/share/javadoc/ # # if you don't set the INSTALLPATH. # #============================================================================= # Copyright 2010-2011 Andreas schneider # Copyright 2010 Ben Boeckel # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) function (__java_copy_file src dest comment) add_custom_command( OUTPUT ${dest} COMMAND cmake -E copy_if_different ARGS ${src} ${dest} DEPENDS ${src} COMMENT ${comment}) endfunction () # define helper scripts #set(_JAVA_CLASS_FILELIST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaClassFilelist.cmake) #set(_JAVA_SYMLINK_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/UseJavaSymlinks.cmake) set(_JAVA_CLASS_FILELIST_SCRIPT ${CMAKE_MODULE_PATH}/UseJavaClassFilelist.cmake) set(_JAVA_SYMLINK_SCRIPT ${CMAKE_MODULE_PATH}/UseJavaSymlinks.cmake) # Apache Qpid Proton: changed to write a source file list to avoid hitting # command line limits when processing many source files. function(add_jar _TARGET_NAME) set(_JAVA_SOURCE_FILES ${ARGN}) if (NOT DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR) set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) endif() if (CMAKE_JAVA_JAR_ENTRY_POINT) set(_ENTRY_POINT_OPTION e) set(_ENTRY_POINT_VALUE ${CMAKE_JAVA_JAR_ENTRY_POINT}) endif () if (LIBRARY_OUTPUT_PATH) set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH}) else () set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR}) endif () set(CMAKE_JAVA_INCLUDE_PATH ${CMAKE_JAVA_INCLUDE_PATH} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_JAVA_OBJECT_OUTPUT_PATH} ${CMAKE_JAVA_LIBRARY_OUTPUT_PATH} ) if (WIN32 AND NOT CYGWIN) set(CMAKE_JAVA_INCLUDE_FLAG_SEP ";") else () set(CMAKE_JAVA_INCLUDE_FLAG_SEP ":") endif() foreach (JAVA_INCLUDE_DIR ${CMAKE_JAVA_INCLUDE_PATH}) set(CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_PATH_FINAL}${CMAKE_JAVA_INCLUDE_FLAG_SEP}${JAVA_INCLUDE_DIR}") endforeach() set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${CMAKE_JAVA_TARGET_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir") set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}.jar") if (CMAKE_JAVA_TARGET_OUTPUT_NAME AND CMAKE_JAVA_TARGET_VERSION) set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar") set(_JAVA_TARGET_OUTPUT_LINK "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar") elseif (CMAKE_JAVA_TARGET_VERSION) set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar") set(_JAVA_TARGET_OUTPUT_LINK "${_TARGET_NAME}.jar") elseif (CMAKE_JAVA_TARGET_OUTPUT_NAME) set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar") endif () # reset set(CMAKE_JAVA_TARGET_OUTPUT_NAME) set(_JAVA_CLASS_FILES) set(_JAVA_COMPILE_FILES) set(_JAVA_DEPENDS) set(_JAVA_RESOURCE_FILES) foreach(_JAVA_SOURCE_FILE ${_JAVA_SOURCE_FILES}) get_filename_component(_JAVA_EXT ${_JAVA_SOURCE_FILE} EXT) get_filename_component(_JAVA_FILE ${_JAVA_SOURCE_FILE} NAME_WE) get_filename_component(_JAVA_PATH ${_JAVA_SOURCE_FILE} PATH) get_filename_component(_JAVA_FULL ${_JAVA_SOURCE_FILE} ABSOLUTE) file(RELATIVE_PATH _JAVA_REL_BINARY_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR} ${_JAVA_FULL}) file(RELATIVE_PATH _JAVA_REL_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${_JAVA_FULL}) string(LENGTH ${_JAVA_REL_BINARY_PATH} _BIN_LEN) string(LENGTH ${_JAVA_REL_SOURCE_PATH} _SRC_LEN) if (${_BIN_LEN} LESS ${_SRC_LEN}) set(_JAVA_REL_PATH ${_JAVA_REL_BINARY_PATH}) else () set(_JAVA_REL_PATH ${_JAVA_REL_SOURCE_PATH}) endif () get_filename_component(_JAVA_REL_PATH ${_JAVA_REL_PATH} PATH) if (_JAVA_EXT MATCHES ".java") list(APPEND _JAVA_COMPILE_FILES ${_JAVA_SOURCE_FILE}) set(_JAVA_CLASS_FILE "${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${_JAVA_REL_PATH}/${_JAVA_FILE}.class") set(_JAVA_CLASS_FILES ${_JAVA_CLASS_FILES} ${_JAVA_CLASS_FILE}) elseif (_JAVA_EXT MATCHES ".jar" OR _JAVA_EXT MATCHES ".war" OR _JAVA_EXT MATCHES ".ear" OR _JAVA_EXT MATCHES ".sar") list(APPEND CMAKE_JAVA_INCLUDE_PATH ${_JAVA_SOURCE_FILE}) elseif (_JAVA_EXT STREQUAL "") list(APPEND CMAKE_JAVA_INCLUDE_PATH ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}} ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}_CLASSPATH}) list(APPEND _JAVA_DEPENDS ${JAVA_JAR_TARGET_${_JAVA_SOURCE_FILE}}) else () __java_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/${_JAVA_SOURCE_FILE} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/${_JAVA_SOURCE_FILE} "Copying ${_JAVA_SOURCE_FILE} to the build directory") list(APPEND _JAVA_RESOURCE_FILES ${_JAVA_SOURCE_FILE}) endif () endforeach() set(CMAKE_JAVA_SOURCE_FILE_LIST ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_source_filelist) string(REPLACE ";" "\n" _JAVA_COMPILE_FILES_NEWLINE_SEPARATED "${_JAVA_COMPILE_FILES}") file(WRITE ${CMAKE_JAVA_SOURCE_FILE_LIST} "${_JAVA_COMPILE_FILES_NEWLINE_SEPARATED}") # create an empty java_class_filelist if (NOT EXISTS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist) file(WRITE ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist "") endif() if (_JAVA_COMPILE_FILES) # Compile the java files and create a list of class files add_custom_command( # NOTE: this command generates an artificial dependency file OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME} COMMAND ${Java_JAVAC_EXECUTABLE} ${CMAKE_JAVA_COMPILE_FLAGS} -classpath "${CMAKE_JAVA_INCLUDE_PATH_FINAL}" -d ${CMAKE_JAVA_CLASS_OUTPUT_PATH} @${CMAKE_JAVA_SOURCE_FILE_LIST} COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME} DEPENDS ${_JAVA_COMPILE_FILES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Building Java objects for ${_TARGET_NAME}.jar" ) add_custom_command( OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist COMMAND ${CMAKE_COMMAND} -DCMAKE_JAVA_CLASS_OUTPUT_PATH=${CMAKE_JAVA_CLASS_OUTPUT_PATH} -DCMAKE_JAR_CLASSES_PREFIX="${CMAKE_JAR_CLASSES_PREFIX}" -P ${_JAVA_CLASS_FILELIST_SCRIPT} DEPENDS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) endif () # create the jar file set(_JAVA_JAR_OUTPUT_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME}) if (CMAKE_JNI_TARGET) add_custom_command( OUTPUT ${_JAVA_JAR_OUTPUT_PATH} COMMAND ${Java_JAR_EXECUTABLE} -cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE} ${_JAVA_RESOURCE_FILES} @java_class_filelist COMMAND ${CMAKE_COMMAND} -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR} -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME} -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK} -P ${_JAVA_SYMLINK_SCRIPT} COMMAND ${CMAKE_COMMAND} -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR} -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_JAR_OUTPUT_PATH} -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK} -P ${_JAVA_SYMLINK_SCRIPT} DEPENDS ${_JAVA_RESOURCE_FILES} ${_JAVA_DEPENDS} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist WORKING_DIRECTORY ${CMAKE_JAVA_CLASS_OUTPUT_PATH} COMMENT "Creating Java archive ${_JAVA_TARGET_OUTPUT_NAME}" ) else () add_custom_command( OUTPUT ${_JAVA_JAR_OUTPUT_PATH} COMMAND ${Java_JAR_EXECUTABLE} -cf${_ENTRY_POINT_OPTION} ${_JAVA_JAR_OUTPUT_PATH} ${_ENTRY_POINT_VALUE} ${_JAVA_RESOURCE_FILES} @java_class_filelist COMMAND ${CMAKE_COMMAND} -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR} -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME} -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK} -P ${_JAVA_SYMLINK_SCRIPT} WORKING_DIRECTORY ${CMAKE_JAVA_CLASS_OUTPUT_PATH} DEPENDS ${_JAVA_RESOURCE_FILES} ${_JAVA_DEPENDS} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist COMMENT "Creating Java archive ${_JAVA_TARGET_OUTPUT_NAME}" ) endif () # Add the target and make sure we have the latest resource files. add_custom_target(${_TARGET_NAME} ALL DEPENDS ${_JAVA_JAR_OUTPUT_PATH}) set_property( TARGET ${_TARGET_NAME} PROPERTY INSTALL_FILES ${_JAVA_JAR_OUTPUT_PATH} ) if (_JAVA_TARGET_OUTPUT_LINK) set_property( TARGET ${_TARGET_NAME} PROPERTY INSTALL_FILES ${_JAVA_JAR_OUTPUT_PATH} ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} ) if (CMAKE_JNI_TARGET) set_property( TARGET ${_TARGET_NAME} PROPERTY JNI_SYMLINK ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} ) endif () endif () set_property( TARGET ${_TARGET_NAME} PROPERTY JAR_FILE ${_JAVA_JAR_OUTPUT_PATH} ) set_property( TARGET ${_TARGET_NAME} PROPERTY CLASSDIR ${CMAKE_JAVA_CLASS_OUTPUT_PATH} ) endfunction() # Apache Qpid Proton: new function that accepts a file containing the Java source # files. This is useful when the set of source files is only discovered at make-time, # and avoids passing a wildcard argument to javac (which fails on some platforms) function(add_jar_from_filelist _TARGET_NAME CMAKE_JAVA_SOURCE_FILE_LIST) if (NOT DEFINED CMAKE_JAVA_TARGET_OUTPUT_DIR) set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) endif() set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${CMAKE_JAVA_TARGET_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir") set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}.jar") if (CMAKE_JAVA_TARGET_OUTPUT_NAME AND CMAKE_JAVA_TARGET_VERSION) set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar") set(_JAVA_TARGET_OUTPUT_LINK "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar") elseif (CMAKE_JAVA_TARGET_VERSION) set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}-${CMAKE_JAVA_TARGET_VERSION}.jar") set(_JAVA_TARGET_OUTPUT_LINK "${_TARGET_NAME}.jar") elseif (CMAKE_JAVA_TARGET_OUTPUT_NAME) set(_JAVA_TARGET_OUTPUT_NAME "${CMAKE_JAVA_TARGET_OUTPUT_NAME}.jar") endif () # reset set(CMAKE_JAVA_TARGET_OUTPUT_NAME) foreach (JAVA_INCLUDE_DIR ${CMAKE_JAVA_INCLUDE_PATH}) set(CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_PATH_FINAL}${CMAKE_JAVA_INCLUDE_FLAG_SEP}${JAVA_INCLUDE_DIR}") endforeach() # create an empty java_class_filelist if (NOT EXISTS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist) file(WRITE ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist "") endif () # Compile the java files and create a list of class files add_custom_command( # NOTE: this command generates an artificial dependency file OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME} COMMAND ${Java_JAVAC_EXECUTABLE} ${CMAKE_JAVA_COMPILE_FLAGS} -classpath "${CMAKE_JAVA_INCLUDE_PATH_FINAL}" -d ${CMAKE_JAVA_CLASS_OUTPUT_PATH} @${CMAKE_JAVA_SOURCE_FILE_LIST} COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME} DEPENDS ${CMAKE_JAVA_SOURCE_FILE_LIST} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Building Java objects for ${_TARGET_NAME}.jar" ) add_custom_command( OUTPUT ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist COMMAND ${CMAKE_COMMAND} -DCMAKE_JAVA_CLASS_OUTPUT_PATH=${CMAKE_JAVA_CLASS_OUTPUT_PATH} -DCMAKE_JAR_CLASSES_PREFIX="${CMAKE_JAR_CLASSES_PREFIX}" -P ${_JAVA_CLASS_FILELIST_SCRIPT} DEPENDS ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) # create the jar file set(_JAVA_JAR_OUTPUT_PATH ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME}) add_custom_command( OUTPUT ${_JAVA_JAR_OUTPUT_PATH} COMMAND ${Java_JAR_EXECUTABLE} -cf ${_JAVA_JAR_OUTPUT_PATH} ${_JAVA_RESOURCE_FILES} @java_class_filelist COMMAND ${CMAKE_COMMAND} -D_JAVA_TARGET_DIR=${CMAKE_JAVA_TARGET_OUTPUT_DIR} -D_JAVA_TARGET_OUTPUT_NAME=${_JAVA_TARGET_OUTPUT_NAME} -D_JAVA_TARGET_OUTPUT_LINK=${_JAVA_TARGET_OUTPUT_LINK} -P ${_JAVA_SYMLINK_SCRIPT} WORKING_DIRECTORY ${CMAKE_JAVA_CLASS_OUTPUT_PATH} DEPENDS ${_JAVA_RESOURCE_FILES} ${_JAVA_DEPENDS} ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_class_filelist COMMENT "Creating Java archive ${_JAVA_TARGET_OUTPUT_NAME}" ) # Add the target and make sure we have the latest resource files. add_custom_target(${_TARGET_NAME} ALL DEPENDS ${_JAVA_JAR_OUTPUT_PATH}) set_property( TARGET ${_TARGET_NAME} PROPERTY INSTALL_FILES ${_JAVA_JAR_OUTPUT_PATH} ) if (_JAVA_TARGET_OUTPUT_LINK) set_property( TARGET ${_TARGET_NAME} PROPERTY INSTALL_FILES ${_JAVA_JAR_OUTPUT_PATH} ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} ) if (CMAKE_JNI_TARGET) set_property( TARGET ${_TARGET_NAME} PROPERTY JNI_SYMLINK ${CMAKE_JAVA_TARGET_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_LINK} ) endif () endif () set_property( TARGET ${_TARGET_NAME} PROPERTY JAR_FILE ${_JAVA_JAR_OUTPUT_PATH} ) set_property( TARGET ${_TARGET_NAME} PROPERTY CLASSDIR ${CMAKE_JAVA_CLASS_OUTPUT_PATH} ) endfunction() function(INSTALL_JAR _TARGET_NAME _DESTINATION) get_property(__FILES TARGET ${_TARGET_NAME} PROPERTY INSTALL_FILES ) if (__FILES) install( FILES ${__FILES} DESTINATION ${_DESTINATION} ) else () message(SEND_ERROR "The target ${_TARGET_NAME} is not known in this scope.") endif () endfunction() function(INSTALL_JNI_SYMLINK _TARGET_NAME _DESTINATION) get_property(__SYMLINK TARGET ${_TARGET_NAME} PROPERTY JNI_SYMLINK ) if (__SYMLINK) install( FILES ${__SYMLINK} DESTINATION ${_DESTINATION} ) else () message(SEND_ERROR "The target ${_TARGET_NAME} is not known in this scope.") endif () endfunction() function (find_jar VARIABLE) set(_jar_names) set(_jar_files) set(_jar_versions) set(_jar_paths /usr/share/java/ /usr/local/share/java/ ${Java_JAR_PATHS}) set(_jar_doc "NOTSET") set(_state "name") foreach (arg ${ARGN}) if (${_state} STREQUAL "name") if (${arg} STREQUAL "VERSIONS") set(_state "versions") elseif (${arg} STREQUAL "NAMES") set(_state "names") elseif (${arg} STREQUAL "PATHS") set(_state "paths") elseif (${arg} STREQUAL "DOC") set(_state "doc") else () set(_jar_names ${arg}) if (_jar_doc STREQUAL "NOTSET") set(_jar_doc "Finding ${arg} jar") endif () endif () elseif (${_state} STREQUAL "versions") if (${arg} STREQUAL "NAMES") set(_state "names") elseif (${arg} STREQUAL "PATHS") set(_state "paths") elseif (${arg} STREQUAL "DOC") set(_state "doc") else () set(_jar_versions ${_jar_versions} ${arg}) endif () elseif (${_state} STREQUAL "names") if (${arg} STREQUAL "VERSIONS") set(_state "versions") elseif (${arg} STREQUAL "PATHS") set(_state "paths") elseif (${arg} STREQUAL "DOC") set(_state "doc") else () set(_jar_names ${_jar_names} ${arg}) if (_jar_doc STREQUAL "NOTSET") set(_jar_doc "Finding ${arg} jar") endif () endif () elseif (${_state} STREQUAL "paths") if (${arg} STREQUAL "VERSIONS") set(_state "versions") elseif (${arg} STREQUAL "NAMES") set(_state "names") elseif (${arg} STREQUAL "DOC") set(_state "doc") else () set(_jar_paths ${_jar_paths} ${arg}) endif () elseif (${_state} STREQUAL "doc") if (${arg} STREQUAL "VERSIONS") set(_state "versions") elseif (${arg} STREQUAL "NAMES") set(_state "names") elseif (${arg} STREQUAL "PATHS") set(_state "paths") else () set(_jar_doc ${arg}) endif () endif () endforeach () if (NOT _jar_names) message(FATAL_ERROR "find_jar: No name to search for given") endif () foreach (jar_name ${_jar_names}) foreach (version ${_jar_versions}) set(_jar_files ${_jar_files} ${jar_name}-${version}.jar) endforeach () set(_jar_files ${_jar_files} ${jar_name}.jar) endforeach () find_file(${VARIABLE} NAMES ${_jar_files} PATHS ${_jar_paths} DOC ${_jar_doc} NO_DEFAULT_PATH) endfunction () function(create_javadoc _target) set(_javadoc_packages) set(_javadoc_files) set(_javadoc_sourcepath) set(_javadoc_classpath) set(_javadoc_installpath "${CMAKE_INSTALL_PREFIX}/share/javadoc") set(_javadoc_doctitle) set(_javadoc_windowtitle) set(_javadoc_author FALSE) set(_javadoc_version FALSE) set(_javadoc_use FALSE) set(_state "package") foreach (arg ${ARGN}) if (${_state} STREQUAL "package") if (${arg} STREQUAL "PACKAGES") set(_state "packages") elseif (${arg} STREQUAL "FILES") set(_state "files") elseif (${arg} STREQUAL "SOURCEPATH") set(_state "sourcepath") elseif (${arg} STREQUAL "CLASSPATH") set(_state "classpath") elseif (${arg} STREQUAL "INSTALLPATH") set(_state "installpath") elseif (${arg} STREQUAL "DOCTITLE") set(_state "doctitle") elseif (${arg} STREQUAL "WINDOWTITLE") set(_state "windowtitle") elseif (${arg} STREQUAL "AUTHOR") set(_state "author") elseif (${arg} STREQUAL "USE") set(_state "use") elseif (${arg} STREQUAL "VERSION") set(_state "version") else () set(_javadoc_packages ${arg}) set(_state "packages") endif () elseif (${_state} STREQUAL "packages") if (${arg} STREQUAL "FILES") set(_state "files") elseif (${arg} STREQUAL "SOURCEPATH") set(_state "sourcepath") elseif (${arg} STREQUAL "CLASSPATH") set(_state "classpath") elseif (${arg} STREQUAL "INSTALLPATH") set(_state "installpath") elseif (${arg} STREQUAL "DOCTITLE") set(_state "doctitle") elseif (${arg} STREQUAL "WINDOWTITLE") set(_state "windowtitle") elseif (${arg} STREQUAL "AUTHOR") set(_state "author") elseif (${arg} STREQUAL "USE") set(_state "use") elseif (${arg} STREQUAL "VERSION") set(_state "version") else () list(APPEND _javadoc_packages ${arg}) endif () elseif (${_state} STREQUAL "files") if (${arg} STREQUAL "PACKAGES") set(_state "packages") elseif (${arg} STREQUAL "SOURCEPATH") set(_state "sourcepath") elseif (${arg} STREQUAL "CLASSPATH") set(_state "classpath") elseif (${arg} STREQUAL "INSTALLPATH") set(_state "installpath") elseif (${arg} STREQUAL "DOCTITLE") set(_state "doctitle") elseif (${arg} STREQUAL "WINDOWTITLE") set(_state "windowtitle") elseif (${arg} STREQUAL "AUTHOR") set(_state "author") elseif (${arg} STREQUAL "USE") set(_state "use") elseif (${arg} STREQUAL "VERSION") set(_state "version") else () list(APPEND _javadoc_files ${arg}) endif () elseif (${_state} STREQUAL "sourcepath") if (${arg} STREQUAL "PACKAGES") set(_state "packages") elseif (${arg} STREQUAL "FILES") set(_state "files") elseif (${arg} STREQUAL "CLASSPATH") set(_state "classpath") elseif (${arg} STREQUAL "INSTALLPATH") set(_state "installpath") elseif (${arg} STREQUAL "DOCTITLE") set(_state "doctitle") elseif (${arg} STREQUAL "WINDOWTITLE") set(_state "windowtitle") elseif (${arg} STREQUAL "AUTHOR") set(_state "author") elseif (${arg} STREQUAL "USE") set(_state "use") elseif (${arg} STREQUAL "VERSION") set(_state "version") else () list(APPEND _javadoc_sourcepath ${arg}) endif () elseif (${_state} STREQUAL "classpath") if (${arg} STREQUAL "PACKAGES") set(_state "packages") elseif (${arg} STREQUAL "FILES") set(_state "files") elseif (${arg} STREQUAL "SOURCEPATH") set(_state "sourcepath") elseif (${arg} STREQUAL "INSTALLPATH") set(_state "installpath") elseif (${arg} STREQUAL "DOCTITLE") set(_state "doctitle") elseif (${arg} STREQUAL "WINDOWTITLE") set(_state "windowtitle") elseif (${arg} STREQUAL "AUTHOR") set(_state "author") elseif (${arg} STREQUAL "USE") set(_state "use") elseif (${arg} STREQUAL "VERSION") set(_state "version") else () list(APPEND _javadoc_classpath ${arg}) endif () elseif (${_state} STREQUAL "installpath") if (${arg} STREQUAL "PACKAGES") set(_state "packages") elseif (${arg} STREQUAL "FILES") set(_state "files") elseif (${arg} STREQUAL "SOURCEPATH") set(_state "sourcepath") elseif (${arg} STREQUAL "DOCTITLE") set(_state "doctitle") elseif (${arg} STREQUAL "WINDOWTITLE") set(_state "windowtitle") elseif (${arg} STREQUAL "AUTHOR") set(_state "author") elseif (${arg} STREQUAL "USE") set(_state "use") elseif (${arg} STREQUAL "VERSION") set(_state "version") else () set(_javadoc_installpath ${arg}) endif () elseif (${_state} STREQUAL "doctitle") if (${arg} STREQUAL "PACKAGES") set(_state "packages") elseif (${arg} STREQUAL "FILES") set(_state "files") elseif (${arg} STREQUAL "SOURCEPATH") set(_state "sourcepath") elseif (${arg} STREQUAL "INSTALLPATH") set(_state "installpath") elseif (${arg} STREQUAL "CLASSPATH") set(_state "classpath") elseif (${arg} STREQUAL "WINDOWTITLE") set(_state "windowtitle") elseif (${arg} STREQUAL "AUTHOR") set(_state "author") elseif (${arg} STREQUAL "USE") set(_state "use") elseif (${arg} STREQUAL "VERSION") set(_state "version") else () set(_javadoc_doctitle ${arg}) endif () elseif (${_state} STREQUAL "windowtitle") if (${arg} STREQUAL "PACKAGES") set(_state "packages") elseif (${arg} STREQUAL "FILES") set(_state "files") elseif (${arg} STREQUAL "SOURCEPATH") set(_state "sourcepath") elseif (${arg} STREQUAL "CLASSPATH") set(_state "classpath") elseif (${arg} STREQUAL "INSTALLPATH") set(_state "installpath") elseif (${arg} STREQUAL "DOCTITLE") set(_state "doctitle") elseif (${arg} STREQUAL "AUTHOR") set(_state "author") elseif (${arg} STREQUAL "USE") set(_state "use") elseif (${arg} STREQUAL "VERSION") set(_state "version") else () set(_javadoc_windowtitle ${arg}) endif () elseif (${_state} STREQUAL "author") if (${arg} STREQUAL "PACKAGES") set(_state "packages") elseif (${arg} STREQUAL "FILES") set(_state "files") elseif (${arg} STREQUAL "SOURCEPATH") set(_state "sourcepath") elseif (${arg} STREQUAL "CLASSPATH") set(_state "classpath") elseif (${arg} STREQUAL "INSTALLPATH") set(_state "installpath") elseif (${arg} STREQUAL "DOCTITLE") set(_state "doctitle") elseif (${arg} STREQUAL "WINDOWTITLE") set(_state "windowtitle") elseif (${arg} STREQUAL "AUTHOR") set(_state "author") elseif (${arg} STREQUAL "USE") set(_state "use") elseif (${arg} STREQUAL "VERSION") set(_state "version") else () set(_javadoc_author ${arg}) endif () elseif (${_state} STREQUAL "use") if (${arg} STREQUAL "PACKAGES") set(_state "packages") elseif (${arg} STREQUAL "FILES") set(_state "files") elseif (${arg} STREQUAL "SOURCEPATH") set(_state "sourcepath") elseif (${arg} STREQUAL "CLASSPATH") set(_state "classpath") elseif (${arg} STREQUAL "INSTALLPATH") set(_state "installpath") elseif (${arg} STREQUAL "DOCTITLE") set(_state "doctitle") elseif (${arg} STREQUAL "WINDOWTITLE") set(_state "windowtitle") elseif (${arg} STREQUAL "AUTHOR") set(_state "author") elseif (${arg} STREQUAL "USE") set(_state "use") elseif (${arg} STREQUAL "VERSION") set(_state "version") else () set(_javadoc_use ${arg}) endif () elseif (${_state} STREQUAL "version") if (${arg} STREQUAL "PACKAGES") set(_state "packages") elseif (${arg} STREQUAL "FILES") set(_state "files") elseif (${arg} STREQUAL "SOURCEPATH") set(_state "sourcepath") elseif (${arg} STREQUAL "CLASSPATH") set(_state "classpath") elseif (${arg} STREQUAL "INSTALLPATH") set(_state "installpath") elseif (${arg} STREQUAL "DOCTITLE") set(_state "doctitle") elseif (${arg} STREQUAL "WINDOWTITLE") set(_state "windowtitle") elseif (${arg} STREQUAL "AUTHOR") set(_state "author") elseif (${arg} STREQUAL "USE") set(_state "use") elseif (${arg} STREQUAL "VERSION") set(_state "version") else () set(_javadoc_version ${arg}) endif () endif () endforeach () set(_javadoc_builddir ${CMAKE_CURRENT_BINARY_DIR}/javadoc/${_target}) set(_javadoc_options -d ${_javadoc_builddir}) if (_javadoc_sourcepath) set(_start TRUE) foreach(_path ${_javadoc_sourcepath}) if (_start) set(_sourcepath ${_path}) set(_start FALSE) else () set(_sourcepath ${_sourcepath}:${_path}) endif () endforeach() set(_javadoc_options ${_javadoc_options} -sourcepath ${_sourcepath}) endif () if (_javadoc_classpath) set(_start TRUE) foreach(_path ${_javadoc_classpath}) if (_start) set(_classpath ${_path}) set(_start FALSE) else () set(_classpath ${_classpath}:${_path}) endif () endforeach() set(_javadoc_options ${_javadoc_options} -classpath "${_classpath}") endif () if (_javadoc_doctitle) set(_javadoc_options ${_javadoc_options} -doctitle '${_javadoc_doctitle}') endif () if (_javadoc_windowtitle) set(_javadoc_options ${_javadoc_options} -windowtitle '${_javadoc_windowtitle}') endif () if (_javadoc_author) set(_javadoc_options ${_javadoc_options} -author) endif () if (_javadoc_use) set(_javadoc_options ${_javadoc_options} -use) endif () if (_javadoc_version) set(_javadoc_options ${_javadoc_options} -version) endif () add_custom_target(${_target}_javadoc ALL COMMAND ${Java_JAVADOC_EXECUTABLE} ${_javadoc_options} ${_javadoc_files} ${_javadoc_packages} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) install( DIRECTORY ${_javadoc_builddir} DESTINATION ${_javadoc_installpath} ) endfunction() qpid-proton-0.10/tools/cmake/Modules/README0000664000000000000000000000060212562450203015303 0ustar CMake Modules ============= Contents: UseJava, UseJavaSymLinks, UseJavaClassFilelist: These are Andreas Schneider's CMake Java Support. We have our own local copy as all versions of CMake < 2.8.9 have defects in their Java support that affect us. Local modifications are commented with "Apache Qpid Proton...". UseProtonJava: Custom support functions for the Proton Java modules qpid-proton-0.10/tools/cmake/Modules/ProtonUseJavaSourceFileList.cmake0000664000000000000000000000513012562450203023003 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Produces a text file containing a list of java source files from one # or more java source directories. Produces output suitable for use # with javac's @ source file argument. # # JAVA_SOURCE_DIR_PATHS - colon (:) separated string of java source directories # JAVA_SOURCE_FILE_LIST - name of text file to write # if (JAVA_SOURCE_DIR_PATHS) string(REPLACE ":" ";" JAVA_SOURCE_DIR_PATHS_LIST ${JAVA_SOURCE_DIR_PATHS}) message(STATUS "Java source paths: ${JAVA_SOURCE_DIR_PATHS}") set(_JAVA_GLOBBED_FILES) foreach(JAVA_SOURCE_DIR_PATH ${JAVA_SOURCE_DIR_PATHS_LIST}) if (EXISTS "${JAVA_SOURCE_DIR_PATH}") file(GLOB_RECURSE _JAVA_GLOBBED_TMP_FILES "${JAVA_SOURCE_DIR_PATH}/*.java") if (_JAVA_GLOBBED_TMP_FILES) list(APPEND _JAVA_GLOBBED_FILES ${_JAVA_GLOBBED_TMP_FILES}) endif () else () message(SEND_ERROR "FATAL: Java source path ${JAVA_SOURCE_DIR_PATH} doesn't exist") endif () endforeach() set (_CHECK_STALE OFF) set(_GENERATE_FILE_LIST ON) if (EXISTS ${JAVA_SOURCE_FILE_LIST}) set (_CHECK_STALE ON) set(_GENERATE_FILE_LIST OFF) endif () set(_JAVA_SOURCE_FILES_SEPARATED) foreach(_JAVA_GLOBBED_FILE ${_JAVA_GLOBBED_FILES}) if (_CHECK_STALE) if (${_JAVA_GLOBBED_FILE} IS_NEWER_THAN ${JAVA_SOURCE_FILE_LIST}) set(_GENERATE_FILE_LIST ON) endif() endif() set(_JAVA_SOURCE_FILES_SEPARATED ${_JAVA_SOURCE_FILES_SEPARATED}${_JAVA_GLOBBED_FILE}\n) endforeach() if (_GENERATE_FILE_LIST) message(STATUS "Writing Java source file list to ${JAVA_SOURCE_FILE_LIST}") file(WRITE ${JAVA_SOURCE_FILE_LIST} ${_JAVA_SOURCE_FILES_SEPARATED}) endif() else () message(SEND_ERROR "FATAL: Can't find JAVA_SOURCE_DIR_PATHS") endif () qpid-proton-0.10/tools/cmake/Modules/ProtonUseJava.cmake0000664000000000000000000000253312562450203020172 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Adds a custom command to rebuild the JAR to include resources and the # directory entries that are missed by add_jar() function (rebuild_jar upstream_target jar_name) add_custom_command(TARGET ${upstream_target} POST_BUILD COMMAND ${Java_JAR_EXECUTABLE} cf ${jar_name} -C ${CMAKE_CURRENT_SOURCE_DIR}/src/main/resources . -C ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${upstream_target}.dir/ org COMMENT "Rebuilding ${jar_name} to include missing resources") endfunction () qpid-proton-0.10/tools/cmake/Modules/ProtonFindPerl.cmake0000664000000000000000000000554312562450203020343 0ustar # - Find Perl Libraries # This module searches for Perl libraries in the event that those files aren't # found by the default Cmake module. # include(${CMAKE_CURRENT_LIST_DIR}/FindPerlLibs.cmake) include(FindPerl) include(FindPerlLibs) if(NOT PERLLIBS_FOUND) MESSAGE ( STATUS "Trying alternative search for Perl" ) # taken from Cmake 2.8 FindPerlLibs.cmake EXECUTE_PROCESS ( COMMAND ${PERL_EXECUTABLE} -V:installarchlib OUTPUT_VARIABLE PERL_ARCHLIB_OUTPUT_VARIABLE RESULT_VARIABLE PERL_ARCHLIB_RESULT_VARIABLE ) if (NOT PERL_ARCHLIB_RESULT_VARIABLE) string(REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_ARCHLIB ${PERL_ARCHLIB_OUTPUT_VARIABLE}) file(TO_CMAKE_PATH "${PERL_ARCHLIB}" PERL_ARCHLIB) endif ( NOT PERL_ARCHLIB_RESULT_VARIABLE ) EXECUTE_PROCESS ( COMMAND ${PERL_EXECUTABLE} -MConfig -e "print \$Config{archlibexp}" OUTPUT_VARIABLE PERL_OUTPUT RESULT_VARIABLE PERL_RETURN_VALUE ) IF ( NOT PERL_RETURN_VALUE ) FIND_PATH ( PERL_INCLUDE_PATH perl.h ${PERL_OUTPUT}/CORE ) IF (PERL_INCLUDE_PATH MATCHES .*-NOTFOUND OR NOT PERL_INCLUDE_PATH) MESSAGE(STATUS "Could not find perl.h") ENDIF () ENDIF ( NOT PERL_RETURN_VALUE ) # if either the library path is not found not set at all # then do our own search if ( NOT PERL_LIBRARY ) EXECUTE_PROCESS( COMMAND ${PERL_EXECUTABLE} -V:libperl OUTPUT_VARIABLE PERL_LIBRARY_OUTPUT RESULT_VARIABLE PERL_LIBRARY_RESULT ) IF ( NOT PERL_LIBRARY_RESULT ) string(REGEX REPLACE "libperl='([^']+)'.*" "\\1" PERL_POSSIBLE_LIBRARIES ${PERL_LIBRARY_OUTPUT}) ENDIF ( NOT PERL_LIBRARY_RESULT ) MESSAGE ( STATUS "Looking for ${PERL_POSSIBLE_LIBRARIES}" ) find_file(PERL_LIBRARY NAMES ${PERL_POSSIBLE_LIBRARIES} PATHS /usr/lib ${PERL_ARCHLIB}/CORE ) endif ( NOT PERL_LIBRARY ) IF ( PERL_LIBRARY MATCHES .*-NOTFOUND OR NOT PERL_LIBRARY ) EXECUTE_PROCESS ( COMMAND ${PERL_EXECUTABLE} -MConfig -e "print \$Config{libperl}" OUTPUT_VARIABLE PERL_OUTPUT RESULT_VARIABLE PERL_RETURN_VALUE ) IF ( NOT PERL_RETURN_VALUE ) FIND_LIBRARY ( PERL_LIBRARY NAMES ${PERL_OUTPUT} PATHS ${PERL_INCLUDE_PATH} ) ENDIF ( NOT PERL_RETURN_VALUE ) ENDIF ( PERL_LIBRARY MATCHES .*-NOTFOUND OR NOT PERL_LIBRARY ) IF(PERL_LIBRARY MATCHES .*-NOTFOUND OR NOT PERL_LIBRARY OR PERL_INCLUDE_PATH MATCHES .*-NOTFOUND OR NOT PERL_INCLUDE_PATH) MESSAGE (STATUS "No Perl devel environment found - skipping Perl bindings") SET (DEFAULT_PERL OFF) ELSE() MESSAGE ( STATUS "Found PerlLibs: ${PERL_LIBRARY}" ) SET (DEFAULT_PERL ON) ENDIF() endif(NOT PERLLIBS_FOUND) qpid-proton-0.10/tools/cmake/Modules/FindNodePackages.cmake0000664000000000000000000000545612562450203020566 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # FindNodePackages # This module finds and installs (using npm) node.js packages that are used by # the JavaScript binding. The binding should still compile if these packages # cannot be installed but certain features might not work as described below. # # * The ws package is the WebSocket library used by emscripten when the target is # node.js, it isn't needed for applications hosted on a browser (where native # WebSockets will be used), but without it it won't work with node.js. # # * The jsdoc package is a JavaScript API document generator analogous to Doxygen # or JavaDoc, it is used by the docs target in the JavaScript binding. if (NOT NODE_PACKAGES_FOUND) # Check if the specified node.js package is already installed, if not install it. macro(InstallPackage varname name) execute_process( COMMAND npm list --local ${name} OUTPUT_VARIABLE check_package ) set(${varname} OFF) if (check_package MATCHES "${name}@.") message(STATUS "Found node.js package: ${name}") set(${varname} ON) else() message(STATUS "Installing node.js package: ${name}") execute_process( COMMAND npm install ${name} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_VARIABLE var ) if (var) message(STATUS "Installed node.js package: ${name}") set(${varname} ON) endif (var) endif() endmacro() # Check if ws WebSocket library https://github.com/websockets/ws is installed # N.B. something changed between ws 0.5.0 and 0.6.0 that breaks proton js # so explicitly pulling version 0.5.0 # TODO update javascript binding/emscripten/both to work with latest ws. InstallPackage("NODE_WS_FOUND" "ws@0.5.0") # Check if jsdoc3 API documentation generator https://github.com/jsdoc3/jsdoc is installed InstallPackage("NODE_JSDOC_FOUND" "jsdoc") set(NODE_PACKAGES_FOUND ON) endif (NOT NODE_PACKAGES_FOUND) qpid-proton-0.10/tools/cmake/Modules/FindJava.cmake0000664000000000000000000001776712562450203017133 0ustar # - Find Java # This module finds if Java is installed and determines where the # include files and libraries are. This code sets the following # variables: # # Java_JAVA_EXECUTABLE = the full path to the Java runtime # Java_JAVAC_EXECUTABLE = the full path to the Java compiler # Java_JAVAH_EXECUTABLE = the full path to the Java header generator # Java_JAVADOC_EXECUTABLE = the full path to the Java documention generator # Java_JAR_EXECUTABLE = the full path to the Java archiver # Java_VERSION_STRING = Version of the package found (java version), eg. 1.6.0_12 # Java_VERSION_MAJOR = The major version of the package found. # Java_VERSION_MINOR = The minor version of the package found. # Java_VERSION_PATCH = The patch version of the package found. # Java_VERSION_TWEAK = The tweak version of the package found (after '_') # Java_VERSION = This is set to: $major.$minor.$patch(.$tweak) # # The minimum required version of Java can be specified using the # standard CMake syntax, e.g. find_package(Java 1.5) # # NOTE: ${Java_VERSION} and ${Java_VERSION_STRING} are not guaranteed to be # identical. For example some java version may return: # Java_VERSION_STRING = 1.5.0_17 # and # Java_VERSION = 1.5.0.17 # # another example is the Java OEM, with: # Java_VERSION_STRING = 1.6.0-oem # and # Java_VERSION = 1.6.0 # # For these components the following variables are set: # # Java_FOUND - TRUE if all components are found. # Java_INCLUDE_DIRS - Full paths to all include dirs. # Java_LIBRARIES - Full paths to all libraries. # Java__FOUND - TRUE if is found. # # Example Usages: # find_package(Java) # find_package(Java COMPONENTS Runtime) # find_package(Java COMPONENTS Development) # #============================================================================= # Copyright 2002-2009 Kitware, Inc. # Copyright 2009-2011 Mathieu Malaterre # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) # The HINTS option should only be used for values computed from the system. set(_JAVA_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\2.0;JavaHome]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/bin" $ENV{JAVA_HOME}/bin ) # Hard-coded guesses should still go in PATHS. This ensures that the user # environment can always override hard guesses. set(_JAVA_PATHS /usr/lib/java/bin /usr/share/java/bin /usr/local/java/bin /usr/local/java/share/bin /usr/java/j2sdk1.4.2_04 /usr/lib/j2sdk1.4-sun/bin /usr/java/j2sdk1.4.2_09/bin /usr/lib/j2sdk1.5-sun/bin /opt/sun-jdk-1.5.0.04/bin ) find_program(Java_JAVA_EXECUTABLE NAMES java HINTS ${_JAVA_HINTS} PATHS ${_JAVA_PATHS} ) if(Java_JAVA_EXECUTABLE) execute_process(COMMAND ${Java_JAVA_EXECUTABLE} -version RESULT_VARIABLE res OUTPUT_VARIABLE var ERROR_VARIABLE var # sun-java output to stderr OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE) if( res ) if(${Java_FIND_REQUIRED}) message( FATAL_ERROR "Error executing java -version" ) else() message( STATUS "Warning, could not run java --version") endif() else() # extract major/minor version and patch level from "java -version" output # Tested on linux using # 1. Sun / Sun OEM # 2. OpenJDK 1.6 # 3. GCJ 1.5 # 4. Kaffe 1.4.2 if(var MATCHES "(java|openjdk) version \"[0-9]+\\.[0-9]+\\.[0-9_.]+.*\".*") # This is most likely Sun / OpenJDK, or maybe GCJ-java compat layer string( REGEX REPLACE ".* version \"([0-9]+\\.[0-9]+\\.[0-9_.]+.*)\".*" "\\1" Java_VERSION_STRING "${var}" ) elseif(var MATCHES "java full version \"kaffe-[0-9]+\\.[0-9]+\\.[0-9_]+\".*") # Kaffe style string( REGEX REPLACE "java full version \"kaffe-([0-9]+\\.[0-9]+\\.[0-9_]+).*" "\\1" Java_VERSION_STRING "${var}" ) else() if(NOT Java_FIND_QUIETLY) message(WARNING "regex not supported: ${var}. Please report") endif() endif() string( REGEX REPLACE "([0-9]+).*" "\\1" Java_VERSION_MAJOR "${Java_VERSION_STRING}" ) string( REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" Java_VERSION_MINOR "${Java_VERSION_STRING}" ) string( REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" Java_VERSION_PATCH "${Java_VERSION_STRING}" ) # warning tweak version can be empty: string( REGEX REPLACE "[0-9]+\\.[0-9]+\\.[0-9]+[_\\.]?([0-9]*).*$" "\\1" Java_VERSION_TWEAK "${Java_VERSION_STRING}" ) if( Java_VERSION_TWEAK STREQUAL "" ) # check case where tweak is not defined set(Java_VERSION ${Java_VERSION_MAJOR}.${Java_VERSION_MINOR}.${Java_VERSION_PATCH}) else() set(Java_VERSION ${Java_VERSION_MAJOR}.${Java_VERSION_MINOR}.${Java_VERSION_PATCH}.${Java_VERSION_TWEAK}) endif() endif() endif() find_program(Java_JAR_EXECUTABLE NAMES jar HINTS ${_JAVA_HINTS} PATHS ${_JAVA_PATHS} ) find_program(Java_JAVAC_EXECUTABLE NAMES javac HINTS ${_JAVA_HINTS} PATHS ${_JAVA_PATHS} ) find_program(Java_JAVAH_EXECUTABLE NAMES javah HINTS ${_JAVA_HINTS} PATHS ${_JAVA_PATHS} ) find_program(Java_JAVADOC_EXECUTABLE NAMES javadoc HINTS ${_JAVA_HINTS} PATHS ${_JAVA_PATHS} ) #include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) include(FindPackageHandleStandardArgs) if(Java_FIND_COMPONENTS) # Apache Qpid Proton doesn't support this because of find_package_handle_standard_args # differences (see comment below) message(FATAL_ERROR "Apache Qpid Proton FindJava does not support Java_FIND_COMPONENTS") foreach(component ${Java_FIND_COMPONENTS}) # User just want to execute some Java byte-compiled if(component STREQUAL "Runtime") find_package_handle_standard_args(Java REQUIRED_VARS Java_JAVA_EXECUTABLE VERSION_VAR Java_VERSION ) elseif(component STREQUAL "Development") find_package_handle_standard_args(Java REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE VERSION_VAR Java_VERSION ) else() message(FATAL_ERROR "Comp: ${component} is not handled") endif() set(Java_${component}_FOUND TRUE) endforeach() else() # Check for everything # Apache Qpid Proton local change: the line below has been tweaked because # the signature of find_package_handle_standard_args in cmake 2.6 lacks the # REQUIRED_VARS and VERSION_VAR parameters, and specifies the error message differently. find_package_handle_standard_args(Java DEFAULT_MSG Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE ) endif() mark_as_advanced( Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE ) # LEGACY set(JAVA_RUNTIME ${Java_JAVA_EXECUTABLE}) set(JAVA_ARCHIVE ${Java_JAR_EXECUTABLE}) set(JAVA_COMPILE ${Java_JAVAC_EXECUTABLE}) qpid-proton-0.10/tools/cmake/Modules/FindEmscripten.cmake0000664000000000000000000000327612562450203020351 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # FindEmscripten # This module checks if Emscripten and its prerequisites are installed and if so # sets EMSCRIPTEN_FOUND Emscripten (https://github.com/kripken/emscripten) is a # C/C++ to JavaScript cross-compiler used to generate the JavaScript bindings. if (NOT EMSCRIPTEN_FOUND) # First check that Node.js is installed as that is needed by Emscripten. find_program(NODE node) if (NOT NODE) message(STATUS "Node.js (http://nodejs.org) is not installed: can't build JavaScript binding") else (NOT NODE) # Check that the Emscripten C/C++ to JavaScript cross-compiler is installed. find_program(EMCC emcc) if (NOT EMCC) message(STATUS "Emscripten (https://github.com/kripken/emscripten) is not installed: can't build JavaScript binding") else (NOT EMCC) set(EMSCRIPTEN_FOUND ON) endif (NOT EMCC) endif (NOT NODE) endif (NOT EMSCRIPTEN_FOUND) qpid-proton-0.10/tests/0000775000000000000000000000000012562450203011737 5ustar qpid-proton-0.10/tests/tools/0000775000000000000000000000000012562450203013077 5ustar qpid-proton-0.10/tests/tools/soak-check0000775000000000000000000001130512562450203015035 0ustar #!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from __future__ import print_function import sys, optparse from subprocess import Popen,PIPE def run_test(cmd): try: process = Popen(cmd) except OSError: assert False, "Unable to execute command '%s', is it in your PATH?" % cmd[0] return process.wait() def main(argv=None): """ Run a subset of the Proton tests for an extended period of time. """ # tests is a list of test configurations. Each configuration is # represented as a two-element tuple. Tuple[0] is the pattern passed to # proton-test that identifies the test case. Tuple[1] is a list of maps. # Each map contains the parameters for one test. A test (of 'pattern') is # executed for each map in Tuple[1] parser = optparse.OptionParser() parser.add_option("-i", "--iterations", action="store", type="int", default=1, help="# of times to repeat each test.") parser.add_option("-v", "--verbose", action="store_true", help="print extra detail to stdout") opts, extra = parser.parse_args(args=argv) iterations = opts.iterations verbose = opts.verbose tests = [ ("proton_tests.soak.MessengerTests.test_oneway_*", # 104,297 * 7 = 730,079 msgs transferred per iteration [{ "iterations": iterations, "send_count": 104297, "target_count": 7 }]), ("proton_tests.soak.MessengerTests.test_echo_*", # 102,811 * 5 * 2 (send+reply) = 1,028,110 msgs transferred per iteration [{"iterations": iterations, "send_count": 102811, "target_count": 5, "send_batch": 3187}]), ("proton_tests.soak.MessengerTests.test_relay_*", # 102,197 * 4 * 3 (send+reply+forward)= 1,226,364 msgs transferred per iteration [{"iterations": iterations, "send_count": 102197, "target_count": 4, "send_batch": 829, "forward_count": 7}]), ("proton_tests.soak.MessengerTests.test_star_topology_*", # 2 ports * 3 senders = 6 connections per iteration # 6 connections * 7 targets = 42 links per iteration # 42 links * 35419 msg * 2 (send/reply) = 2,975,196 msgs per iteration [{"iterations": iterations, "port_count": 2, "sender_count": 3, "target_count": 7, "send_count": 35419, "send_batch": 311}]), # # Scale up the number of connections and links # ("proton_tests.soak.MessengerTests.test_star_topology_C", # 10 ports * 10 senders = 100 connections per iteration # 100 connections * 11 targets = 1100 links per iteration # 1100 links * 311 msg * 2 (send/reply) = 684,200 msgs per iteration [{"iterations": iterations, "port_count": 10, "sender_count": 10, "target_count": 11, "send_count": 311, "send_batch": 3}]), ("proton_tests.soak.MessengerTests.test_star_topology_C_SSL", # 10 ports * 10 senders = 100 connections per iteration # 100 connections * 11 targets = 1100 links per iteration # 1100 links * 30 msg * 2 (send/reply) = 66000 msgs per iteration [{"iterations": iterations, "port_count": 10, "sender_count": 10, "target_count": 11, "send_count": 30, "send_batch": 3}]) ] for test in tests: pattern = test[0] param_list = test[1] for test_params in param_list: command = ["proton-test"] for (k, v) in test_params.iteritems(): command.append( "-D%s=%s" % (k,v) ) if verbose: command.append( "-Dverbose" ) command.append( pattern ) if verbose: print("command='%s'" % str(command)) run_test(command) return 0 if __name__ == "__main__": sys.exit(main()) qpid-proton-0.10/tests/tools/apps/0000775000000000000000000000000012562450203014042 5ustar qpid-proton-0.10/tests/tools/apps/python/0000775000000000000000000000000012562450203015363 5ustar qpid-proton-0.10/tests/tools/apps/python/msgr-send.py0000775000000000000000000001554412562450203017650 0ustar #!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from __future__ import print_function import sys, optparse, time import logging from proton import * # Hi python3! try: long() except: long = int usage = """ Usage: msgr-send [OPTIONS] -a [,]* \tThe target address [amqp[s]://domain[/name]] -c # \tNumber of messages to send before exiting [0=forever] -b # \tSize of message body in bytes [1024] -p # \tSend batches of # messages (wait for replies before sending next batch if -R) [1024] -w # \t# outgoing window size [0] -e # \t# seconds to report statistics, 0 = end of test [0] -R \tWait for a reply to each sent message -t # \tInactivity timeout in seconds, -1 = no timeout [-1] -W # \tIncoming window size [0] -B # \tArgument to Messenger::recv(n) [-1] -N \tSet the container name to -V \tEnable debug logging""" def parse_options( argv ): parser = optparse.OptionParser(usage=usage) parser.add_option("-a", dest="targets", action="append", type="string") parser.add_option("-c", dest="msg_count", type="int", default=0) parser.add_option("-b", dest="msg_size", type="int", default=1024) parser.add_option("-p", dest="send_batch", type="int", default=1024) parser.add_option("-w", dest="outgoing_window", type="int") parser.add_option("-e", dest="report_interval", type="int", default=0) parser.add_option("-R", dest="get_replies", action="store_true") parser.add_option("-t", dest="timeout", type="int", default=-1) parser.add_option("-W", dest="incoming_window", type="int") parser.add_option("-B", dest="recv_count", type="int", default=-1) parser.add_option("-N", dest="name", type="string") parser.add_option("-V", dest="verbose", action="store_true") return parser.parse_args(args=argv) class Statistics(object): def __init__(self): self.start_time = 0.0 self.latency_samples = 0 self.latency_total = 0.0 self.latency_min = None self.latency_max = None def start(self): self.start_time = time.time() def msg_received(self, msg): ts = msg.creation_time if ts: l = long(time.time() * 1000) - ts if l > 0.0: self.latency_total += l self.latency_samples += 1 if self.latency_samples == 1: self.latency_min = self.latency_max = l else: if self.latency_min > l: self.latency_min = l if self.latency_max < l: self.latency_max = l def report(self, sent, received): secs = time.time() - self.start_time print("Messages sent: %d recv: %d" % (sent, received) ) print("Total time: %f sec" % secs ) if secs: print("Throughput: %f msgs/sec" % (sent/secs) ) if self.latency_samples: print("Latency (sec): %f min %f max %f avg" % (self.latency_min/1000.0, self.latency_max/1000.0, (self.latency_total/self.latency_samples)/1000.0)) def process_replies( messenger, message, stats, max_count, log): """ Return the # of reply messages received """ received = 0 log.debug("Calling pn_messenger_recv(%d)", max_count) messenger.recv( max_count ) log.debug("Messages on incoming queue: %d", messenger.incoming) while messenger.incoming > 0: messenger.get( message ) received += 1 # TODO: header decoding? stats.msg_received( message ) # uint64_t id = pn_message_get_correlation_id( message ).u.as_ulong; return received def main(argv=None): opts = parse_options(argv)[0] if opts.targets is None: opts.targets = ["amqp://0.0.0.0"] stats = Statistics() sent = 0 received = 0 target_index = 0 log = logging.getLogger("msgr-send") log.addHandler(logging.StreamHandler()) if opts.verbose: log.setLevel(logging.DEBUG) else: log.setLevel(logging.INFO) message = Message() message.reply_to = "~" message.body = "X" * opts.msg_size reply_message = Message() messenger = Messenger( opts.name ) if opts.outgoing_window is not None: messenger.outgoing_window = opts.outgoing_window if opts.timeout > 0: opts.timeout *= 1000 messenger.timeout = opts.timeout messenger.start() # unpack targets that were specified using comma-separated list # targets = [] for x in opts.targets: z = x.split(",") for y in z: if y: targets.append(y) stats.start() while opts.msg_count == 0 or sent < opts.msg_count: # send a message message.address = targets[target_index] if target_index == len(targets) - 1: target_index = 0 else: target_index += 1 message.correlation_id = sent message.creation_time = long(time.time() * 1000) messenger.put( message ) sent += 1 if opts.send_batch and (messenger.outgoing >= opts.send_batch): if opts.get_replies: while received < sent: # this will also transmit any pending sent messages received += process_replies( messenger, reply_message, stats, opts.recv_count, log ) else: log.debug("Calling pn_messenger_send()") messenger.send() log.debug("Messages received=%d sent=%d", received, sent) if opts.get_replies: # wait for the last of the replies while received < sent: count = process_replies( messenger, reply_message, stats, opts.recv_count, log ) received += count log.debug("Messages received=%d sent=%d", received, sent) elif messenger.outgoing > 0: log.debug("Calling pn_messenger_send()") messenger.send() messenger.stop() stats.report( sent, received ) return 0 if __name__ == "__main__": sys.exit(main()) qpid-proton-0.10/tests/tools/apps/python/msgr-recv.py0000775000000000000000000001577312562450203017662 0ustar #!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from __future__ import print_function import sys, optparse, time import logging from proton import * # Hi python3! try: long() except: long = int usage = """ Usage: msgr-recv [OPTIONS] -a [,]* \tAddresses to listen on [amqp://~0.0.0.0] -c # \tNumber of messages to receive before exiting [0=forever] -b # \tArgument to Messenger::recv(n) [2048] -w # \tSize for incoming window [0] -t # \tInactivity timeout in seconds, -1 = no timeout [-1] -e # \t# seconds to report statistics, 0 = end of test [0] *TBD* -R \tSend reply if 'reply-to' present -W # \t# outgoing window size [0] -F [,]* \tAddresses used for forwarding received messages -N \tSet the container name to -X \tPrint '\\n' to stdout after all subscriptions are created -V \tEnable debug logging""" def parse_options( argv ): parser = optparse.OptionParser(usage=usage) parser.add_option("-a", dest="subscriptions", action="append", type="string") parser.add_option("-c", dest="msg_count", type="int", default=0) parser.add_option("-b", dest="recv_count", type="int", default=-1) parser.add_option("-w", dest="incoming_window", type="int") parser.add_option("-t", dest="timeout", type="int", default=-1) parser.add_option("-e", dest="report_interval", type="int", default=0) parser.add_option("-R", dest="reply", action="store_true") parser.add_option("-W", dest="outgoing_window", type="int") parser.add_option("-F", dest="forwarding_targets", action="append", type="string") parser.add_option("-N", dest="name", type="string") parser.add_option("-X", dest="ready_text", type="string") parser.add_option("-V", dest="verbose", action="store_true") return parser.parse_args(args=argv) class Statistics(object): def __init__(self): self.start_time = 0.0 self.latency_samples = 0 self.latency_total = 0.0 self.latency_min = None self.latency_max = None def start(self): self.start_time = time.time() def msg_received(self, msg): ts = msg.creation_time if ts: l = long(time.time() * 1000) - ts if l > 0.0: self.latency_total += l self.latency_samples += 1 if self.latency_samples == 1: self.latency_min = self.latency_max = l else: if self.latency_min > l: self.latency_min = l if self.latency_max < l: self.latency_max = l def report(self, sent, received): secs = time.time() - self.start_time print("Messages sent: %d recv: %d" % (sent, received) ) print("Total time: %f sec" % secs ) if secs: print("Throughput: %f msgs/sec" % (sent/secs) ) if self.latency_samples: print("Latency (sec): %f min %f max %f avg" % (self.latency_min/1000.0, self.latency_max/1000.0, (self.latency_total/self.latency_samples)/1000.0)) def main(argv=None): opts = parse_options(argv)[0] if opts.subscriptions is None: opts.subscriptions = ["amqp://~0.0.0.0"] stats = Statistics() sent = 0 received = 0 forwarding_index = 0 log = logging.getLogger("msgr-recv") log.addHandler(logging.StreamHandler()) if opts.verbose: log.setLevel(logging.DEBUG) else: log.setLevel(logging.INFO) message = Message() messenger = Messenger( opts.name ) if opts.incoming_window is not None: messenger.incoming_window = opts.incoming_window if opts.timeout > 0: opts.timeout *= 1000 messenger.timeout = opts.timeout messenger.start() # unpack addresses that were specified using comma-separated list for x in opts.subscriptions: z = x.split(",") for y in z: if y: log.debug("Subscribing to %s", y) messenger.subscribe(y) forwarding_targets = [] if opts.forwarding_targets: for x in opts.forwarding_targets: z = x.split(",") for y in z: if y: forwarding_targets.append(y) # hack to let test scripts know when the receivers are ready (so that the # senders may be started) if opts.ready_text: print("%s" % opts.ready_text) sys.stdout.flush() while opts.msg_count == 0 or received < opts.msg_count: log.debug("Calling pn_messenger_recv(%d)", opts.recv_count) rc = messenger.recv(opts.recv_count) # start the timer only after receiving the first msg if received == 0: stats.start() log.debug("Messages on incoming queue: %d", messenger.incoming) while messenger.incoming > 0: messenger.get(message) received += 1 # TODO: header decoding? # uint64_t id = pn_message_get_correlation_id( message ).u.as_ulong; stats.msg_received( message ) if opts.reply: if message.reply_to: log.debug("Replying to: %s", message.reply_to ) message.address = message.reply_to message.creation_time = long(time.time() * 1000) messenger.put( message ) sent += 1 if forwarding_targets: forward_addr = forwarding_targets[forwarding_index] forwarding_index += 1 if forwarding_index == len(forwarding_targets): forwarding_index = 0 log.debug("Forwarding to: %s", forward_addr ) message.address = forward_addr message.reply_to = None message.creation_time = long(time.time() * 1000) messenger.put( message ) sent += 1 log.debug("Messages received=%lu sent=%lu", received, sent) # this will flush any pending sends if messenger.outgoing > 0: log.debug("Calling pn_messenger_send()") messenger.send() messenger.stop() stats.report( sent, received ) return 0 if __name__ == "__main__": sys.exit(main()) qpid-proton-0.10/tests/tools/apps/c/0000775000000000000000000000000012562450203014264 5ustar qpid-proton-0.10/tests/tools/apps/c/reactor-send.c0000664000000000000000000003036412562450203017024 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /* * Implements a subset of msgr-send.c using reactor events. */ #include "proton/message.h" #include "proton/error.h" #include "proton/types.h" #include "proton/reactor.h" #include "proton/handlers.h" #include "proton/engine.h" #include "proton/url.h" #include "msgr-common.h" #include #include #include #include typedef struct { Addresses_t targets; uint64_t msg_count; uint32_t msg_size; // of body uint32_t send_batch; int outgoing_window; unsigned int report_interval; // in seconds //Addresses_t subscriptions; //Addresses_t reply_tos; int get_replies; int timeout; // in seconds int incoming_window; int recv_count; const char *name; char *certificate; char *privatekey; // used to sign certificate char *password; // for private key file char *ca_db; // trusted CA database } Options_t; static void usage(int rc) { printf("Usage: reactor-send [OPTIONS] \n" " -a \tThe target address [amqp[s]://domain[/name]]\n" " -c # \tNumber of messages to send before exiting [0=forever]\n" " -b # \tSize of message body in bytes [1024]\n" " -R \tWait for a reply to each sent message\n" " -V \tEnable debug logging\n" ); exit(rc); } typedef struct { Options_t *opts; Statistics_t *stats; uint64_t sent; uint64_t received; pn_message_t *message; pn_message_t *reply_message; pn_atom_t id; char *encoded_data; size_t encoded_data_size; pn_url_t *send_url; pn_string_t *hostname; pn_string_t *container_id; } sender_context_t; void sender_context_init(sender_context_t *sc, Options_t *opts, Statistics_t *stats) { sc->opts = opts; sc->stats = stats; sc->sent = 0; sc->received = 0; sc->id.type = PN_ULONG; sc->reply_message = 0; // 4096 extra bytes should easily cover the message metadata sc->encoded_data_size = sc->opts->msg_size + 4096; sc->encoded_data = (char *)calloc(1, sc->encoded_data_size); check(sc->encoded_data, "failed to allocate encoding buffer"); sc->container_id = pn_string("reactor-send"); // prefer uuid-like name sc->reply_message = (sc->opts->get_replies) ? pn_message() : 0; sc->message = pn_message(); check(sc->message, "failed to allocate a message"); pn_string_t *rpto = pn_string("amqp://"); pn_string_addf(rpto, "%s", pn_string_get(sc->container_id)); pn_message_set_reply_to(sc->message, pn_string_get(rpto)); pn_free(rpto); pn_data_t *body = pn_message_body(sc->message); // borrow the encoding buffer this one time char *data = sc->encoded_data; pn_data_put_binary(body, pn_bytes(sc->opts->msg_size, data)); check(sc->opts->targets.count > 0, "no specified address"); sc->send_url = pn_url_parse(sc->opts->targets.addresses[0]); const char *host = pn_url_get_host(sc->send_url); const char *port = pn_url_get_port(sc->send_url); sc->hostname = pn_string(host); if (port && strlen(port)) pn_string_addf(sc->hostname, ":%s", port); } sender_context_t *sender_context(pn_handler_t *h) { return (sender_context_t *) pn_handler_mem(h); } void sender_cleanup(pn_handler_t *h) { sender_context_t *sc = sender_context(h); pn_message_free(sc->message); pn_message_free(sc->reply_message); pn_url_free(sc->send_url); pn_free(sc->hostname); pn_free(sc->container_id); free(sc->encoded_data); } pn_handler_t *replyto_handler(sender_context_t *sc); void sender_dispatch(pn_handler_t *h, pn_event_t *event, pn_event_type_t type) { sender_context_t *sc = sender_context(h); switch (type) { case PN_CONNECTION_INIT: { pn_connection_t *conn = pn_event_connection(event); pn_connection_set_container(conn, pn_string_get(sc->container_id)); pn_connection_set_hostname(conn, pn_string_get(sc->hostname)); pn_connection_open(conn); pn_session_t *ssn = pn_session(conn); pn_session_open(ssn); pn_link_t *snd = pn_sender(ssn, "sender"); const char *path = pn_url_get_path(sc->send_url); if (path && strlen(path)) { pn_terminus_set_address(pn_link_target(snd), path); pn_terminus_set_address(pn_link_source(snd), path); } pn_link_open(snd); } break; case PN_LINK_FLOW: { pn_link_t *snd = pn_event_link(event); while (pn_link_credit(snd) > 0 && sc->sent < sc->opts->msg_count) { if (sc->sent == 0) statistics_start(sc->stats); char tag[8]; void *ptr = &tag; *((uint64_t *) ptr) = sc->sent; pn_delivery_t *dlv = pn_delivery(snd, pn_dtag(tag, 8)); // setup the message to send pn_message_t *msg = sc->message; pn_message_set_address(msg, sc->opts->targets.addresses[0]); sc->id.u.as_ulong = sc->sent; pn_message_set_correlation_id(msg, sc->id); pn_message_set_creation_time(msg, msgr_now()); size_t size = sc->encoded_data_size; int err = pn_message_encode(msg, sc->encoded_data, &size); check(err == 0, "message encoding error"); pn_link_send(snd, sc->encoded_data, size); pn_delivery_settle(dlv); sc->sent++; } if (sc->sent == sc->opts->msg_count && !sc->opts->get_replies) { pn_link_close(snd); pn_connection_t *conn = pn_event_connection(event); pn_connection_close(conn); } } break; case PN_LINK_INIT: { pn_link_t *link = pn_event_link(event); if (pn_link_is_receiver(link)) { // Response messages link. Could manage credit and deliveries in this handler but // a dedicated handler also works. pn_handler_t *replyto = replyto_handler(sc); pn_flowcontroller_t *fc = pn_flowcontroller(1024); pn_handler_add(replyto, fc); pn_decref(fc); pn_handshaker_t *handshaker = pn_handshaker(); pn_handler_add(replyto, handshaker); pn_decref(handshaker); pn_record_t *record = pn_link_attachments(link); pn_record_set_handler(record, replyto); pn_decref(replyto); } } break; case PN_CONNECTION_LOCAL_CLOSE: { statistics_report(sc->stats, sc->sent, sc->received); } break; default: break; } } pn_handler_t *sender_handler(Options_t *opts, Statistics_t *stats) { pn_handler_t *h = pn_handler_new(sender_dispatch, sizeof(sender_context_t), sender_cleanup); sender_context_t *sc = sender_context(h); sender_context_init(sc, opts, stats); return h; } sender_context_t *replyto_sender_context(pn_handler_t *h) { sender_context_t **p = (sender_context_t **) pn_handler_mem(h); return *p; } void replyto_cleanup(pn_handler_t *h) {} void replyto_dispatch(pn_handler_t *h, pn_event_t *event, pn_event_type_t type) { sender_context_t *sc = replyto_sender_context(h); switch (type) { case PN_DELIVERY: { check(sc->opts->get_replies, "Unexpected reply message"); pn_link_t *recv_link = pn_event_link(event); pn_delivery_t *dlv = pn_event_delivery(event); if (pn_link_is_receiver(recv_link) && !pn_delivery_partial(dlv)) { size_t encoded_size = pn_delivery_pending(dlv); check(encoded_size <= sc->encoded_data_size, "decoding buffer too small"); ssize_t n = pn_link_recv(recv_link, sc->encoded_data, encoded_size); check(n == (ssize_t)encoded_size, "read fail on reply link"); pn_message_t *msg = sc->reply_message; int err = pn_message_decode(msg, sc->encoded_data, n); check(err == 0, "message decode error"); statistics_msg_received(sc->stats, msg); sc->received++; pn_delivery_settle(dlv); } if (sc->received == sc->opts->msg_count) { pn_link_close(recv_link); pn_connection_t *conn = pn_event_connection(event); pn_connection_close(conn); } } break; default: break; } } pn_handler_t *replyto_handler(sender_context_t *sc) { pn_handler_t *h = pn_handler_new(replyto_dispatch, sizeof(sender_context_t *), replyto_cleanup); sender_context_t **p = (sender_context_t **) pn_handler_mem(h); *p = sc; return h; } static void parse_options( int argc, char **argv, Options_t *opts ) { int c; opterr = 0; memset( opts, 0, sizeof(*opts) ); opts->msg_size = 1024; opts->send_batch = 1024; opts->timeout = -1; opts->recv_count = -1; addresses_init(&opts->targets); while ((c = getopt(argc, argv, "a:c:b:p:w:e:l:Rt:W:B:VN:T:C:K:P:")) != -1) { switch(c) { case 'a': { // TODO: multiple addresses? To keep tests happy, accept multiple for now, // but ignore all but the first. addresses_merge( &opts->targets, optarg ); } break; case 'c': if (sscanf( optarg, "%" SCNu64, &opts->msg_count ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'b': if (sscanf( optarg, "%u", &opts->msg_size ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'p': if (sscanf( optarg, "%u", &opts->send_batch ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'w': if (sscanf( optarg, "%d", &opts->outgoing_window ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'e': if (sscanf( optarg, "%u", &opts->report_interval ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'R': opts->get_replies = 1; break; case 't': if (sscanf( optarg, "%d", &opts->timeout ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } if (opts->timeout > 0) opts->timeout *= 1000; break; case 'W': if (sscanf( optarg, "%d", &opts->incoming_window ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'B': if (sscanf( optarg, "%d", &opts->recv_count ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'V': enable_logging(); break; case 'N': opts->name = optarg; break; case 'T': opts->ca_db = optarg; break; case 'C': opts->certificate = optarg; break; case 'K': opts->privatekey = optarg; break; case 'P': parse_password( optarg, &opts->password ); break; default: usage(1); } } // default target if none specified if (opts->targets.count == 0) addresses_add( &opts->targets, "amqp://0.0.0.0" ); } int main(int argc, char** argv) { Options_t opts; Statistics_t stats; parse_options( argc, argv, &opts ); pn_reactor_t *reactor = pn_reactor(); pn_handler_t *sh = sender_handler(&opts, &stats); pn_handler_add(sh, pn_handshaker()); pn_reactor_connection(reactor, sh); pn_reactor_run(reactor); pn_reactor_free(reactor); pn_handler_free(sh); addresses_free(&opts.targets); return 0; } qpid-proton-0.10/tests/tools/apps/c/reactor-recv.c0000664000000000000000000003324712562450203017035 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /* * Implements a subset of msgr-recv.c using reactor events. */ #include "proton/message.h" #include "proton/error.h" #include "proton/types.h" #include "proton/reactor.h" #include "proton/handlers.h" #include "proton/engine.h" #include "proton/url.h" #include "msgr-common.h" #include #include #include #include // The exact struct from msgr-recv, mostly fallow. typedef struct { Addresses_t subscriptions; uint64_t msg_count; int recv_count; int incoming_window; int timeout; // seconds unsigned int report_interval; // in seconds int outgoing_window; int reply; const char *name; const char *ready_text; char *certificate; char *privatekey; // used to sign certificate char *password; // for private key file char *ca_db; // trusted CA database } Options_t; static void usage(int rc) { printf("Usage: reactor-recv [OPTIONS] \n" " -c # \tNumber of messages to receive before exiting [0=forever]\n" " -R \tSend reply if 'reply-to' present\n" " -t # \tInactivity timeout in seconds, -1 = no timeout [-1]\n" " -X \tPrint '\\n' to stdout after all subscriptions are created\n" ); exit(rc); } // Global context for this process typedef struct { Options_t *opts; Statistics_t *stats; uint64_t sent; uint64_t received; pn_message_t *message; pn_acceptor_t *acceptor; char *encoded_data; size_t encoded_data_size; int connections; pn_list_t *active_connections; bool shutting_down; pn_handler_t *listener_handler; int quiesce_count; } global_context_t; // Per connection context typedef struct { global_context_t *global; int connection_id; pn_link_t *recv_link; pn_link_t *reply_link; } connection_context_t; static char *ensure_buffer(char *buf, size_t needed, size_t *actual) { char* new_buf; // Make room for the largest message seen so far, plus extra for slight changes in metadata content if (needed + 1024 <= *actual) return buf; needed += 2048; new_buf = (char *) realloc(buf, needed); if (new_buf != NULL) { buf = new_buf; *actual = buf ? needed : 0; } return buf; } void global_shutdown(global_context_t *gc) { if (gc->shutting_down) return; gc->shutting_down = true; pn_acceptor_close(gc->acceptor); size_t n = pn_list_size(gc->active_connections); for (size_t i = 0; i < n; i++) { pn_connection_t *conn = (pn_connection_t *) pn_list_get(gc->active_connections, i); if (!(pn_connection_state(conn) & PN_LOCAL_CLOSED)) { pn_connection_close(conn); } } } connection_context_t *connection_context(pn_handler_t *h) { connection_context_t *p = (connection_context_t *) pn_handler_mem(h); return p; } void connection_context_init(connection_context_t *cc, global_context_t *gc) { cc->global = gc; pn_incref(gc->listener_handler); cc->connection_id = gc->connections++; cc->recv_link = 0; cc->reply_link = 0; } void connection_cleanup(pn_handler_t *h) { connection_context_t *cc = connection_context(h); // Undo pn_incref() from connection_context_init() pn_decref(cc->global->listener_handler); } void connection_dispatch(pn_handler_t *h, pn_event_t *event, pn_event_type_t type) { connection_context_t *cc = connection_context(h); bool replying = cc->global->opts->reply; switch (type) { case PN_LINK_REMOTE_OPEN: { pn_link_t *link = pn_event_link(event); if (pn_link_is_receiver(link)) { check(cc->recv_link == NULL, "Multiple incomming links on one connection"); cc->recv_link = link; pn_connection_t *conn = pn_event_connection(event); pn_list_add(cc->global->active_connections, conn); if (cc->global->shutting_down) { pn_connection_close(conn); break; } if (replying) { // Set up a reply link and defer granting credit to the incoming link pn_connection_t *conn = pn_session_connection(pn_link_session(link)); pn_session_t *ssn = pn_session(conn); pn_session_open(ssn); char name[100]; // prefer a multiplatform uuid generator sprintf(name, "reply_sender_%d", cc->connection_id); cc->reply_link = pn_sender(ssn, name); pn_link_open(cc->reply_link); } else { pn_flowcontroller_t *fc = pn_flowcontroller(1024); pn_handler_add(h, fc); pn_decref(fc); } } } break; case PN_LINK_FLOW: { if (replying) { pn_link_t *reply_link = pn_event_link(event); // pn_flowcontroller handles the non-reply case check(reply_link == cc->reply_link, "internal error"); // Grant the sender as much credit as just given to us for replies int delta = pn_link_credit(reply_link) - pn_link_credit(cc->recv_link); if (delta > 0) pn_link_flow(cc->recv_link, delta); } } break; case PN_DELIVERY: { pn_link_t *recv_link = pn_event_link(event); pn_delivery_t *dlv = pn_event_delivery(event); if (pn_link_is_receiver(recv_link) && !pn_delivery_partial(dlv)) { if (cc->global->received == 0) statistics_start(cc->global->stats); size_t encoded_size = pn_delivery_pending(dlv); cc->global->encoded_data = ensure_buffer(cc->global->encoded_data, encoded_size, &cc->global->encoded_data_size); check(cc->global->encoded_data, "decoding buffer realloc failure"); ssize_t n = pn_link_recv(recv_link, cc->global->encoded_data, encoded_size); check(n == (ssize_t) encoded_size, "message data read fail"); pn_message_t *msg = cc->global->message; int err = pn_message_decode(msg, cc->global->encoded_data, n); check(err == 0, "message decode error"); cc->global->received++; pn_delivery_settle(dlv); statistics_msg_received(cc->global->stats, msg); if (replying) { const char *reply_addr = pn_message_get_reply_to(msg); if (reply_addr) { pn_link_t *rl = cc->reply_link; check(pn_link_credit(rl) > 0, "message received without corresponding reply credit"); LOG("Replying to: %s\n", reply_addr ); pn_message_set_address(msg, reply_addr); pn_message_set_creation_time(msg, msgr_now()); char tag[8]; void *ptr = &tag; *((uint64_t *) ptr) = cc->global->sent; pn_delivery_t *dlv = pn_delivery(rl, pn_dtag(tag, 8)); size_t size = cc->global->encoded_data_size; int err = pn_message_encode(msg, cc->global->encoded_data, &size); check(err == 0, "message encoding error"); pn_link_send(rl, cc->global->encoded_data, size); pn_delivery_settle(dlv); cc->global->sent++; } } } if (cc->global->received >= cc->global->opts->msg_count) { global_shutdown(cc->global); } } break; case PN_CONNECTION_UNBOUND: { pn_connection_t *conn = pn_event_connection(event); pn_list_remove(cc->global->active_connections, conn); pn_connection_release(conn); } break; default: break; } } pn_handler_t *connection_handler(global_context_t *gc) { pn_handler_t *h = pn_handler_new(connection_dispatch, sizeof(connection_context_t), connection_cleanup); connection_context_t *cc = connection_context(h); connection_context_init(cc, gc); return h; } void start_listener(global_context_t *gc, pn_reactor_t *reactor) { check(gc->opts->subscriptions.count > 0, "no listening address"); pn_url_t *listen_url = pn_url_parse(gc->opts->subscriptions.addresses[0]); const char *host = pn_url_get_host(listen_url); const char *port = pn_url_get_port(listen_url); if (port == 0 || strlen(port) == 0) port = "5672"; if (host == 0 || strlen(host) == 0) host = "0.0.0.0"; if (*host == '~') host++; gc->acceptor = pn_reactor_acceptor(reactor, host, port, NULL); check(gc->acceptor, "acceptor creation failed"); pn_url_free(listen_url); } void global_context_init(global_context_t *gc, Options_t *o, Statistics_t *s) { gc->opts = o; gc->stats = s; gc->sent = 0; gc->received = 0; gc->encoded_data_size = 0; gc->encoded_data = 0; gc->message = pn_message(); check(gc->message, "failed to allocate a message"); gc->connections = 0; gc->active_connections = pn_list(PN_OBJECT, 0); gc->acceptor = 0; gc->shutting_down = false; gc->listener_handler = 0; gc->quiesce_count = 0; } global_context_t *global_context(pn_handler_t *h) { return (global_context_t *) pn_handler_mem(h); } void listener_cleanup(pn_handler_t *h) { global_context_t *gc = global_context(h); pn_message_free(gc->message); free(gc->encoded_data); pn_free(gc->active_connections); } void listener_dispatch(pn_handler_t *h, pn_event_t *event, pn_event_type_t type) { global_context_t *gc = global_context(h); if (type == PN_REACTOR_QUIESCED) gc->quiesce_count++; else gc->quiesce_count = 0; switch (type) { case PN_CONNECTION_INIT: { pn_connection_t *connection = pn_event_connection(event); // New incoming connection on listener socket. Give each a separate handler. pn_handler_t *ch = connection_handler(gc); pn_handshaker_t *handshaker = pn_handshaker(); pn_handler_add(ch, handshaker); pn_decref(handshaker); pn_record_t *record = pn_connection_attachments(connection); pn_record_set_handler(record, ch); pn_decref(ch); } break; case PN_REACTOR_QUIESCED: { // Two quiesce in a row means we have been idle for a timout period if (gc->opts->timeout != -1 && gc->quiesce_count > 1) global_shutdown(gc); } break; case PN_REACTOR_INIT: { pn_reactor_t *reactor = pn_event_reactor(event); start_listener(gc, reactor); // hack to let test scripts know when the receivers are ready (so // that the senders may be started) if (gc->opts->ready_text) { fprintf(stdout, "%s\n", gc->opts->ready_text); fflush(stdout); } if (gc->opts->timeout != -1) pn_reactor_set_timeout(pn_event_reactor(event), gc->opts->timeout); } break; case PN_REACTOR_FINAL: { if (gc->received == 0) statistics_start(gc->stats); statistics_report(gc->stats, gc->sent, gc->received); } break; default: break; } } pn_handler_t *listener_handler(Options_t *opts, Statistics_t *stats) { pn_handler_t *h = pn_handler_new(listener_dispatch, sizeof(global_context_t), listener_cleanup); global_context_t *gc = global_context(h); global_context_init(gc, opts, stats); gc->listener_handler = h; return h; } static void parse_options( int argc, char **argv, Options_t *opts ) { int c; opterr = 0; memset( opts, 0, sizeof(*opts) ); opts->recv_count = -1; opts->timeout = -1; addresses_init( &opts->subscriptions); while ((c = getopt(argc, argv, "a:c:b:w:t:e:RW:F:VN:X:T:C:K:P:")) != -1) { switch (c) { case 'a': { // TODO: multiple addresses? char *comma = strchr(optarg, ','); check(comma == 0, "multiple addresses not implemented"); check(opts->subscriptions.count == 0, "multiple addresses not implemented"); addresses_merge( &opts->subscriptions, optarg ); } break; case 'c': if (sscanf( optarg, "%" SCNu64, &opts->msg_count ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 't': if (sscanf( optarg, "%d", &opts->timeout ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } if (opts->timeout > 0) opts->timeout *= 1000; break; case 'R': opts->reply = 1; break; case 'V': enable_logging(); break; case 'X': opts->ready_text = optarg; break; default: usage(1); } } if (opts->subscriptions.count == 0) addresses_add( &opts->subscriptions, "amqp://~0.0.0.0" ); } int main(int argc, char** argv) { Options_t opts; Statistics_t stats; parse_options( argc, argv, &opts ); pn_reactor_t *reactor = pn_reactor(); // set up default handlers for our reactor pn_handler_t *root = pn_reactor_get_handler(reactor); pn_handler_t *lh = listener_handler(&opts, &stats); pn_handler_add(root, lh); pn_handshaker_t *handshaker = pn_handshaker(); pn_handler_add(root, handshaker); // Omit decrefs else segfault. Not sure why they are necessary // to keep valgrind happy for the connection_handler, but not here. // pn_decref(handshaker); // pn_decref(lh); pn_reactor_run(reactor); pn_reactor_free(reactor); addresses_free( &opts.subscriptions ); return 0; } qpid-proton-0.10/tests/tools/apps/c/msgr-send.c0000664000000000000000000002611212562450203016331 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ #include "msgr-common.h" #include "proton/message.h" #include "proton/messenger.h" #include "proton/error.h" #include #include #include #include typedef struct { Addresses_t targets; uint64_t msg_count; uint32_t msg_size; // of body uint32_t send_batch; int outgoing_window; unsigned int report_interval; // in seconds //Addresses_t subscriptions; //Addresses_t reply_tos; int get_replies; int timeout; // in seconds int incoming_window; int recv_count; const char *name; char *certificate; char *privatekey; // used to sign certificate char *password; // for private key file char *ca_db; // trusted CA database } Options_t; static void usage(int rc) { printf("Usage: msgr-send [OPTIONS] \n" " -a [,]* \tThe target address [amqp[s]://domain[/name]]\n" " -c # \tNumber of messages to send before exiting [0=forever]\n" " -b # \tSize of message body in bytes [1024]\n" " -p # \tSend batches of # messages (wait for replies before sending next batch if -R) [1024]\n" " -w # \t# outgoing window size [0]\n" " -e # \t# seconds to report statistics, 0 = end of test [0]\n" " -R \tWait for a reply to each sent message\n" " -t # \tInactivity timeout in seconds, -1 = no timeout [-1]\n" " -W # \tIncoming window size [0]\n" " -B # \tArgument to Messenger::recv(n) [-1]\n" " -N \tSet the container name to \n" " -V \tEnable debug logging\n" " SSL options:\n" " -T \tDatabase of trusted CA certificates for validating peer\n" " -C \tFile containing self-identifying certificate\n" " -K \tFile containing private key used to sign certificate\n" " -P [pass:|path] \tPassword to unlock private key file.\n" ); //printf("-p \t*TODO* Add N sample properties to each message [3]\n"); exit(rc); } static void parse_options( int argc, char **argv, Options_t *opts ) { int c; opterr = 0; memset( opts, 0, sizeof(*opts) ); opts->msg_size = 1024; opts->send_batch = 1024; opts->timeout = -1; opts->recv_count = -1; addresses_init(&opts->targets); while ((c = getopt(argc, argv, "a:c:b:p:w:e:l:Rt:W:B:VN:T:C:K:P:")) != -1) { switch(c) { case 'a': addresses_merge( &opts->targets, optarg ); break; case 'c': if (sscanf( optarg, "%" SCNu64, &opts->msg_count ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'b': if (sscanf( optarg, "%u", &opts->msg_size ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'p': if (sscanf( optarg, "%u", &opts->send_batch ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'w': if (sscanf( optarg, "%d", &opts->outgoing_window ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'e': if (sscanf( optarg, "%u", &opts->report_interval ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'R': opts->get_replies = 1; break; case 't': if (sscanf( optarg, "%d", &opts->timeout ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } if (opts->timeout > 0) opts->timeout *= 1000; break; case 'W': if (sscanf( optarg, "%d", &opts->incoming_window ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'B': if (sscanf( optarg, "%d", &opts->recv_count ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'V': enable_logging(); break; case 'N': opts->name = optarg; break; case 'T': opts->ca_db = optarg; break; case 'C': opts->certificate = optarg; break; case 'K': opts->privatekey = optarg; break; case 'P': parse_password( optarg, &opts->password ); break; default: usage(1); } } // default target if none specified if (opts->targets.count == 0) addresses_add( &opts->targets, "amqp://0.0.0.0" ); } // return the # of reply messages received static int process_replies( pn_messenger_t *messenger, pn_message_t *message, Statistics_t *stats, int max_count) { int received = 0; LOG("Calling pn_messenger_recv(%d)\n", max_count); int rc = pn_messenger_recv( messenger, max_count ); check((rc == 0 || rc == PN_TIMEOUT), "pn_messenger_recv() failed"); LOG("Messages on incoming queue: %d\n", pn_messenger_incoming(messenger)); while (pn_messenger_incoming(messenger)) { pn_messenger_get(messenger, message); check_messenger(messenger); received++; // TODO: header decoding? statistics_msg_received( stats, message ); // uint64_t id = pn_message_get_correlation_id( message ).u.as_ulong; } return received; } int main(int argc, char** argv) { Options_t opts; Statistics_t stats; uint64_t sent = 0; uint64_t received = 0; int target_index = 0; int rc; pn_message_t *message = 0; pn_message_t *reply_message = 0; pn_messenger_t *messenger = 0; parse_options( argc, argv, &opts ); messenger = pn_messenger( opts.name ); if (opts.certificate) { rc = pn_messenger_set_certificate(messenger, opts.certificate); check( rc == 0, "Failed to set certificate" ); } if (opts.privatekey) { rc = pn_messenger_set_private_key(messenger, opts.privatekey); check( rc == 0, "Failed to set private key" ); } if (opts.password) { rc = pn_messenger_set_password(messenger, opts.password); check( rc == 0, "Failed to set password" ); } if (opts.ca_db) { rc = pn_messenger_set_trusted_certificates(messenger, opts.ca_db); check( rc == 0, "Failed to set trusted CA database" ); } if (opts.outgoing_window) { pn_messenger_set_outgoing_window( messenger, opts.outgoing_window ); } pn_messenger_set_timeout( messenger, opts.timeout ); pn_messenger_start(messenger); message = pn_message(); check(message, "failed to allocate a message"); pn_message_set_reply_to(message, "~"); pn_data_t *body = pn_message_body(message); char *data = (char *)calloc(1, opts.msg_size); pn_data_put_binary(body, pn_bytes(opts.msg_size, data)); free(data); pn_atom_t id; id.type = PN_ULONG; #if 0 // TODO: how do we effectively benchmark header processing overhead??? pn_data_t *props = pn_message_properties(message); pn_data_put_map(props); pn_data_enter(props); // //pn_data_put_string(props, pn_bytes(6, "string")); //pn_data_put_string(props, pn_bytes(10, "this is awkward")); // //pn_data_put_string(props, pn_bytes(4, "long")); pn_data_put_long(props, 12345); // //pn_data_put_string(props, pn_bytes(9, "timestamp")); pn_data_put_timestamp(props, (pn_timestamp_t) 54321); pn_data_exit(props); #endif const int get_replies = opts.get_replies; if (get_replies) { // disable the timeout so that pn_messenger_recv() won't block reply_message = pn_message(); check(reply_message, "failed to allocate a message"); } statistics_start( &stats ); while (!opts.msg_count || (sent < opts.msg_count)) { // setup the message to send pn_message_set_address(message, opts.targets.addresses[target_index]); target_index = NEXT_ADDRESS(opts.targets, target_index); id.u.as_ulong = sent; pn_message_set_correlation_id( message, id ); pn_message_set_creation_time( message, msgr_now() ); pn_messenger_put(messenger, message); sent++; if (opts.send_batch && (pn_messenger_outgoing(messenger) >= (int)opts.send_batch)) { if (get_replies) { while (received < sent) { // this will also transmit any pending sent messages received += process_replies( messenger, reply_message, &stats, opts.recv_count ); } } else { LOG("Calling pn_messenger_send()\n"); rc = pn_messenger_send(messenger, -1); check((rc == 0 || rc == PN_TIMEOUT), "pn_messenger_send() failed"); } } check_messenger(messenger); } LOG("Messages received=%llu sent=%llu\n", received, sent); if (get_replies) { // wait for the last of the replies while (received < sent) { int count = process_replies( messenger, reply_message, &stats, opts.recv_count ); check( count > 0 || (opts.timeout == 0), "Error: timed out waiting for reply messages\n"); received += count; LOG("Messages received=%llu sent=%llu\n", received, sent); } } else if (pn_messenger_outgoing(messenger) > 0) { LOG("Calling pn_messenger_send()\n"); rc = pn_messenger_send(messenger, -1); check(rc == 0, "pn_messenger_send() failed"); } rc = pn_messenger_stop(messenger); check(rc == 0, "pn_messenger_stop() failed"); check_messenger(messenger); statistics_report( &stats, sent, received ); pn_messenger_free(messenger); pn_message_free(message); if (reply_message) pn_message_free( reply_message ); addresses_free( &opts.targets ); return 0; } qpid-proton-0.10/tests/tools/apps/c/msgr-recv.c0000664000000000000000000002354512562450203016346 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ #include "msgr-common.h" #include "proton/message.h" #include "proton/messenger.h" #include "proton/error.h" #include #include #include #include typedef struct { Addresses_t subscriptions; uint64_t msg_count; int recv_count; int incoming_window; int timeout; // seconds unsigned int report_interval; // in seconds int outgoing_window; Addresses_t forwarding_targets; int reply; const char *name; const char *ready_text; char *certificate; char *privatekey; // used to sign certificate char *password; // for private key file char *ca_db; // trusted CA database } Options_t; static void usage(int rc) { printf("Usage: msgr-recv [OPTIONS] \n" " -a [,]* \tAddresses to listen on [amqp://~0.0.0.0]\n" " -c # \tNumber of messages to receive before exiting [0=forever]\n" " -b # \tArgument to Messenger::recv(n) [2048]\n" " -w # \tSize for incoming window [0]\n" " -t # \tInactivity timeout in seconds, -1 = no timeout [-1]\n" " -e # \t# seconds to report statistics, 0 = end of test [0] *TBD*\n" " -R \tSend reply if 'reply-to' present\n" " -W # \t# outgoing window size [0]\n" " -F [,]* \tAddresses used for forwarding received messages\n" " -N \tSet the container name to \n" " -X \tPrint '\\n' to stdout after all subscriptions are created\n" " -V \tEnable debug logging\n" " SSL options:\n" " -T \tDatabase of trusted CA certificates for validating peer\n" " -C \tFile containing self-identifying certificate\n" " -K \tFile containing private key used to sign certificate\n" " -P [pass:|path] \tPassword to unlock private key file.\n" ); exit(rc); } static void parse_options( int argc, char **argv, Options_t *opts ) { int c; opterr = 0; memset( opts, 0, sizeof(*opts) ); opts->recv_count = -1; opts->timeout = -1; addresses_init(&opts->subscriptions); addresses_init(&opts->forwarding_targets); while ((c = getopt(argc, argv, "a:c:b:w:t:e:RW:F:VN:X:T:C:K:P:")) != -1) { switch (c) { case 'a': addresses_merge( &opts->subscriptions, optarg ); break; case 'c': if (sscanf( optarg, "%" SCNu64, &opts->msg_count ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'b': if (sscanf( optarg, "%d", &opts->recv_count ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'w': if (sscanf( optarg, "%d", &opts->incoming_window ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 't': if (sscanf( optarg, "%d", &opts->timeout ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } if (opts->timeout > 0) opts->timeout *= 1000; break; case 'e': if (sscanf( optarg, "%u", &opts->report_interval ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'R': opts->reply = 1; break; case 'W': if (sscanf( optarg, "%d", &opts->outgoing_window ) != 1) { fprintf(stderr, "Option -%c requires an integer argument.\n", optopt); usage(1); } break; case 'F': addresses_merge( &opts->forwarding_targets, optarg ); break; case 'V': enable_logging(); break; case 'N': opts->name = optarg; break; case 'X': opts->ready_text = optarg; break; case 'T': opts->ca_db = optarg; break; case 'C': opts->certificate = optarg; break; case 'K': opts->privatekey = optarg; break; case 'P': parse_password( optarg, &opts->password ); break; default: usage(1); } } // default subscription if none specified if (opts->subscriptions.count == 0) addresses_add( &opts->subscriptions, "amqp://~0.0.0.0" ); } int main(int argc, char** argv) { Options_t opts; Statistics_t stats; uint64_t sent = 0; uint64_t received = 0; int forwarding_index = 0; int rc; pn_message_t *message; pn_messenger_t *messenger; parse_options( argc, argv, &opts ); const int forward = opts.forwarding_targets.count != 0; message = pn_message(); messenger = pn_messenger( opts.name ); /* load the various command line options if they're set */ if (opts.certificate) { rc = pn_messenger_set_certificate(messenger, opts.certificate); check_messenger(messenger); check( rc == 0, "Failed to set certificate" ); } if (opts.privatekey) { rc = pn_messenger_set_private_key(messenger, opts.privatekey); check_messenger(messenger); check( rc == 0, "Failed to set private key" ); } if (opts.password) { rc = pn_messenger_set_password(messenger, opts.password); check_messenger(messenger); check( rc == 0, "Failed to set password" ); } if (opts.ca_db) { rc = pn_messenger_set_trusted_certificates(messenger, opts.ca_db); check_messenger(messenger); check( rc == 0, "Failed to set trusted CA database" ); } if (opts.incoming_window) { // RAFI: seems to cause receiver to hang: pn_messenger_set_incoming_window( messenger, opts.incoming_window ); } pn_messenger_set_timeout( messenger, opts.timeout ); pn_messenger_start(messenger); check_messenger(messenger); int i; for (i = 0; i < opts.subscriptions.count; i++) { pn_messenger_subscribe(messenger, opts.subscriptions.addresses[i]); check_messenger(messenger); LOG("Subscribing to '%s'\n", opts.subscriptions.addresses[i]); } // hack to let test scripts know when the receivers are ready (so // that the senders may be started) if (opts.ready_text) { fprintf(stdout, "%s\n", opts.ready_text); fflush(stdout); } while (!opts.msg_count || received < opts.msg_count) { LOG("Calling pn_messenger_recv(%d)\n", opts.recv_count); rc = pn_messenger_recv(messenger, opts.recv_count); check_messenger(messenger); check(rc == 0 || (opts.timeout == 0 && rc == PN_TIMEOUT), "pn_messenger_recv() failed"); // start the timer only after receiving the first msg if (received == 0) statistics_start( &stats ); LOG("Messages on incoming queue: %d\n", pn_messenger_incoming(messenger)); while (pn_messenger_incoming(messenger)) { pn_messenger_get(messenger, message); check_messenger(messenger); received++; // TODO: header decoding? // uint64_t id = pn_message_get_correlation_id( message ).u.as_ulong; statistics_msg_received( &stats, message ); if (opts.reply) { const char *reply_addr = pn_message_get_reply_to( message ); if (reply_addr) { LOG("Replying to: %s\n", reply_addr ); pn_message_set_address( message, reply_addr ); pn_message_set_creation_time( message, msgr_now() ); pn_messenger_put(messenger, message); sent++; } } if (forward) { const char *forward_addr = opts.forwarding_targets.addresses[forwarding_index]; forwarding_index = NEXT_ADDRESS(opts.forwarding_targets, forwarding_index); LOG("Forwarding to: %s\n", forward_addr ); pn_message_set_address( message, forward_addr ); pn_message_set_reply_to( message, NULL ); // else points to origin sender pn_message_set_creation_time( message, msgr_now() ); pn_messenger_put(messenger, message); sent++; } } LOG("Messages received=%llu sent=%llu\n", received, sent); } // this will flush any pending sends if (pn_messenger_outgoing(messenger) > 0) { LOG("Calling pn_messenger_send()\n"); rc = pn_messenger_send(messenger, -1); check_messenger(messenger); check(rc == 0, "pn_messenger_send() failed"); } rc = pn_messenger_stop(messenger); check(rc == 0, "pn_messenger_stop() failed"); check_messenger(messenger); statistics_report( &stats, sent, received ); pn_messenger_free(messenger); pn_message_free(message); addresses_free( &opts.subscriptions ); addresses_free( &opts.forwarding_targets ); return 0; } qpid-proton-0.10/tests/tools/apps/c/msgr-common.h0000664000000000000000000000471512562450203016702 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ #include "pncompat/misc_defs.h" #if defined(USE_INTTYPES) #ifdef __cplusplus #define __STDC_FORMAT_MACROS #endif #include #endif #ifdef _MSC_VER #if !defined(PRIu64) #define PRIu64 "I64u" #endif #if !defined(SCNu64) #define SCNu64 "I64u" #endif #endif /* If still not defined, best guess */ #if !defined(SCNu64) #define SCNu64 "ul" #endif #if !defined(PRIu64) #define PRIu64 "ul" #endif #include "proton/types.h" #include "proton/message.h" void msgr_die(const char *file, int line, const char *message); char *msgr_strdup( const char *src ); pn_timestamp_t msgr_now(void); void parse_password( const char *, char ** ); #define check_messenger(m) \ { check(pn_messenger_errno(m) == 0, pn_error_text(pn_messenger_error(m))) } #define check( expression, message ) \ { if (!(expression)) msgr_die(__FILE__,__LINE__, message); } // manage an ordered list of addresses typedef struct { const char **addresses; int size; // room in 'addresses' int count; // # entries } Addresses_t; #define NEXT_ADDRESS(a, i) (((i) + 1) % (a).count) void addresses_init( Addresses_t *a ); void addresses_free( Addresses_t *a ); void addresses_add( Addresses_t *a, const char *addr ); void addresses_merge( Addresses_t *a, const char *list ); // Statistics handling typedef struct { pn_timestamp_t start; uint64_t latency_samples; double latency_total; double latency_min; double latency_max; } Statistics_t; void statistics_start( Statistics_t *s ); void statistics_msg_received( Statistics_t *s, pn_message_t *message ); void statistics_report( Statistics_t *s, uint64_t sent, uint64_t received ); void enable_logging(void); void LOG( const char *fmt, ... ); qpid-proton-0.10/tests/tools/apps/c/msgr-common.c0000664000000000000000000001125612562450203016673 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ #include "msgr-common.h" #include #include #include #include #include void msgr_die(const char *file, int line, const char *message) { fprintf(stderr, "%s:%i: %s\n", file, line, message); exit(1); } //sigh - would be nice if proton exported pn_strdup() char *msgr_strdup( const char *src ) { char *r = NULL; if (src) { r = (char *) malloc(sizeof(char) * (strlen(src) + 1)); if (r) strcpy(r,src); } return r; } pn_timestamp_t msgr_now() { // from "pncompat/misc_funcs.inc" return time_now(); } void addresses_init( Addresses_t *a ) { a->size = 10; // whatever a->count = 0; a->addresses = (const char **) calloc( a->size, sizeof(const char *)); check(a->addresses, "malloc failure"); } void addresses_free( Addresses_t *a ) { if (a->addresses) { int i; for (i = 0; i < a->count; i++) if (a->addresses[i]) free( (void *)a->addresses[i] ); free( a->addresses ); a->addresses = NULL; } } void addresses_add( Addresses_t *a, const char *addr ) { if (a->count == a->size) { a->size += 10; a->addresses = (const char **) realloc( a->addresses, a->size * sizeof(const char *) ); check( a->addresses, "malloc failure" ); int i; for (i = a->count; i < a->size; i++) a->addresses[i] = NULL; } a->addresses[a->count] = msgr_strdup(addr); check( a->addresses[a->count], "malloc failure" ); a->count++; } // merge a comma-separated list of addresses void addresses_merge( Addresses_t *a, const char *list ) { char *const l = msgr_strdup(list); check( l, "malloc failure" ); char *addr = l; while (addr && *addr) { char *comma = strchr( addr, ',' ); if (comma) { *comma++ = '\0'; } addresses_add( a, addr ); addr = comma; } free(l); } void statistics_start( Statistics_t *s ) { s->latency_samples = 0; s->latency_total = s->latency_min = s->latency_max = 0.0; s->start = msgr_now(); } void statistics_msg_received( Statistics_t *s, pn_message_t *message ) { pn_timestamp_t ts = pn_message_get_creation_time( message ); if (ts) { double l = (double)(msgr_now() - ts); if (l > 0) { s->latency_total += l; if (++s->latency_samples == 1) { s->latency_min = s->latency_max = l; } else { if (s->latency_min > l) s->latency_min = l; if (s->latency_max < l) s->latency_max = l; } } } } void statistics_report( Statistics_t *s, uint64_t sent, uint64_t received ) { pn_timestamp_t end = msgr_now() - s->start; double secs = end/(double)1000.0; fprintf(stdout, "Messages sent: %" PRIu64 " recv: %" PRIu64 "\n", sent, received ); fprintf(stdout, "Total time: %f sec\n", secs ); fprintf(stdout, "Throughput: %f msgs/sec\n", (secs != 0.0) ? (double)sent/secs : 0); fprintf(stdout, "Latency (sec): %f min %f max %f avg\n", s->latency_min/1000.0, s->latency_max/1000.0, (s->latency_samples) ? (s->latency_total/s->latency_samples)/1000.0 : 0); } void parse_password( const char *input, char **password ) { if (strncmp( input, "pass:", 5 ) == 0) { // password provided on command line (not secure, shows up in 'ps') *password = msgr_strdup( input + 5 ); } else { // input assumed to be file containing password FILE *f = fopen( input, "r" ); check( f, "Cannot open password file\n" ); *password = (char *)malloc(256); // 256 should be enough for anybody! check( *password, "malloc failure" ); int rc = fscanf( f, "%255s", *password ); check( rc == 1, "Cannot read password from file\n" ); fclose(f); } } static int log = 0; void enable_logging() { log = 1; } void LOG( const char *fmt, ... ) { if (log) { va_list ap; va_start(ap, fmt); vfprintf( stdout, fmt, ap ); va_end(ap); } } qpid-proton-0.10/tests/tools/apps/c/CMakeLists.txt0000664000000000000000000000376512562450203017037 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # include(CheckIncludeFiles) include_directories(${CMAKE_SOURCE_DIR}/examples/include) CHECK_INCLUDE_FILES("inttypes.h" INTTYPES_AVAILABLE) if (INTTYPES_AVAILABLE) list(APPEND PLATFORM_DEFINITIONS "USE_INTTYPES") else (INTTYPES_AVAILABLE) if (CMAKE_COMPILER_IS_GNUCC) # since inttypes.h provides portable printf format macros set (COMPILE_WARNING_FLAGS "${COMPILE_WARNING_FLAGS} -Wno-format") endif (CMAKE_COMPILER_IS_GNUCC) endif (INTTYPES_AVAILABLE) add_executable(msgr-recv msgr-recv.c msgr-common.c) add_executable(msgr-send msgr-send.c msgr-common.c) add_executable(reactor-recv reactor-recv.c msgr-common.c) add_executable(reactor-send reactor-send.c msgr-common.c) target_link_libraries(msgr-recv qpid-proton) target_link_libraries(msgr-send qpid-proton) target_link_libraries(reactor-recv qpid-proton) target_link_libraries(reactor-send qpid-proton) set_target_properties ( msgr-recv msgr-send reactor-recv reactor-send PROPERTIES COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_LANGUAGE_FLAGS}" COMPILE_DEFINITIONS "${PLATFORM_DEFINITIONS}" ) if (BUILD_WITH_CXX) set_source_files_properties (msgr-recv.c msgr-send.c msgr-common.c reactor-recv.c reactor-send.c PROPERTIES LANGUAGE CXX) endif (BUILD_WITH_CXX) qpid-proton-0.10/tests/tools/apps/README.txt0000664000000000000000000000103512562450203015537 0ustar This directory contains applications built using proton. These applications are used by the testbed for soak tests. See the "soak.py" file for the tests that utilize these applications. These applications can be used standalone to generate or consume message traffic. Contents: msgr-send - this Messenger-based application generates message traffic, and can be configured to consume responses. msgr-recv - this Messenger-based application consumes message traffic, and can be configured to forward or reply to received messages. qpid-proton-0.10/tests/smoke/0000775000000000000000000000000012562450203013055 5ustar qpid-proton-0.10/tests/smoke/send.rb0000775000000000000000000000103012562450203014330 0ustar #!/usr/bin/env ruby require 'qpid_proton.rb' messenger = Qpid::Proton::Messenger.new() messenger.outgoing_window = 10 message = Qpid::Proton::Message.new() address = ARGV[0] if not address then address = "0.0.0.0" end message.address = address message.properties = {"binding" => "ruby", "version" => "#{RUBY_VERSION} #{RUBY_PLATFORM}"} message.body = "Hello World!" messenger.start() tracker = messenger.put(message) print "Put: #{message}\n" messenger.send() print "Status: ", messenger.status(tracker), "\n" messenger.stop() qpid-proton-0.10/tests/smoke/send.py0000775000000000000000000000104212562450203014360 0ustar #!/usr/bin/env python from __future__ import print_function import sys from proton import * messenger = Messenger() messenger.outgoing_window = 10 message = Message() address = "0.0.0.0" if len(sys.argv) > 1: address = sys.argv[1] message.address = address message.properties = {u"binding": u"python", u"version": sys.version} message.body = u"Hello World!" messenger.start() tracker = messenger.put(message) print("Put: %s" % message) messenger.send() print("Status: %s" % messenger.status(tracker)) messenger.stop() qpid-proton-0.10/tests/smoke/send.pl0000775000000000000000000000075712562450203014357 0ustar #!/usr/bin/env perl require 'qpid_proton.pm'; my $messenger = qpid::proton::Messenger->new(); $messenger->set_outgoing_window(10); my $message = qpid::proton::Message->new(); my $address = $ARGV[0]; $address = "0.0.0.0" if !defined $address; $message->set_address($address); # how do we set properties and body? $messenger->start(); my $tracker = $messenger->put($message); print "Put: $message\n"; $messenger->send(); print "Status: ", $messenger->status($tracker), "\n"; $messenger->stop(); qpid-proton-0.10/tests/smoke/send.php0000775000000000000000000000105712562450203014525 0ustar #!/usr/bin/env php outgoing_window = 10; $message = new Message(); $address = $argv[1]; if (!$address) { $address = "0.0.0.0"; } $message->address = $address; $message->properties = Array("binding" => "php", "version" => phpversion()); $message->body = "Hello World!"; $messenger->start(); $tracker = $messenger->put($message); print "Put: $message\n"; $messenger->send(); print "Status: " . $messenger->status($tracker) . "\n"; $messenger->stop(); ?>qpid-proton-0.10/tests/smoke/recv.rb0000775000000000000000000000062612562450203014350 0ustar #!/usr/bin/env ruby require 'qpid_proton.rb' messenger = Qpid::Proton::Messenger.new() messenger.incoming_window = 1 message = Qpid::Proton::Message.new() address = ARGV[0] if not address then address = "~0.0.0.0" end messenger.subscribe(address) messenger.start() while (true) do messenger.receive() messenger.get(message) print "Got: #{message}\n" messenger.accept() end messenger.stop() qpid-proton-0.10/tests/smoke/recv.py0000775000000000000000000000063012562450203014370 0ustar #!/usr/bin/env python from __future__ import print_function import sys from proton import * messenger = Messenger() messenger.incoming_window = 1 message = Message() address = "~0.0.0.0" if len(sys.argv) > 1: address = sys.argv[1] messenger.subscribe(address) messenger.start() while True: messenger.recv() messenger.get(message) print("Got: %s" % message) messenger.accept() messenger.stop() qpid-proton-0.10/tests/smoke/recv.pl0000775000000000000000000000102412562450203014351 0ustar #!/usr/bin/env perl require 'qpid_proton.pm'; my $messenger = qpid::proton::Messenger->new(); $messenger->set_incoming_window(1); my $message = qpid::proton::Message->new(); my $address = $ARGV[0]; $address = "~0.0.0.0" if !defined $address; $messenger->subscribe($address); $messenger->start(); while (true) { my $err = $messenger->receive(); # XXX: no exceptions! die $messenger->get_error() if $err < 0; $messenger->get($message); print "Got: $message\n"; $messenger->accept(); } $messenger->stop(); qpid-proton-0.10/tests/smoke/recv.php0000775000000000000000000000062512562450203014533 0ustar #!/usr/bin/env php incoming_window = 10; $message = new Message(); $address = $argv[1]; if (!$address) { $address = "~0.0.0.0"; } $messenger->subscribe($address); $messenger->start(); while (true) { $messenger->recv(); $messenger->get($message); print "Got: $message\n"; $messenger->accept(); } $messenger->stop(); ?>qpid-proton-0.10/tests/ruby/0000775000000000000000000000000012562450203012720 5ustar qpid-proton-0.10/tests/ruby/proton_tests/0000775000000000000000000000000012562450203015463 5ustar qpid-proton-0.10/tests/ruby/proton_tests/smoke.rb0000775000000000000000000000230312562450203017127 0ustar #!/usr/bin/env ruby require 'test/unit' require 'qpid_proton' class SmokeTest < Test::Unit::TestCase Messenger = Qpid::Proton::Messenger::Messenger Message = Qpid::Proton::Message def setup @server = Messenger.new() @client = Messenger.new() @server.blocking = false @client.blocking = false @server.subscribe("~0.0.0.0:12345") @server.start() @client.start() pump() end def pump while (@server.work(0) or @client.work(0)) do end end def teardown @server.stop() @client.stop() pump() assert @client.stopped? assert @server.stopped? end def testSmoke(count=10) msg = Message.new() msg.address = "0.0.0.0:12345" @server.receive() count.times {|i| msg.body = "Hello World! #{i}" @client.put(msg) } msg2 = Message.new() count.times {|i| if (@server.incoming == 0) then pump() end @server.get(msg2) assert msg2.body == "Hello World! #{i}" } assert(@client.outgoing == 0, "Expected 0 outgoing messages, found #{@client.outgoing}") assert(@server.incoming == 0, "Expected 0 incoming messages, found #{@server.incoming}") end end qpid-proton-0.10/tests/ruby/proton_tests/interop.rb0000775000000000000000000001051512562450203017475 0ustar #!/usr/bin/env ruby require 'test/unit' require 'qpid_proton' if ((RUBY_VERSION.split(".").map {|x| x.to_i} <=> [1, 9]) < 0) require 'pathname' class File def self.absolute_path(name) return Pathname.new(name).realpath end end end class InteropTest < Test::Unit::TestCase Data = Qpid::Proton::Codec::Data Message = Qpid::Proton::Message def setup @data = Data.new @message = Message.new end # Walk up the directory tree to find the tests directory. def get_data(name) path = File.absolute_path(__FILE__) while path and File.basename(path) != "tests" do path = File.dirname(path); end path = File.join(path,"interop") raise "Can't find test/interop directory from #{__FILE__}" unless File.directory?(path) path = File.join(path,"#{name}.amqp") File.open(path, "rb") { |f| f.read } end # Decode encoded bytes as a Data object def decode_data(encoded) buffer = encoded while buffer.size > 0 n = @data.decode(buffer) buffer = buffer[n..-1] end @data.rewind reencoded = @data.encode # Test the round-trip re-encoding gives the same result. assert_equal(encoded, reencoded) end def decode_data_file(name) decode_data(get_data(name)); end def decode_message_file(name) message = Message.new() message.decode(self.get_data(name)) self.decode_data(message.body) end def assert_next(type, value) assert @data.next assert_equal(type, @data.type) assert_equal(value, type.get(@data)) end def assert_array_next(expected, header) assert_next(Qpid::Proton::Codec::ARRAY, expected) result = @data.type.get(@data) assert_equal(result.proton_array_header, header) end def test_message decode_message_file("message") assert_next(Qpid::Proton::Codec::STRING, "hello") assert !@data.next end def test_primitives decode_data_file("primitives") assert_next(Qpid::Proton::Codec::BOOL, true) assert_next(Qpid::Proton::Codec::BOOL, false) assert_next(Qpid::Proton::Codec::UBYTE, 42) assert_next(Qpid::Proton::Codec::USHORT, 42) assert_next(Qpid::Proton::Codec::SHORT, -42) assert_next(Qpid::Proton::Codec::UINT, 12345) assert_next(Qpid::Proton::Codec::INT, -12345) assert_next(Qpid::Proton::Codec::ULONG, 12345) assert_next(Qpid::Proton::Codec::LONG, -12345) assert_next(Qpid::Proton::Codec::FLOAT, 0.125) assert_next(Qpid::Proton::Codec::DOUBLE, 0.125) assert !@data.next end def test_strings decode_data_file("strings") assert_next(Qpid::Proton::Codec::BINARY, "abc\0defg") assert_next(Qpid::Proton::Codec::STRING, "abcdefg") assert_next(Qpid::Proton::Codec::SYMBOL, "abcdefg") assert_next(Qpid::Proton::Codec::BINARY, "") assert_next(Qpid::Proton::Codec::STRING, "") assert_next(Qpid::Proton::Codec::SYMBOL, "") assert !@data.next end def test_described decode_data_file("described") assert_next(Qpid::Proton::Codec::DESCRIBED, Qpid::Proton::Types::Described.new("foo-descriptor", "foo-value")) assert(@data.described?) assert_next(Qpid::Proton::Codec::DESCRIBED, Qpid::Proton::Types::Described.new(12, 13)) assert(@data.described?) assert !@data.next end def test_described_array decode_data_file("described_array") assert_array_next((0...10).to_a, Qpid::Proton::Types::ArrayHeader.new(Qpid::Proton::Codec::INT, "int-array")) end def test_arrays decode_data_file("arrays") assert_array_next((0...100).to_a, Qpid::Proton::Types::ArrayHeader.new(Qpid::Proton::Codec::INT)) assert_array_next(["a", "b", "c"], Qpid::Proton::Types::ArrayHeader.new(Qpid::Proton::Codec::STRING)) assert_array_next([], Qpid::Proton::Types::ArrayHeader.new(Qpid::Proton::Codec::INT)) assert !@data.next end def test_lists decode_data_file("lists") assert_next(Qpid::Proton::Codec::LIST, [32, "foo", true]) assert_next(Qpid::Proton::Codec::LIST, []) assert !@data.next end def test_maps decode_data_file("maps") assert_next(Qpid::Proton::Codec::MAP, {"one" => 1, "two" => 2, "three" => 3 }) assert_next(Qpid::Proton::Codec::MAP, {1 => "one", 2 => "two", 3 => "three"}) assert_next(Qpid::Proton::Codec::MAP, {}) assert !@data.next end end qpid-proton-0.10/tests/ruby/proton-test0000775000000000000000000000027612562450203015151 0ustar #!/usr/bin/env ruby if RUBY_VERSION < "1.9" require 'rubygems' end gem 'minitest', '= 4.7.0', '< 5.0' require 'test/unit' require 'proton_tests/interop.rb' require 'proton_tests/smoke.rb' qpid-proton-0.10/tests/resources/0000775000000000000000000000000012562450203013751 5ustar qpid-proton-0.10/tests/resources/logging.properties0000664000000000000000000000220612562450203017515 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # handlers = java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level = ALL java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter # Note: the following line forces log statements to appear on a single line # when running on JDK 1.7 and later java.util.logging.SimpleFormatter.format = %1$tF %1$tT.%tL %4$s %5$s%n .level = INFO qpid-proton-0.10/tests/python/0000775000000000000000000000000012562450203013260 5ustar qpid-proton-0.10/tests/python/proton_tests/0000775000000000000000000000000012562450203016023 5ustar qpid-proton-0.10/tests/python/proton_tests/valgrind.supp0000664000000000000000000000327412562450203020550 0ustar { SSL does a number of uninitialized accesses (expected) 1 Memcheck:Cond fun:BN_bin2bn obj:* obj:* } { SSL does a number of uninitialized accesses (expected) 2 Memcheck:Cond fun:BN_num_bits_word fun:BN_num_bits } { SSL does a number of uninitialized accesses (expected) 3 Memcheck:Value8 fun:BN_num_bits_word fun:BN_num_bits fun:BN_mod_exp_mont_consttime obj:* fun:ssl3_ctx_ctrl } { SSL does a number of uninitialized accesses (expected) 4 Memcheck:Value8 fun:BN_mod_exp_mont_consttime obj:* fun:ssl3_ctx_ctrl } { SSL does a number of uninitialized accesses (expected) 5 Memcheck:Value4 fun:BN_mod_exp_mont_consttime fun:BN_mod_exp_mont obj:* obj:* } { SSL does a number of uninitialized accesses (expected) 6 Memcheck:Value4 fun:BN_num_bits_word fun:BN_mod_exp_mont_consttime fun:BN_mod_exp_mont obj:* obj:* } { Since we can never safely uninitialize SSL, allow this Memcheck:Leak fun:_vgrZU_libcZdsoZa_realloc fun:CRYPTO_realloc fun:lh_insert obj:/lib64/libcrypto.so.0.9.8e fun:ERR_load_strings fun:ERR_load_X509V3_strings fun:ERR_load_crypto_strings fun:SSL_load_error_strings } { Since we can never safely uninitialize SSL, allow this Memcheck:Leak fun:_vgrZU_libcZdsoZa_malloc fun:CRYPTO_malloc fun:lh_new fun:OBJ_NAME_init fun:OBJ_NAME_add fun:EVP_add_cipher fun:SSL_library_init } { Since we can never safely uninitialize SSL, allow this Memcheck:Leak fun:malloc obj:* fun:CRYPTO_malloc } { Known memory leak in cyrus-sasl (fixed in 2.1.26) Memcheck:Leak fun:malloc fun:* fun:sasl_config_init fun:sasl_server_init } qpid-proton-0.10/tests/python/proton_tests/utils.py0000664000000000000000000000643612562450203017546 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import os, time from threading import Thread, Event from unittest import TestCase from proton_tests.common import Test, free_tcp_port from copy import copy from proton import Message, Url, generate_uuid from proton.handlers import MessagingHandler from proton.reactor import Container from proton.utils import SyncRequestResponse, BlockingConnection class EchoServer(MessagingHandler, Thread): """ Simple echo server that echos messages to their reply-to. Runs in a thread. Will only accept a single connection and shut down when that connection closes. """ def __init__(self, url, timeout): MessagingHandler.__init__(self) Thread.__init__(self) self.daemon = True self.timeout = timeout self.url = url self.senders = {} self.container = None self.event = Event() def on_start(self, event): self.acceptor = event.container.listen(self.url) self.container = event.container self.event.set() def on_link_opening(self, event): if event.link.is_sender: if event.link.remote_source and event.link.remote_source.dynamic: event.link.source.address = str(generate_uuid()) self.senders[event.link.source.address] = event.link def on_message(self, event): m = event.message sender = self.senders.get(m.reply_to) if sender: reply = Message(address=m.reply_to, body=m.body, correlation_id=m.correlation_id) sender.send(reply) def on_connection_closing(self, event): self.acceptor.close() def run(self): Container(self).run() def wait(self): self.event.wait(self.timeout) class SyncRequestResponseTest(Test): """Test SyncRequestResponse""" def test_request_response(self): def test(name, address="x"): for i in range(5): body="%s%s" % (name, i) response = client.call(Message(address=address, body=body)) self.assertEquals(response.address, client.reply_to) self.assertEquals(response.body, body) server = EchoServer(Url(host="127.0.0.1", port=free_tcp_port()), self.timeout) server.start() server.wait() connection = BlockingConnection(server.url, timeout=self.timeout) client = SyncRequestResponse(connection) try: test("foo") # Simple request/resposne finally: client.connection.close() server.join(timeout=self.timeout) qpid-proton-0.10/tests/python/proton_tests/url.py0000664000000000000000000001402312562450203017177 0ustar from __future__ import absolute_import # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from . import common from proton import Url class UrlTest(common.Test): def assertEqual(self, a, b): assert a == b, "%s != %s" % (a, b) def assertNotEqual(self, a, b): assert a != b, "%s == %s" % (a, b) def assertUrl(self, u, scheme, username, password, host, port, path): self.assertEqual((u.scheme, u.username, u.password, u.host, u.port, u.path), (scheme, username, password, host, port, path)) def testUrl(self): url = Url('amqp://me:secret@myhost:1234/foobar') self.assertEqual(str(url), "amqp://me:secret@myhost:1234/foobar") self.assertUrl(url, 'amqp', 'me', 'secret', 'myhost', 1234, 'foobar') self.assertEqual(str(url), "amqp://me:secret@myhost:1234/foobar") def testDefaults(self): # Check that we allow None for scheme, port url = Url(username='me', password='secret', host='myhost', path='foobar', defaults=False) self.assertEqual(str(url), "me:secret@myhost/foobar") self.assertUrl(url, None, 'me', 'secret', 'myhost', None, 'foobar') self.assertEqual(str(Url("amqp://me:secret@myhost/foobar")), "amqp://me:secret@myhost:amqp/foobar") # Empty string vs. None for path self.assertEqual(Url("myhost/").path, "") assert Url("myhost", defaults=False).path is None # Expanding abbreviated url strings. for s, u in [ ("", "amqp://0.0.0.0:amqp"), ("foo", "amqp://foo:amqp"), (":1234", "amqp://0.0.0.0:1234"), ("/path", "amqp://0.0.0.0:amqp/path") ]: self.assertEqual(str(Url(s)), u) def assertPort(self, port, portint, portstr): self.assertEqual((port, port), (portint, portstr)) self.assertEqual((int(port), str(port)), (portint, portstr)) def testPort(self): self.assertPort(Url.Port('amqp'), 5672, 'amqp') self.assertPort(Url.Port(5672), 5672, '5672') self.assertPort(Url.Port(5671), 5671, '5671') self.assertEqual(Url.Port(5671)+1, 5672) # Treat as int self.assertEqual(str(Url.Port(5672)), '5672') self.assertPort(Url.Port(Url.Port('amqp')), 5672, 'amqp') self.assertPort(Url.Port(Url.Port(5672)), 5672, '5672') try: Url.Port('xxx') assert False, "Expected ValueError" except ValueError: pass self.assertEqual(str(Url("host:amqp", defaults=False)), "host:amqp") self.assertEqual(Url("host:amqp", defaults=False).port, 5672) def testArgs(self): u = Url("amqp://u:p@host:amqp/path", scheme='foo', host='bar', port=1234, path='garden', defaults=False) self.assertUrl(u, 'foo', 'u', 'p', 'bar', 1234, 'garden') u = Url(defaults=False) self.assertUrl(u, None, None, None, None, None, None) def assertRaises(self, exception, function, *args, **kwargs): try: function(*args, **kwargs) assert False, "Expected exception %s" % exception.__name__ except exception: pass def testMissing(self): self.assertUrl(Url(defaults=False), None, None, None, None, None, None) self.assertUrl(Url('amqp://', defaults=False), 'amqp', None, None, None, None, None) self.assertUrl(Url('username@', defaults=False), None, 'username', None, None, None, None) self.assertUrl(Url(':pass@', defaults=False), None, '', 'pass', None, None, None) self.assertUrl(Url('host', defaults=False), None, None, None, 'host', None, None) self.assertUrl(Url(':1234', defaults=False), None, None, None, None, 1234, None) self.assertUrl(Url('/path', defaults=False), None, None, None, None, None, 'path') for s in ['amqp://', 'username@', ':pass@', ':1234', '/path']: self.assertEqual(s, str(Url(s, defaults=False))) for s, full in [ ('amqp://', 'amqp://0.0.0.0:amqp'), ('username@', 'amqp://username@0.0.0.0:amqp'), (':pass@', 'amqp://:pass@0.0.0.0:amqp'), (':1234', 'amqp://0.0.0.0:1234'), ('/path', 'amqp://0.0.0.0:amqp/path'), ('foo/path', 'amqp://foo:amqp/path'), (':1234/path', 'amqp://0.0.0.0:1234/path') ]: self.assertEqual(str(Url(s)), full) def testAmqps(self): # Scheme defaults self.assertEqual(str(Url("me:secret@myhost/foobar")), "amqp://me:secret@myhost:amqp/foobar") # Correct port for amqps vs. amqps self.assertEqual(str(Url("amqps://me:secret@myhost/foobar")), "amqps://me:secret@myhost:amqps/foobar") self.assertPort(Url.Port('amqps'), 5671, 'amqps') self.assertEqual(str(Url("host:amqps", defaults=False)), "host:amqps") self.assertEqual(Url("host:amqps", defaults=False).port, 5671) def testEqual(self): self.assertEqual(Url("foo/path"), 'amqp://foo:amqp/path') self.assertEqual('amqp://foo:amqp/path', Url("foo/path")) self.assertEqual(Url("foo/path"), Url("foo/path")) self.assertNotEqual(Url("foo/path"), 'xamqp://foo:amqp/path') self.assertNotEqual('xamqp://foo:amqp/path', Url("foo/path")) self.assertNotEqual(Url("foo/path"), Url("bar/path")) qpid-proton-0.10/tests/python/proton_tests/transport.py0000664000000000000000000002570712562450203020444 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import os import sys from . import common from proton import * from proton._compat import str2bin class Test(common.Test): pass class ClientTransportTest(Test): def setup(self): self.transport = Transport() self.peer = Transport() self.conn = Connection() self.peer.bind(self.conn) def teardown(self): self.transport = None self.peer = None self.conn = None def drain(self): while True: p = self.transport.pending() if p < 0: return elif p > 0: data = self.transport.peek(p) self.peer.push(data) self.transport.pop(len(data)) else: assert False def assert_error(self, name): assert self.conn.remote_container is None, self.conn.remote_container self.drain() # verify that we received an open frame assert self.conn.remote_container is not None, self.conn.remote_container # verify that we received a close frame assert self.conn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_CLOSED, self.conn.state # verify that a framing error was reported assert self.conn.remote_condition.name == name, self.conn.remote_condition def testEOS(self): self.transport.push(str2bin("")) # should be a noop self.transport.close_tail() # should result in framing error self.assert_error(u'amqp:connection:framing-error') def testPartial(self): self.transport.push(str2bin("AMQ")) # partial header self.transport.close_tail() # should result in framing error self.assert_error(u'amqp:connection:framing-error') def testGarbage(self, garbage=str2bin("GARBAGE_")): self.transport.push(garbage) self.assert_error(u'amqp:connection:framing-error') assert self.transport.pending() < 0 self.transport.close_tail() assert self.transport.pending() < 0 def testSmallGarbage(self): self.testGarbage(str2bin("XXX")) def testBigGarbage(self): self.testGarbage(str2bin("GARBAGE_XXX")) def testHeader(self): self.transport.push(str2bin("AMQP\x00\x01\x00\x00")) self.transport.close_tail() self.assert_error(u'amqp:connection:framing-error') def testHeaderBadDOFF1(self): """Verify doff > size error""" self.testGarbage(str2bin("AMQP\x00\x01\x00\x00\x00\x00\x00\x08\x08\x00\x00\x00")) def testHeaderBadDOFF2(self): """Verify doff < 2 error""" self.testGarbage(str2bin("AMQP\x00\x01\x00\x00\x00\x00\x00\x08\x01\x00\x00\x00")) def testHeaderBadSize(self): """Verify size > max_frame_size error""" self.transport.max_frame_size = 512 self.testGarbage(str2bin("AMQP\x00\x01\x00\x00\x00\x00\x02\x01\x02\x00\x00\x00")) def testProtocolNotSupported(self): self.transport.push(str2bin("AMQP\x01\x01\x0a\x00")) p = self.transport.pending() assert p >= 8, p bytes = self.transport.peek(p) assert bytes[:8] == str2bin("AMQP\x00\x01\x00\x00") self.transport.pop(p) self.drain() assert self.transport.closed def testPeek(self): out = self.transport.peek(1024) assert out is not None def testBindAfterOpen(self): conn = Connection() ssn = conn.session() conn.open() ssn.open() conn.container = "test-container" conn.hostname = "test-hostname" trn = Transport() trn.bind(conn) out = trn.peek(1024) assert str2bin("test-container") in out, repr(out) assert str2bin("test-hostname") in out, repr(out) self.transport.push(out) c = Connection() assert c.remote_container == None assert c.remote_hostname == None assert c.session_head(0) == None self.transport.bind(c) assert c.remote_container == "test-container" assert c.remote_hostname == "test-hostname" assert c.session_head(0) != None def testCloseHead(self): n = self.transport.pending() assert n > 0, n try: self.transport.close_head() except TransportException: e = sys.exc_info()[1] assert "aborted" in str(e), str(e) n = self.transport.pending() assert n < 0, n def testCloseTail(self): n = self.transport.capacity() assert n > 0, n try: self.transport.close_tail() except TransportException: e = sys.exc_info()[1] assert "aborted" in str(e), str(e) n = self.transport.capacity() assert n < 0, n def testUnpairedPop(self): conn = Connection() self.transport.bind(conn) conn.hostname = "hostname" conn.open() dat1 = self.transport.peek(1024) ssn = conn.session() ssn.open() dat2 = self.transport.peek(1024) assert dat2[:len(dat1)] == dat1 snd = ssn.sender("sender") snd.open() self.transport.pop(len(dat1)) self.transport.pop(len(dat2) - len(dat1)) dat3 = self.transport.peek(1024) self.transport.pop(len(dat3)) assert self.transport.peek(1024) == str2bin("") self.peer.push(dat1) self.peer.push(dat2[len(dat1):]) self.peer.push(dat3) class ServerTransportTest(Test): def setup(self): self.transport = Transport(Transport.SERVER) self.peer = Transport() self.conn = Connection() self.peer.bind(self.conn) def teardown(self): self.transport = None self.peer = None self.conn = None def drain(self): while True: p = self.transport.pending() if p < 0: return elif p > 0: bytes = self.transport.peek(p) self.peer.push(bytes) self.transport.pop(len(bytes)) else: assert False def assert_error(self, name): assert self.conn.remote_container is None, self.conn.remote_container self.drain() # verify that we received an open frame assert self.conn.remote_container is not None, self.conn.remote_container # verify that we received a close frame assert self.conn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_CLOSED, self.conn.state # verify that a framing error was reported assert self.conn.remote_condition.name == name, self.conn.remote_condition # TODO: This may no longer be testing anything def testEOS(self): self.transport.push(str2bin("")) # should be a noop self.transport.close_tail() p = self.transport.pending() self.drain() assert self.transport.closed def testPartial(self): self.transport.push(str2bin("AMQ")) # partial header self.transport.close_tail() p = self.transport.pending() assert p >= 8, p bytes = self.transport.peek(p) assert bytes[:8] == str2bin("AMQP\x00\x01\x00\x00") self.transport.pop(p) self.drain() assert self.transport.closed def testGarbage(self, garbage="GARBAGE_"): self.transport.push(str2bin(garbage)) p = self.transport.pending() assert p >= 8, p bytes = self.transport.peek(p) assert bytes[:8] == str2bin("AMQP\x00\x01\x00\x00") self.transport.pop(p) self.drain() assert self.transport.closed def testSmallGarbage(self): self.testGarbage("XXX") def testBigGarbage(self): self.testGarbage("GARBAGE_XXX") def testHeader(self): self.transport.push(str2bin("AMQP\x00\x01\x00\x00")) self.transport.close_tail() self.assert_error(u'amqp:connection:framing-error') def testProtocolNotSupported(self): self.transport.push(str2bin("AMQP\x01\x01\x0a\x00")) p = self.transport.pending() assert p >= 8, p bytes = self.transport.peek(p) assert bytes[:8] == str2bin("AMQP\x00\x01\x00\x00") self.transport.pop(p) self.drain() assert self.transport.closed def testPeek(self): out = self.transport.peek(1024) assert out is not None def testBindAfterOpen(self): conn = Connection() ssn = conn.session() conn.open() ssn.open() conn.container = "test-container" conn.hostname = "test-hostname" trn = Transport() trn.bind(conn) out = trn.peek(1024) assert str2bin("test-container") in out, repr(out) assert str2bin("test-hostname") in out, repr(out) self.transport.push(out) c = Connection() assert c.remote_container == None assert c.remote_hostname == None assert c.session_head(0) == None self.transport.bind(c) assert c.remote_container == "test-container" assert c.remote_hostname == "test-hostname" assert c.session_head(0) != None def testCloseHead(self): n = self.transport.pending() assert n >= 0, n try: self.transport.close_head() except TransportException: e = sys.exc_info()[1] assert "aborted" in str(e), str(e) n = self.transport.pending() assert n < 0, n def testCloseTail(self): n = self.transport.capacity() assert n > 0, n try: self.transport.close_tail() except TransportException: e = sys.exc_info()[1] assert "aborted" in str(e), str(e) n = self.transport.capacity() assert n < 0, n def testUnpairedPop(self): conn = Connection() self.transport.bind(conn) conn.hostname = "hostname" conn.open() dat1 = self.transport.peek(1024) ssn = conn.session() ssn.open() dat2 = self.transport.peek(1024) assert dat2[:len(dat1)] == dat1 snd = ssn.sender("sender") snd.open() self.transport.pop(len(dat1)) self.transport.pop(len(dat2) - len(dat1)) dat3 = self.transport.peek(1024) self.transport.pop(len(dat3)) assert self.transport.peek(1024) == str2bin("") self.peer.push(dat1) self.peer.push(dat2[len(dat1):]) self.peer.push(dat3) def testEOSAfterSASL(self): self.transport.sasl().allowed_mechs('ANONYMOUS') self.peer.sasl().allowed_mechs('ANONYMOUS') # this should send over the sasl header plus a sasl-init set up # for anonymous p = self.peer.pending() self.transport.push(self.peer.peek(p)) self.peer.pop(p) # now we send EOS self.transport.close_tail() # the server may send an error back p = self.transport.pending() while p>0: self.peer.push(self.transport.peek(p)) self.transport.pop(p) p = self.transport.pending() # server closed assert self.transport.pending() < 0 class LogTest(Test): def testTracer(self): t = Transport() assert t.tracer is None messages = [] def tracer(transport, message): messages.append((transport, message)) t.tracer = tracer assert t.tracer is tracer t.log("one") t.log("two") t.log("three") assert messages == [(t, "one"), (t, "two"), (t, "three")], messages qpid-proton-0.10/tests/python/proton_tests/ssl_db/0000775000000000000000000000000012562450203017271 5ustar qpid-proton-0.10/tests/python/proton_tests/ssl_db/server.pkcs120000664000000000000000000000564312562450203021634 0ustar 0‚ Ÿ0‚ Y *†H†÷  ‚ J‚ F0‚ B0‚ *†H†÷  ‚ø‚ô0‚ð0‚û *†H†÷   ‚Š0‚†0( *†H†÷  0Öž­èm»škQQµÛ]‡K»:‚XÝ šøákî¿ÌèÏ|Õ¾Ì%½eÚ€UîáñQ·ìcet™½z¢Û 1߉ÍòòêÜ7¤€E+B…¸òÙ¶|¥öPtÆ–zNnüþ¦§äîølõÈ‹µš„0g2[k“æ‘Zž¡§îÕ $¹ü.Õ/ijÿV-ƒÌV•À{U¨Öõ‚Wq§FÇQœb™ä5—çàÉó¶YŸÎ†V’Ý*êÚ‚ wz•Jjõ°‚¸ô¨4%IÕÄ0*¥0R]e]鉋×-™ËºÑø.¯˜.î›cÂü6åGf«L–s;r¢IN‘FúÅëQ=šuætùóòS/tÈßd+øã‰`×bÝ\ÿ›~àVÜcM¾7CÌ#Âr*P¼í1‚^@—ö¤a‹fÀßâ¾ÎB—Üø] C“ÐlÍm0æFNM åó÷½ a¤É®ÓD©Ä"/Ç÷⤠ò%h/91^09 *†H†÷  1,*server-wc-certificate0! *†H†÷  1Time 13637944250220‚í *†H†÷   ‚‚0‚~0( *†H†÷  0„îL…‹PÖ›(S½ð¦´¦Š‚P|T£„Rp mîÿ‹ª¦Íj«ê^lö¹¬™M쳴푌úR¿ÙópÁ„[E†ÇZñ:¨ñM¡á2F#Cœï˜,ËzV³T«=ðú]•ÑÕ¤ÁݤŒ¤Â+(ô—VôËjßÞ`P…ëK«ä`XSvqÝW*÷@…mJ,ËäƒSÆU¤0ᮇÍ.'Ûæ+>  &’ƒí<êm=ÝÁ F„ýq¡7•ç&ѽ×úAb= 50&»¯ªg½Ê /÷ŠÍñ̳ÉbQ6#qòdŸ9SάòH)b¸i–Ç;UŸ2Z>ÏAà0¹‰ÖÍ™zlšßVܬtÖÑÙ¦[‚@W3 9œwR’»$àm–ƒ¯÷`¹ä2ÑòqÐ&áe^ï¿÷ ͧ0áe0+iy»›rª§ºç>@a=|Ú¿Q°@½M/1X03 *†H†÷  1&$server-certificate0! *†H†÷  1Time 13637944223450‚3 *†H†÷  ‚$0‚ 0‚ *†H†÷ 0( *†H†÷  09³~Q¢PÖBAn×¾rxBª–€‚à;K1)\ÆXî÷žŒñgÇ<ºžØO ÌÆ×|‚*ÂÞ˜2ºêD¿Ö(HàÔJ¥ä§Ü¼]·>sGà-4Y°­Æëªâ·L>E0¬.Q€Žß\Œ}r”kÑÕ<óÁS]`åzÒl½XŒyœP¦Î•+Ý ªZÙö¢e±}[Pö«Œ¤Óð'X9gêP63µFP9tîBžY3ðئ.Tƒ¢®„ÔaR£ùl#’ÔÚÐæUy 黯 ¯jáI U[ͯ<&á9€lõs*5¼£ Â{AŽÙê:ô°O›~XŒ£X j‹—£u›Gþ3AðW8Ñhë„+ˆüh[: T`:{¯Ãͱ‹rÔ J KŠtšû vì/έ³‰Ì™‡¸@ï J~XŠ©Q½Ùà+„Ãjˆ]†¨¥ÚÜTjæ‰ ››MÚD¶:n¹Gå†úŽN¶Ýüíÿ6_÷7œô¢Ó¡†AÙT¸š­÷®Íµ°+p쮥¯…óüÙâ^p$C|f4vÿúTÜ”dH¡Ç˹tð!~õ®äl*[%‘-ƒÿKê”t<%Fß»;ãq÷Êö(ú¨ENyc$àÇ#ð;\zgCŠqâUoõaÃrâœj$óÐ’¾ø†¥ÆÕHhÐŽ¹LžÊ¶©míÙŽSÄ©žqô„þÆK5½„"W§ã:¿´l@ó,ZÊn“¼LáÕ!n¦äÞûò±÷÷âP•Œ`éH³ú ÊêO&×ßzÝìõ¶v8ì‰Þ*•™ÿgxÝD M¯3Z»_³J1iO[Œ6^ZÅȨN(ý”*ó#ÓºfÙÈ59‹ ´ÿ= w¨'ÎI_‚EK¼@Ìæ}³œ’=^=¨B©3Åoltl0¿2ýó\Ùnå¾^!ÂG=Ö+`Ï[ׇþ>ß°î“ ËG® 94‹F£Å@RL‰ Ó’%kÆu×bC89R«·`_»{ }«Û/HAPóÆ`åhû·2œ‘¾G3%#gcqñJû•þ& mäàRÛ<ÈΰnØbÚ‰‡wò_ßQ Ê Ô?•ð×~Z­$Ze˜4_ôë*#e‹ëG[a Û¨¼:KEµÜX!E Ä KÔìlÐtõ¯´Bd“B]«y*È‹­h$Útš’‹“sXâFõ¶gEÙG¢j{‘Ü{_"ÛçD$´Stu‡kˆweŸ˜¹ÔÂ?©š›­Lè$¢²+¢ÿ¯¡Rói5i¨Áâ¯ñÀè¨n ÖȽ››šnábgXuÑEs~"ÕiÔ-ÁîÔ—ù%;22~#|²%nùñ”‡ï>—'iXÙ¯_7T0=0!0 +~D?ýüyƒ{lõÃõ.´a¬®3‚§[k%FEäŒGÍ1>^qpid-proton-0.10/tests/python/proton_tests/ssl_db/server-wc-request.pem0000664000000000000000000000172612562450203023405 0ustar -----BEGIN NEW CERTIFICATE REQUEST----- MIICmTCCAlcCAQAwMDEdMBsGA1UEAwwUKi5wcmVmaXgqLmRvbWFpbi5jb20xDzANBgNVBAoTBlNl cnZlcjCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+A tlEmaUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb +DtX58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5 gqLrhAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQ gYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6o UZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GEAAKBgHh6cYK11FLLKpMn6ruhkIfKMH/ZB28g oxmtxrRs1uSJUvRVPTdpDleXNEJg8wEXBfxXhqnlcqYKPcYNUMDpxq3UjRrg9YmZTYyC/WMKCS2t GCGr712/7yL3j1xl/oW8xwD4IQKRxHW35XZ2htBHB+EGB6qXZO1SS41GaSdemVDRoGUwYwYJKoZI hvcNAQkOMVYwVDAdBgNVHQ4EFgQU9e9v++H7LKnfxt/p6h2RIUpdErEwMwYDVR0RBCwwKoIWYWx0 ZXJuYXRlLm5hbWUub25lLmNvbYIQYW5vdGhlci5uYW1lLmNvbTALBgcqhkjOOAQDBQADLwAwLAIU HwrrI5XVNNTolSMnuOEQ2uhE3lwCFEASAlVD+LyszXTiFF/8zOgbRy/Z -----END NEW CERTIFICATE REQUEST----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/server-wc-private-key.pem0000664000000000000000000000340112562450203024145 0ustar Bag Attributes friendlyName: server-wc-certificate localKeyID: 54 69 6D 65 20 31 33 36 33 37 39 34 34 32 35 30 32 32 Key Attributes: -----BEGIN DSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,4AA7362A0A1CE3D0 sLqxs1MtHOj0O0sO2YUSQMrsvl19KBlabPwiLhrLKPMzyK8Xad4S8V6J9U4QZl3I n6vY7XvLPx+OqPE9X6vuRfErzDzzjkrL3/4+VTj+bFdetR85ysg1iOVnM2B3MhxW qF9TeOpxOWokN8ck5X6TYuo1V6NcYO0rZ+oTcqe7nNdmJruwHf6dgWPeLRhyT7Cj IoidnCiTYKCIVH+3Hu30ZhnF81hE+vXt2EtN78kUNojlsSSsxmzOXIaPGwVRYMzw QqhKcX08Uo+1gHfcNfvjDpWyybBo0oznEneGvxxGoACC3KIJMAf6CB0ToP4JnSO9 GuNj51k2M47MdCOlkvWD6OvwMNU+qtfFo02cHj2ZyjSYTry0/XnBSKfdMs8Yz0Xw GxsWY7f2041XBqP1gXUbjLygpNzNoD4jyxoPbgPequsCnSl6x+dORc7HICJ4VXFk 9DCk0Xu+22PMuMl3i743SjOoxGntJCzQfJABbo6txbXbLnHrByRHgZyPeIBNrQZY fZm1BXRexrnXMiKyVhl0rgZaIlVwxW8yq76mRv3E+srYncWaPzPvI2UoNGJI6kqv TfQP2IYr3QQ4FsN70rZAe1kdur8qmo10 -----END DSA PRIVATE KEY----- Bag Attributes friendlyName: server-certificate localKeyID: 54 69 6D 65 20 31 33 36 33 37 39 34 34 32 32 33 34 35 Key Attributes: -----BEGIN DSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,2EC922782CE1727C fsM0zmhcMgj70OG+cX5FFIbS1dVFZDVpqUFXASlVzYgx5t8nTISPSBA9mQup34MG 28sv2zxLdb+bXFuzkuq3mzuj3NLZizo7o6wRuUpbpbmp6hR6K5fkfu7GsPXCl380 EjbrUCdt2iDiDJLyNT9Pu3ngdx3tOqz8JE3oD93FAfVZDKlzigfmX1sS+qOyqrCO JbRqaCJOQ5F+g73QvM9cOQLw1F/n9FqtPFNSy+Q0LFBcxfznsTk4pnPFJEko/2F0 r9fudQS0vouNgZ4i1OzrQnWTzVeqVoSaa6AywCrynpiSWBfxMIbT78zjyoUBD47H nlGjMdtpoo6Xmd3CjY/pHc7Gi4RiTvBR225V/djdZpIDp7Hoyp2jMSWmsamCEFMj aEx7VJQtAEIyrVsCbYfvY6pE0id9dQOZSZnBtn8sHqy9DMfd6bR8FFQx48yXzO8H sxBNOFjkNjnjm3YWTm5q6iQ0LTke+EplixN2J1wjKz16Iy/36zCd+2rks2KXIXXX 4dHTDPvV+9WKrfmk2ZQx/j2XQfPt34a0TIERJ5zAJuHH7a9zSCX0j4k7XRCI2GOQ Mu7wsBLassVgVCPF3J0Flw== -----END DSA PRIVATE KEY----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/server-wc-certificate.pem0000664000000000000000000000215012562450203024167 0ustar -----BEGIN CERTIFICATE----- MIIDFTCCAtOgAwIBAgIEeHbOXTALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1c3RlZC5DQS5j b20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTMwMzIwMTU0NzA1WhgPMjI4NzAxMDIxNTQ3 MDVaMDAxHTAbBgNVBAMMFCoucHJlZml4Ki5kb21haW4uY29tMQ8wDQYDVQQKEwZTZXJ2ZXIwggG3 MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAi UftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYV DwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc 9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPo TCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa 5Z8GkotmXoB7VSVkAUw7/s9JKgOBhAACgYB4enGCtdRSyyqTJ+q7oZCHyjB/2QdvIKMZrca0bNbk iVL0VT03aQ5XlzRCYPMBFwX8V4ap5XKmCj3GDVDA6cat1I0a4PWJmU2Mgv1jCgktrRghq+9dv+8i 949cZf6FvMcA+CECkcR1t+V2dobQRwfhBgeql2TtUkuNRmknXplQ0aN3MHUwHQYDVR0OBBYEFPXv b/vh+yyp38bf6eodkSFKXRKxMB8GA1UdIwQYMBaAFKsQvo74oH6YkejN32+l6aYBsRSWMDMGA1Ud EQQsMCqCFmFsdGVybmF0ZS5uYW1lLm9uZS5jb22CEGFub3RoZXIubmFtZS5jb20wCwYHKoZIzjgE AwUAAy8AMCwCFFKqHg73AIZ9lsNClefQQqUqMp4/AhQjpVnd799wousXAvTtYNlH/7kWFA== -----END CERTIFICATE----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/server-request.pem0000664000000000000000000000163112562450203022771 0ustar -----BEGIN NEW CERTIFICATE REQUEST----- MIICajCCAicCAQAwNTEiMCAGA1UEAxMZQTEuR29vZC5TZXJ2ZXIuZG9tYWluLmNvbTEPMA0GA1UE ChMGU2VydmVyMIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up 1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUj C8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZ T+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7 zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAZ3nV9bAohUzrAixWTS+jzoer eraDGU/RJOX8TMQF7D1u5Ixc8KpC9AiHD9R3r9/9DQrFy0+fwyo776MIJJgxgfl3UwTzlf1AzaaH j/F6NhZB1SWokqQc+joxsuAR9BjtTFfEyr0SSKP9PozJLVF33HAIJ/bAmGNXomrfkqmWdYygMDAu BgkqhkiG9w0BCQ4xITAfMB0GA1UdDgQWBBSVmCi/vFuniRy7Awjt3sADPgMfxjALBgcqhkjOOAQD BQADMAAwLQIUH7G2vQMVP1JURjsKcruCMMN2Nv8CFQCL3mjZX5zQE68aBdaL6163zvWMSQ== -----END NEW CERTIFICATE REQUEST----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/server-private-key.pem0000664000000000000000000000157312562450203023546 0ustar Bag Attributes friendlyName: server-certificate localKeyID: 54 69 6D 65 20 31 33 36 33 37 39 34 34 32 32 33 34 35 Key Attributes: -----BEGIN DSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,58EA06E340D4B8FB cYo9OeXX1j8HazOZUVLCLaA5hbVd92OY5JufYXXzJsyfoBSWsH2IPIWw6oolJfD/ Nd53xpl3gW5AuVk6gZkfV/qUQeymTJPtQUPjfgEEK50s7PCj5GKNL63/SOVVYudc HOczB9wb5VrVstKBdPe5SkxtOoMGka76uXDAaApezpHcwxFKyzmixevc8f7/3Q7q 02TCaufgzAKYzO9sjY/U8nR0qvn1Cnx/AO8Lwt0K3mEExqCR0R7yyW1GwRRiMdDe x7QnYosHScSao7f1ToMLYPGdtMSUWBt1m10hrcPaCzvH5Zqy7w+wqQp5mG8dHp7o v767dWezeY1k8RpKiTZHlKZCksfqWr3TSgICOcFZrrQbxsCjIlpSW+65uhrDtUN1 CqJmTzeUeRFBKGGdBMe+I1gUxsVohHyQzxyxUMwmu3fQQipSsvEyjq2O3CxaoPyi bbvbmvhdHGhjOQXeSJpZ8QsKRCUbeQQbaEzD6cGZv/VVzgYZfbEFz3xAb+nqVeKA JftTQeful80+cpUNalFMY7ozhbXznLwKGB4X5EnC5COLhJJdXOTEx9F0ASwvdi1p hvNdZ1wiRQvyvLyhvI2wQw== -----END DSA PRIVATE KEY----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/server-certificate.pem0000664000000000000000000000205012562450203023557 0ustar -----BEGIN CERTIFICATE----- MIIC5TCCAqOgAwIBAgIEGK67vDALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1c3RlZC5DQS5j b20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTMwMzIwMTU0NzAzWhgPMjI4NzAxMDIxNTQ3 MDNaMDUxIjAgBgNVBAMTGUExLkdvb2QuU2VydmVyLmRvbWFpbi5jb20xDzANBgNVBAoTBlNlcnZl cjCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEm aUVdQCJR+1k9jVj6v8X1ujD2y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX 58aophUPBPuD9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLr hAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrUWU/mcQcQgYC0 SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6ITVi8ftiegEkO8yk8b6oUZCJ qIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GEAAKBgGd51fWwKIVM6wIsVk0vo86Hq3q2gxlP0STl /EzEBew9buSMXPCqQvQIhw/Ud6/f/Q0KxctPn8MqO++jCCSYMYH5d1ME85X9QM2mh4/xejYWQdUl qJKkHPo6MbLgEfQY7UxXxMq9Ekij/T6MyS1Rd9xwCCf2wJhjV6Jq35KplnWMo0IwQDAdBgNVHQ4E FgQUlZgov7xbp4kcuwMI7d7AAz4DH8YwHwYDVR0jBBgwFoAUqxC+jvigfpiR6M3fb6XppgGxFJYw CwYHKoZIzjgEAwUAAy8AMCwCFBTG8MXcRKCTW6gBKIjp23BGWJfIAhRLFMZ4oYLsdCImFOl7/Hi3 NdK9cw== -----END CERTIFICATE----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/client.pkcs120000664000000000000000000000300412562450203021571 0ustar 0‚0‚º *†H†÷  ‚«‚§0‚£0‚ *†H†÷  ‚ù‚õ0‚ñ0‚í *†H†÷   ‚‚0‚~0( *†H†÷  0YMRš)H„u+¼çBw)%.È‚P¬¬˜utbæßIœýšáˆè¼°3¯Srao‰õ4Œ¹HA.ºÚJ²H…ìBdé.ñq‡š…bgžï²Ï¸RsË^7©ÿT³"[rýõT,â2ùš ‡ÄVBjš¯¬~ÛéA©QFs ^´›!kh*§1a:„Q· Ê`ñ ¥ñO–°Ê(‘xØeQ ÛW¯ƒ]ÏíkuMå¿4Ò^lìø—c°rã./ZkßRË ´Ù­ºaè1ñÊR©°Ú9Ò«Á9?Âð©ÓÍë=™@¿OF°C‚Â9ˆrØ|þfÏÀÄmñöŒ‹ 3:GŠ%p²>Ý‚Vüìç˴àÕÅ”Zàx?ïÂîYLsœOúEî+q‰ûf' /Zg Ñ·BÝéú?B±)Q_~i'v¨xëûì)p˜@¿ß+«®¿à„3•oŸ‹ ßÚå8kÛÞmG÷y å4SÁ.žr|é®[NS- Q†€7ƒp2 )a{ÓËýÒsYí„:5ü=&y…cnä b^Yõu5"à½ÔÚš!G$¿=Õ«€Ö–ÂRY×õÆ%¸`@°ðMfåŒð à\ùKé;ÝÚáµ=ê9TR¥(ûTÒg9®8Ak@(’+ZçZ2z¸©= J@½Ò»ÂOeèÓ`_”ÉB®sL"ý%à¬òÿ?—ñ þÞÔµÆI( ÍŒö¡ò4®Â€î³ÅñGÔv%æOœEa"|Gégš‰žMÑuA¥JbõÐ/”\+|2%·R‚©mJÚå·¹PžË–\ƒK_ fD£­˜Ñ‘¢ jÆ7|‹÷• £¥´:5۬܈J"lÃNèÑjù : æËxý¥—@¢À&³Œ0³O¿Ñû¤ûàhøàóÓÁeÂ2Q ’ºôiQú¨j™eðɦæ1sðfÎxÓA¬”?‚kØ‘ôВŪ”Ïã#3%lV[OÈGÇ1dæb±oŸÞÊÙ2m»&f—B,ƒºÝö/rÖN@b¯èIÚïû5þIÿMý0=0!0 +ß๪ùH)ÆòpÎ-Ú—¬b²C¥xj $ÒEI‚zUʰlh“qpid-proton-0.10/tests/python/proton_tests/ssl_db/client-request.pem0000664000000000000000000000160112562450203022736 0ustar -----BEGIN NEW CERTIFICATE REQUEST----- MIICWjCCAhgCAQAwJTESMBAGA1UEAxMJMTI3LjAuMC4xMQ8wDQYDVQQKEwZDbGllbnQwggG4MIIB LAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZ PY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7 g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKB gQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgW E7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8G kotmXoB7VSVkAUw7/s9JKgOBhQACgYEA9i8UBf21xW/1P6uxsXekPf76OLw8Pqw8WYflFDxHJlcP OzmN2S7gBVsG2Yun6zCZD82dBG+hHqUu98HmA7PKQ9T8uu0QQsRunVJxeo3BNCTLY6Rfv5gZIqeW JZmbm/vau22AYv2P5z+MpwMCPtn6/aQe6BtO5nT0DFctD1w/FbGgMDAuBgkqhkiG9w0BCQ4xITAf MB0GA1UdDgQWBBRotQi4DTooKy1HKd/ovpfz4D7/KDALBgcqhkjOOAQDBQADLwAwLAIUWRqolXje 1mMzoode9hn5ngboHpsCFBIGJt8s5WYcW3j4JVCaoqUypJB/ -----END NEW CERTIFICATE REQUEST----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/client-private-key.pem0000664000000000000000000000160312562450203023510 0ustar Bag Attributes friendlyName: client-certificate localKeyID: 54 69 6D 65 20 31 33 36 33 37 39 34 34 32 33 34 36 33 Key Attributes: -----BEGIN DSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,357362201C460FE9 L7ubHRpBWVYpCicB5srjF7AFpTDN/faMbz9FuvFmA/8HBhwOrlbKau0ASoDqvGbq Gcx4BqXvNx22gJbu4S8224elyov7beI58VQ4/k1kJROa7Gyi84RpqxmdScCaYrNE 2beGa+AshN2vgwtRzeUDHxjKj/vPlDjdBq3cT88W7zrfm7J2E4HuNtwTwQ+EhBh9 c5P+yxOmF93AxQzywGQPkmhXfhSHkoUWX/7NNtdhL07m4CY8nWwrGfHm828/d20Y eaGhyuxiC9hN5mhSct0THIyLSTz6fm7sJLZzDM1poqEKVdZQyytfUkpzCjDik3em y1Pjymve8QcrWEN4SLO7V7J8Zkv2N9AjJt/XiZWAdn13Gj+qLs/DI//AtlthqntJ qH0rZeV0DPf6tKZmj3sTegOdmvv8hAVX/DkEwC9wkxhKU7xHmBzX+uMqIauL70GH F4w9dVGOCSFNFP3bwoDCotJbLHx/vMpu/1AMibXUnPVQkZaWf3xlmz7ufJZh3Vhq buAuLw6t2ji8wnpOfOOB9hm2cGBcPlw2s3AHiM66vhLgOvtKQbGxMTni6g/kya5u BuWOjFk54PyY1DM54VK0FHoBxcvMmLo5 -----END DSA PRIVATE KEY----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/client-certificate.pem0000664000000000000000000000202312562450203023527 0ustar -----BEGIN CERTIFICATE----- MIIC2DCCApSgAwIBAgIETM/4+TALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1c3RlZC5DQS5j b20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTMwMzIwMTU0NzA0WhgPMjI4NzAxMDIxNTQ3 MDRaMCUxEjAQBgNVBAMTCTEyNy4wLjAuMTEPMA0GA1UEChMGQ2xpZW50MIIBuDCCASwGByqGSM44 BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6 MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1 VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+Gghdab Pd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim 4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1Ul ZAFMO/7PSSoDgYUAAoGBAPYvFAX9tcVv9T+rsbF3pD3++ji8PD6sPFmH5RQ8RyZXDzs5jdku4AVb BtmLp+swmQ/NnQRvoR6lLvfB5gOzykPU/LrtEELEbp1ScXqNwTQky2OkX7+YGSKnliWZm5v72rtt gGL9j+c/jKcDAj7Z+v2kHugbTuZ09AxXLQ9cPxWxo0IwQDAdBgNVHQ4EFgQUaLUIuA06KCstRynf 6L6X8+A+/ygwHwYDVR0jBBgwFoAUqxC+jvigfpiR6M3fb6XppgGxFJYwCwYHKoZIzjgEAwUAAzEA MC4CFQCWcpy1LVRqK+Udtq4qCpIKDZwTdwIVAJS+GitAJeY2L1ltlgi+cpRLIgGU -----END CERTIFICATE----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/ca.pkcs120000664000000000000000000000273412562450203020707 0ustar 0‚Ø0‚’ *†H†÷  ‚ƒ‚0‚{0‚è *†H†÷  ‚Ù‚Õ0‚Ñ0‚Í *†H†÷   ‚‚0‚~0( *†H†÷  0póqÚ“Ç¢iÍ©»áÆ>- ’ׂPjÁî4àßÈlÕƒ‰¸Ð¸F,t›a˜ «ä³)]MÌÒS2ìKGcz9ð ’º7N¬Ú\Tž1(Òà*—nÞ÷ü¹°`¦Ôˆü+ ËÆ pÒº’/akp"EO:,ó…\»—Ód¨\õy´‡Æ5{ÜÌ%qÊÍÓUO‡µc‚þ;ñ­Û”˜¿Òž%¸›¢¯ö߆:#nÑ¢uÒ§ v¿ ¸ûΫâµ}ªQ”FÄ/­ÕF˜¬®¹ílb¾Û³‰·WWsb„“cAh«0³@·Áj;Yꉉ‚GšE²fG<ZÄÎI­%xäl{ƒÃ`jhý|%C:Q€ ÉyR¨ª8Éã’‚ÇÃv›ýLÎ" I{‰¼'É«¢Q´TÀNù °\(06nÏD™õbHöž~á?ʈlòÝ;Ñ7»>€ÄÎÖLÏJ¯õhôAÎh180 *†H†÷  1ca0! *†H†÷  1Time 13637944219250‚‹ *†H†÷  ‚|0‚x0‚q *†H†÷ 0( *†H†÷  0)Cšæb F0VŸŸÙ;‚m5Šý€‚8E™ØgœŸø¸C>5B¢ލ†ßü¨_<±Ä×yùe¬UªÖ `ˆ:%ú?'’gŽ —é8ؽÝá]"nŽðsïÇæNåîÛ…šn¿á"VdŸØ]xÜmFËåU˜ím|¼¿;ŽÌliÌ*%º“ìÁçù3‰ÐAÔüªÞË-U4=w,´£¯wÖ·0ªð¥†ÕxãËä£Z£ýŠTÕÞDÍg‡ZörÕ#“²Nð Mµ„ÌåÊ|›ò­å»u”Œ™i±JÆð¸Œ±¹éà57~&ߢaÞ«»-ª*7^;ä—mžÒW¨.6Å_¸Úf²k±ã 4à¥UÍê/…ó“~-jÀ'–&[ù«sWƒÑßÃ;ââÁz^uT޲rv£ÅóE öÉ4 Ã÷< îÖé©VpMÅŃEÞyÄÑ(;/ÕWõ%^°ø%¢Ì+?ÃúüÉ NÃ¥  ‡g7ìíqý.›µmC°Ìë’Bª`_N'ºS,åûùÒ”ãûhËžjëO’«N‰:4™Åayšö¯-QZØ›³a4Ò%5qî2/˜”íŸÈSi¿-ðÆÂd\x!ñ,>ð@"2¦Œ\,NÍR±†³ë[ÁÔ/¥/H?I–2¨ÿQþŒê©š£CÑ26”Ù®òÝ•j¤t ûV}F§g\îŸèãÒÜ@Û¹žÜ @¦?UQ0Ð3-±d+í‹n¼ùói77IÅ…ˆ^p¬„á=#…è„äzߥ4·.µ—´;ë¸Ykòosªt›ê¬]ö"MÌ?g8„?ØìªQ™õNqÞy ¯g(½&P¥L&Ü Áaÿ¬6wþ”©Š8kœXu)‘¾¼¿å¨Ž¨“ûwÄÛ•f.¦ìÔÔßSi³’íËÂHdÍ”§Î«eÄ+ 4ë"ìJed/åâÂ4V§ó~üò’sø$Š-Kœ&P®µªÊÐôG¯F0=0!0 +“‰£™g¢Ž¢W6‡¤ì1"ñ\üY§·©®Eî«Êš\<;룺S«Äqpid-proton-0.10/tests/python/proton_tests/ssl_db/ca-certificate.pem0000664000000000000000000000227112562450203022641 0ustar Bag Attributes friendlyName: ca localKeyID: 54 69 6D 65 20 31 33 36 33 37 39 34 34 32 31 39 32 35 subject=/CN=Trusted.CA.com/O=Trust Me Inc. issuer=/CN=Trusted.CA.com/O=Trust Me Inc. -----BEGIN CERTIFICATE----- MIICwTCCAn+gAwIBAgIEe/AadjALBgcqhkjOOAQDBQAwMTEXMBUGA1UEAxMOVHJ1 c3RlZC5DQS5jb20xFjAUBgNVBAoTDVRydXN0IE1lIEluYy4wIBcNMTMwMzIwMTU0 NzAxWhgPMjI4NzAxMDIxNTQ3MDFaMDExFzAVBgNVBAMTDlRydXN0ZWQuQ0EuY29t MRYwFAYDVQQKEw1UcnVzdCBNZSBJbmMuMIIBuDCCASwGByqGSM44BAEwggEfAoGB AP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6 MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E +4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeO utRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/ C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYUA AoGBAOAw2uKAz6k56DRzZBjSJ/W8OfYg6LV64IliFhE93hhseHF7iOaCycuVocQA fJVO0DDtssf0CM3uCxPNiEbDrdfUu75BCvX6h/CT/Qzgf+eLldJSHtAJjU1zSxN+ GtIBB8cQhCdh5sQL6sEJYgOiIxdW1jKf3/n0MuD6qTXi/9f1oyEwHzAdBgNVHQ4E FgQUqxC+jvigfpiR6M3fb6XppgGxFJYwCwYHKoZIzjgEAwUAAy8AMCwCFD2ikCZi 8V4H+LuqCBD4Vz0ug0ntAhQ4kE+VGY7YK++kDZ8jHcfyDUNVAw== -----END CERTIFICATE----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/bad-server.pkcs120000664000000000000000000000276412562450203022361 0ustar 0‚ð0‚ª *†H†÷  ‚›‚—0‚“0‚ø *†H†÷  ‚é‚å0‚á0‚Ý *†H†÷   ‚‚0‚~0( *†H†÷  0Ì£©ÄÆr|ˆ^-¨^±Ao¡4ð‚P^â½¹ƒ˜Š­»èFôØ55¨¿è’ŸL³)WÉù'jˆ3¼}@Ç,Öë?ð÷š4ìRÍž¢ØRu¦Ô1¹q†—ã ’»¿šB¯“ÿê+;:v/ð î¹â…Ïü惷àÎ/¿TêÒ[®è©>Q £D´M8©¯ïýÑü˜«Âä¾!3áž6&·QÜ‘7ʹÚEÒP#:žŽ_ÎB”¬9ãjÛÄè¡„ •U&ò¼Yi·¶áS÷MGúZ0¾,‘ døá,áºîÜ6‰¼õ-W2Ù4#©3M§^®W¯«DÍíô8r¢þzò­¯a Ó`õ+j?ÎîÎU²¡ÐœÈ™©].~1ØiSvч=+ YÜ1ÖƒãôG¢Š²ÈŠíò ²øü{ÃÛ2«oµi°GhúHkËW¿o´ƒ„%HöM\R¶Ê¨Œ´c Ù׌†Á n1H0# *†H†÷  1bad-server0! *†H†÷  1Time 13637944246040‚“ *†H†÷  ‚„0‚€0‚y *†H†÷ 0( *†H†÷  0ÝZLÓ¿LdÐÁWê4›{Úù}V€‚@£ãl¹tVÄМ9¡çâooúî>tPABîíÑœ˜,&9b×Ú¤éð÷’¾8$°ž"Nô«O0ëöMùðñã#u8÷ùQŽgÌ" “e÷Ûvý y<Õ<Ž;F nÛ ú™´Áv¦ÁÖ*,\ؤíAh4ÉÌÌWÔ‹göd)D9ÌVy¬rÄqAìÉÞm=Ûð«’ZŸ¯T™Â·7ƒFÎŽQapÕÔp1*Ç Õ„9¯ÌRô_Z†(¤£»¦J¥È*—T]Š.1Ôþ¤bˆ'Ð#뤙#­@ŽÏJä_aÑ«ÝØÈ\'åþz¥kïZüÅ‚ c>i^¦ŽçŠõ~ù+ªKˆRÞõÀ\Ä}@™_ ºXF&:GÐípS)'YxB´‡%ä”uƒk)8—¡±BĬu$¿<|1GÁmA²ÿˆá£.²{vðFt¡‚pS|ª¶ “úh˜òï\/\ N#¸LØý[\!ÝÄÙÌÕáÓ @šOR×çM±„±DŠtä¯%털zÖ f+ë¿ë]ßÊ-°6‘½ ¯Œóà´fÀ!ŽS ^¶[ú× kçz™QršiKæY&†É‰Ý½Núý) _­Ú!ô ’¤oѨy2¡§i)Ía¡ Y*úÍžšèhËïyR4Gr°vv¹ »q‚‘æD¿üWùÔ2LBˆ[{Þr¸øôît™Z"¼¦¬¹&ú X¦AJ¡ŸžhW4Òf»(sÿvþ8å0ÇFâ~\ÎݨÂJˆjÜ«g<äõîÊ8«oWžÿÔýHUËX;cÖƒ35skHI 7M38Æ’–Ðô¾³+EÓŸ@oÆÜT‰XÑá*Í#3ßcÞknd±TM÷Oo±®ÞÝ«j….M¢Š -Îì¾È­+îKÎk6™0[]¹20”µ^:÷ºwß±°jaY«—‹§Y¢†ž ÝHÕp4È–NÙö²Å#l¥:WµF¢”£ÙgQëïVÜÃD^Ò‘€ ¸4WË.{ [çpþOdtŒn“ÈùöÁ&†•S:+`"·Œ¤|:º±ž™ÉW(´3ðèe^‚ÓÈ1Ö¹<‰¶§0=0!0 +0{t4YÀ•ŽäуŸhÆŒÕU'šæöö>ëDÑÛá0’[±b9qpid-proton-0.10/tests/python/proton_tests/ssl_db/bad-server-private-key.pem0000664000000000000000000000156312562450203024271 0ustar Bag Attributes friendlyName: bad-server localKeyID: 54 69 6D 65 20 31 33 36 33 37 39 34 34 32 34 36 30 34 Key Attributes: -----BEGIN DSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,AB078D4A74BE8031 iEW6u5kMfaX9SIynirmIQk6EvqrGjl8uhGC5k1UHBoQRnYUy/wrz9Ufcw4JLXXmo 8CoX1JCwo/gvlqV3KSszujgkCvCndhlLoe5PwbhMsSSiruTkt9b70bOHxG5AHp/m sr/0cFgs+O1USt9IVmAXj6+ALndWfOBSVH7J40BTDHCGbizB/QRnAk6+VWW2tQRZ mU2xL1drY7n9bvF4O9faDe5C2C0v1+asswXnJmZnQVsTnA5+kwQok6uLfJjVWt7j WS9ME5nIJSOi/ZkIyr2cr4m4TPbPw/UB+funT1/OKg8iyMyUvjwV3fopjo/9Sz/S Tpt+sjUJelL7VBBkuppiZDHjPQ/g0IAc7+HEbc1or8h15AIiSWxEg/HRUtZqbsgC UyW+5qvKyYrPzZYkkJIeRLwkMEAU1sdmHBVutALc9xUyVR8jXJtXNu3V82NQ7otv pRlLpAs4Fn6SOIKAJvL6YdxgSiZFdta/Ory2VXqopJad+EEPPprf8ndk3Mv38l7M gIMQdZD8hhWaPw8zhXfhfnjz7ejPhtgQznkyzJPIFtbrq2HUZKuKpOBkCFfu/E4s k6PC6aW9pNGQW0PqdKuHPA== -----END DSA PRIVATE KEY----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/bad-server-certificate.pem0000664000000000000000000000225712562450203024314 0ustar Bag Attributes friendlyName: bad-server localKeyID: 54 69 6D 65 20 31 33 36 33 37 39 34 34 32 34 36 30 34 subject=/CN=127.0.0.1/O=Not Trusted Inc issuer=/CN=127.0.0.1/O=Not Trusted Inc -----BEGIN CERTIFICATE----- MIICujCCAnigAwIBAgIEfWGDZDALBgcqhkjOOAQDBQAwLjESMBAGA1UEAxMJMTI3 LjAuMC4xMRgwFgYDVQQKEw9Ob3QgVHJ1c3RlZCBJbmMwIBcNMTMwMzIwMTU0NzA0 WhgPMjI4NzAxMDIxNTQ3MDRaMC4xEjAQBgNVBAMTCTEyNy4wLjAuMTEYMBYGA1UE ChMPTm90IFRydXN0ZWQgSW5jMIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4Ed dRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs 14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208Ue wwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BY HPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+Zx BxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx +2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGATqLV argkIbJ0kfQxODtbtouvBPjA2n7VMbmC+YrKQj/YUOjtW/AtD+9lfFy3aekHAMcS HFYmo3U6rUCF6sFnnesq6eGi5F5oGVWCI1trUMVx6zFx2zMg+47RpbD0K2JEwzUg WJmMgu+ZFvzt76lrlS06K33I260dcbUDECWjKNSjITAfMB0GA1UdDgQWBBTSy0ab MCPY1+u0078oxrvoZYwnAzALBgcqhkjOOAQDBQADLwAwLAIUYOCVrWN5+KrdFD6F HDAMD/MQ7OkCFByiloyK+lFrZI+AYo/xEdbJLqcH -----END CERTIFICATE----- qpid-proton-0.10/tests/python/proton_tests/ssl_db/README.txt0000664000000000000000000001126012562450203020767 0ustar The following certificate files are used by the SSL unit tests (ssl.py): ca-certificate.pem - contains the public certificate identifying a "trusted" Certificate Authority. This certificate is used to sign the certificates that identify the SSL servers and clients run by the tests. client-certificate.pem - the public certificate used to identify the client. Signed by the CA. client-private-key.pem - encrypted key used to create client-certificate.pem. Password is "client-password" server-certificate.pem - the public certificate used to identify the server. Signed by the CA. The CommonName is "A1.Good.Server.domain.com", and is checked by some unit tests. server-private-key.pem - encrypted key used to create server-certificate.pem. Password is "server-password" bad-server-certificate.pem, bad-server-private-key.pem - a certificate/key that is not trusted by the client, for negative test. server-wc-certificate.pem and server-wc-private-key.pem - similar to server-certificate.pem and server-private-key.pem, but contains Subject Alternate Name entries, and a wildcard CommonName. Used for certificate name checking tests. These certificates have been created using the OpenSSL tool. The following bash script can be used to create these certificates (requires keytool from Java 1.7, and openssl): --8<-- #!/bin/bash #set -x rm -f *.pem *.pkcs12 # Create a self-signed certificate for the CA, and a private key to sign certificate requests: keytool -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -genkey -dname "O=Trust Me Inc.,CN=Trusted.CA.com" -validity 99999 openssl pkcs12 -nokeys -passin pass:ca-password -in ca.pkcs12 -passout pass:ca-password -out ca-certificate.pem # Create a certificate request for the server certificate. Use the CA's certificate to sign it: keytool -storetype pkcs12 -keystore server.pkcs12 -storepass server-password -alias server-certificate -keypass server-password -genkey -dname "O=Server,CN=A1.Good.Server.domain.com" -validity 99999 keytool -storetype pkcs12 -keystore server.pkcs12 -storepass server-password -alias server-certificate -keypass server-password -certreq -file server-request.pem keytool -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -gencert -rfc -validity 99999 -infile server-request.pem -outfile server-certificate.pem openssl pkcs12 -nocerts -passin pass:server-password -in server.pkcs12 -passout pass:server-password -out server-private-key.pem # Create a certificate request for the client certificate. Use the CA's certificate to sign it: keytool -storetype pkcs12 -keystore client.pkcs12 -storepass client-password -alias client-certificate -keypass client-password -genkey -dname "O=Client,CN=127.0.0.1" -validity 99999 keytool -storetype pkcs12 -keystore client.pkcs12 -storepass client-password -alias client-certificate -keypass client-password -certreq -file client-request.pem keytool -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -gencert -rfc -validity 99999 -infile client-request.pem -outfile client-certificate.pem openssl pkcs12 -nocerts -passin pass:client-password -in client.pkcs12 -passout pass:client-password -out client-private-key.pem # Create a "bad" certificate - not signed by a trusted authority keytool -storetype pkcs12 -keystore bad-server.pkcs12 -storepass server-password -alias bad-server -keypass server-password -genkey -dname "O=Not Trusted Inc,CN=127.0.0.1" -validity 99999 openssl pkcs12 -nocerts -passin pass:server-password -in bad-server.pkcs12 -passout pass:server-password -out bad-server-private-key.pem openssl pkcs12 -nokeys -passin pass:server-password -in bad-server.pkcs12 -passout pass:server-password -out bad-server-certificate.pem # Create a server certificate with several alternate names, including a wildcarded common name: keytool -ext san=dns:alternate.name.one.com,dns:another.name.com -storetype pkcs12 -keystore server.pkcs12 -storepass server-password -alias server-wc-certificate -keypass server-password -genkeypair -dname "O=Server,CN=*.prefix*.domain.com" -validity 99999 keytool -ext san=dns:alternate.name.one.com,dns:another.name.com -storetype pkcs12 -keystore server.pkcs12 -storepass server-password -alias server-wc-certificate -keypass server-password -certreq -file server-wc-request.pem keytool -ext san=dns:alternate.name.one.com,dns:another.name.com -storetype pkcs12 -keystore ca.pkcs12 -storepass ca-password -alias ca -keypass ca-password -gencert -rfc -validity 99999 -infile server-wc-request.pem -outfile server-wc-certificate.pem openssl pkcs12 -nocerts -passin pass:server-password -in server.pkcs12 -passout pass:server-password -out server-wc-private-key.pem qpid-proton-0.10/tests/python/proton_tests/ssl.py0000664000000000000000000012255112562450203017204 0ustar from __future__ import absolute_import # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import os from . import common import random import string import subprocess from proton import * from .common import Skipped, pump def _testpath(file): """ Set the full path to the certificate,keyfile, etc. for the test. """ return os.path.join(os.path.dirname(__file__), "ssl_db/%s" % file) class SslTest(common.Test): def __init__(self, *args): common.Test.__init__(self, *args) self._testpath = _testpath def setup(self): if not common.isSSLPresent(): raise Skipped("No SSL libraries found.") self.server_domain = SSLDomain(SSLDomain.MODE_SERVER) self.client_domain = SSLDomain(SSLDomain.MODE_CLIENT) def teardown(self): self.server_domain = None self.client_domain = None class SslTestConnection(object): """ Represents a single SSL connection. """ def __init__(self, domain=None, mode=Transport.CLIENT, session_details=None, conn_hostname=None, ssl_peername=None): if not common.isSSLPresent(): raise Skipped("No SSL libraries found.") self.ssl = None self.domain = domain self.transport = Transport(mode) self.connection = Connection() if conn_hostname: self.connection.hostname = conn_hostname if domain: self.ssl = SSL( self.transport, self.domain, session_details ) if ssl_peername: self.ssl.peer_hostname = ssl_peername # bind last, after all configuration complete: self.transport.bind(self.connection) def _pump(self, ssl_client, ssl_server, buffer_size=1024): pump(ssl_client.transport, ssl_server.transport, buffer_size) def _do_handshake(self, client, server): """ Attempt to connect client to server. Will throw a TransportException if the SSL handshake fails. """ client.connection.open() server.connection.open() self._pump(client, server) if client.transport.closed: return assert client.ssl.protocol_name() is not None client.connection.close() server.connection.close() self._pump(client, server) def test_defaults(self): """ By default, both the server and the client support anonymous ciphers - they should connect without need for a certificate. """ server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) # check that no SSL connection exists assert not server.ssl.cipher_name() assert not client.ssl.protocol_name() #client.transport.trace(Transport.TRACE_DRV) #server.transport.trace(Transport.TRACE_DRV) client.connection.open() server.connection.open() self._pump( client, server ) # now SSL should be active assert server.ssl.cipher_name() is not None assert client.ssl.protocol_name() is not None client.connection.close() server.connection.close() self._pump( client, server ) def test_ssl_with_small_buffer(self): self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.connection.open() server.connection.open() small_buffer_size = 1 self._pump( client, server, small_buffer_size ) assert client.ssl.protocol_name() is not None client.connection.close() server.connection.close() self._pump( client, server ) def test_server_certificate(self): """ Test that anonymous clients can still connect to a server that has a certificate configured. """ self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.connection.open() server.connection.open() self._pump( client, server ) assert client.ssl.protocol_name() is not None client.connection.close() server.connection.close() self._pump( client, server ) def test_server_authentication(self): """ Simple SSL connection with authentication of the server """ self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.connection.open() server.connection.open() self._pump( client, server ) assert client.ssl.protocol_name() is not None client.connection.close() server.connection.close() self._pump( client, server ) def test_client_authentication(self): """ Force the client to authenticate. """ # note: when requesting client auth, the server _must_ send its # certificate, so make sure we configure one! self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER, self._testpath("ca-certificate.pem") ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) # give the client a certificate, but let's not require server authentication self.client_domain.set_credentials(self._testpath("client-certificate.pem"), self._testpath("client-private-key.pem"), "client-password") self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER ) client = SslTest.SslTestConnection( self.client_domain ) client.connection.open() server.connection.open() self._pump( client, server ) assert client.ssl.protocol_name() is not None client.connection.close() server.connection.close() self._pump( client, server ) def test_client_authentication_fail_bad_cert(self): """ Ensure that the server can detect a bad client certificate. """ # note: when requesting client auth, the server _must_ send its # certificate, so make sure we configure one! self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER, self._testpath("ca-certificate.pem") ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) self.client_domain.set_credentials(self._testpath("bad-server-certificate.pem"), self._testpath("bad-server-private-key.pem"), "server-password") self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER ) client = SslTest.SslTestConnection( self.client_domain ) client.connection.open() server.connection.open() self._pump( client, server ) assert client.transport.closed assert server.transport.closed assert client.connection.state & Endpoint.REMOTE_UNINIT assert server.connection.state & Endpoint.REMOTE_UNINIT def test_client_authentication_fail_no_cert(self): """ Ensure that the server will fail a client that does not provide a certificate. """ # note: when requesting client auth, the server _must_ send its # certificate, so make sure we configure one! self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER, self._testpath("ca-certificate.pem") ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER ) client = SslTest.SslTestConnection( self.client_domain ) client.connection.open() server.connection.open() self._pump( client, server ) assert client.transport.closed assert server.transport.closed assert client.connection.state & Endpoint.REMOTE_UNINIT assert server.connection.state & Endpoint.REMOTE_UNINIT def test_client_server_authentication(self): """ Require both client and server to mutually identify themselves. """ self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER, self._testpath("ca-certificate.pem") ) self.client_domain.set_credentials(self._testpath("client-certificate.pem"), self._testpath("client-private-key.pem"), "client-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.connection.open() server.connection.open() self._pump( client, server ) assert client.ssl.protocol_name() is not None client.connection.close() server.connection.close() self._pump( client, server ) def test_server_only_authentication(self): """ Client verifies server, but server does not verify client. """ self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER ) self.client_domain.set_credentials(self._testpath("client-certificate.pem"), self._testpath("client-private-key.pem"), "client-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.connection.open() server.connection.open() self._pump( client, server ) assert client.ssl.protocol_name() is not None client.connection.close() server.connection.close() self._pump( client, server ) def test_bad_server_certificate(self): """ A server with a self-signed certificate that is not trusted by the client. The client should reject the server. """ self.server_domain.set_credentials(self._testpath("bad-server-certificate.pem"), self._testpath("bad-server-private-key.pem"), "server-password") self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER ) self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.connection.open() server.connection.open() self._pump( client, server ) assert client.transport.closed assert server.transport.closed assert client.connection.state & Endpoint.REMOTE_UNINIT assert server.connection.state & Endpoint.REMOTE_UNINIT del server del client # now re-try with a client that does not require peer verification self.client_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER ) client = SslTest.SslTestConnection( self.client_domain ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client.connection.open() server.connection.open() self._pump( client, server ) assert client.ssl.protocol_name() is not None client.connection.close() server.connection.close() self._pump( client, server ) def test_allow_unsecured_client_which_connects_unsecured(self): """ Server allows an unsecured client to connect if configured. """ self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER, self._testpath("ca-certificate.pem") ) # allow unsecured clients on this connection self.server_domain.allow_unsecured_client() server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) # non-ssl connection client = SslTest.SslTestConnection() client.connection.open() server.connection.open() self._pump( client, server ) assert server.ssl.protocol_name() is None client.connection.close() server.connection.close() self._pump( client, server ) def test_allow_unsecured_client_which_connects_secured(self): """ As per test_allow_unsecured_client_which_connects_unsecured but client actually uses SSL """ self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER, self._testpath("ca-certificate.pem") ) self.client_domain.set_credentials(self._testpath("client-certificate.pem"), self._testpath("client-private-key.pem"), "client-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER ) # allow unsecured clients on this connection #self.server_domain.allow_unsecured_client() # client uses ssl. Server should detect this. client = SslTest.SslTestConnection( self.client_domain ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client.connection.open() server.connection.open() self._pump( client, server ) assert server.ssl.protocol_name() is not None client.connection.close() server.connection.close() self._pump( client, server ) def test_disallow_unsecured_client(self): """ Non-SSL Client is disallowed from connecting to server. """ self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) # non-ssl connection client = SslTest.SslTestConnection() client.connection.open() server.connection.open() self._pump( client, server ) assert client.transport.closed assert server.transport.closed assert client.connection.state & Endpoint.REMOTE_UNINIT assert server.connection.state & Endpoint.REMOTE_UNINIT def test_session_resume(self): """ Test resume of client session. """ self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.server_domain.set_peer_authentication( SSLDomain.ANONYMOUS_PEER ) self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER ) # details will be used in initial and subsequent connections to allow session to be resumed initial_session_details = SSLSessionDetails("my-session-id") server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain, session_details=initial_session_details ) # bring up the connection and store its state client.connection.open() server.connection.open() self._pump( client, server ) assert client.ssl.protocol_name() is not None # cleanly shutdown the connection client.connection.close() server.connection.close() self._pump( client, server ) # destroy the existing clients del client del server # now create a new set of connections, use last session id server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) # provide the details of the last session, allowing it to be resumed client = SslTest.SslTestConnection( self.client_domain, session_details=initial_session_details ) #client.transport.trace(Transport.TRACE_DRV) #server.transport.trace(Transport.TRACE_DRV) client.connection.open() server.connection.open() self._pump( client, server ) assert server.ssl.protocol_name() is not None if(API_LANGUAGE=="C"): assert client.ssl.resume_status() == SSL.RESUME_REUSED else: # Java gives no way to check whether a previous session has been resumed pass client.connection.close() server.connection.close() self._pump( client, server ) # now try to resume using an unknown session-id, expect resume to fail # and a new session is negotiated del client del server server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain, session_details=SSLSessionDetails("some-other-session-id") ) client.connection.open() server.connection.open() self._pump( client, server ) assert server.ssl.protocol_name() is not None if(API_LANGUAGE=="C"): assert client.ssl.resume_status() == SSL.RESUME_NEW client.connection.close() server.connection.close() self._pump( client, server ) def test_multiple_sessions(self): """ Test multiple simultaineous active SSL sessions with bi-directional certificate verification, shared across two domains. """ self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.server_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.server_domain.set_peer_authentication( SSLDomain.VERIFY_PEER, self._testpath("ca-certificate.pem") ) self.client_domain.set_credentials(self._testpath("client-certificate.pem"), self._testpath("client-private-key.pem"), "client-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER ) max_count = 100 sessions = [(SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ), SslTest.SslTestConnection( self.client_domain )) for x in range(max_count)] for s in sessions: s[0].connection.open() self._pump( s[0], s[1] ) for s in sessions: s[1].connection.open() self._pump( s[1], s[0] ) assert s[0].ssl.cipher_name() is not None assert s[1].ssl.cipher_name() == s[0].ssl.cipher_name() for s in sessions: s[1].connection.close() self._pump( s[0], s[1] ) for s in sessions: s[0].connection.close() self._pump( s[1], s[0] ) def test_server_hostname_authentication(self): """ Test authentication of the names held in the server's certificate against various configured hostnames. """ # Check the CommonName matches (case insensitive). # Assumes certificate contains "CN=A1.Good.Server.domain.com" self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.ssl.peer_hostname = "a1.good.server.domain.com" assert client.ssl.peer_hostname == "a1.good.server.domain.com" self._do_handshake( client, server ) del server del client self.teardown() # Should fail on CN name mismatch: self.setup() self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.ssl.peer_hostname = "A1.Good.Server.domain.comX" self._do_handshake( client, server ) assert client.transport.closed assert server.transport.closed assert client.connection.state & Endpoint.REMOTE_UNINIT assert server.connection.state & Endpoint.REMOTE_UNINIT del server del client self.teardown() # Wildcarded Certificate # Assumes: # 1) certificate contains Server Alternate Names: # "alternate.name.one.com" and "another.name.com" # 2) certificate has wildcarded CommonName "*.prefix*.domain.com" # # Pass: match an alternate self.setup() self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"), self._testpath("server-wc-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.ssl.peer_hostname = "alternate.Name.one.com" self._do_handshake( client, server ) del client del server self.teardown() # Pass: match an alternate self.setup() self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"), self._testpath("server-wc-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.ssl.peer_hostname = "ANOTHER.NAME.COM" self._do_handshake(client, server) del client del server self.teardown() # Pass: match the pattern self.setup() self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"), self._testpath("server-wc-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.ssl.peer_hostname = "SOME.PREfix.domain.COM" self._do_handshake( client, server ) del client del server self.teardown() # Pass: match the pattern self.setup() self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"), self._testpath("server-wc-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.ssl.peer_hostname = "FOO.PREfixZZZ.domain.com" self._do_handshake( client, server ) del client del server self.teardown() # Fail: must match prefix on wildcard self.setup() self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"), self._testpath("server-wc-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.ssl.peer_hostname = "FOO.PREfi.domain.com" self._do_handshake( client, server ) assert client.transport.closed assert server.transport.closed assert client.connection.state & Endpoint.REMOTE_UNINIT assert server.connection.state & Endpoint.REMOTE_UNINIT del server del client self.teardown() # Fail: leading wildcards are not optional self.setup() self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"), self._testpath("server-wc-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME ) server = SslTest.SslTestConnection( self.server_domain, mode=Transport.SERVER ) client = SslTest.SslTestConnection( self.client_domain ) client.ssl.peer_hostname = "PREfix.domain.COM" self._do_handshake( client, server ) assert client.transport.closed assert server.transport.closed assert client.connection.state & Endpoint.REMOTE_UNINIT assert server.connection.state & Endpoint.REMOTE_UNINIT self.teardown() # Pass: ensure that the user can give an alternate name that overrides # the connection's configured hostname self.setup() self.server_domain.set_credentials(self._testpath("server-wc-certificate.pem"), self._testpath("server-wc-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME ) server = SslTest.SslTestConnection(self.server_domain, mode=Transport.SERVER) client = SslTest.SslTestConnection(self.client_domain, conn_hostname="This.Name.Does.not.Match", ssl_peername="alternate.name.one.com") self._do_handshake(client, server) del client del server self.teardown() # Pass: ensure that the hostname supplied by the connection is used if # none has been specified for the SSL instanace self.setup() self.server_domain.set_credentials(self._testpath("server-certificate.pem"), self._testpath("server-private-key.pem"), "server-password") self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER_NAME ) server = SslTest.SslTestConnection(self.server_domain, mode=Transport.SERVER) client = SslTest.SslTestConnection(self.client_domain, conn_hostname="a1.good.server.domain.com") self._do_handshake(client, server) del client del server self.teardown() def test_defaults_messenger_app(self): """ Test an SSL connection using the Messenger apps (no certificates) """ port = common.free_tcp_ports()[0] receiver = common.MessengerReceiverC() receiver.subscriptions = ["amqps://~0.0.0.0:%s" % port] receiver.receive_count = 1 receiver.timeout = self.timeout receiver.start() sender = common.MessengerSenderC() sender.targets = ["amqps://0.0.0.0:%s/X" % port] sender.send_count = 1 sender.timeout = self.timeout sender.start() sender.wait() assert sender.status() == 0, "Command '%s' failed" % str(sender.cmdline()) receiver.wait() assert receiver.status() == 0, "Command '%s' failed" % str(receiver.cmdline()) def test_server_authentication_messenger_app(self): """ Test an SSL authentication using the Messenger apps. """ port = common.free_tcp_ports()[0] receiver = common.MessengerReceiverC() receiver.subscriptions = ["amqps://~0.0.0.0:%s" % port] receiver.receive_count = 1 receiver.timeout = self.timeout # Note hack - by default we use the client-certificate for the # _server_ because the client-certificate's common name field # is "127.0.0.1", which will match the target address used by # the sender. receiver.certificate = self._testpath("client-certificate.pem") receiver.privatekey = self._testpath("client-private-key.pem") receiver.password = "client-password" receiver.start() sender = common.MessengerSenderC() sender.targets = ["amqps://127.0.0.1:%s/X" % port] sender.send_count = 1 sender.timeout = self.timeout sender.ca_db = self._testpath("ca-certificate.pem") sender.start() sender.wait() assert sender.status() == 0, "Command '%s' failed" % str(sender.cmdline()) receiver.wait() assert receiver.status() == 0, "Command '%s' failed" % str(receiver.cmdline()) def DISABLED_test_defaults_valgrind(self): """ Run valgrind over a simple SSL connection (no certificates) """ # the openssl libraries produce far too many valgrind errors to be # useful. AFAIK, there is no way to wriate a valgrind suppression # expression that will ignore all errors from a given library. # Until we can, skip this test. port = common.free_tcp_ports()[0] receiver = common.MessengerReceiverValgrind() receiver.subscriptions = ["amqps://~127.0.0.1:%s" % port] receiver.receive_count = 1 receiver.timeout = self.timeout receiver.start() sender = common.MessengerSenderValgrind() sender.targets = ["amqps://127.0.0.1:%s/X" % port] sender.send_count = 1 sender.timeout = self.timeout sender.start() sender.wait() assert sender.status() == 0, "Command '%s' failed" % str(sender.cmdline()) receiver.wait() assert receiver.status() == 0, "Command '%s' failed" % str(receiver.cmdline()) # self.server_domain.set_credentials(self._testpath("client-certificate.pem"), # self._testpath("client-private-key.pem"), # "client-password") # self.client_domain.set_trusted_ca_db(self._testpath("ca-certificate.pem")) # self.client_domain.set_peer_authentication( SSLDomain.VERIFY_PEER ) def test_singleton(self): """Verify that only a single instance of SSL can exist per Transport""" transport = Transport() ssl1 = SSL(transport, self.client_domain) ssl2 = transport.ssl(self.client_domain) ssl3 = transport.ssl(self.client_domain) assert ssl1 is ssl2 assert ssl1 is ssl3 transport = Transport() ssl1 = transport.ssl(self.client_domain) ssl2 = SSL(transport, self.client_domain) assert ssl1 is ssl2 # catch attempt to re-configure existing SSL try: ssl3 = SSL(transport, self.server_domain) assert False, "Expected error did not occur!" except SSLException: pass class MessengerSSLTests(common.Test): def setup(self): if not common.isSSLPresent(): raise Skipped("No SSL libraries found.") self.server = Messenger() self.client = Messenger() self.server.blocking = False self.client.blocking = False def teardown(self): self.server.stop() self.client.stop() self.pump() assert self.server.stopped assert self.client.stopped def pump(self, timeout=0): while self.client.work(0) or self.server.work(0): pass self.client.work(timeout) self.server.work(timeout) while self.client.work(0) or self.server.work(0): pass def test_server_credentials(self, cert="server-certificate.pem", key="server-private-key.pem", password="server-password", exception=None): import sys # java doesn't do validation in the same way (yet) if exception and "java" in sys.platform: raise Skipped() self.server.certificate = _testpath(cert) self.server.private_key = _testpath(key) self.server.password = password try: self.server.start() self.server.subscribe("amqps://~0.0.0.0:12345") if exception is not None: assert False, "expected failure did not occur" except MessengerException: e = sys.exc_info()[1] if exception: assert exception in str(e), str(e) else: raise e def test_server_credentials_bad_cert(self): self.test_server_credentials(cert="bad", exception="invalid credentials") def test_server_credentials_bad_key(self): self.test_server_credentials(key="bad", exception="invalid credentials") def test_server_credentials_bad_password(self): self.test_server_credentials(password="bad", exception="invalid credentials") def test_client_credentials(self, trusted="ca-certificate.pem", cert="client-certificate.pem", key="client-private-key.pem", password="client-password", altserv=False, fail=False): if altserv: self.server.certificate = _testpath("bad-server-certificate.pem") self.server.private_key = _testpath("bad-server-private-key.pem") self.server.password = "server-password" else: self.server.certificate = _testpath("client-certificate.pem") self.server.private_key = _testpath("client-private-key.pem") self.server.password = "client-password" self.server.start() self.server.subscribe("amqps://~0.0.0.0:12345") self.server.incoming_window = 10 self.client.trusted_certificates = _testpath(trusted) self.client.certificate = _testpath(cert) self.client.private_key = _testpath(key) self.client.password = password self.client.outgoing_window = 10 self.client.start() self.server.recv() msg = Message() msg.address = "amqps://127.0.0.1:12345" # make sure a large, uncompressible message body works! msg.body = "".join(random.choice(string.ascii_letters) for x in range(10099)) trk = self.client.put(msg) self.client.send() self.pump() if fail: assert self.server.incoming == 0, self.server.incoming assert self.client.status(trk) == ABORTED, self.client.status(trk) else: assert self.server.incoming == 1, self.server.incoming rmsg = Message() self.server.get(rmsg) assert rmsg.body == msg.body self.server.accept() self.pump() assert self.client.status(trk) == ACCEPTED, self.client.status(trk) def test_client_credentials_bad_cert(self): self.test_client_credentials(cert="bad", fail=True) def test_client_credentials_bad_trusted(self): self.test_client_credentials(trusted="bad", fail=True) def test_client_credentials_bad_password(self): self.test_client_credentials(password="bad", fail=True) def test_client_credentials_untrusted(self): self.test_client_credentials(altserv=True, fail=True) qpid-proton-0.10/tests/python/proton_tests/soak.py0000664000000000000000000003170012562450203017333 0ustar from __future__ import absolute_import # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import os import sys from .common import Test, Skipped, free_tcp_ports, \ MessengerReceiverC, MessengerSenderC, \ MessengerReceiverValgrind, MessengerSenderValgrind, \ MessengerReceiverPython, MessengerSenderPython, \ ReactorReceiverC, ReactorSenderC, \ ReactorReceiverValgrind, ReactorSenderValgrind, \ isSSLPresent from proton import * # # Tests that run the apps # class AppTests(Test): def __init__(self, *args): Test.__init__(self, *args) self.is_valgrind = False def default(self, name, value, **kwargs): if self.is_valgrind: default = kwargs.get("valgrind", value) else: default = value return Test.default(self, name, default, **kwargs) @property def iterations(self): return int(self.default("iterations", 2, fast=1, valgrind=2)) @property def send_count(self): return int(self.default("send_count", 17, fast=1, valgrind=2)) @property def target_count(self): return int(self.default("target_count", 5, fast=1, valgrind=2)) @property def send_batch(self): return int(self.default("send_batch", 7, fast=1, valgrind=2)) @property def forward_count(self): return int(self.default("forward_count", 5, fast=1, valgrind=2)) @property def port_count(self): return int(self.default("port_count", 3, fast=1, valgrind=2)) @property def sender_count(self): return int(self.default("sender_count", 3, fast=1, valgrind=2)) def valgrind_test(self): self.is_valgrind = True def setup(self): self.senders = [] self.receivers = [] def teardown(self): pass def _do_test(self, iterations=1): verbose = self.verbose for R in self.receivers: R.start( verbose ) for j in range(iterations): for S in self.senders: S.start( verbose ) for S in self.senders: S.wait() #print("SENDER OUTPUT:") #print( S.stdout() ) assert S.status() == 0, ("Command '%s' failed status=%d: '%s' '%s'" % (str(S.cmdline()), S.status(), S.stdout(), S.stderr())) for R in self.receivers: R.wait() #print("RECEIVER OUTPUT") #print( R.stdout() ) assert R.status() == 0, ("Command '%s' failed status=%d: '%s' '%s'" % (str(R.cmdline()), R.status(), R.stdout(), R.stderr())) # # Traffic passing tests based on the Messenger apps # class MessengerTests(AppTests): _timeout = 60 def _ssl_check(self): if not isSSLPresent(): raise Skipped("No SSL libraries found.") def __init__(self, *args): AppTests.__init__(self, *args) def _do_oneway_test(self, receiver, sender, domain="amqp"): """ Send N messages to a receiver. Parameters: iterations - repeat the senders this many times target_count = # of targets to send to. send_count = # messages sent to each target """ iterations = self.iterations send_count = self.send_count target_count = self.target_count send_total = send_count * target_count receive_total = send_total * iterations port = free_tcp_ports()[0] receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port)] receiver.receive_count = receive_total receiver.timeout = MessengerTests._timeout self.receivers.append( receiver ) sender.targets = ["%s://0.0.0.0:%s/X%d" % (domain, port, j) for j in range(target_count)] sender.send_count = send_total sender.timeout = MessengerTests._timeout self.senders.append( sender ) self._do_test(iterations) def _do_echo_test(self, receiver, sender, domain="amqp"): """ Send N messages to a receiver, which responds to each. Parameters: iterations - repeat the senders this many times target_count - # targets to send to send_count = # messages sent to each target send_batch - wait for replies after this many messages sent """ iterations = self.iterations send_count = self.send_count target_count = self.target_count send_batch = self.send_batch send_total = send_count * target_count receive_total = send_total * iterations port = free_tcp_ports()[0] receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port)] receiver.receive_count = receive_total receiver.send_reply = True receiver.timeout = MessengerTests._timeout self.receivers.append( receiver ) sender.targets = ["%s://0.0.0.0:%s/%dY" % (domain, port, j) for j in range(target_count)] sender.send_count = send_total sender.get_reply = True sender.send_batch = send_batch sender.timeout = MessengerTests._timeout self.senders.append( sender ) self._do_test(iterations) def _do_relay_test(self, receiver, relay, sender, domain="amqp"): """ Send N messages to a receiver, which replies to each and forwards each of them to different receiver. Parameters: iterations - repeat the senders this many times target_count - # targets to send to send_count = # messages sent to each target send_batch - wait for replies after this many messages sent forward_count - forward to this many targets """ iterations = self.iterations send_count = self.send_count target_count = self.target_count send_batch = self.send_batch forward_count = self.forward_count send_total = send_count * target_count receive_total = send_total * iterations port = free_tcp_ports()[0] receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port)] receiver.receive_count = receive_total receiver.send_reply = True # forward to 'relay' - uses two links # ## THIS FAILS: # receiver.forwards = ["amqp://Relay/%d" % j for j in range(forward_count)] receiver.forwards = ["%s://Relay" % domain] receiver.timeout = MessengerTests._timeout self.receivers.append( receiver ) relay.subscriptions = ["%s://0.0.0.0:%s" % (domain, port)] relay.name = "Relay" relay.receive_count = receive_total relay.timeout = MessengerTests._timeout self.receivers.append( relay ) # send to 'receiver' sender.targets = ["%s://0.0.0.0:%s/X%dY" % (domain, port, j) for j in range(target_count)] sender.send_count = send_total sender.get_reply = True sender.timeout = MessengerTests._timeout self.senders.append( sender ) self._do_test(iterations) def _do_star_topology_test(self, r_factory, s_factory, domain="amqp"): """ A star-like topology, with a central receiver at the hub, and senders at the spokes. Each sender will connect to each of the ports the receiver is listening on. Each sender will then create N links per each connection. Each sender will send X messages per link, waiting for a response. Parameters: iterations - repeat the senders this many times port_count - # of ports the receiver will listen on. Each sender connects to all ports. sender_count - # of senders target_count - # of targets per connection send_count - # of messages sent to each target send_batch - # of messages to send before waiting for response """ iterations = self.iterations port_count = self.port_count sender_count = self.sender_count target_count = self.target_count send_count = self.send_count send_batch = self.send_batch send_total = port_count * target_count * send_count receive_total = send_total * sender_count * iterations ports = free_tcp_ports(port_count) receiver = r_factory() receiver.subscriptions = ["%s://~0.0.0.0:%s" % (domain, port) for port in ports] receiver.receive_count = receive_total receiver.send_reply = True receiver.timeout = MessengerTests._timeout self.receivers.append( receiver ) for i in range(sender_count): sender = s_factory() sender.targets = ["%s://0.0.0.0:%s/%d" % (domain, port, j) for port in ports for j in range(target_count)] sender.send_count = send_total sender.send_batch = send_batch sender.get_reply = True sender.timeout = MessengerTests._timeout self.senders.append( sender ) self._do_test(iterations) def test_oneway_C(self): self._do_oneway_test(MessengerReceiverC(), MessengerSenderC()) def test_oneway_C_SSL(self): self._ssl_check() self._do_oneway_test(MessengerReceiverC(), MessengerSenderC(), "amqps") def test_oneway_valgrind(self): self.valgrind_test() self._do_oneway_test(MessengerReceiverValgrind(), MessengerSenderValgrind()) def test_oneway_Python(self): self._do_oneway_test(MessengerReceiverPython(), MessengerSenderPython()) def test_oneway_C_Python(self): self._do_oneway_test(MessengerReceiverC(), MessengerSenderPython()) def test_oneway_Python_C(self): self._do_oneway_test(MessengerReceiverPython(), MessengerSenderC()) def test_echo_C(self): self._do_echo_test(MessengerReceiverC(), MessengerSenderC()) def test_echo_C_SSL(self): self._ssl_check() self._do_echo_test(MessengerReceiverC(), MessengerSenderC(), "amqps") def test_echo_valgrind(self): self.valgrind_test() self._do_echo_test(MessengerReceiverValgrind(), MessengerSenderValgrind()) def test_echo_Python(self): self._do_echo_test(MessengerReceiverPython(), MessengerSenderPython()) def test_echo_C_Python(self): self._do_echo_test(MessengerReceiverC(), MessengerSenderPython()) def test_echo_Python_C(self): self._do_echo_test(MessengerReceiverPython(), MessengerSenderC()) def test_relay_C(self): self._do_relay_test(MessengerReceiverC(), MessengerReceiverC(), MessengerSenderC()) def test_relay_C_SSL(self): self._ssl_check() self._do_relay_test(MessengerReceiverC(), MessengerReceiverC(), MessengerSenderC(), "amqps") def test_relay_valgrind(self): self.valgrind_test() self._do_relay_test(MessengerReceiverValgrind(), MessengerReceiverValgrind(), MessengerSenderValgrind()) def test_relay_C_Python(self): self._do_relay_test(MessengerReceiverC(), MessengerReceiverPython(), MessengerSenderPython()) def test_relay_Python(self): self._do_relay_test(MessengerReceiverPython(), MessengerReceiverPython(), MessengerSenderPython()) def test_star_topology_C(self): self._do_star_topology_test( MessengerReceiverC, MessengerSenderC ) def test_star_topology_C_SSL(self): self._ssl_check() self._do_star_topology_test( MessengerReceiverC, MessengerSenderC, "amqps" ) def test_star_topology_valgrind(self): self.valgrind_test() self._do_star_topology_test( MessengerReceiverValgrind, MessengerSenderValgrind ) def test_star_topology_Python(self): self._do_star_topology_test( MessengerReceiverPython, MessengerSenderPython ) def test_star_topology_Python_C(self): self._do_star_topology_test( MessengerReceiverPython, MessengerSenderC ) def test_star_topology_C_Python(self): self._do_star_topology_test( MessengerReceiverPython, MessengerSenderC ) def test_oneway_reactor(self): self._do_oneway_test(ReactorReceiverC(), ReactorSenderC()) def test_oneway_reactor_valgrind(self): self.valgrind_test() self._do_oneway_test(ReactorReceiverValgrind(), ReactorSenderValgrind()) qpid-proton-0.10/tests/python/proton_tests/scratch.py0000664000000000000000000000224512562450203020027 0ustar def xxx_test_reopen_on_same_session(self): ssn1 = self.snd.session ssn2 = self.rcv.session self.snd.open() self.rcv.open() self.pump() assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE self.snd.close() self.rcv.close() self.pump() assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED print self.snd._link self.snd = ssn1.sender("test-link") print self.snd._link self.rcv = ssn2.receiver("test-link") self.snd.open() self.rcv.open() self.pump() assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE class SessionPipelineTest(PeerTest): def xxx_test(self): self.connection.open() self.peer.open() self.pump() ssn = self.connection.session() ssn.open() self.pump() peer_ssn = self.peer.session_head(0) ssn.close() self.pump() peer_ssn.close() self.peer.close() self.pump() qpid-proton-0.10/tests/python/proton_tests/sasl.py0000664000000000000000000004717212562450203017352 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from __future__ import absolute_import import sys, os from . import common from . import engine from proton import * from .common import pump, Skipped from proton._compat import str2bin def _sslCertpath(file): """ Return the full path to the certificate,keyfile, etc. """ return os.path.join(os.path.dirname(__file__), "ssl_db/%s" % file) def _testSaslMech(self, mech, clientUser='user@proton', authUser='user@proton', encrypted=False, authenticated=True): self.s1.allowed_mechs(mech) self.c1.open() self.c2.open() pump(self.t1, self.t2, 1024) if encrypted is not None: assert self.t2.encrypted == encrypted, encrypted assert self.t1.encrypted == encrypted, encrypted assert self.t2.authenticated == authenticated, authenticated assert self.t1.authenticated == authenticated, authenticated if authenticated: # Server assert self.t2.user == authUser assert self.s2.user == authUser assert self.s2.mech == mech.strip() assert self.s2.outcome == SASL.OK, self.s2.outcome assert self.c2.state & Endpoint.LOCAL_ACTIVE and self.c2.state & Endpoint.REMOTE_ACTIVE,\ "local_active=%s, remote_active=%s" % (self.c1.state & Endpoint.LOCAL_ACTIVE, self.c1.state & Endpoint.REMOTE_ACTIVE) # Client assert self.t1.user == clientUser assert self.s1.user == clientUser assert self.s1.mech == mech.strip() assert self.s1.outcome == SASL.OK, self.s1.outcome assert self.c1.state & Endpoint.LOCAL_ACTIVE and self.c1.state & Endpoint.REMOTE_ACTIVE,\ "local_active=%s, remote_active=%s" % (self.c1.state & Endpoint.LOCAL_ACTIVE, self.c1.state & Endpoint.REMOTE_ACTIVE) else: # Server assert self.t2.user == None assert self.s2.user == None assert self.s2.outcome != SASL.OK, self.s2.outcome # Client assert self.t1.user == clientUser assert self.s1.user == clientUser assert self.s1.outcome != SASL.OK, self.s1.outcome class Test(common.Test): pass class SaslTest(Test): def setup(self): self.t1 = Transport() self.s1 = SASL(self.t1) self.t2 = Transport(Transport.SERVER) self.t2.max_frame_size = 65536 self.s2 = SASL(self.t2) def pump(self): pump(self.t1, self.t2, 1024) # Note that due to server protocol autodetect, there can be no "pipelining" # of protocol frames from the server end only from the client end. # # This is because the server cannot know which protocol layers are active # and therefore which headers need to be sent, # until it sees the respective protocol headers from the client. def testPipelinedClient(self): if "java" in sys.platform: raise Skipped("Proton-J does not support client pipelining") # Client self.s1.allowed_mechs('ANONYMOUS') # Server self.s2.allowed_mechs('ANONYMOUS') assert self.s1.outcome is None assert self.s2.outcome is None # Push client bytes into server out1 = self.t1.peek(1024) self.t1.pop(len(out1)) self.t2.push(out1) out2 = self.t2.peek(1024) self.t2.pop(len(out2)) assert self.s1.outcome is None self.t1.push(out2) assert self.s1.outcome == SASL.OK assert self.s2.outcome == SASL.OK def testPipelinedClientFail(self): if "java" in sys.platform: raise Skipped("Proton-J does not support client pipelining") # Client self.s1.allowed_mechs('ANONYMOUS') # Server self.s2.allowed_mechs('PLAIN DIGEST-MD5 SCRAM-SHA-1') assert self.s1.outcome is None assert self.s2.outcome is None # Push client bytes into server out1 = self.t1.peek(1024) self.t1.pop(len(out1)) self.t2.push(out1) out2 = self.t2.peek(1024) self.t2.pop(len(out2)) assert self.s1.outcome is None self.t1.push(out2) assert self.s1.outcome == SASL.AUTH assert self.s2.outcome == SASL.AUTH def testSaslAndAmqpInSingleChunk(self): if "java" in sys.platform: raise Skipped("Proton-J does not support client pipelining") self.s1.allowed_mechs('ANONYMOUS') self.s2.allowed_mechs('ANONYMOUS') # do some work to generate AMQP data c1 = Connection() c2 = Connection() self.t1.bind(c1) c1._transport = self.t1 self.t2.bind(c2) c2._transport = self.t2 c1.open() # get all t1's output in one buffer then pass it all to t2 out1_sasl_and_amqp = str2bin("") t1_still_producing = True while t1_still_producing: out1 = self.t1.peek(1024) self.t1.pop(len(out1)) out1_sasl_and_amqp += out1 t1_still_producing = out1 t2_still_consuming = True while t2_still_consuming: num = min(self.t2.capacity(), len(out1_sasl_and_amqp)) self.t2.push(out1_sasl_and_amqp[:num]) out1_sasl_and_amqp = out1_sasl_and_amqp[num:] t2_still_consuming = num > 0 and len(out1_sasl_and_amqp) > 0 assert len(out1_sasl_and_amqp) == 0, (len(out1_sasl_and_amqp), out1_sasl_and_amqp) # check that t2 processed both the SASL data and the AMQP data assert self.s2.outcome == SASL.OK assert c2.state & Endpoint.REMOTE_ACTIVE def testPipelined2(self): if "java" in sys.platform: raise Skipped("Proton-J does not support client pipelining") out1 = self.t1.peek(1024) self.t1.pop(len(out1)) self.t2.push(out1) self.s2.allowed_mechs('ANONYMOUS') c2 = Connection() c2.open() self.t2.bind(c2) out2 = self.t2.peek(1024) self.t2.pop(len(out2)) self.t1.push(out2) out1 = self.t1.peek(1024) assert len(out1) > 0 def testFracturedSASL(self): """ PROTON-235 """ assert self.s1.outcome is None # self.t1.trace(Transport.TRACE_FRM) out = self.t1.peek(1024) self.t1.pop(len(out)) self.t1.push(str2bin("AMQP\x03\x01\x00\x00")) out = self.t1.peek(1024) self.t1.pop(len(out)) self.t1.push(str2bin("\x00\x00\x00")) out = self.t1.peek(1024) self.t1.pop(len(out)) self.t1.push(str2bin("6\x02\x01\x00\x00\x00S@\xc04\x01\xe01\x04\xa3\x05PLAIN\x0aDIGEST-MD5\x09ANONYMOUS\x08CRAM-MD5")) out = self.t1.peek(1024) self.t1.pop(len(out)) self.t1.push(str2bin("\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00")) out = self.t1.peek(1024) self.t1.pop(len(out)) while out: out = self.t1.peek(1024) self.t1.pop(len(out)) assert self.s1.outcome == SASL.OK, self.s1.outcome def test_singleton(self): """Verify that only a single instance of SASL can exist per Transport""" transport = Transport() attr = object() sasl1 = SASL(transport) sasl1.my_attribute = attr sasl2 = transport.sasl() sasl3 = SASL(transport) assert sasl1 == sasl2 assert sasl1 == sasl3 assert sasl1.my_attribute == attr assert sasl2.my_attribute == attr assert sasl3.my_attribute == attr transport = Transport() sasl1 = transport.sasl() sasl1.my_attribute = attr sasl2 = SASL(transport) assert sasl1 == sasl2 assert sasl1.my_attribute == attr assert sasl2.my_attribute == attr def testSaslSkipped(self): """Verify that the server (with SASL) correctly handles a client without SASL""" self.t1 = Transport() self.t2.require_auth(False) self.pump() assert self.s2.outcome == None assert self.t2.condition == None assert self.t2.authenticated == False assert self.s1.outcome == None assert self.t1.condition == None assert self.t1.authenticated == False def testSaslSkippedFail(self): """Verify that the server (with SASL) correctly handles a client without SASL""" self.t1 = Transport() self.t2.require_auth(True) self.pump() assert self.s2.outcome == None assert self.t2.condition != None assert self.s1.outcome == None assert self.t1.condition != None def testMechNotFound(self): if "java" in sys.platform: raise Skipped("Proton-J does not support checking authentication state") self.c1 = Connection() self.c1.open() self.t1.bind(self.c1) self.s1.allowed_mechs('IMPOSSIBLE') self.pump() assert self.t2.authenticated == False assert self.t1.authenticated == False assert self.s1.outcome != SASL.OK assert self.s2.outcome != SASL.OK class SASLMechTest(Test): def setup(self): self.t1 = Transport() self.s1 = SASL(self.t1) self.t2 = Transport(Transport.SERVER) self.s2 = SASL(self.t2) self.c1 = Connection() self.c1.user = 'user@proton' self.c1.password = 'password' self.c1.hostname = 'localhost' self.c2 = Connection() def testANON(self): self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'ANONYMOUS', authUser='anonymous') def testCRAMMD5(self): common.ensureCanTestExtendedSASL() self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'CRAM-MD5') def testDIGESTMD5(self): common.ensureCanTestExtendedSASL() self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'DIGEST-MD5') # PLAIN shouldn't work without encryption without special setting def testPLAINfail(self): common.ensureCanTestExtendedSASL() self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'PLAIN', authenticated=False) # Client won't accept PLAIN even if offered by server without special setting def testPLAINClientFail(self): common.ensureCanTestExtendedSASL() self.s2.allow_insecure_mechs = True self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'PLAIN', authenticated=False) # PLAIN will only work if both ends are specially set up def testPLAIN(self): common.ensureCanTestExtendedSASL() self.s1.allow_insecure_mechs = True self.s2.allow_insecure_mechs = True self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'PLAIN') # SCRAM not supported before Cyrus SASL 2.1.26 # so not universal and hance need a test for support # to keep it in tests. # def testSCRAMSHA1(self): # common.ensureCanTestExtendedSASL() # # self.t1.bind(self.c1) # self.t2.bind(self.c2) # _testSaslMech(self, 'SCRAM-SHA-1') def _sslConnection(domain, transport, connection): transport.bind(connection) ssl = SSL(transport, domain, None ) return connection class SSLSASLTest(Test): def setup(self): if not common.isSSLPresent(): raise Skipped("No SSL libraries found.") self.server_domain = SSLDomain(SSLDomain.MODE_SERVER) self.client_domain = SSLDomain(SSLDomain.MODE_CLIENT) self.t1 = Transport() self.s1 = SASL(self.t1) self.t2 = Transport(Transport.SERVER) self.s2 = SASL(self.t2) self.c1 = Connection() self.c2 = Connection() def testSSLPlainSimple(self): if "java" in sys.platform: raise Skipped("Proton-J does not support SSL with SASL") if not SASL.extended(): raise Skipped("Simple SASL server does not support PLAIN") common.ensureCanTestExtendedSASL() clientUser = 'user@proton' mech = 'PLAIN' self.c1.user = clientUser self.c1.password = 'password' self.c1.hostname = 'localhost' ssl1 = _sslConnection(self.client_domain, self.t1, self.c1) ssl2 = _sslConnection(self.server_domain, self.t2, self.c2) _testSaslMech(self, mech, encrypted=True) def testSSLPlainSimpleFail(self): if "java" in sys.platform: raise Skipped("Proton-J does not support SSL with SASL") if not SASL.extended(): raise Skipped("Simple SASL server does not support PLAIN") common.ensureCanTestExtendedSASL() clientUser = 'usr@proton' mech = 'PLAIN' self.c1.user = clientUser self.c1.password = 'password' self.c1.hostname = 'localhost' ssl1 = _sslConnection(self.client_domain, self.t1, self.c1) ssl2 = _sslConnection(self.server_domain, self.t2, self.c2) _testSaslMech(self, mech, clientUser='usr@proton', encrypted=True, authenticated=False) def testSSLExternalSimple(self): if "java" in sys.platform: raise Skipped("Proton-J does not support SSL with SASL") extUser = 'O=Client,CN=127.0.0.1' mech = 'EXTERNAL' self.server_domain.set_credentials(_sslCertpath("server-certificate.pem"), _sslCertpath("server-private-key.pem"), "server-password") self.server_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem")) self.server_domain.set_peer_authentication(SSLDomain.VERIFY_PEER, _sslCertpath("ca-certificate.pem") ) self.client_domain.set_credentials(_sslCertpath("client-certificate.pem"), _sslCertpath("client-private-key.pem"), "client-password") self.client_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem")) self.client_domain.set_peer_authentication(SSLDomain.VERIFY_PEER) ssl1 = _sslConnection(self.client_domain, self.t1, self.c1) ssl2 = _sslConnection(self.server_domain, self.t2, self.c2) _testSaslMech(self, mech, clientUser=None, authUser=extUser, encrypted=True) def testSSLExternalSimpleFail(self): if "java" in sys.platform: raise Skipped("Proton-J does not support SSL with SASL") mech = 'EXTERNAL' self.server_domain.set_credentials(_sslCertpath("server-certificate.pem"), _sslCertpath("server-private-key.pem"), "server-password") self.server_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem")) self.server_domain.set_peer_authentication(SSLDomain.VERIFY_PEER, _sslCertpath("ca-certificate.pem") ) self.client_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem")) self.client_domain.set_peer_authentication(SSLDomain.VERIFY_PEER) ssl1 = _sslConnection(self.client_domain, self.t1, self.c1) ssl2 = _sslConnection(self.server_domain, self.t2, self.c2) _testSaslMech(self, mech, clientUser=None, authUser=None, encrypted=None, authenticated=False) class SASLEventTest(engine.CollectorTest): def setup(self): engine.CollectorTest.setup(self) self.t1 = Transport() self.s1 = SASL(self.t1) self.t2 = Transport(Transport.SERVER) self.s2 = SASL(self.t2) self.c1 = Connection() self.c1.user = 'user@proton' self.c1.password = 'password' self.c1.hostname = 'localhost' self.c2 = Connection() self.collector = Collector() def testNormalAuthenticationClient(self): common.ensureCanTestExtendedSASL() self.c1.collect(self.collector) self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'DIGEST-MD5') self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.CONNECTION_REMOTE_OPEN) def testNormalAuthenticationServer(self): common.ensureCanTestExtendedSASL() self.c2.collect(self.collector) self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'DIGEST-MD5') self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.CONNECTION_REMOTE_OPEN) def testFailedAuthenticationClient(self): common.ensureCanTestExtendedSASL() clientUser = "usr@proton" self.c1.user = clientUser self.c1.collect(self.collector) self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'DIGEST-MD5', clientUser=clientUser, authenticated=False) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED) def testFailedAuthenticationServer(self): common.ensureCanTestExtendedSASL() clientUser = "usr@proton" self.c1.user = clientUser self.c2.collect(self.collector) self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'DIGEST-MD5', clientUser=clientUser, authenticated=False) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED) def testNoMechClient(self): common.ensureCanTestExtendedSASL() self.c1.collect(self.collector) self.s2.allowed_mechs('IMPOSSIBLE') self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'DIGEST-MD5', authenticated=False) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED) def testNoMechServer(self): common.ensureCanTestExtendedSASL() self.c2.collect(self.collector) self.s2.allowed_mechs('IMPOSSIBLE') self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'DIGEST-MD5', authenticated=False) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_ERROR, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED) def testDisallowedMechClient(self): self.c1.collect(self.collector) self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'IMPOSSIBLE', authenticated=False) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED) def testDisallowedMechServer(self): self.c2.collect(self.collector) self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'IMPOSSIBLE', authenticated=False) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_ERROR, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED) def testDisallowedPlainClient(self): self.c1.collect(self.collector) self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'PLAIN', authenticated=False) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED) def testDisallowedPlainServer(self): self.c2.collect(self.collector) self.t1.bind(self.c1) self.t2.bind(self.c2) _testSaslMech(self, 'PLAIN', authenticated=False) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_ERROR, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED) qpid-proton-0.10/tests/python/proton_tests/reactor_interop.py0000664000000000000000000001101612562450203021573 0ustar #!/usr/bin/python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from __future__ import absolute_import from .common import Test, free_tcp_port, Skipped from proton import Message from proton.handlers import CHandshaker, CFlowController from proton.reactor import Reactor import os import subprocess from threading import Thread import time class JavaThread(Thread): def __init__(self, operation, port, count): Thread.__init__(self) self.operation = operation self.port = str(port) self.count = str(count) self.result = 1 def run(self): self.result = subprocess.call(['java', 'org.apache.qpid.proton.ProtonJInterop', self.operation, self.port, self.count]) class ReceiveHandler: def __init__(self, count): self.count = count self.handlers = [CHandshaker(), CFlowController()] self.messages = [] def on_reactor_init(self, event): port = free_tcp_port() self.acceptor = event.reactor.acceptor("127.0.0.1", port) self.java_thread = JavaThread("send", port, self.count) self.java_thread.start() def on_delivery(self, event): rcv = event.receiver msg = Message() if rcv and msg.recv(rcv): event.delivery.settle() self.messages += [msg.body] self.count -= 1 if (self.count == 0): self.acceptor.close() class SendHandler: def __init__(self, host, num_msgs): self.host = host self.num_msgs = num_msgs self.count = 0 self.handlers = [CHandshaker()] def on_connection_init(self, event): conn = event.connection conn.hostname = self.host ssn = conn.session() snd = ssn.sender("sender") conn.open() ssn.open() snd.open() def on_link_flow(self, event): snd = event.sender if snd.credit > 0 and self.count < self.num_msgs: self.count += 1 msg = Message("message-" + str(self.count)) dlv = snd.send(msg) dlv.settle() if (self.count == self.num_msgs): snd.close() snd.session.close() snd.connection.close() def on_reactor_init(self, event): event.reactor.connection(self) class ReactorInteropTest(Test): def setup(self): classpath = "" if ('CLASSPATH' in os.environ): classpath = os.environ['CLASSPATH'] entries = classpath.split(os.pathsep) self.proton_j_available = False for entry in entries: self.proton_j_available |= entry != "" and os.path.exists(entry) def protonc_to_protonj(self, count): if (not self.proton_j_available): raise Skipped("ProtonJ not found") port = free_tcp_port() java_thread = JavaThread("recv", port, count) java_thread.start() # Give the Java thread time to spin up a JVM and start listening # XXX: would be better to parse the stdout output for a message time.sleep(1) sh = SendHandler('127.0.0.1:' + str(port), count) r = Reactor(sh) r.run() java_thread.join() assert(java_thread.result == 0) def protonj_to_protonc(self, count): if (not self.proton_j_available): raise Skipped("ProtonJ not found") rh = ReceiveHandler(count) r = Reactor(rh) r.run() rh.java_thread.join() assert(rh.java_thread.result == 0) for i in range(1, count): assert(rh.messages[i-1] == ("message-" + str(i))) def test_protonc_to_protonj_1(self): self.protonc_to_protonj(1) def test_protonc_to_protonj_5(self): self.protonc_to_protonj(5) def test_protonc_to_protonj_500(self): self.protonc_to_protonj(500) def test_protonc_to_protonj_5000(self): self.protonc_to_protonj(5000) def test_protonj_to_protonc_1(self): self.protonj_to_protonc(1) def test_protonj_to_protonc_5(self): self.protonj_to_protonc(5) def test_protonj_to_protonc_500(self): self.protonj_to_protonc(500) def test_protonj_to_protonc_5000(self): self.protonj_to_protonc(5000) qpid-proton-0.10/tests/python/proton_tests/reactor.py0000664000000000000000000001610412562450203020036 0ustar from __future__ import absolute_import # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from .common import Test from proton.reactor import Reactor class Barf(Exception): pass class BarfOnInit: def on_reactor_init(self, event): raise Barf() def on_connection_init(self, event): raise Barf() def on_session_init(self, event): raise Barf() def on_link_init(self, event): raise Barf() class BarfOnTask: def on_timer_task(self, event): raise Barf() class BarfOnFinal: def on_reactor_final(self, event): raise Barf() class ExceptionTest(Test): def setup(self): self.reactor = Reactor() def test_reactor_final(self): self.reactor.global_handler = BarfOnFinal() try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_global_set(self): self.reactor.global_handler = BarfOnInit() try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_global_add(self): self.reactor.global_handler.add(BarfOnInit()) try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_reactor_set(self): self.reactor.handler = BarfOnInit() try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_reactor_add(self): self.reactor.handler.add(BarfOnInit()) try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_connection(self): self.reactor.connection(BarfOnInit()) try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_connection_set(self): c = self.reactor.connection() c.handler = BarfOnInit() try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_connection_add(self): c = self.reactor.connection() c.handler = object() c.handler.add(BarfOnInit()) try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_session_set(self): c = self.reactor.connection() s = c.session() s.handler = BarfOnInit() try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_session_add(self): c = self.reactor.connection() s = c.session() s.handler = object() s.handler.add(BarfOnInit()) try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_link_set(self): c = self.reactor.connection() s = c.session() l = s.sender("xxx") l.handler = BarfOnInit() try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_link_add(self): c = self.reactor.connection() s = c.session() l = s.sender("xxx") l.handler = object() l.handler.add(BarfOnInit()) try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_schedule(self): self.reactor.schedule(0, BarfOnTask()) try: self.reactor.run() assert False, "expected to barf" except Barf: pass def test_schedule_many_nothings(self): class Nothing: results = [] def on_timer_task(self, event): self.results.append(None) num = 12345 for a in range(num): self.reactor.schedule(0, Nothing()) self.reactor.run() assert len(Nothing.results) == num def test_schedule_many_nothing_refs(self): class Nothing: results = [] def on_timer_task(self, event): self.results.append(None) num = 12345 tasks = [] for a in range(num): tasks.append(self.reactor.schedule(0, Nothing())) self.reactor.run() assert len(Nothing.results) == num def test_schedule_many_nothing_refs_cancel_before_run(self): class Nothing: results = [] def on_timer_task(self, event): self.results.append(None) num = 12345 tasks = [] for a in range(num): tasks.append(self.reactor.schedule(0, Nothing())) for task in tasks: task.cancel() self.reactor.run() assert len(Nothing.results) == 0 def test_schedule_cancel(self): barf = self.reactor.schedule(10, BarfOnTask()) class CancelBarf: def __init__(self, barf): self.barf = barf def on_timer_task(self, event): self.barf.cancel() pass self.reactor.schedule(0, CancelBarf(barf)) now = self.reactor.mark() try: self.reactor.run() elapsed = self.reactor.mark() - now assert elapsed < 10, "expected cancelled task to not delay the reactor by %s" % elapsed except Barf: assert False, "expected barf to be cancelled" def test_schedule_cancel_many(self): num = 12345 barfs = set() for a in range(num): barf = self.reactor.schedule(10*(a+1), BarfOnTask()) class CancelBarf: def __init__(self, barf): self.barf = barf def on_timer_task(self, event): self.barf.cancel() barfs.discard(self.barf) pass self.reactor.schedule(0, CancelBarf(barf)) barfs.add(barf) now = self.reactor.mark() try: self.reactor.run() elapsed = self.reactor.mark() - now assert elapsed < num, "expected cancelled task to not delay the reactor by %s" % elapsed assert not barfs, "expected all barfs to be discarded" except Barf: assert False, "expected barf to be cancelled" qpid-proton-0.10/tests/python/proton_tests/messenger.py0000664000000000000000000007271612562450203020402 0ustar from __future__ import absolute_import # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import os, sys, traceback from . import common from proton import * from threading import Thread, Event from time import sleep, time from .common import Skipped class Test(common.Test): def setup(self): self.server_credit = 10 self.server_received = 0 self.server_finite_credit = False self.server = Messenger("server") self.server.timeout = self.timeout self.server.start() self.server.subscribe("amqp://~0.0.0.0:12345") self.server_thread = Thread(name="server-thread", target=self.run_server) self.server_thread.daemon = True self.server_is_running_event = Event() self.running = True self.server_thread_started = False self.client = Messenger("client") self.client.timeout = self.timeout def start(self): self.server_thread_started = True self.server_thread.start() self.server_is_running_event.wait(self.timeout) self.client.start() def _safelyStopClient(self): self.server.interrupt() self.client.stop() self.client = None def teardown(self): try: if self.running: if not self.server_thread_started: self.start() # send a message to cause the server to promptly exit self.running = False self._safelyStopClient() finally: self.server_thread.join(self.timeout) self.server = None REJECT_ME = "*REJECT-ME*" class MessengerTest(Test): def run_server(self): if self.server_finite_credit: self._run_server_finite_credit() else: self._run_server_recv() def _run_server_recv(self): """ Use recv() to replenish credit each time the server waits """ msg = Message() try: while self.running: self.server_is_running_event.set() try: self.server.recv(self.server_credit) self.process_incoming(msg) except Interrupt: pass finally: self.server.stop() self.running = False def _run_server_finite_credit(self): """ Grant credit once, process until credit runs out """ msg = Message() self.server_is_running_event.set() try: self.server.recv(self.server_credit) while self.running: try: # do not grant additional credit (eg. call recv()) self.process_incoming(msg) self.server.work() except Interrupt: break finally: self.server.stop() self.running = False def process_incoming(self, msg): while self.server.incoming: self.server.get(msg) self.server_received += 1 if msg.body == REJECT_ME: self.server.reject() else: self.server.accept() self.dispatch(msg) def dispatch(self, msg): if msg.reply_to: msg.address = msg.reply_to self.server.put(msg) self.server.settle() def testSendReceive(self, size=None, address_size=None): self.start() msg = Message() if address_size: msg.address="amqp://127.0.0.1:12345/%s" % ("x"*address_size) else: msg.address="amqp://127.0.0.1:12345" msg.reply_to = "~" msg.subject="Hello World!" body = "First the world, then the galaxy!" if size is not None: while len(body) < size: body = 2*body body = body[:size] msg.body = body self.client.put(msg) self.client.send() reply = Message() self.client.recv(1) assert self.client.incoming == 1, self.client.incoming self.client.get(reply) assert reply.subject == "Hello World!" rbod = reply.body assert rbod == body, (rbod, body) def testSendReceive1K(self): self.testSendReceive(1024) def testSendReceive2K(self): self.testSendReceive(2*1024) def testSendReceive4K(self): self.testSendReceive(4*1024) def testSendReceive10K(self): self.testSendReceive(10*1024) def testSendReceive100K(self): self.testSendReceive(100*1024) def testSendReceive1M(self): self.testSendReceive(1024*1024) def testSendReceiveLargeAddress(self): self.testSendReceive(address_size=2048) # PROTON-285 - prevent continually failing test def xtestSendBogus(self): self.start() msg = Message() msg.address="totally-bogus-address" try: self.client.put(msg) assert False, "Expecting MessengerException" except MessengerException: exc = sys.exc_info()[1] err = str(exc) assert "unable to send to address: totally-bogus-address" in err, err def testOutgoingWindow(self): self.server.incoming_window = 10 self.start() msg = Message() msg.address="amqp://127.0.0.1:12345" msg.subject="Hello World!" trackers = [] for i in range(10): trackers.append(self.client.put(msg)) self.client.send() for t in trackers: assert self.client.status(t) is None # reduce outgoing_window to 5 and then try to send 10 messages self.client.outgoing_window = 5 trackers = [] for i in range(10): trackers.append(self.client.put(msg)) for i in range(5): t = trackers[i] assert self.client.status(t) is None, (t, self.client.status(t)) for i in range(5, 10): t = trackers[i] assert self.client.status(t) is PENDING, (t, self.client.status(t)) self.client.send() for i in range(5): t = trackers[i] assert self.client.status(t) is None for i in range(5, 10): t = trackers[i] assert self.client.status(t) is ACCEPTED def testReject(self, process_incoming=None): if process_incoming: self.process_incoming = process_incoming self.server.incoming_window = 10 self.start() msg = Message() msg.address="amqp://127.0.0.1:12345" msg.subject="Hello World!" self.client.outgoing_window = 10 trackers = [] rejected = [] for i in range(10): if i == 5: msg.body = REJECT_ME else: msg.body = "Yay!" trackers.append(self.client.put(msg)) if msg.body == REJECT_ME: rejected.append(trackers[-1]) self.client.send() for t in trackers: if t in rejected: assert self.client.status(t) is REJECTED, (t, self.client.status(t)) else: assert self.client.status(t) is ACCEPTED, (t, self.client.status(t)) def testRejectIndividual(self): self.testReject(self.reject_individual) def reject_individual(self, msg): if self.server.incoming < 10: self.server.work(0) return while self.server.incoming: t = self.server.get(msg) if msg.body == REJECT_ME: self.server.reject(t) self.dispatch(msg) self.server.accept() def testIncomingWindow(self): self.server.incoming_window = 10 self.server.outgoing_window = 10 self.start() msg = Message() msg.address="amqp://127.0.0.1:12345" msg.reply_to = "~" msg.subject="Hello World!" self.client.outgoing_window = 10 trackers = [] for i in range(10): trackers.append(self.client.put(msg)) self.client.send() for t in trackers: assert self.client.status(t) is ACCEPTED, (t, self.client.status(t)) self.client.incoming_window = 10 remaining = 10 trackers = [] while remaining: self.client.recv(remaining) while self.client.incoming: t = self.client.get() trackers.append(t) self.client.accept(t) remaining -= 1 for t in trackers: assert self.client.status(t) is ACCEPTED, (t, self.client.status(t)) def testIncomingQueueBiggerThanWindow(self, size=10): self.server.outgoing_window = size self.client.incoming_window = size self.start() msg = Message() msg.address = "amqp://127.0.0.1:12345" msg.reply_to = "~" msg.subject = "Hello World!" for i in range(2*size): self.client.put(msg) trackers = [] while len(trackers) < 2*size: self.client.recv(2*size - len(trackers)) while self.client.incoming: t = self.client.get(msg) assert self.client.status(t) is SETTLED, (t, self.client.status(t)) trackers.append(t) for t in trackers[:size]: assert self.client.status(t) is None, (t, self.client.status(t)) for t in trackers[size:]: assert self.client.status(t) is SETTLED, (t, self.client.status(t)) self.client.accept() for t in trackers[:size]: assert self.client.status(t) is None, (t, self.client.status(t)) for t in trackers[size:]: assert self.client.status(t) is ACCEPTED, (t, self.client.status(t)) def testIncomingQueueBiggerThanSessionWindow(self): self.testIncomingQueueBiggerThanWindow(2048) def testBuffered(self): self.client.outgoing_window = 1000 self.client.incoming_window = 1000 self.start(); assert self.server_received == 0 buffering = 0 count = 100 for i in range(count): msg = Message() msg.address="amqp://127.0.0.1:12345" msg.subject="Hello World!" msg.body = "First the world, then the galaxy!" t = self.client.put(msg) buffered = self.client.buffered(t) # allow transition from False to True, but not back if buffered: buffering += 1 else: assert not buffering, ("saw %s buffered deliveries before?" % buffering) while self.client.outgoing: last = self.client.outgoing self.client.send() #print "sent ", last - self.client.outgoing assert self.server_received == count def test_proton222(self): self.start() msg = Message() msg.address="amqp://127.0.0.1:12345" msg.subject="Hello World!" msg.body = "First the world, then the galaxy!" assert self.server_received == 0 self.client.put(msg) self.client.send() # ensure the server got the message without requiring client to stop first deadline = time() + 10 while self.server_received == 0: assert time() < deadline, "Server did not receive message!" sleep(.1) assert self.server_received == 1 def testUnlimitedCredit(self): """ Bring up two links. Verify credit is granted to each link by transferring a message over each. """ self.server_credit = -1 self.start() msg = Message() msg.address="amqp://127.0.0.1:12345/XXX" msg.reply_to = "~" msg.subject="Hello World!" body = "First the world, then the galaxy!" msg.body = body self.client.put(msg) self.client.send() reply = Message() self.client.recv(1) assert self.client.incoming == 1 self.client.get(reply) assert reply.subject == "Hello World!" rbod = reply.body assert rbod == body, (rbod, body) msg = Message() msg.address="amqp://127.0.0.1:12345/YYY" msg.reply_to = "~" msg.subject="Hello World!" body = "First the world, then the galaxy!" msg.body = body self.client.put(msg) self.client.send() reply = Message() self.client.recv(1) assert self.client.incoming == 1 self.client.get(reply) assert reply.subject == "Hello World!" rbod = reply.body assert rbod == body, (rbod, body) def _DISABLE_test_proton268(self): """ Reproducer for JIRA Proton-268 """ """ DISABLED: Causes failure on Jenkins, appears to be unrelated to fix """ self.server_credit = 2048 self.start() msg = Message() msg.address="amqp://127.0.0.1:12345" msg.body = "X" * 1024 for x in range( 100 ): self.client.put( msg ) self.client.send() try: self.client.stop() except Timeout: assert False, "Timeout waiting for client stop()" # need to restart client, as teardown() uses it to stop server self.client.start() def testRoute(self): if not common.isSSLPresent(): domain = "amqp" else: domain = "amqps" self.server.subscribe(domain + "://~0.0.0.0:12346") self.start() self.client.route("route1", "amqp://127.0.0.1:12345") self.client.route("route2", domain + "://127.0.0.1:12346") msg = Message() msg.address = "route1" msg.reply_to = "~" msg.body = "test" self.client.put(msg) self.client.recv(1) reply = Message() self.client.get(reply) msg = Message() msg.address = "route2" msg.reply_to = "~" msg.body = "test" self.client.put(msg) self.client.recv(1) self.client.get(reply) assert reply.body == "test" def testDefaultRoute(self): self.start() self.client.route("*", "amqp://127.0.0.1:12345") msg = Message() msg.address = "asdf" msg.body = "test" msg.reply_to = "~" self.client.put(msg) self.client.recv(1) reply = Message() self.client.get(reply) assert reply.body == "test" def testDefaultRouteSubstitution(self): self.start() self.client.route("*", "amqp://127.0.0.1:12345/$1") msg = Message() msg.address = "asdf" msg.body = "test" msg.reply_to = "~" self.client.put(msg) self.client.recv(1) reply = Message() self.client.get(reply) assert reply.body == "test" def testIncomingRoute(self): self.start() self.client.route("in", "amqp://~0.0.0.0:12346") self.client.subscribe("in") msg = Message() msg.address = "amqp://127.0.0.1:12345" msg.reply_to = "amqp://127.0.0.1:12346" msg.body = "test" self.client.put(msg) self.client.recv(1) reply = Message() self.client.get(reply) assert reply.body == "test" def echo_address(self, msg): while self.server.incoming: self.server.get(msg) msg.body = msg.address self.dispatch(msg) def _testRewrite(self, original, rewritten): self.start() self.process_incoming = self.echo_address self.client.route("*", "amqp://127.0.0.1:12345") msg = Message() msg.address = original msg.body = "test" msg.reply_to = "~" self.client.put(msg) assert msg.address == original self.client.recv(1) assert self.client.incoming == 1 echo = Message() self.client.get(echo) assert echo.body == rewritten, (echo.body, rewritten) assert msg.address == original def testDefaultRewriteH(self): self._testRewrite("original", "original") def testDefaultRewriteUH(self): self._testRewrite("user@original", "original") def testDefaultRewriteUPH(self): self._testRewrite("user:pass@original", "original") def testDefaultRewriteHP(self): self._testRewrite("original:123", "original:123") def testDefaultRewriteUHP(self): self._testRewrite("user@original:123", "original:123") def testDefaultRewriteUPHP(self): self._testRewrite("user:pass@original:123", "original:123") def testDefaultRewriteHN(self): self._testRewrite("original/name", "original/name") def testDefaultRewriteUHN(self): self._testRewrite("user@original/name", "original/name") def testDefaultRewriteUPHN(self): self._testRewrite("user:pass@original/name", "original/name") def testDefaultRewriteHPN(self): self._testRewrite("original:123/name", "original:123/name") def testDefaultRewriteUHPN(self): self._testRewrite("user@original:123/name", "original:123/name") def testDefaultRewriteUPHPN(self): self._testRewrite("user:pass@original:123/name", "original:123/name") def testDefaultRewriteSH(self): self._testRewrite("amqp://original", "amqp://original") def testDefaultRewriteSUH(self): self._testRewrite("amqp://user@original", "amqp://original") def testDefaultRewriteSUPH(self): self._testRewrite("amqp://user:pass@original", "amqp://original") def testDefaultRewriteSHP(self): self._testRewrite("amqp://original:123", "amqp://original:123") def testDefaultRewriteSUHP(self): self._testRewrite("amqp://user@original:123", "amqp://original:123") def testDefaultRewriteSUPHP(self): self._testRewrite("amqp://user:pass@original:123", "amqp://original:123") def testDefaultRewriteSHN(self): self._testRewrite("amqp://original/name", "amqp://original/name") def testDefaultRewriteSUHN(self): self._testRewrite("amqp://user@original/name", "amqp://original/name") def testDefaultRewriteSUPHN(self): self._testRewrite("amqp://user:pass@original/name", "amqp://original/name") def testDefaultRewriteSHPN(self): self._testRewrite("amqp://original:123/name", "amqp://original:123/name") def testDefaultRewriteSUHPN(self): self._testRewrite("amqp://user@original:123/name", "amqp://original:123/name") def testDefaultRewriteSUPHPN(self): self._testRewrite("amqp://user:pass@original:123/name", "amqp://original:123/name") def testRewriteSupress(self): self.client.rewrite("*", None) self._testRewrite("asdf", None) def testRewrite(self): self.client.rewrite("a", "b") self._testRewrite("a", "b") def testRewritePattern(self): self.client.rewrite("amqp://%@*", "amqp://$2") self._testRewrite("amqp://foo@bar", "amqp://bar") def testRewriteToAt(self): self.client.rewrite("amqp://%/*", "$2@$1") self._testRewrite("amqp://domain/name", "name@domain") def testRewriteOverrideDefault(self): self.client.rewrite("*", "$1") self._testRewrite("amqp://user:pass@host", "amqp://user:pass@host") def testCreditBlockingRebalance(self): """ The server is given a fixed amount of credit, and runs until that credit is exhausted. """ self.server_finite_credit = True self.server_credit = 11 self.start() # put one message out on "Link1" - since there are no other links, it # should get all the credit (10 after sending) msg = Message() msg.address="amqp://127.0.0.1:12345/Link1" msg.subject="Hello World!" body = "First the world, then the galaxy!" msg.body = body msg.reply_to = "~" self.client.put(msg) self.client.send() self.client.recv(1) assert self.client.incoming == 1 # Now attempt to exhaust credit using a different link for i in range(10): msg.address="amqp://127.0.0.1:12345/Link2" self.client.put(msg) self.client.send() deadline = time() + self.timeout count = 0 while count < 11 and time() < deadline: self.client.recv(-1) while self.client.incoming: self.client.get(msg) count += 1 assert count == 11, count # now attempt to send one more. There isn't enough credit, so it should # not be sent self.client.timeout = 1 msg.address="amqp://127.0.0.1:12345/Link2" self.client.put(msg) try: self.client.send() assert False, "expected client to time out in send()" except Timeout: pass assert self.client.outgoing == 1 class NBMessengerTest(common.Test): def setup(self): self.client = Messenger("client") self.client2 = Messenger("client2") self.server = Messenger("server") self.messengers = [self.client, self.client2, self.server] self.client.blocking = False self.client2.blocking = False self.server.blocking = False self.server.start() self.client.start() self.client2.start() self.address = "amqp://127.0.0.1:12345" self.server.subscribe("amqp://~0.0.0.0:12345") def _pump(self, timeout, work_triggers_exit): for msgr in self.messengers: if msgr.work(timeout) and work_triggers_exit: return True return False def pump(self, timeout=0): while self._pump(0, True): pass self._pump(timeout, False) while self._pump(0, True): pass def teardown(self): self.server.stop() self.client.stop() self.client2.stop() self.pump() assert self.server.stopped assert self.client.stopped assert self.client2.stopped def testSmoke(self, count=1): self.server.recv() msg = Message() msg.address = self.address for i in range(count): msg.body = "Hello %s" % i self.client.put(msg) msg2 = Message() for i in range(count): if self.server.incoming == 0: self.pump() assert self.server.incoming > 0, self.server.incoming self.server.get(msg2) assert msg2.body == "Hello %s" % i, (msg2.body, i) assert self.client.outgoing == 0, self.client.outgoing assert self.server.incoming == 0, self.client.incoming def testSmoke1024(self): self.testSmoke(1024) def testSmoke4096(self): self.testSmoke(4096) def testPushback(self): self.server.recv() msg = Message() msg.address = self.address for i in range(16): for i in range(1024): self.client.put(msg) self.pump() if self.client.outgoing > 0: break assert self.client.outgoing > 0 def testRecvBeforeSubscribe(self): self.client.recv() self.client.subscribe(self.address + "/foo") self.pump() msg = Message() msg.address = "amqp://client/foo" msg.body = "Hello World!" self.server.put(msg) assert self.client.incoming == 0 self.pump(self.delay) assert self.client.incoming == 1 msg2 = Message() self.client.get(msg2) assert msg2.address == msg.address assert msg2.body == msg.body def testCreditAutoBackpressure(self): """ Verify that use of automatic credit (pn_messenger_recv(-1)) does not fill the incoming queue indefinitely. If the receiver does not 'get' the message, eventually the sender will block. See PROTON-350 """ self.server.recv() msg = Message() msg.address = self.address deadline = time() + self.timeout while time() < deadline: old = self.server.incoming for j in range(1001): self.client.put(msg) self.pump() if old == self.server.incoming: break; assert old == self.server.incoming, "Backpressure not active!" def testCreditRedistribution(self): """ Verify that a fixed amount of credit will redistribute to new links. """ self.server.recv( 5 ) # first link will get all credit msg1 = Message() msg1.address = self.address + "/msg1" self.client.put(msg1) self.pump() assert self.server.incoming == 1, self.server.incoming assert self.server.receiving == 4, self.server.receiving # no credit left over for this link msg2 = Message() msg2.address = self.address + "/msg2" self.client.put(msg2) self.pump() assert self.server.incoming == 1, self.server.incoming assert self.server.receiving == 4, self.server.receiving # eventually, credit will rebalance and the new link will send deadline = time() + self.timeout while time() < deadline: sleep(.1) self.pump() if self.server.incoming == 2: break; assert self.server.incoming == 2, self.server.incoming assert self.server.receiving == 3, self.server.receiving def testCreditReclaim(self): """ Verify that credit is reclaimed when a link with outstanding credit is torn down. """ self.server.recv( 9 ) # first link will get all credit msg1 = Message() msg1.address = self.address + "/msg1" self.client.put(msg1) self.pump() assert self.server.incoming == 1, self.server.incoming assert self.server.receiving == 8, self.server.receiving # no credit left over for this link msg2 = Message() msg2.address = self.address + "/msg2" self.client.put(msg2) self.pump() assert self.server.incoming == 1, self.server.incoming assert self.server.receiving == 8, self.server.receiving # and none for this new client msg3 = Message() msg3.address = self.address + "/msg3" self.client2.put(msg3) self.pump() # eventually, credit will rebalance and all links will # send a message deadline = time() + self.timeout while time() < deadline: sleep(.1) self.pump() if self.server.incoming == 3: break; assert self.server.incoming == 3, self.server.incoming assert self.server.receiving == 6, self.server.receiving # now tear down client two, this should cause its outstanding credit to be # made available to the other links self.client2.stop() self.pump() for i in range(4): self.client.put(msg1) self.client.put(msg2) # should exhaust all credit deadline = time() + self.timeout while time() < deadline: sleep(.1) self.pump() if self.server.incoming == 9: break; assert self.server.incoming == 9, self.server.incoming assert self.server.receiving == 0, self.server.receiving def testCreditReplenish(self): """ When extra credit is available it should be granted to the first link that can use it. """ # create three links msg = Message() for i in range(3): msg.address = self.address + "/%d" % i self.client.put(msg) self.server.recv( 50 ) # 50/3 = 16 per link + 2 extra self.pump() assert self.server.incoming == 3, self.server.incoming assert self.server.receiving == 47, self.server.receiving # 47/3 = 15 per link, + 2 extra # verify one link can send 15 + the two extra (17) for i in range(17): msg.address = self.address + "/0" self.client.put(msg) self.pump() assert self.server.incoming == 20, self.server.incoming assert self.server.receiving == 30, self.server.receiving # now verify that the remaining credit (30) will eventually rebalance # across all links (10 per link) for j in range(10): for i in range(3): msg.address = self.address + "/%d" % i self.client.put(msg) deadline = time() + self.timeout while time() < deadline: sleep(.1) self.pump() if self.server.incoming == 50: break assert self.server.incoming == 50, self.server.incoming assert self.server.receiving == 0, self.server.receiving from select import select class Pump: def __init__(self, *messengers): self.messengers = messengers self.selectables = [] def pump_once(self): for m in self.messengers: while True: sel = m.selectable() if sel: self.selectables.append(sel) else: break reading = [] writing = [] for sel in self.selectables[:]: if sel.is_terminal: sel.release() self.selectables.remove(sel) else: if sel.reading: reading.append(sel) if sel.writing: writing.append(sel) readable, writable, _ = select(reading, writing, [], 0) count = 0 for s in readable: s.readable() count += 1 for s in writable: s.writable() count += 1 return count def pump(self): while self.pump_once(): pass class SelectableMessengerTest(common.Test): def testSelectable(self, count = 1): if os.name=="nt": # Conflict between native OS select() in Pump and IOCP based pn_selector_t # makes this fail on Windows (see PROTON-668). raise Skipped("Invalid test on Windows with IOCP.") mrcv = Messenger() mrcv.passive = True mrcv.subscribe("amqp://~0.0.0.0:1234") msnd = Messenger() msnd.passive = True m = Message() m.address = "amqp://127.0.0.1:1234" for i in range(count): m.body = u"Hello World! %s" % i msnd.put(m) p = Pump(msnd, mrcv) p.pump() assert msnd.outgoing == count assert mrcv.incoming == 0 mrcv.recv() mc = Message() try: for i in range(count): while mrcv.incoming == 0: p.pump() assert mrcv.incoming > 0, (count, msnd.outgoing, mrcv.incoming) mrcv.get(mc) assert mc.body == u"Hello World! %s" % i, (i, mc.body) finally: mrcv.stop() msnd.stop() assert not mrcv.stopped assert not msnd.stopped p.pump() assert mrcv.stopped assert msnd.stopped def testSelectable16(self): self.testSelectable(count=16) def testSelectable1024(self): self.testSelectable(count=1024) def testSelectable4096(self): self.testSelectable(count=4096) class IdleTimeoutTest(common.Test): def testIdleTimeout(self): """ Verify that a Messenger connection is kept alive using empty idle frames when a idle_timeout is advertised by the remote peer. """ if "java" in sys.platform: raise Skipped() idle_timeout_secs = self.delay try: idle_server = common.TestServer(idle_timeout=idle_timeout_secs) idle_server.timeout = self.timeout idle_server.start() idle_client = Messenger("idle_client") idle_client.timeout = self.timeout idle_client.start() idle_client.subscribe("amqp://%s:%s/foo" % (idle_server.host, idle_server.port)) idle_client.work(idle_timeout_secs/10) # wait up to 3x the idle timeout and hence verify that everything stays # connected during that time by virtue of no Exception being raised duration = 3 * idle_timeout_secs deadline = time() + duration while time() <= deadline: idle_client.work(idle_timeout_secs/10) continue # confirm link is still active assert not idle_server.conditions, idle_server.conditions finally: try: idle_client.stop() except: pass try: idle_server.stop() except: pass qpid-proton-0.10/tests/python/proton_tests/message.py0000664000000000000000000000734612562450203020033 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import os from . import common from proton import * from proton._compat import str2bin try: from uuid import uuid4 except ImportError: from proton import uuid4 class Test(common.Test): def setup(self): self.msg = Message() def teardown(self): self.msg = None class AccessorsTest(Test): def _test(self, name, default, values): d = getattr(self.msg, name) assert d == default, (d, default) for v in values: setattr(self.msg, name, v) gotten = getattr(self.msg, name) assert gotten == v, gotten def _test_str(self, name): self._test(name, None, ("asdf", "fdsa", "")) def _test_time(self, name): self._test(name, 0, (0, 123456789, 987654321)) def testId(self): self._test("id", None, ("bytes", None, 123, u"string", uuid4())) def testCorrelationId(self): self._test("correlation_id", None, ("bytes", None, 123, u"string", uuid4())) def testDurable(self): self._test("durable", False, (True, False)) def testPriority(self): self._test("priority", Message.DEFAULT_PRIORITY, range(0, 255)) def testTtl(self): self._test("ttl", 0, range(12345, 54321)) def testFirstAquirer(self): self._test("first_acquirer", False, (True, False)) def testDeliveryCount(self): self._test("delivery_count", 0, range(0, 1024)) def testUserId(self): self._test("user_id", str2bin(""), (str2bin("asdf"), str2bin("fdsa"), str2bin("asd\x00fdsa"), str2bin(""))) def testAddress(self): self._test_str("address") def testSubject(self): self._test_str("subject") def testReplyTo(self): self._test_str("reply_to") def testContentType(self): self._test_str("content_type") def testContentEncoding(self): self._test_str("content_encoding") def testExpiryTime(self): self._test_time("expiry_time") def testCreationTime(self): self._test_time("creation_time") def testGroupId(self): self._test_str("group_id") def testGroupSequence(self): self._test("group_sequence", 0, (0, -10, 10, 20, -20)) def testReplyToGroupId(self): self._test_str("reply_to_group_id") class CodecTest(Test): def testRoundTrip(self): self.msg.id = "asdf" self.msg.correlation_id = uuid4() self.msg.ttl = 3 self.msg.priority = 100 self.msg.address = "address" self.msg.subject = "subject" self.msg.body = 'Hello World!' data = self.msg.encode() msg2 = Message() msg2.decode(data) assert self.msg.id == msg2.id, (self.msg.id, msg2.id) assert self.msg.correlation_id == msg2.correlation_id, (self.msg.correlation_id, msg2.correlation_id) assert self.msg.ttl == msg2.ttl, (self.msg.ttl, msg2.ttl) assert self.msg.priority == msg2.priority, (self.msg.priority, msg2.priority) assert self.msg.address == msg2.address, (self.msg.address, msg2.address) assert self.msg.subject == msg2.subject, (self.msg.subject, msg2.subject) assert self.msg.body == msg2.body, (self.msg.body, msg2.body) qpid-proton-0.10/tests/python/proton_tests/interop.py0000664000000000000000000001230612562450203020057 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from proton import * import os from . import common from proton._compat import str2bin def find_test_interop_dir(): """Walk up the directory tree to find the tests directory.""" f = os.path.dirname(__file__) while f and os.path.basename(f) != "tests": f = os.path.dirname(f) f = os.path.join(f, "interop") if not os.path.isdir(f): raise Exception("Cannot find test/interop directory from "+__file__) return f test_interop_dir=find_test_interop_dir() class InteropTest(common.Test): def setup(self): self.data = Data() self.message = Message() def teardown(self): self.data = None def get_data(self, name): filename = os.path.join(test_interop_dir, name+".amqp") f = open(filename,"rb") try: return f.read() finally: f.close() def decode_data(self, encoded): buffer = encoded while buffer: n = self.data.decode(buffer) buffer = buffer[n:] self.data.rewind() def decode_data_file(self, name): encoded = self.get_data(name) self.decode_data(encoded) encoded_size = self.data.encoded_size() # Re-encode and verify pre-computed and actual encoded size match. reencoded = self.data.encode() assert encoded_size == len(reencoded), "%d != %d" % (encoded_size, len(reencoded)) def decode_message_file(self, name): self.message.decode(self.get_data(name)) body = self.message.body if str(type(body)) == "": body = body.array.tostring() self.decode_data(body) def assert_next(self, type, value): next_type = self.data.next() assert next_type == type, "Type mismatch: %s != %s"%( Data.type_names[next_type], Data.type_names[type]) next_value = self.data.get_object() assert next_value == value, "Value mismatch: %s != %s"%(next_value, value) def test_message(self): self.decode_message_file("message") self.assert_next(Data.STRING, "hello") assert self.data.next() is None def test_primitives(self): self.decode_data_file("primitives") self.assert_next(Data.BOOL, True) self.assert_next(Data.BOOL, False) self.assert_next(Data.UBYTE, 42) self.assert_next(Data.USHORT, 42) self.assert_next(Data.SHORT, -42) self.assert_next(Data.UINT, 12345) self.assert_next(Data.INT, -12345) self.assert_next(Data.ULONG, 12345) self.assert_next(Data.LONG, -12345) self.assert_next(Data.FLOAT, 0.125) self.assert_next(Data.DOUBLE, 0.125) assert self.data.next() is None def test_strings(self): self.decode_data_file("strings") self.assert_next(Data.BINARY, str2bin("abc\0defg")) self.assert_next(Data.STRING, "abcdefg") self.assert_next(Data.SYMBOL, "abcdefg") self.assert_next(Data.BINARY, str2bin("")) self.assert_next(Data.STRING, "") self.assert_next(Data.SYMBOL, "") assert self.data.next() is None def test_described(self): self.decode_data_file("described") self.assert_next(Data.DESCRIBED, Described("foo-descriptor", "foo-value")) self.data.exit() assert self.data.next() == Data.DESCRIBED self.data.enter() self.assert_next(Data.INT, 12) self.assert_next(Data.INT, 13) self.data.exit() assert self.data.next() is None def test_described_array(self): self.decode_data_file("described_array") self.assert_next(Data.ARRAY, Array("int-array", Data.INT, *range(0,10))) def test_arrays(self): self.decode_data_file("arrays") self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.INT, *range(0,100))) self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.STRING, *["a", "b", "c"])) self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.INT)) assert self.data.next() is None def test_lists(self): self.decode_data_file("lists") self.assert_next(Data.LIST, [32, "foo", True]) self.assert_next(Data.LIST, []) assert self.data.next() is None def test_maps(self): self.decode_data_file("maps") self.assert_next(Data.MAP, {"one":1, "two":2, "three":3 }) self.assert_next(Data.MAP, {1:"one", 2:"two", 3:"three"}) self.assert_next(Data.MAP, {}) assert self.data.next() is None qpid-proton-0.10/tests/python/proton_tests/engine.py0000664000000000000000000022432512562450203017652 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from __future__ import absolute_import import os, gc import sys from . import common from time import time, sleep from proton import * from .common import pump, Skipped from proton.reactor import Reactor from proton._compat import str2bin # older versions of gc do not provide the garbage list if not hasattr(gc, "garbage"): gc.garbage=[] # future test areas # + different permutations of setup # - creating deliveries and calling input/output before opening the session/link # + shrinking output_size down to something small? should the enginge buffer? # + resuming # - locally and remotely created deliveries with the same tag # Jython 2.5 needs this: try: bytes() except: bytes = str # and this... try: bytearray() except: def bytearray(x): return str2bin('\x00') * x OUTPUT_SIZE = 10*1024 class Test(common.Test): def __init__(self, *args): common.Test.__init__(self, *args) self._wires = [] def connection(self): c1 = Connection() c2 = Connection() t1 = Transport() t1.bind(c1) t2 = Transport() t2.bind(c2) self._wires.append((c1, t1, c2, t2)) mask1 = 0 mask2 = 0 for cat in ("TRACE_FRM", "TRACE_RAW"): trc = os.environ.get("PN_%s" % cat) if trc and trc.lower() in ("1", "2", "yes", "true"): mask1 = mask1 | getattr(Transport, cat) if trc == "2": mask2 = mask2 | getattr(Transport, cat) t1.trace(mask1) t2.trace(mask2) return c1, c2 def link(self, name, max_frame=None, idle_timeout=None): c1, c2 = self.connection() if max_frame: c1.transport.max_frame_size = max_frame[0] c2.transport.max_frame_size = max_frame[1] if idle_timeout: # idle_timeout in seconds expressed as float c1.transport.idle_timeout = idle_timeout[0] c2.transport.idle_timeout = idle_timeout[1] c1.open() c2.open() ssn1 = c1.session() ssn1.open() self.pump() ssn2 = c2.session_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE) ssn2.open() self.pump() snd = ssn1.sender(name) rcv = ssn2.receiver(name) return snd, rcv def cleanup(self): self._wires = [] def pump(self, buffer_size=OUTPUT_SIZE): for c1, t1, c2, t2 in self._wires: pump(t1, t2, buffer_size) class ConnectionTest(Test): def setup(self): gc.enable() self.c1, self.c2 = self.connection() def cleanup(self): # release resources created by this class super(ConnectionTest, self).cleanup() self.c1 = None self.c2 = None def teardown(self): self.cleanup() gc.collect() assert not gc.garbage def test_open_close(self): assert self.c1.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT self.c1.open() self.pump() assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE self.c2.open() self.pump() assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE self.c1.close() self.pump() assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED self.c2.close() self.pump() assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED assert self.c2.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED def test_simultaneous_open_close(self): assert self.c1.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT self.c1.open() self.c2.open() self.pump() assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE self.c1.close() self.c2.close() self.pump() assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED assert self.c2.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED def test_capabilities(self): self.c1.offered_capabilities = Array(UNDESCRIBED, Data.SYMBOL, symbol("O_one"), symbol("O_two"), symbol("O_three")) self.c1.desired_capabilities = Array(UNDESCRIBED, Data.SYMBOL, symbol("D_one"), symbol("D_two"), symbol("D_three")) self.c1.open() assert self.c2.remote_offered_capabilities is None assert self.c2.remote_desired_capabilities is None self.pump() assert self.c2.remote_offered_capabilities == self.c1.offered_capabilities, \ (self.c2.remote_offered_capabilities, self.c1.offered_capabilities) assert self.c2.remote_desired_capabilities == self.c1.desired_capabilities, \ (self.c2.remote_desired_capabilities, self.c1.desired_capabilities) def test_condition(self): self.c1.open() self.c2.open() self.pump() assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"}) self.c1.condition = cond self.c1.close() self.pump() assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED rcond = self.c2.remote_condition assert rcond == cond, (rcond, cond) def test_properties(self, p1={symbol("key"): symbol("value")}, p2=None): self.c1.properties = p1 self.c2.properties = p2 self.c1.open() self.c2.open() self.pump() assert self.c2.remote_properties == p1, (self.c2.remote_properties, p1) assert self.c1.remote_properties == p2, (self.c2.remote_properties, p2) # The proton implementation limits channel_max to 32767. # If I set the application's limit lower than that, I should # get my wish. If I set it higher -- not. def test_channel_max_low(self, value=1234): self.c1.transport.channel_max = value self.c1.open() self.pump() assert self.c1.transport.channel_max == value, (self.c1.transport.channel_max, value) def test_channel_max_high(self, value=65535): self.c1.transport.channel_max = value self.c1.open() self.pump() if "java" in sys.platform: assert self.c1.transport.channel_max == 65535, (self.c1.transport.channel_max, value) else: assert self.c1.transport.channel_max == 32767, (self.c1.transport.channel_max, value) def test_channel_max_raise_and_lower(self): if "java" in sys.platform: upper_limit = 65535 else: upper_limit = 32767 # It's OK to lower the max below upper_limit. self.c1.transport.channel_max = 12345 assert self.c1.transport.channel_max == 12345 # But it won't let us raise the limit above PN_IMPL_CHANNEL_MAX. self.c1.transport.channel_max = 65535 assert self.c1.transport.channel_max == upper_limit # send the OPEN frame self.c1.open() self.pump() # Now it's too late to make any change, because # we have already sent the OPEN frame. try: self.c1.transport.channel_max = 666 assert False, "expected session exception" except: pass assert self.c1.transport.channel_max == upper_limit def test_channel_max_limits_sessions(self): return # This is an index -- so max number of channels should be 1. self.c1.transport.channel_max = 0 self.c1.open() self.c2.open() ssn_0 = self.c2.session() assert ssn_0 != None ssn_0.open() self.pump() try: ssn_1 = self.c2.session() assert False, "expected session exception" except SessionException: pass def test_cleanup(self): self.c1.open() self.c2.open() self.pump() assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE t1 = self.c1.transport t2 = self.c2.transport c2 = self.c2 self.c1.close() # release all references to C1, except that held by the transport self.cleanup() gc.collect() # transport should flush last state from C1: pump(t1, t2) assert c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED def test_user_config(self): if "java" in sys.platform: raise Skipped("Unsupported API") self.c1.user = "vindaloo" self.c1.password = "secret" self.c1.open() self.pump() self.c2.user = "leela" self.c2.password = "trustno1" self.c2.open() self.pump() assert self.c1.user == "vindaloo", self.c1.user assert self.c1.password == None, self.c1.password assert self.c2.user == "leela", self.c2.user assert self.c2.password == None, self.c2.password class SessionTest(Test): def setup(self): gc.enable() self.c1, self.c2 = self.connection() self.ssn = self.c1.session() self.c1.open() self.c2.open() def cleanup(self): # release resources created by this class super(SessionTest, self).cleanup() self.c1 = None self.c2 = None self.ssn = None def teardown(self): self.cleanup() gc.collect() assert not gc.garbage def test_open_close(self): assert self.ssn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT self.ssn.open() assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT self.pump() assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT) assert ssn != None assert ssn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT ssn.open() assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT self.pump() assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE ssn.close() assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE self.pump() assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED self.ssn.close() assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED self.pump() assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED def test_simultaneous_close(self): self.ssn.open() self.pump() ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT) assert ssn != None ssn.open() self.pump() assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE self.ssn.close() ssn.close() assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE self.pump() assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED def test_closing_connection(self): self.ssn.open() self.pump() self.c1.close() self.pump() self.ssn.close() self.pump() def test_condition(self): self.ssn.open() self.pump() ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT) assert ssn != None ssn.open() self.pump() assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"}) self.ssn.condition = cond self.ssn.close() self.pump() assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED rcond = ssn.remote_condition assert rcond == cond, (rcond, cond) def test_cleanup(self): snd, rcv = self.link("test-link") snd.open() rcv.open() self.pump() snd_ssn = snd.session rcv_ssn = rcv.session assert rcv_ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE self.ssn = None snd_ssn.close() snd_ssn.free() del snd_ssn gc.collect() self.pump() assert rcv_ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED def test_reopen_on_same_session_without_free(self): """ confirm that a link is correctly opened when attaching to a previously closed link *that has not been freed yet* on the same session """ self.ssn.open() self.pump() ssn2 = self.c2.session_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE) ssn2.open() self.pump() snd = self.ssn.sender("test-link") rcv = ssn2.receiver("test-link") assert snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT assert rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT snd.open() rcv.open() self.pump() assert snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE snd.close() rcv.close() self.pump() assert snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED assert rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED snd = self.ssn.sender("test-link") rcv = ssn2.receiver("test-link") assert snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT assert rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT snd.open() rcv.open() self.pump() assert snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE def test_set_get_outgoing_window(self): assert self.ssn.outgoing_window == 2147483647 self.ssn.outgoing_window = 1024 assert self.ssn.outgoing_window == 1024 class LinkTest(Test): def setup(self): gc.enable() self.snd, self.rcv = self.link("test-link") def cleanup(self): # release resources created by this class super(LinkTest, self).cleanup() self.snd = None self.rcv = None def teardown(self): self.cleanup() gc.collect() assert not gc.garbage, gc.garbage def test_open_close(self): assert self.snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT self.snd.open() assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT self.pump() assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE self.rcv.open() assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE self.pump() assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE self.snd.close() assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE self.pump() assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED self.rcv.close() assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED self.pump() assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED def test_simultaneous_open_close(self): assert self.snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT self.snd.open() self.rcv.open() assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT self.pump() assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE self.snd.close() self.rcv.close() assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE self.pump() assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED def test_multiple(self): rcv = self.snd.session.receiver("second-rcv") assert rcv.name == "second-rcv" self.snd.open() rcv.open() self.pump() c2 = self.rcv.session.connection l = c2.link_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE) while l: l.open() l = l.next(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE) self.pump() assert self.snd assert rcv self.snd.close() rcv.close() ssn = rcv.session conn = ssn.connection ssn.close() conn.close() self.pump() def test_closing_session(self): self.snd.open() self.rcv.open() ssn1 = self.snd.session self.pump() ssn1.close() self.pump() self.snd.close() self.pump() def test_closing_connection(self): self.snd.open() self.rcv.open() ssn1 = self.snd.session c1 = ssn1.connection self.pump() c1.close() self.pump() self.snd.close() self.pump() def assertEqualTermini(self, t1, t2): assert t1.type == t2.type, (t1.type, t2.type) assert t1.address == t2.address, (t1.address, t2.address) assert t1.durability == t2.durability, (t1.durability, t2.durability) assert t1.expiry_policy == t2.expiry_policy, (t1.expiry_policy, t2.expiry_policy) assert t1.timeout == t2.timeout, (t1.timeout, t2.timeout) assert t1.dynamic == t2.dynamic, (t1.dynamic, t2.dynamic) for attr in ["properties", "capabilities", "outcomes", "filter"]: d1 = getattr(t1, attr) d2 = getattr(t2, attr) assert d1.format() == d2.format(), (attr, d1.format(), d2.format()) def _test_source_target(self, config_source, config_target): if config_source is None: self.snd.source.type = Terminus.UNSPECIFIED else: config_source(self.snd.source) if config_target is None: self.snd.target.type = Terminus.UNSPECIFIED else: config_target(self.snd.target) self.snd.open() self.pump() self.assertEqualTermini(self.rcv.remote_source, self.snd.source) self.assertEqualTermini(self.rcv.remote_target, self.snd.target) self.rcv.target.copy(self.rcv.remote_target) self.rcv.source.copy(self.rcv.remote_source) self.rcv.open() self.pump() self.assertEqualTermini(self.snd.remote_target, self.snd.target) self.assertEqualTermini(self.snd.remote_source, self.snd.source) def test_source_target(self): self._test_source_target(TerminusConfig(address="source"), TerminusConfig(address="target")) def test_source(self): self._test_source_target(TerminusConfig(address="source"), None) def test_target(self): self._test_source_target(None, TerminusConfig(address="target")) def test_coordinator(self): self._test_source_target(None, TerminusConfig(type=Terminus.COORDINATOR)) def test_source_target_full(self): self._test_source_target(TerminusConfig(address="source", timeout=3, dist_mode=Terminus.DIST_MODE_MOVE, filter=[("int", 1), ("symbol", "two"), ("string", "three")], capabilities=["one", "two", "three"]), TerminusConfig(address="source", timeout=7, capabilities=[])) def test_distribution_mode(self): self._test_source_target(TerminusConfig(address="source", dist_mode=Terminus.DIST_MODE_COPY), TerminusConfig(address="target")) assert self.rcv.remote_source.distribution_mode == Terminus.DIST_MODE_COPY assert self.rcv.remote_target.distribution_mode == Terminus.DIST_MODE_UNSPECIFIED def test_dynamic_link(self): self._test_source_target(TerminusConfig(address=None, dynamic=True), None) assert self.rcv.remote_source.dynamic assert self.rcv.remote_source.address is None def test_condition(self): self.snd.open() self.rcv.open() self.pump() assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"}) self.snd.condition = cond self.snd.close() self.pump() assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED rcond = self.rcv.remote_condition assert rcond == cond, (rcond, cond) def test_settle_mode(self): self.snd.snd_settle_mode = Link.SND_UNSETTLED assert self.snd.snd_settle_mode == Link.SND_UNSETTLED self.rcv.rcv_settle_mode = Link.RCV_SECOND assert self.rcv.rcv_settle_mode == Link.RCV_SECOND assert self.snd.remote_rcv_settle_mode != Link.RCV_SECOND assert self.rcv.remote_snd_settle_mode != Link.SND_UNSETTLED self.snd.open() self.rcv.open() self.pump() assert self.snd.remote_rcv_settle_mode == Link.RCV_SECOND assert self.rcv.remote_snd_settle_mode == Link.SND_UNSETTLED def test_cleanup(self): snd, rcv = self.link("test-link") snd.open() rcv.open() self.pump() assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE snd.close() snd.free() del snd gc.collect() self.pump() assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED class TerminusConfig: def __init__(self, type=None, address=None, timeout=None, durability=None, filter=None, capabilities=None, dynamic=False, dist_mode=None): self.address = address self.timeout = timeout self.durability = durability self.filter = filter self.capabilities = capabilities self.dynamic = dynamic self.dist_mode = dist_mode self.type = type def __call__(self, terminus): if self.type is not None: terminus.type = self.type if self.address is not None: terminus.address = self.address if self.timeout is not None: terminus.timeout = self.timeout if self.durability is not None: terminus.durability = self.durability if self.capabilities is not None: terminus.capabilities.put_array(False, Data.SYMBOL) terminus.capabilities.enter() for c in self.capabilities: terminus.capabilities.put_symbol(c) if self.filter is not None: terminus.filter.put_map() terminus.filter.enter() for (t, v) in self.filter: setter = getattr(terminus.filter, "put_%s" % t) setter(v) if self.dynamic: terminus.dynamic = True if self.dist_mode is not None: terminus.distribution_mode = self.dist_mode class TransferTest(Test): def setup(self): gc.enable() self.snd, self.rcv = self.link("test-link") self.c1 = self.snd.session.connection self.c2 = self.rcv.session.connection self.snd.open() self.rcv.open() self.pump() def cleanup(self): # release resources created by this class super(TransferTest, self).cleanup() self.c1 = None self.c2 = None self.snd = None self.rcv = None def teardown(self): self.cleanup() gc.collect() assert not gc.garbage def test_work_queue(self): assert self.c1.work_head is None self.snd.delivery("tag") assert self.c1.work_head is None self.rcv.flow(1) self.pump() d = self.c1.work_head assert d is not None tag = d.tag assert tag == "tag", tag assert d.writable n = self.snd.send(str2bin("this is a test")) assert self.snd.advance() assert self.c1.work_head is None self.pump() d = self.c2.work_head assert d.tag == "tag" assert d.readable def test_multiframe(self): self.rcv.flow(1) self.snd.delivery("tag") msg = str2bin("this is a test") n = self.snd.send(msg) assert n == len(msg) self.pump() d = self.rcv.current assert d assert d.tag == "tag", repr(d.tag) assert d.readable binary = self.rcv.recv(1024) assert binary == msg, (binary, msg) binary = self.rcv.recv(1024) assert binary == str2bin("") msg = str2bin("this is more") n = self.snd.send(msg) assert n == len(msg) assert self.snd.advance() self.pump() binary = self.rcv.recv(1024) assert binary == msg, (binary, msg) binary = self.rcv.recv(1024) assert binary is None def test_disposition(self): self.rcv.flow(1) self.pump() sd = self.snd.delivery("tag") msg = str2bin("this is a test") n = self.snd.send(msg) assert n == len(msg) assert self.snd.advance() self.pump() rd = self.rcv.current assert rd is not None assert rd.tag == sd.tag rmsg = self.rcv.recv(1024) assert rmsg == msg rd.update(Delivery.ACCEPTED) self.pump() rdisp = sd.remote_state ldisp = rd.local_state assert rdisp == ldisp == Delivery.ACCEPTED, (rdisp, ldisp) assert sd.updated sd.update(Delivery.ACCEPTED) self.pump() assert sd.local_state == rd.remote_state == Delivery.ACCEPTED sd.settle() def test_delivery_id_ordering(self): self.rcv.flow(1024) self.pump(buffer_size=64*1024) #fill up delivery buffer on sender for m in range(1024): sd = self.snd.delivery("tag%s" % m) msg = ("message %s" % m).encode('ascii') n = self.snd.send(msg) assert n == len(msg) assert self.snd.advance() self.pump(buffer_size=64*1024) #receive a session-windows worth of messages and accept them for m in range(1024): rd = self.rcv.current assert rd is not None, m assert rd.tag == ("tag%s" % m), (rd.tag, m) msg = self.rcv.recv(1024) assert msg == ("message %s" % m).encode('ascii'), (msg, m) rd.update(Delivery.ACCEPTED) rd.settle() self.pump(buffer_size=64*1024) #add some new deliveries for m in range(1024, 1450): sd = self.snd.delivery("tag%s" % m) msg = ("message %s" % m).encode('ascii') n = self.snd.send(msg) assert n == len(msg) assert self.snd.advance() #handle all disposition changes to sent messages d = self.c1.work_head while d: next_d = d.work_next if d.updated: d.update(Delivery.ACCEPTED) d.settle() d = next_d #submit some more deliveries for m in range(1450, 1500): sd = self.snd.delivery("tag%s" % m) msg = ("message %s" % m).encode('ascii') n = self.snd.send(msg) assert n == len(msg) assert self.snd.advance() self.pump(buffer_size=64*1024) self.rcv.flow(1024) self.pump(buffer_size=64*1024) #verify remaining messages can be received and accepted for m in range(1024, 1500): rd = self.rcv.current assert rd is not None, m assert rd.tag == ("tag%s" % m), (rd.tag, m) msg = self.rcv.recv(1024) assert msg == ("message %s" % m).encode('ascii'), (msg, m) rd.update(Delivery.ACCEPTED) rd.settle() def test_cleanup(self): self.rcv.flow(10) self.pump() for x in range(10): self.snd.delivery("tag%d" % x) msg = str2bin("this is a test") n = self.snd.send(msg) assert n == len(msg) assert self.snd.advance() self.snd.close() self.snd.free() self.snd = None gc.collect() self.pump() for x in range(10): rd = self.rcv.current assert rd is not None assert rd.tag == "tag%d" % x rmsg = self.rcv.recv(1024) assert self.rcv.advance() assert rmsg == msg # close of snd should've settled: assert rd.settled rd.settle() class MaxFrameTransferTest(Test): def setup(self): pass def cleanup(self): # release resources created by this class super(MaxFrameTransferTest, self).cleanup() self.c1 = None self.c2 = None self.snd = None self.rcv = None def teardown(self): self.cleanup() def message(self, size): parts = [] for i in range(size): parts.append(str(i)) return "/".join(parts)[:size].encode("utf-8") def testMinFrame(self): """ Configure receiver to support minimum max-frame as defined by AMQP-1.0. Verify transfer of messages larger than 512. """ self.snd, self.rcv = self.link("test-link", max_frame=[0,512]) self.c1 = self.snd.session.connection self.c2 = self.rcv.session.connection self.snd.open() self.rcv.open() self.pump() assert self.rcv.session.connection.transport.max_frame_size == 512 assert self.snd.session.connection.transport.remote_max_frame_size == 512 self.rcv.flow(1) self.snd.delivery("tag") msg = self.message(513) n = self.snd.send(msg) assert n == len(msg) assert self.snd.advance() self.pump() binary = self.rcv.recv(513) assert binary == msg binary = self.rcv.recv(1024) assert binary == None def testOddFrame(self): """ Test an odd sized max limit with data that will require multiple frames to be transfered. """ self.snd, self.rcv = self.link("test-link", max_frame=[0,521]) self.c1 = self.snd.session.connection self.c2 = self.rcv.session.connection self.snd.open() self.rcv.open() self.pump() assert self.rcv.session.connection.transport.max_frame_size == 521 assert self.snd.session.connection.transport.remote_max_frame_size == 521 self.rcv.flow(2) self.snd.delivery("tag") msg = ("X" * 1699).encode('utf-8') n = self.snd.send(msg) assert n == len(msg) assert self.snd.advance() self.pump() binary = self.rcv.recv(1699) assert binary == msg binary = self.rcv.recv(1024) assert binary == None self.rcv.advance() self.snd.delivery("gat") msg = self.message(1426) n = self.snd.send(msg) assert n == len(msg) assert self.snd.advance() self.pump() binary = self.rcv.recv(1426) assert binary == msg self.pump() binary = self.rcv.recv(1024) assert binary == None def testBigMessage(self): """ Test transfering a big message. """ self.snd, self.rcv = self.link("test-link") self.c1 = self.snd.session.connection self.c2 = self.rcv.session.connection self.snd.open() self.rcv.open() self.pump() self.rcv.flow(2) self.snd.delivery("tag") msg = self.message(1024*256) n = self.snd.send(msg) assert n == len(msg) assert self.snd.advance() self.pump() binary = self.rcv.recv(1024*256) assert binary == msg binary = self.rcv.recv(1024) assert binary == None class IdleTimeoutTest(Test): def setup(self): pass def cleanup(self): # release resources created by this class super(IdleTimeoutTest, self).cleanup() self.snd = None self.rcv = None self.c1 = None self.c2 = None def teardown(self): self.cleanup() def message(self, size): parts = [] for i in range(size): parts.append(str(i)) return "/".join(parts)[:size] def testGetSet(self): """ Verify the configuration and negotiation of the idle timeout. """ self.snd, self.rcv = self.link("test-link", idle_timeout=[1.0,2.0]) self.c1 = self.snd.session.connection self.c2 = self.rcv.session.connection self.snd.open() self.rcv.open() self.pump() # proton advertises 1/2 the configured timeout to the peer: assert self.rcv.session.connection.transport.idle_timeout == 2.0 assert self.rcv.session.connection.transport.remote_idle_timeout == 0.5 assert self.snd.session.connection.transport.idle_timeout == 1.0 assert self.snd.session.connection.transport.remote_idle_timeout == 1.0 def testTimeout(self): """ Verify the AMQP Connection idle timeout. """ # snd will timeout the Connection if no frame is received within 1000 ticks self.snd, self.rcv = self.link("test-link", idle_timeout=[1.0,0]) self.c1 = self.snd.session.connection self.c2 = self.rcv.session.connection self.snd.open() self.rcv.open() self.pump() t_snd = self.snd.session.connection.transport t_rcv = self.rcv.session.connection.transport assert t_rcv.idle_timeout == 0.0 # proton advertises 1/2 the timeout (see spec) assert t_rcv.remote_idle_timeout == 0.5 assert t_snd.idle_timeout == 1.0 assert t_snd.remote_idle_timeout == 0.0 sndr_frames_in = t_snd.frames_input rcvr_frames_out = t_rcv.frames_output # at t+1msec, nothing should happen: clock = 0.001 assert t_snd.tick(clock) == 1.001, "deadline for remote timeout" assert t_rcv.tick(clock) == 0.251, "deadline to send keepalive" self.pump() assert sndr_frames_in == t_snd.frames_input, "unexpected received frame" # at one tick from expected idle frame send, nothing should happen: clock = 0.250 assert t_snd.tick(clock) == 1.001, "deadline for remote timeout" assert t_rcv.tick(clock) == 0.251, "deadline to send keepalive" self.pump() assert sndr_frames_in == t_snd.frames_input, "unexpected received frame" # this should cause rcvr to expire and send a keepalive clock = 0.251 assert t_snd.tick(clock) == 1.001, "deadline for remote timeout" assert t_rcv.tick(clock) == 0.501, "deadline to send keepalive" self.pump() sndr_frames_in += 1 rcvr_frames_out += 1 assert sndr_frames_in == t_snd.frames_input, "unexpected received frame" assert rcvr_frames_out == t_rcv.frames_output, "unexpected frame" # since a keepalive was received, sndr will rebase its clock against this tick: # and the receiver should not change its deadline clock = 0.498 assert t_snd.tick(clock) == 1.498, "deadline for remote timeout" assert t_rcv.tick(clock) == 0.501, "deadline to send keepalive" self.pump() assert sndr_frames_in == t_snd.frames_input, "unexpected received frame" # now expire sndr clock = 1.499 t_snd.tick(clock) self.pump() assert self.c2.state & Endpoint.REMOTE_CLOSED assert self.c2.remote_condition.name == "amqp:resource-limit-exceeded" class CreditTest(Test): def setup(self): self.snd, self.rcv = self.link("test-link", max_frame=(16*1024, 16*1024)) self.c1 = self.snd.session.connection self.c2 = self.rcv.session.connection self.snd.open() self.rcv.open() self.pump() def cleanup(self): # release resources created by this class super(CreditTest, self).cleanup() self.c1 = None self.snd = None self.c2 = None self.rcv2 = None self.snd2 = None def teardown(self): self.cleanup() def testCreditSender(self, count=1024): credit = self.snd.credit assert credit == 0, credit self.rcv.flow(10) self.pump() credit = self.snd.credit assert credit == 10, credit self.rcv.flow(count) self.pump() credit = self.snd.credit assert credit == 10 + count, credit def testCreditReceiver(self): self.rcv.flow(10) self.pump() assert self.rcv.credit == 10, self.rcv.credit d = self.snd.delivery("tag") assert d assert self.snd.advance() self.pump() assert self.rcv.credit == 10, self.rcv.credit assert self.rcv.queued == 1, self.rcv.queued c = self.rcv.current assert c.tag == "tag", c.tag assert self.rcv.advance() assert self.rcv.credit == 9, self.rcv.credit assert self.rcv.queued == 0, self.rcv.queued def _testBufferingOnClose(self, a, b): for i in range(10): d = self.snd.delivery("tag-%s" % i) assert d d.settle() self.pump() assert self.snd.queued == 10 endpoints = {"connection": (self.c1, self.c2), "session": (self.snd.session, self.rcv.session), "link": (self.snd, self.rcv)} local_a, remote_a = endpoints[a] local_b, remote_b = endpoints[b] remote_b.close() self.pump() assert local_b.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED local_a.close() self.pump() assert remote_a.state & Endpoint.REMOTE_CLOSED assert self.snd.queued == 10 def testBufferingOnCloseLinkLink(self): self._testBufferingOnClose("link", "link") def testBufferingOnCloseLinkSession(self): self._testBufferingOnClose("link", "session") def testBufferingOnCloseLinkConnection(self): self._testBufferingOnClose("link", "connection") def testBufferingOnCloseSessionLink(self): self._testBufferingOnClose("session", "link") def testBufferingOnCloseSessionSession(self): self._testBufferingOnClose("session", "session") def testBufferingOnCloseSessionConnection(self): self._testBufferingOnClose("session", "connection") def testBufferingOnCloseConnectionLink(self): self._testBufferingOnClose("connection", "link") def testBufferingOnCloseConnectionSession(self): self._testBufferingOnClose("connection", "session") def testBufferingOnCloseConnectionConnection(self): self._testBufferingOnClose("connection", "connection") def testFullDrain(self): assert self.rcv.credit == 0 assert self.snd.credit == 0 self.rcv.drain(10) assert self.rcv.draining() assert self.rcv.credit == 10 assert self.snd.credit == 0 self.pump() assert self.rcv.credit == 10 assert self.snd.credit == 10 assert self.rcv.draining() self.snd.drained() assert self.rcv.credit == 10 assert self.snd.credit == 0 assert self.rcv.draining() self.pump() assert self.rcv.credit == 0 assert self.snd.credit == 0 assert not self.rcv.draining() drained = self.rcv.drained() assert drained == 10, drained def testPartialDrain(self): self.rcv.drain(2) assert self.rcv.draining() self.pump() d = self.snd.delivery("tag") assert d assert self.snd.advance() self.snd.drained() assert self.rcv.draining() self.pump() assert not self.rcv.draining() c = self.rcv.current assert self.rcv.queued == 1, self.rcv.queued assert c.tag == d.tag, c.tag assert self.rcv.advance() assert not self.rcv.current assert self.rcv.credit == 0, self.rcv.credit assert not self.rcv.draining() drained = self.rcv.drained() assert drained == 1, drained def testDrainFlow(self): assert self.rcv.credit == 0 assert self.snd.credit == 0 self.rcv.drain(10) assert self.rcv.credit == 10 assert self.snd.credit == 0 self.pump() assert self.rcv.credit == 10 assert self.snd.credit == 10 self.snd.drained() assert self.rcv.credit == 10 assert self.snd.credit == 0 self.pump() assert self.rcv.credit == 0 assert self.snd.credit == 0 self.rcv.flow(10) assert self.rcv.credit == 10 assert self.snd.credit == 0 self.pump() assert self.rcv.credit == 10 assert self.snd.credit == 10 self.snd.drained() assert self.rcv.credit == 10 assert self.snd.credit == 10 self.pump() assert self.rcv.credit == 10 assert self.snd.credit == 10 drained = self.rcv.drained() assert drained == 10, drained def testNegative(self): assert self.snd.credit == 0 d = self.snd.delivery("tag") assert d assert self.snd.advance() self.pump() assert self.rcv.credit == 0 assert self.rcv.queued == 0 self.rcv.flow(1) assert self.rcv.credit == 1 assert self.rcv.queued == 0 self.pump() assert self.rcv.credit == 1 assert self.rcv.queued == 1, self.rcv.queued c = self.rcv.current assert c assert c.tag == "tag" assert self.rcv.advance() assert self.rcv.credit == 0 assert self.rcv.queued == 0 def testDrainZero(self): assert self.snd.credit == 0 assert self.rcv.credit == 0 assert self.rcv.queued == 0 drained = self.rcv.drained() assert drained == 0 self.rcv.flow(10) self.pump() assert self.snd.credit == 10 assert self.rcv.credit == 10 assert self.rcv.queued == 0 self.snd.drained() self.pump() assert self.snd.credit == 10 assert self.rcv.credit == 10 assert self.rcv.queued == 0 drained = self.rcv.drained() assert drained == 0 self.rcv.drain(0) assert self.snd.credit == 10 assert self.rcv.credit == 10 assert self.rcv.queued == 0 self.pump() assert self.snd.credit == 10 assert self.rcv.credit == 10 assert self.rcv.queued == 0 self.snd.drained() assert self.snd.credit == 0 assert self.rcv.credit == 10 assert self.rcv.queued == 0 drained = self.rcv.drained() assert drained == 0 self.pump() assert self.snd.credit == 0 assert self.rcv.credit == 0 assert self.rcv.queued == 0 drained = self.rcv.drained() assert drained == 10 def testDrainOrder(self): """ Verify drain/drained works regardless of ordering. See PROTON-401 """ assert self.snd.credit == 0 assert self.rcv.credit == 0 assert self.rcv.queued == 0 #self.rcv.session.connection.transport.trace(Transport.TRACE_FRM) #self.snd.session.connection.transport.trace(Transport.TRACE_FRM) ## verify that a sender that has reached the drain state will respond ## promptly to a drain issued by the peer. self.rcv.flow(10) self.pump() assert self.snd.credit == 10, self.snd.credit assert self.rcv.credit == 10, self.rcv.credit sd = self.snd.delivery("tagA") assert sd n = self.snd.send(str2bin("A")) assert n == 1 self.pump() self.snd.advance() # done sending, so signal that we are drained: self.snd.drained() self.pump() assert self.snd.credit == 9, self.snd.credit assert self.rcv.credit == 10, self.rcv.credit self.rcv.drain(0) self.pump() assert self.snd.credit == 9, self.snd.credit assert self.rcv.credit == 10, self.rcv.credit data = self.rcv.recv(10) assert data == str2bin("A"), data self.rcv.advance() self.pump() assert self.snd.credit == 9, self.snd.credit assert self.rcv.credit == 9, self.rcv.credit self.snd.drained() self.pump() assert self.snd.credit == 0, self.snd.credit assert self.rcv.credit == 0, self.rcv.credit # verify that a drain requested by the peer is not "acknowledged" until # after the sender has completed sending its pending messages self.rcv.flow(10) self.pump() assert self.snd.credit == 10, self.snd.credit assert self.rcv.credit == 10, self.rcv.credit sd = self.snd.delivery("tagB") assert sd n = self.snd.send(str2bin("B")) assert n == 1 self.snd.advance() self.pump() assert self.snd.credit == 9, self.snd.credit assert self.rcv.credit == 10, self.rcv.credit self.rcv.drain(0) self.pump() assert self.snd.credit == 9, self.snd.credit assert self.rcv.credit == 10, self.rcv.credit sd = self.snd.delivery("tagC") assert sd n = self.snd.send(str2bin("C")) assert n == 1 self.snd.advance() self.pump() assert self.snd.credit == 8, self.snd.credit assert self.rcv.credit == 10, self.rcv.credit # now that the sender has finished sending everything, it can signal # drained self.snd.drained() self.pump() assert self.snd.credit == 0, self.snd.credit assert self.rcv.credit == 2, self.rcv.credit data = self.rcv.recv(10) assert data == str2bin("B"), data self.rcv.advance() data = self.rcv.recv(10) assert data == str2bin("C"), data self.rcv.advance() self.pump() assert self.snd.credit == 0, self.snd.credit assert self.rcv.credit == 0, self.rcv.credit def testPushback(self, count=10): assert self.snd.credit == 0 assert self.rcv.credit == 0 self.rcv.flow(count) self.pump() for i in range(count): d = self.snd.delivery("tag%s" % i) assert d self.snd.advance() assert self.snd.queued == count assert self.rcv.queued == 0 self.pump() assert self.snd.queued == 0 assert self.rcv.queued == count d = self.snd.delivery("extra") self.snd.advance() assert self.snd.queued == 1 assert self.rcv.queued == count self.pump() assert self.snd.queued == 1 assert self.rcv.queued == count def testHeadOfLineBlocking(self): self.snd2 = self.snd.session.sender("link-2") self.rcv2 = self.rcv.session.receiver("link-2") self.snd2.open() self.rcv2.open() self.pump() assert self.snd2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE assert self.rcv2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE self.rcv.flow(5) self.rcv2.flow(10) self.pump() assert self.snd.credit == 5 assert self.snd2.credit == 10 for i in range(10): tag = "test %d" % i self.snd.delivery( tag ) self.snd.send( tag.encode("ascii") ) assert self.snd.advance() self.snd2.delivery( tag ) self.snd2.send( tag.encode("ascii") ) assert self.snd2.advance() self.pump() for i in range(5): b = self.rcv.recv( 512 ) assert self.rcv.advance() b = self.rcv2.recv( 512 ) assert self.rcv2.advance() for i in range(5): b = self.rcv2.recv( 512 ) assert self.rcv2.advance() class SessionCreditTest(Test): def teardown(self): self.cleanup() def testBuffering(self, count=32, size=1024, capacity=16*1024, max_frame=1024): snd, rcv = self.link("test-link", max_frame=(max_frame, max_frame)) rcv.session.incoming_capacity = capacity snd.open() rcv.open() rcv.flow(count) self.pump() assert count > 0 total_bytes = count * size assert snd.session.outgoing_bytes == 0, snd.session.outgoing_bytes assert rcv.session.incoming_bytes == 0, rcv.session.incoming_bytes assert snd.queued == 0, snd.queued assert rcv.queued == 0, rcv.queued data = bytes(bytearray(size)) idx = 0 while snd.credit: d = snd.delivery("tag%s" % idx) assert d n = snd.send(data) assert n == size, (n, size) assert snd.advance() self.pump() idx += 1 assert idx == count, (idx, count) assert snd.session.outgoing_bytes < total_bytes, (snd.session.outgoing_bytes, total_bytes) assert rcv.session.incoming_bytes < capacity, (rcv.session.incoming_bytes, capacity) assert snd.session.outgoing_bytes + rcv.session.incoming_bytes == total_bytes, \ (snd.session.outgoing_bytes, rcv.session.incoming_bytes, total_bytes) if snd.session.outgoing_bytes > 0: available = rcv.session.incoming_capacity - rcv.session.incoming_bytes assert available < max_frame, (available, max_frame) for i in range(count): d = rcv.current assert d, i pending = d.pending before = rcv.session.incoming_bytes assert rcv.advance() after = rcv.session.incoming_bytes assert before - after == pending, (before, after, pending) snd_before = snd.session.incoming_bytes self.pump() snd_after = snd.session.incoming_bytes assert rcv.session.incoming_bytes < capacity if snd_before > 0: assert capacity - after <= max_frame assert snd_before > snd_after if snd_after > 0: available = rcv.session.incoming_capacity - rcv.session.incoming_bytes assert available < max_frame, available def testBufferingSize16(self): self.testBuffering(size=16) def testBufferingSize256(self): self.testBuffering(size=256) def testBufferingSize512(self): self.testBuffering(size=512) def testBufferingSize2048(self): self.testBuffering(size=2048) def testBufferingSize1025(self): self.testBuffering(size=1025) def testBufferingSize1023(self): self.testBuffering(size=1023) def testBufferingSize989(self): self.testBuffering(size=989) def testBufferingSize1059(self): self.testBuffering(size=1059) def testCreditWithBuffering(self): snd, rcv = self.link("test-link", max_frame=(1024, 1024)) rcv.session.incoming_capacity = 64*1024 snd.open() rcv.open() rcv.flow(128) self.pump() assert snd.credit == 128, snd.credit assert rcv.queued == 0, rcv.queued idx = 0 while snd.credit: d = snd.delivery("tag%s" % idx) snd.send(("x"*1024).encode('ascii')) assert d assert snd.advance() self.pump() idx += 1 assert idx == 128, idx assert rcv.queued < 128, rcv.queued rcv.flow(1) self.pump() assert snd.credit == 1, snd.credit class SettlementTest(Test): def setup(self): self.snd, self.rcv = self.link("test-link") self.c1 = self.snd.session.connection self.c2 = self.rcv.session.connection self.snd.open() self.rcv.open() self.pump() def cleanup(self): # release resources created by this class super(SettlementTest, self).cleanup() self.c1 = None self.snd = None self.c2 = None self.rcv2 = None self.snd2 = None def teardown(self): self.cleanup() def testSettleCurrent(self): self.rcv.flow(10) self.pump() assert self.snd.credit == 10, self.snd.credit d = self.snd.delivery("tag") e = self.snd.delivery("tag2") assert d assert e c = self.snd.current assert c.tag == "tag", c.tag c.settle() c = self.snd.current assert c.tag == "tag2", c.tag c.settle() c = self.snd.current assert not c self.pump() c = self.rcv.current assert c assert c.tag == "tag", c.tag assert c.settled c.settle() c = self.rcv.current assert c assert c.tag == "tag2", c.tag assert c.settled c.settle() c = self.rcv.current assert not c def testUnsettled(self): self.rcv.flow(10) self.pump() assert self.snd.unsettled == 0, self.snd.unsettled assert self.rcv.unsettled == 0, self.rcv.unsettled d = self.snd.delivery("tag") assert d assert self.snd.unsettled == 1, self.snd.unsettled assert self.rcv.unsettled == 0, self.rcv.unsettled assert self.snd.advance() self.pump() assert self.snd.unsettled == 1, self.snd.unsettled assert self.rcv.unsettled == 1, self.rcv.unsettled c = self.rcv.current assert c c.settle() assert self.snd.unsettled == 1, self.snd.unsettled assert self.rcv.unsettled == 0, self.rcv.unsettled def testMultipleUnsettled(self, count=1024, size=1024): self.rcv.flow(count) self.pump() assert self.snd.unsettled == 0, self.snd.unsettled assert self.rcv.unsettled == 0, self.rcv.unsettled unsettled = [] for i in range(count): sd = self.snd.delivery("tag%s" % i) assert sd n = self.snd.send(("x"*size).encode('ascii')) assert n == size, n assert self.snd.advance() self.pump() rd = self.rcv.current assert rd, "did not receive delivery %s" % i n = rd.pending b = self.rcv.recv(n) assert len(b) == n, (b, n) rd.update(Delivery.ACCEPTED) assert self.rcv.advance() self.pump() unsettled.append(rd) assert self.rcv.unsettled == count for rd in unsettled: rd.settle() def testMultipleUnsettled2K1K(self): self.testMultipleUnsettled(2048, 1024) def testMultipleUnsettled4K1K(self): self.testMultipleUnsettled(4096, 1024) def testMultipleUnsettled1K2K(self): self.testMultipleUnsettled(1024, 2048) def testMultipleUnsettled2K2K(self): self.testMultipleUnsettled(2048, 2048) def testMultipleUnsettled4K2K(self): self.testMultipleUnsettled(4096, 2048) class PipelineTest(Test): def setup(self): self.c1, self.c2 = self.connection() def cleanup(self): # release resources created by this class super(PipelineTest, self).cleanup() self.c1 = None self.c2 = None def teardown(self): self.cleanup() def test(self): ssn = self.c1.session() snd = ssn.sender("sender") self.c1.open() ssn.open() snd.open() for i in range(10): d = snd.delivery("delivery-%s" % i) snd.send(str2bin("delivery-%s" % i)) d.settle() snd.close() ssn.close() self.c1.close() self.pump() state = self.c2.state assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state ssn2 = self.c2.session_head(Endpoint.LOCAL_UNINIT) assert ssn2 state == ssn2.state assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state rcv = self.c2.link_head(Endpoint.LOCAL_UNINIT) assert rcv state = rcv.state assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state self.c2.open() ssn2.open() rcv.open() rcv.flow(10) assert rcv.queued == 0, rcv.queued self.pump() assert rcv.queued == 10, rcv.queued state = rcv.state assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state state = ssn2.state assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state state = self.c2.state assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state for i in range(rcv.queued): d = rcv.current assert d assert d.tag == "delivery-%s" % i d.settle() assert rcv.queued == 0, rcv.queued class ServerTest(Test): def testKeepalive(self): """ Verify that idle frames are sent to keep a Connection alive """ if "java" in sys.platform: raise Skipped() idle_timeout = self.delay server = common.TestServer() server.start() class Program: def on_reactor_init(self, event): self.conn = event.reactor.connection() self.conn.hostname = "%s:%s" % (server.host, server.port) self.conn.open() self.old_count = None event.reactor.schedule(3 * idle_timeout, self) def on_connection_bound(self, event): event.transport.idle_timeout = idle_timeout def on_connection_remote_open(self, event): self.old_count = event.transport.frames_input def on_timer_task(self, event): assert self.conn.state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE), "Connection terminated" assert self.conn.transport.frames_input > self.old_count, "No idle frames received" self.conn.close() Reactor(Program()).run() server.stop() def testIdleTimeout(self): """ Verify that a Connection is terminated properly when Idle frames do not arrive in a timely manner. """ if "java" in sys.platform: raise Skipped() idle_timeout = self.delay server = common.TestServer(idle_timeout=idle_timeout) server.start() class Program: def on_reactor_init(self, event): self.conn = event.reactor.connection() self.conn.hostname = "%s:%s" % (server.host, server.port) self.conn.open() self.remote_condition = None self.old_count = None # verify the connection stays up even if we don't explicitly send stuff # wait up to 3x the idle timeout event.reactor.schedule(3 * idle_timeout, self) def on_connection_bound(self, event): self.transport = event.transport def on_connection_remote_open(self, event): self.old_count = event.transport.frames_output def on_connection_remote_close(self, event): assert self.conn.remote_condition assert self.conn.remote_condition.name == "amqp:resource-limit-exceeded" self.remote_condition = self.conn.remote_condition def on_timer_task(self, event): assert self.conn.state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE), "Connection terminated" assert self.conn.transport.frames_output > self.old_count, "No idle frames sent" # now wait to explicitly cause the other side to expire: sleep(3 * idle_timeout) p = Program() Reactor(p).run() assert p.remote_condition assert p.remote_condition.name == "amqp:resource-limit-exceeded" server.stop() class NoValue: def __init__(self): pass def apply(self, dlv): pass def check(self, dlv): assert dlv.data == None assert dlv.section_number == 0 assert dlv.section_offset == 0 assert dlv.condition == None assert dlv.failed == False assert dlv.undeliverable == False assert dlv.annotations == None class RejectValue: def __init__(self, condition): self.condition = condition def apply(self, dlv): dlv.condition = self.condition def check(self, dlv): assert dlv.data == None, dlv.data assert dlv.section_number == 0 assert dlv.section_offset == 0 assert dlv.condition == self.condition, (dlv.condition, self.condition) assert dlv.failed == False assert dlv.undeliverable == False assert dlv.annotations == None class ReceivedValue: def __init__(self, section_number, section_offset): self.section_number = section_number self.section_offset = section_offset def apply(self, dlv): dlv.section_number = self.section_number dlv.section_offset = self.section_offset def check(self, dlv): assert dlv.data == None, dlv.data assert dlv.section_number == self.section_number, (dlv.section_number, self.section_number) assert dlv.section_offset == self.section_offset assert dlv.condition == None assert dlv.failed == False assert dlv.undeliverable == False assert dlv.annotations == None class ModifiedValue: def __init__(self, failed, undeliverable, annotations): self.failed = failed self.undeliverable = undeliverable self.annotations = annotations def apply(self, dlv): dlv.failed = self.failed dlv.undeliverable = self.undeliverable dlv.annotations = self.annotations def check(self, dlv): assert dlv.data == None, dlv.data assert dlv.section_number == 0 assert dlv.section_offset == 0 assert dlv.condition == None assert dlv.failed == self.failed assert dlv.undeliverable == self.undeliverable assert dlv.annotations == self.annotations, (dlv.annotations, self.annotations) class CustomValue: def __init__(self, data): self.data = data def apply(self, dlv): dlv.data = self.data def check(self, dlv): assert dlv.data == self.data, (dlv.data, self.data) assert dlv.section_number == 0 assert dlv.section_offset == 0 assert dlv.condition == None assert dlv.failed == False assert dlv.undeliverable == False assert dlv.annotations == None class DeliveryTest(Test): def teardown(self): self.cleanup() def testDisposition(self, count=1, tag="tag%i", type=Delivery.ACCEPTED, value=NoValue()): snd, rcv = self.link("test-link") snd.open() rcv.open() snd_deliveries = [] for i in range(count): d = snd.delivery(tag % i) snd_deliveries.append(d) snd.advance() rcv.flow(count) self.pump() rcv_deliveries = [] for i in range(count): d = rcv.current assert d.tag == (tag % i) rcv_deliveries.append(d) rcv.advance() for d in rcv_deliveries: value.apply(d.local) d.update(type) self.pump() for d in snd_deliveries: assert d.remote_state == type assert d.remote.type == type value.check(d.remote) value.apply(d.local) d.update(type) self.pump() for d in rcv_deliveries: assert d.remote_state == type assert d.remote.type == type value.check(d.remote) for d in snd_deliveries: d.settle() self.pump() for d in rcv_deliveries: assert d.settled, d.settled d.settle() def testReceived(self): self.testDisposition(type=Disposition.RECEIVED, value=ReceivedValue(1, 2)) def testRejected(self): self.testDisposition(type=Disposition.REJECTED, value=RejectValue(Condition(symbol("foo")))) def testReleased(self): self.testDisposition(type=Disposition.RELEASED) def testModified(self): self.testDisposition(type=Disposition.MODIFIED, value=ModifiedValue(failed=True, undeliverable=True, annotations={"key": "value"})) def testCustom(self): self.testDisposition(type=0x12345, value=CustomValue([1, 2, 3])) class CollectorTest(Test): def setup(self): self.collector = Collector() def drain(self): result = [] while True: e = self.collector.peek() if e: result.append(e) self.collector.pop() else: break return result def expect(self, *types): return self.expect_oneof(types) def expect_oneof(self, *sequences): events = self.drain() types = tuple([e.type for e in events]) for alternative in sequences: if types == alternative: if len(events) == 1: return events[0] elif len(events) > 1: return events else: return assert False, "actual events %s did not match any of the expected sequences: %s" % (events, sequences) def expect_until(self, *types): events = self.drain() etypes = tuple([e.type for e in events[-len(types):]]) assert etypes == types, "actual events %s did not end in expect sequence: %s" % (events, types) class EventTest(CollectorTest): def teardown(self): self.cleanup() def testEndpointEvents(self): c1, c2 = self.connection() c1.collect(self.collector) self.expect(Event.CONNECTION_INIT) self.pump() self.expect() c2.open() self.pump() self.expect(Event.CONNECTION_REMOTE_OPEN) self.pump() self.expect() ssn = c2.session() snd = ssn.sender("sender") ssn.open() snd.open() self.expect() self.pump() self.expect(Event.SESSION_INIT, Event.SESSION_REMOTE_OPEN, Event.LINK_INIT, Event.LINK_REMOTE_OPEN) c1.open() ssn2 = c1.session() ssn2.open() rcv = ssn2.receiver("receiver") rcv.open() self.pump() self.expect(Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.SESSION_INIT, Event.SESSION_LOCAL_OPEN, Event.TRANSPORT, Event.LINK_INIT, Event.LINK_LOCAL_OPEN, Event.TRANSPORT) rcv.close() self.expect(Event.LINK_LOCAL_CLOSE, Event.TRANSPORT) self.pump() rcv.free() del rcv self.expect(Event.LINK_FINAL) ssn2.free() del ssn2 self.pump() c1.free() c1.transport.unbind() self.expect_oneof((Event.SESSION_FINAL, Event.LINK_FINAL, Event.SESSION_FINAL, Event.CONNECTION_UNBOUND, Event.CONNECTION_FINAL), (Event.CONNECTION_UNBOUND, Event.SESSION_FINAL, Event.LINK_FINAL, Event.SESSION_FINAL, Event.CONNECTION_FINAL)) def testConnectionINIT_FINAL(self): c = Connection() c.collect(self.collector) self.expect(Event.CONNECTION_INIT) c.free() self.expect(Event.CONNECTION_FINAL) def testSessionINIT_FINAL(self): c = Connection() c.collect(self.collector) self.expect(Event.CONNECTION_INIT) s = c.session() self.expect(Event.SESSION_INIT) s.free() self.expect(Event.SESSION_FINAL) c.free() self.expect(Event.CONNECTION_FINAL) def testLinkINIT_FINAL(self): c = Connection() c.collect(self.collector) self.expect(Event.CONNECTION_INIT) s = c.session() self.expect(Event.SESSION_INIT) r = s.receiver("asdf") self.expect(Event.LINK_INIT) r.free() self.expect(Event.LINK_FINAL) c.free() self.expect(Event.SESSION_FINAL, Event.CONNECTION_FINAL) def testFlowEvents(self): snd, rcv = self.link("test-link") snd.session.connection.collect(self.collector) rcv.open() rcv.flow(10) self.pump() self.expect(Event.CONNECTION_INIT, Event.SESSION_INIT, Event.LINK_INIT, Event.LINK_REMOTE_OPEN, Event.LINK_FLOW) rcv.flow(10) self.pump() self.expect(Event.LINK_FLOW) return snd, rcv def testDeliveryEvents(self): snd, rcv = self.link("test-link") rcv.session.connection.collect(self.collector) rcv.open() rcv.flow(10) self.pump() self.expect(Event.CONNECTION_INIT, Event.SESSION_INIT, Event.LINK_INIT, Event.LINK_LOCAL_OPEN, Event.TRANSPORT) snd.delivery("delivery") snd.send(str2bin("Hello World!")) snd.advance() self.pump() self.expect() snd.open() self.pump() self.expect(Event.LINK_REMOTE_OPEN, Event.DELIVERY) rcv.session.connection.transport.unbind() rcv.session.connection.free() self.expect(Event.CONNECTION_UNBOUND, Event.TRANSPORT, Event.LINK_FINAL, Event.SESSION_FINAL, Event.CONNECTION_FINAL) def testDeliveryEventsDisp(self): snd, rcv = self.testFlowEvents() snd.open() dlv = snd.delivery("delivery") snd.send(str2bin("Hello World!")) assert snd.advance() self.expect(Event.LINK_LOCAL_OPEN, Event.TRANSPORT) self.pump() self.expect(Event.LINK_FLOW) rdlv = rcv.current assert rdlv != None assert rdlv.tag == "delivery" rdlv.update(Delivery.ACCEPTED) self.pump() event = self.expect(Event.DELIVERY) assert event.context == dlv, (dlv, event.context) def testConnectionBOUND_UNBOUND(self): c = Connection() c.collect(self.collector) self.expect(Event.CONNECTION_INIT) t = Transport() t.bind(c) self.expect(Event.CONNECTION_BOUND) t.unbind() self.expect(Event.CONNECTION_UNBOUND, Event.TRANSPORT) def testTransportERROR_CLOSE(self): c = Connection() c.collect(self.collector) self.expect(Event.CONNECTION_INIT) t = Transport() t.bind(c) self.expect(Event.CONNECTION_BOUND) assert t.condition is None t.push(str2bin("asdf")) self.expect(Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED) assert t.condition is not None assert t.condition.name == "amqp:connection:framing-error" assert "AMQP header mismatch" in t.condition.description p = t.pending() assert p > 0 t.pop(p) self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED) def testTransportCLOSED(self): c = Connection() c.collect(self.collector) self.expect(Event.CONNECTION_INIT) t = Transport() t.bind(c) c.open() self.expect(Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT) c2 = Connection() t2 = Transport() t2.bind(c2) c2.open() c2.close() pump(t, t2) self.expect(Event.CONNECTION_REMOTE_OPEN, Event.CONNECTION_REMOTE_CLOSE, Event.TRANSPORT_TAIL_CLOSED) c.close() pump(t, t2) self.expect(Event.CONNECTION_LOCAL_CLOSE, Event.TRANSPORT, Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED) def testLinkDetach(self): c1 = Connection() c1.collect(self.collector) t1 = Transport() t1.bind(c1) c1.open() s1 = c1.session() s1.open() l1 = s1.sender("asdf") l1.open() l1.detach() self.expect_until(Event.LINK_LOCAL_DETACH, Event.TRANSPORT) c2 = Connection() c2.collect(self.collector) t2 = Transport() t2.bind(c2) pump(t1, t2) self.expect_until(Event.LINK_REMOTE_DETACH) class PeerTest(CollectorTest): def setup(self): CollectorTest.setup(self) self.connection = Connection() self.connection.collect(self.collector) self.transport = Transport() self.transport.bind(self.connection) self.peer = Connection() self.peer_transport = Transport() self.peer_transport.bind(self.peer) self.peer_transport.trace(Transport.TRACE_OFF) def pump(self): pump(self.transport, self.peer_transport) class TeardownLeakTest(PeerTest): def doLeak(self, local, remote): self.connection.open() self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT) ssn = self.connection.session() ssn.open() self.expect(Event.SESSION_INIT, Event.SESSION_LOCAL_OPEN, Event.TRANSPORT) snd = ssn.sender("sender") snd.open() self.expect(Event.LINK_INIT, Event.LINK_LOCAL_OPEN, Event.TRANSPORT) self.pump() self.peer.open() self.peer.session_head(0).open() self.peer.link_head(0).open() self.pump() self.expect_oneof((Event.CONNECTION_REMOTE_OPEN, Event.SESSION_REMOTE_OPEN, Event.LINK_REMOTE_OPEN, Event.LINK_FLOW), (Event.CONNECTION_REMOTE_OPEN, Event.SESSION_REMOTE_OPEN, Event.LINK_REMOTE_OPEN)) if local: snd.close() # ha!! self.expect(Event.LINK_LOCAL_CLOSE, Event.TRANSPORT) ssn.close() self.expect(Event.SESSION_LOCAL_CLOSE, Event.TRANSPORT) self.connection.close() self.expect(Event.CONNECTION_LOCAL_CLOSE, Event.TRANSPORT) if remote: self.peer.link_head(0).close() # ha!! self.peer.session_head(0).close() self.peer.close() self.pump() if remote: self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.LINK_REMOTE_CLOSE, Event.SESSION_REMOTE_CLOSE, Event.CONNECTION_REMOTE_CLOSE, Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_CLOSED) else: self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.SESSION_REMOTE_CLOSE, Event.CONNECTION_REMOTE_CLOSE, Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_CLOSED) self.connection.free() self.expect(Event.LINK_FINAL, Event.SESSION_FINAL) self.transport.unbind() self.expect(Event.CONNECTION_UNBOUND, Event.CONNECTION_FINAL) def testLocalRemoteLeak(self): self.doLeak(True, True) def testLocalLeak(self): self.doLeak(True, False) def testRemoteLeak(self): self.doLeak(False, True) def testLeak(self): self.doLeak(False, False) class IdleTimeoutEventTest(PeerTest): def half_pump(self): p = self.transport.pending() if p>0: self.transport.pop(p) def testTimeoutWithZombieServer(self, expectOpenCloseFrames=True): self.transport.idle_timeout = self.delay self.connection.open() self.half_pump() self.transport.tick(time()) sleep(self.delay*2) self.transport.tick(time()) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT, Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED) assert self.transport.capacity() < 0 if expectOpenCloseFrames: assert self.transport.pending() > 0 self.half_pump() self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED) assert self.transport.pending() < 0 def testTimeoutWithZombieServerAndSASL(self): sasl = self.transport.sasl() self.testTimeoutWithZombieServer(expectOpenCloseFrames=False) class DeliverySegFaultTest(Test): def testDeliveryAfterUnbind(self): conn = Connection() t = Transport() ssn = conn.session() snd = ssn.sender("sender") dlv = snd.delivery("tag") dlv.settle() del dlv t.bind(conn) t.unbind() dlv = snd.delivery("tag") class SaslEventTest(CollectorTest): def testAnonymousNoInitialResponse(self): if "java" in sys.platform: raise Skipped() conn = Connection() conn.collect(self.collector) transport = Transport(Transport.SERVER) transport.bind(conn) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND) transport.push(str2bin('AMQP\x03\x01\x00\x00\x00\x00\x00 \x02\x01\x00\x00\x00SA' '\xd0\x00\x00\x00\x10\x00\x00\x00\x02\xa3\tANONYMOUS@' 'AMQP\x00\x01\x00\x00')) self.expect(Event.TRANSPORT) for i in range(1024): p = transport.pending() self.drain() p = transport.pending() self.expect() def testPipelinedServerReadFirst(self): if "java" in sys.platform: raise Skipped() conn = Connection() conn.collect(self.collector) transport = Transport(Transport.CLIENT) s = transport.sasl() s.allowed_mechs("ANONYMOUS PLAIN") transport.bind(conn) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND) transport.push(str2bin('AMQP\x03\x01\x00\x00\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@' '\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS\x00\x00\x00\x10' '\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00AMQP\x00\x01\x00' '\x00')) self.expect(Event.TRANSPORT) p = transport.pending() bytes = transport.peek(p) transport.pop(p) server = Transport(Transport.SERVER) server.push(bytes) assert server.sasl().outcome == SASL.OK def testPipelinedServerWriteFirst(self): if "java" in sys.platform: raise Skipped() conn = Connection() conn.collect(self.collector) transport = Transport(Transport.CLIENT) s = transport.sasl() s.allowed_mechs("ANONYMOUS") transport.bind(conn) p = transport.pending() bytes = transport.peek(p) transport.pop(p) self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND, Event.TRANSPORT) transport.push(str2bin('AMQP\x03\x01\x00\x00\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@' '\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS\x00\x00\x00\x10' '\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00AMQP\x00\x01\x00' '\x00')) self.expect(Event.TRANSPORT) p = transport.pending() bytes = transport.peek(p) transport.pop(p) # XXX: the bytes above appear to be correct, but we don't get any # sort of event indicating that the transport is authenticated qpid-proton-0.10/tests/python/proton_tests/common.py0000664000000000000000000004456712562450203017705 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from unittest import TestCase from random import randint from threading import Thread from socket import socket, AF_INET, SOCK_STREAM from subprocess import Popen,PIPE,STDOUT import sys, os, string, subprocess from proton import Connection, Transport, SASL, Endpoint, Delivery, SSL from proton.reactor import Container from proton.handlers import CHandshaker, CFlowController from string import Template if sys.version_info[0] == 2 and sys.version_info[1] < 6: # this is for compatibility, apparently the version of jython we # use doesn't have the next() builtin. # we should remove this when we upgrade to a python 2.6+ compatible version # of jython #_DEF = object() This causes the test loader to fail (why?) class _dummy(): pass _DEF = _dummy def next(iter, default=_DEF): try: return iter.next() except StopIteration: if default is _DEF: raise else: return default # I may goto hell for this: import __builtin__ __builtin__.__dict__['next'] = next def free_tcp_ports(count=1): """ return a list of 'count' TCP ports that are free to used (ie. unbound) """ retry = 0 ports = [] sockets = [] while len(ports) != count: port = randint(49152, 65535) sockets.append( socket( AF_INET, SOCK_STREAM ) ) try: sockets[-1].bind( ("0.0.0.0", port ) ) ports.append( port ) retry = 0 except: retry += 1 assert retry != 100, "No free sockets available for test!" for s in sockets: s.close() return ports def free_tcp_port(): return free_tcp_ports(1)[0] def pump_uni(src, dst, buffer_size=1024): p = src.pending() c = dst.capacity() if c < 0: if p < 0: return False else: src.close_head() return True if p < 0: dst.close_tail() elif p == 0 or c == 0: return False else: binary = src.peek(min(c, buffer_size)) dst.push(binary) src.pop(len(binary)) return True def pump(transport1, transport2, buffer_size=1024): """ Transfer all pending bytes between two Proton engines by repeatedly calling peek/pop and push. Asserts that each engine accepts some bytes every time (unless it's already closed). """ while (pump_uni(transport1, transport2, buffer_size) or pump_uni(transport2, transport1, buffer_size)): pass def isSSLPresent(): return SSL.present() createdSASLDb = False def _cyrusSetup(conf_dir): """Write out simple SASL config. """ saslpasswd = "" if 'SASLPASSWD' in os.environ: saslpasswd = os.environ['SASLPASSWD'] if os.path.exists(saslpasswd): t = Template("""sasldb_path: ${db} mech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS """) abs_conf_dir = os.path.abspath(conf_dir) subprocess.call(args=['rm','-rf',abs_conf_dir]) os.mkdir(abs_conf_dir) db = os.path.join(abs_conf_dir,'proton.sasldb') conf = os.path.join(abs_conf_dir,'proton-server.conf') f = open(conf, 'w') f.write(t.substitute(db=db)) f.close() cmd_template = Template("echo password | ${saslpasswd} -c -p -f ${db} -u proton user") cmd = cmd_template.substitute(db=db, saslpasswd=saslpasswd) subprocess.call(args=cmd, shell=True) os.environ['PN_SASL_CONFIG_PATH'] = abs_conf_dir global createdSASLDb createdSASLDb = True # Globally initialize Cyrus SASL configuration if SASL.extended(): _cyrusSetup('sasl_conf') def ensureCanTestExtendedSASL(): if not SASL.extended(): raise Skipped('Extended SASL not supported') if not createdSASLDb: raise Skipped("Can't Test Extended SASL: Couldn't create auth db") class Test(TestCase): def __init__(self, name): super(Test, self).__init__(name) self.name = name def configure(self, config): self.config = config def default(self, name, value, **profiles): default = value profile = self.config.defines.get("profile") if profile: default = profiles.get(profile, default) return self.config.defines.get(name, default) @property def delay(self): return float(self.default("delay", "1", fast="0.1")) @property def timeout(self): return float(self.default("timeout", "60", fast="10")) @property def verbose(self): return int(self.default("verbose", 0)) class Skipped(Exception): skipped = True class TestServer(object): """ Base class for creating test-specific message servers. """ def __init__(self, **kwargs): self.args = kwargs self.reactor = Container(self) self.host = "127.0.0.1" self.port = 0 if "host" in kwargs: self.host = kwargs["host"] if "port" in kwargs: self.port = kwargs["port"] self.handlers = [CFlowController(10), CHandshaker()] self.thread = Thread(name="server-thread", target=self.run) self.thread.daemon = True self.running = True self.conditions = [] def start(self): self.reactor.start() retry = 0 if self.port == 0: self.port = str(randint(49152, 65535)) retry = 10 while retry > 0: try: self.acceptor = self.reactor.acceptor(self.host, self.port) break except IOError: self.port = str(randint(49152, 65535)) retry -= 1 assert retry > 0, "No free port for server to listen on!" self.thread.start() def stop(self): self.running = False self.reactor.wakeup() self.thread.join() # Note: all following methods all run under the thread: def run(self): self.reactor.timeout = 3.14159265359 while self.reactor.process(): if not self.running: self.acceptor.close() self.reactor.stop() break def on_connection_bound(self, event): if "idle_timeout" in self.args: event.transport.idle_timeout = self.args["idle_timeout"] def on_connection_local_close(self, event): self.conditions.append(event.connection.condition) def on_delivery(self, event): event.delivery.settle() # # Classes that wrap the messenger applications msgr-send and msgr-recv. # These applications reside in the tests/tools/apps directory # class MessengerApp(object): """ Interface to control a MessengerApp """ def __init__(self): self._cmdline = None # options common to Receivers and Senders: self.ca_db = None self.certificate = None self.privatekey = None self.password = None self._output = None def findfile(self, filename, searchpath): """Find filename in the searchpath return absolute path to the file or None """ paths = string.split(searchpath, os.pathsep) for path in paths: if os.path.exists(os.path.join(path, filename)): return os.path.abspath(os.path.join(path, filename)) return None def start(self, verbose=False): """ Begin executing the test """ cmd = self.cmdline() self._verbose = verbose if self._verbose: print("COMMAND='%s'" % str(cmd)) #print("ENV='%s'" % str(os.environ.copy())) try: if os.name=="nt": # Windows handles python launch by replacing script 'filename' with # 'python abspath-to-filename' in cmdline arg list. if cmd[0].endswith('.py'): foundfile = self.findfile(cmd[0], os.environ['PATH']) if foundfile is None: foundfile = self.findfile(cmd[0], os.environ['PYTHONPATH']) msg = "Unable to locate file '%s' in PATH or PYTHONPATH" % cmd[0] raise Skipped("Skipping test - %s" % msg) del cmd[0:1] cmd.insert(0, foundfile) cmd.insert(0, sys.executable) self._process = Popen(cmd, stdout=PIPE, stderr=STDOUT, bufsize=4096, universal_newlines=True) except OSError: e = sys.exc_info()[1] print("ERROR: '%s'" % e) msg = "Unable to execute command '%s', is it in your PATH?" % cmd[0] # NOTE(flaper87): Skip the test if the command is not found. if e.errno == 2: raise Skipped("Skipping test - %s" % msg) assert False, msg self._ready() # wait for it to initialize def stop(self): """ Signal the client to start clean shutdown """ pass def wait(self): """ Wait for client to complete """ self._output = self._process.communicate() if self._verbose: print("OUTPUT='%s'" % self.stdout()) def status(self): """ Return status from client process """ return self._process.returncode def stdout(self): #self._process.communicate()[0] if not self._output or not self._output[0]: return "*** NO STDOUT ***" return self._output[0] def stderr(self): if not self._output or not self._output[1]: return "*** NO STDERR ***" return self._output[1] def cmdline(self): if not self._cmdline: self._build_command() return self._cmdline def _build_command(self): assert False, "_build_command() needs override" def _ready(self): assert False, "_ready() needs override" def _do_common_options(self): """ Common option handling """ if self.ca_db is not None: self._cmdline.append("-T") self._cmdline.append(str(self.ca_db)) if self.certificate is not None: self._cmdline.append("-C") self._cmdline.append(str(self.certificate)) if self.privatekey is not None: self._cmdline.append("-K") self._cmdline.append(str(self.privatekey)) if self.password is not None: self._cmdline.append("-P") self._cmdline.append("pass:" + str(self.password)) class MessengerSender(MessengerApp): """ Interface to configure a sending MessengerApp """ def __init__(self): MessengerApp.__init__(self) self._command = None # @todo make these properties self.targets = [] self.send_count = None self.msg_size = None self.send_batch = None self.outgoing_window = None self.report_interval = None self.get_reply = False self.timeout = None self.incoming_window = None self.recv_count = None self.name = None # command string? def _build_command(self): self._cmdline = self._command self._do_common_options() assert self.targets, "Missing targets, required for sender!" self._cmdline.append("-a") self._cmdline.append(",".join(self.targets)) if self.send_count is not None: self._cmdline.append("-c") self._cmdline.append(str(self.send_count)) if self.msg_size is not None: self._cmdline.append("-b") self._cmdline.append(str(self.msg_size)) if self.send_batch is not None: self._cmdline.append("-p") self._cmdline.append(str(self.send_batch)) if self.outgoing_window is not None: self._cmdline.append("-w") self._cmdline.append(str(self.outgoing_window)) if self.report_interval is not None: self._cmdline.append("-e") self._cmdline.append(str(self.report_interval)) if self.get_reply: self._cmdline.append("-R") if self.timeout is not None: self._cmdline.append("-t") self._cmdline.append(str(self.timeout)) if self.incoming_window is not None: self._cmdline.append("-W") self._cmdline.append(str(self.incoming_window)) if self.recv_count is not None: self._cmdline.append("-B") self._cmdline.append(str(self.recv_count)) if self.name is not None: self._cmdline.append("-N") self._cmdline.append(str(self.name)) def _ready(self): pass class MessengerReceiver(MessengerApp): """ Interface to configure a receiving MessengerApp """ def __init__(self): MessengerApp.__init__(self) self._command = None # @todo make these properties self.subscriptions = [] self.receive_count = None self.recv_count = None self.incoming_window = None self.timeout = None self.report_interval = None self.send_reply = False self.outgoing_window = None self.forwards = [] self.name = None # command string? def _build_command(self): self._cmdline = self._command self._do_common_options() self._cmdline += ["-X", "READY"] assert self.subscriptions, "Missing subscriptions, required for receiver!" self._cmdline.append("-a") self._cmdline.append(",".join(self.subscriptions)) if self.receive_count is not None: self._cmdline.append("-c") self._cmdline.append(str(self.receive_count)) if self.recv_count is not None: self._cmdline.append("-b") self._cmdline.append(str(self.recv_count)) if self.incoming_window is not None: self._cmdline.append("-w") self._cmdline.append(str(self.incoming_window)) if self.timeout is not None: self._cmdline.append("-t") self._cmdline.append(str(self.timeout)) if self.report_interval is not None: self._cmdline.append("-e") self._cmdline.append(str(self.report_interval)) if self.send_reply: self._cmdline.append("-R") if self.outgoing_window is not None: self._cmdline.append("-W") self._cmdline.append(str(self.outgoing_window)) if self.forwards: self._cmdline.append("-F") self._cmdline.append(",".join(self.forwards)) if self.name is not None: self._cmdline.append("-N") self._cmdline.append(str(self.name)) def _ready(self): """ wait for subscriptions to complete setup. """ r = self._process.stdout.readline() assert r.strip() == "READY", "Unexpected input while waiting for receiver to initialize: %s" % r class MessengerSenderC(MessengerSender): def __init__(self): MessengerSender.__init__(self) self._command = ["msgr-send"] class MessengerSenderValgrind(MessengerSenderC): """ Run the C sender under Valgrind """ def __init__(self, suppressions=None): if "VALGRIND" not in os.environ: raise Skipped("Skipping test - $VALGRIND not set.") MessengerSenderC.__init__(self) if not suppressions: suppressions = os.path.join(os.path.dirname(__file__), "valgrind.supp" ) self._command = [os.environ["VALGRIND"], "--error-exitcode=1", "--quiet", "--trace-children=yes", "--leak-check=full", "--suppressions=%s" % suppressions] + self._command class MessengerReceiverC(MessengerReceiver): def __init__(self): MessengerReceiver.__init__(self) self._command = ["msgr-recv"] class MessengerReceiverValgrind(MessengerReceiverC): """ Run the C receiver under Valgrind """ def __init__(self, suppressions=None): if "VALGRIND" not in os.environ: raise Skipped("Skipping test - $VALGRIND not set.") MessengerReceiverC.__init__(self) if not suppressions: suppressions = os.path.join(os.path.dirname(__file__), "valgrind.supp" ) self._command = [os.environ["VALGRIND"], "--error-exitcode=1", "--quiet", "--trace-children=yes", "--leak-check=full", "--suppressions=%s" % suppressions] + self._command class MessengerSenderPython(MessengerSender): def __init__(self): MessengerSender.__init__(self) self._command = ["msgr-send.py"] class MessengerReceiverPython(MessengerReceiver): def __init__(self): MessengerReceiver.__init__(self) self._command = ["msgr-recv.py"] class ReactorSenderC(MessengerSender): def __init__(self): MessengerSender.__init__(self) self._command = ["reactor-send"] class ReactorSenderValgrind(ReactorSenderC): """ Run the C sender under Valgrind """ def __init__(self, suppressions=None): if "VALGRIND" not in os.environ: raise Skipped("Skipping test - $VALGRIND not set.") ReactorSenderC.__init__(self) if not suppressions: suppressions = os.path.join(os.path.dirname(__file__), "valgrind.supp" ) self._command = [os.environ["VALGRIND"], "--error-exitcode=1", "--quiet", "--trace-children=yes", "--leak-check=full", "--suppressions=%s" % suppressions] + self._command class ReactorReceiverC(MessengerReceiver): def __init__(self): MessengerReceiver.__init__(self) self._command = ["reactor-recv"] class ReactorReceiverValgrind(ReactorReceiverC): """ Run the C receiver under Valgrind """ def __init__(self, suppressions=None): if "VALGRIND" not in os.environ: raise Skipped("Skipping test - $VALGRIND not set.") ReactorReceiverC.__init__(self) if not suppressions: suppressions = os.path.join(os.path.dirname(__file__), "valgrind.supp" ) self._command = [os.environ["VALGRIND"], "--error-exitcode=1", "--quiet", "--trace-children=yes", "--leak-check=full", "--suppressions=%s" % suppressions] + self._command qpid-proton-0.10/tests/python/proton_tests/codec.py0000664000000000000000000002641112562450203017456 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import os, sys from . import common from proton import * from proton._compat import raise_, str2unicode, unichar, str2bin try: from uuid import uuid4 except ImportError: from proton import uuid4 class Test(common.Test): def setup(self): self.data = Data() def teardown(self): self.data = None class DataTest(Test): def testTopLevelNext(self): assert self.data.next() is None self.data.put_null() self.data.put_bool(False) self.data.put_int(0) assert self.data.next() is None self.data.rewind() assert self.data.next() == Data.NULL assert self.data.next() == Data.BOOL assert self.data.next() == Data.INT assert self.data.next() is None def testNestedNext(self): assert self.data.next() is None self.data.put_null() assert self.data.next() is None self.data.put_list() assert self.data.next() is None self.data.put_bool(False) assert self.data.next() is None self.data.rewind() assert self.data.next() is Data.NULL assert self.data.next() is Data.LIST self.data.enter() assert self.data.next() is None self.data.put_ubyte(0) assert self.data.next() is None self.data.put_uint(0) assert self.data.next() is None self.data.put_int(0) assert self.data.next() is None self.data.exit() assert self.data.next() is Data.BOOL assert self.data.next() is None self.data.rewind() assert self.data.next() is Data.NULL assert self.data.next() is Data.LIST assert self.data.enter() assert self.data.next() is Data.UBYTE assert self.data.next() is Data.UINT assert self.data.next() is Data.INT assert self.data.next() is None assert self.data.exit() assert self.data.next() is Data.BOOL assert self.data.next() is None def testEnterExit(self): assert self.data.next() is None assert not self.data.enter() self.data.put_list() assert self.data.enter() assert self.data.next() is None self.data.put_list() assert self.data.enter() self.data.put_list() assert self.data.enter() assert self.data.exit() assert self.data.get_list() == 0 assert self.data.exit() assert self.data.get_list() == 1 assert self.data.exit() assert self.data.get_list() == 1 assert not self.data.exit() assert self.data.get_list() == 1 assert self.data.next() is None self.data.rewind() assert self.data.next() is Data.LIST assert self.data.get_list() == 1 assert self.data.enter() assert self.data.next() is Data.LIST assert self.data.get_list() == 1 assert self.data.enter() assert self.data.next() is Data.LIST assert self.data.get_list() == 0 assert self.data.enter() assert self.data.next() is None assert self.data.exit() assert self.data.get_list() == 0 assert self.data.exit() assert self.data.get_list() == 1 assert self.data.exit() assert self.data.get_list() == 1 assert not self.data.exit() def put(self, putter, v): """More informative exception from putters, include bad value""" try: putter(v) except Exception: etype, value, trace = sys.exc_info() raise_(etype, etype("%s(%r): %s" % (putter.__name__, v, value)), trace) return putter # (bits, signed) for each integer type INT_TYPES = { "byte": (8, True), "ubyte": (8, False), "int": (32, True), "uint": (32, False), "long": (64, True), "ulong": (64, False) } def int_values(self, dtype): """Set of test values for integer type dtype, include extreme and medial values""" bits, signed = self.INT_TYPES[dtype] values = [0, 1, 2, 5, 42] if signed: min, max = -2**(bits-1), 2**(bits-1)-1 values.append(max // 2) values += [-i for i in values if i] values += [min, max] else: max = 2**(bits) - 1 values += [max // 2, max] return sorted(values) def _testArray(self, dtype, descriptor, atype, *values): if dtype: dTYPE = getattr(self.data, dtype.upper()) aTYPE = getattr(self.data, atype.upper()) self.data.put_array(dtype is not None, aTYPE) self.data.enter() if dtype is not None: putter = getattr(self.data, "put_%s" % dtype) self.put(putter, descriptor) putter = getattr(self.data, "put_%s" % atype) for v in values: self.put(putter, v) self.data.exit() self.data.rewind() assert self.data.next() == Data.ARRAY count, described, type = self.data.get_array() assert count == len(values), count if dtype is None: assert described == False else: assert described == True assert type == aTYPE, type assert self.data.enter() if described: assert self.data.next() == dTYPE getter = getattr(self.data, "get_%s" % dtype) gotten = getter() assert gotten == descriptor, gotten if values: getter = getattr(self.data, "get_%s" % atype) for v in values: assert self.data.next() == aTYPE gotten = getter() assert gotten == v, gotten assert self.data.next() is None assert self.data.exit() def testStringArray(self): self._testArray(None, None, "string", "one", "two", "three") def testDescribedStringArray(self): self._testArray("symbol", "url", "string", "one", "two", "three") def _test_int_array(self, atype): self._testArray(None, None, atype, *self.int_values(atype)) def testByteArray(self): self._test_int_array("byte") def testUbyteArray(self): self._test_int_array("ubyte") def testIntArray(self): self._test_int_array("int") def testUintArray(self): self._test_int_array("uint") def testLongArray(self): self._test_int_array("long") def testUlongArray(self): self._test_int_array("ulong") def testUUIDArray(self): self._testArray(None, None, "uuid", uuid4(), uuid4(), uuid4()) def testEmptyArray(self): self._testArray(None, None, "null") def testDescribedEmptyArray(self): self._testArray("long", 0, "null") def _test(self, dtype, *values, **kwargs): eq=kwargs.get("eq", lambda x, y: x == y) ntype = getattr(Data, dtype.upper()) putter = getattr(self.data, "put_%s" % dtype) getter = getattr(self.data, "get_%s" % dtype) for v in values: self.put(putter, v) gotten = getter() assert eq(gotten, v), (gotten, v) self.data.rewind() for v in values: vtype = self.data.next() assert vtype == ntype, vtype gotten = getter() assert eq(gotten, v), (gotten, v) encoded = self.data.encode() copy = Data(0) while encoded: n = copy.decode(encoded) encoded = encoded[n:] copy.rewind() cgetter = getattr(copy, "get_%s" % dtype) for v in values: vtype = copy.next() assert vtype == ntype, vtype gotten = cgetter() assert eq(gotten, v), (gotten, v) def _test_int(self, itype): self._test(itype, *self.int_values(itype)) def testByte(self): self._test_int("byte") def testUbyte(self): self._test_int("ubyte") def testInt(self): self._test_int("int") def testUint(self): self._test_int("uint") def testLong(self): self._test_int("long") def testUlong(self): self._test_int("ulong") def testString(self): self._test("string", "one", "two", "three", "this is a test", "") def testFloat(self): # we have to use a special comparison here because python # internaly only uses doubles and converting between floats and # doubles is imprecise self._test("float", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3, eq=lambda x, y: x - y < 0.000001) def testDouble(self): self._test("double", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3) def testBinary(self): self._test("binary", str2bin("this"), str2bin("is"), str2bin("a"), str2bin("test"), str2bin("of" "b\x00inary")) def testSymbol(self): self._test("symbol", "this is a symbol test", "bleh", "blah") def testTimestamp(self): self._test("timestamp", 0, 12345, 1000000) def testChar(self): self._test("char", 'a', 'b', 'c', unichar(0x20AC)) def testUUID(self): self._test("uuid", uuid4(), uuid4(), uuid4()) def testDecimal32(self): self._test("decimal32", 0, 1, 2, 3, 4, 2**30) def testDecimal64(self): self._test("decimal64", 0, 1, 2, 3, 4, 2**60) def testDecimal128(self): self._test("decimal128", str2bin("fdsaasdf;lkjjkl;"), str2bin("x"*16)) def testCopy(self): self.data.put_described() self.data.enter() self.data.put_ulong(123) self.data.put_map() self.data.enter() self.data.put_string("pi") self.data.put_double(3.14159265359) dst = Data() dst.copy(self.data) copy = dst.format() orig = self.data.format() assert copy == orig, (copy, orig) def testCopyNested(self): nested = [1, 2, 3, [4, 5, 6], 7, 8, 9] self.data.put_object(nested) dst = Data() dst.copy(self.data) assert dst.format() == self.data.format() def testCopyNestedArray(self): nested = [Array(UNDESCRIBED, Data.LIST, ["first", [Array(UNDESCRIBED, Data.INT, 1,2,3)]], ["second", [Array(UNDESCRIBED, Data.INT, 1,2,3)]], ["third", [Array(UNDESCRIBED, Data.INT, 1,2,3)]], ), "end"] self.data.put_object(nested) dst = Data() dst.copy(self.data) assert dst.format() == self.data.format() def testRoundTrip(self): obj = {symbol("key"): timestamp(1234), ulong(123): "blah", char("c"): "bleh", str2unicode("desc"): Described(symbol("url"), str2unicode("http://example.org")), str2unicode("array"): Array(UNDESCRIBED, Data.INT, 1, 2, 3), str2unicode("list"): [1, 2, 3, None, 4], str2unicode("boolean"): True} self.data.put_object(obj) enc = self.data.encode() data = Data() data.decode(enc) data.rewind() assert data.next() copy = data.get_object() assert copy == obj, (copy, obj) def testLookup(self): obj = {symbol("key"): str2unicode("value"), symbol("pi"): 3.14159, symbol("list"): [1, 2, 3, 4]} self.data.put_object(obj) self.data.rewind() self.data.next() self.data.enter() self.data.narrow() assert self.data.lookup("pi") assert self.data.get_object() == 3.14159 self.data.rewind() assert self.data.lookup("key") assert self.data.get_object() == str2unicode("value") self.data.rewind() assert self.data.lookup("list") assert self.data.get_object() == [1, 2, 3, 4] self.data.widen() self.data.rewind() assert not self.data.lookup("pi") qpid-proton-0.10/tests/python/proton_tests/__init__.py0000664000000000000000000000217512562450203020141 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import proton_tests.codec import proton_tests.engine import proton_tests.message import proton_tests.reactor import proton_tests.reactor_interop import proton_tests.messenger import proton_tests.sasl import proton_tests.transport import proton_tests.ssl import proton_tests.interop import proton_tests.soak import proton_tests.url import proton_tests.utils qpid-proton-0.10/tests/python/proton-test0000775000000000000000000004672312562450203015520 0ustar #!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # TODO: summarize, test harness preconditions (e.g. broker is alive) import logging, optparse, os, struct, sys, time, traceback, types, cgi from fnmatch import fnmatchcase as match from getopt import GetoptError from logging import getLogger, StreamHandler, Formatter, Filter, \ WARN, DEBUG, ERROR if sys.version_info[0] == 3: CLASS_TYPES = (type,) else: CLASS_TYPES = (type, types.ClassType) levels = { "DEBUG": DEBUG, "WARN": WARN, "ERROR": ERROR } sorted_levels = [(v, k) for k, v in list(levels.items())] sorted_levels.sort() sorted_levels = [v for k, v in sorted_levels] parser = optparse.OptionParser(usage="usage: %prog [options] PATTERN ...", description="Run tests matching the specified PATTERNs.") parser.add_option("-l", "--list", action="store_true", default=False, help="list tests instead of executing them") parser.add_option("-f", "--log-file", metavar="FILE", help="log output to FILE") parser.add_option("-v", "--log-level", metavar="LEVEL", default="WARN", help="only display log messages of LEVEL or higher severity: " "%s (default %%default)" % ", ".join(sorted_levels)) parser.add_option("-c", "--log-category", metavar="CATEGORY", action="append", dest="log_categories", default=[], help="log only categories matching CATEGORY pattern") parser.add_option("-m", "--module", action="append", default=[], dest="modules", help="add module to test search path") parser.add_option("-i", "--ignore", action="append", default=[], help="ignore tests matching IGNORE pattern") parser.add_option("-I", "--ignore-file", metavar="IFILE", action="append", default=[], help="ignore tests matching patterns in IFILE") parser.add_option("-H", "--halt-on-error", action="store_true", default=False, dest="hoe", help="halt if an error is encountered") parser.add_option("-t", "--time", action="store_true", default=False, help="report timing information on test run") parser.add_option("-D", "--define", metavar="DEFINE", dest="defines", action="append", default=[], help="define test parameters") parser.add_option("-x", "--xml", metavar="XML", dest="xml", help="write test results in Junit style xml suitable for use by CI tools etc") parser.add_option("-a", "--always-colorize", action="store_true", dest="always_colorize", default=False, help="always colorize the test results rather than relying on terminal tty detection. Useful when invoked from Jython/Maven.") parser.add_option("-n", metavar="count", dest="count", type=int, default=1, help="run the tests times") parser.add_option("-b", "--bare", action="store_true", default=False, help="Run bare, i.e. don't capture stack traces. This is useful under Jython as " + "captured stack traces do not include the Java portion of the stack," + "whereas non captured stack traces do.") parser.add_option("-j", "--javatrace", action="store_true", default=False, help="Show the full java stack trace. This disables heuristics to eliminate the " + "jython portion of java stack traces.") class Config: def __init__(self): self.defines = {} self.log_file = None self.log_level = WARN self.log_categories = [] opts, args = parser.parse_args() includes = [] excludes = ["*__*__"] config = Config() list_only = opts.list for d in opts.defines: try: idx = d.index("=") name = d[:idx] value = d[idx+1:] config.defines[name] = value except ValueError: config.defines[d] = None config.log_file = opts.log_file config.log_level = levels[opts.log_level.upper()] config.log_categories = opts.log_categories excludes.extend([v.strip() for v in opts.ignore]) for v in opts.ignore_file: f = open(v) for line in f: line = line.strip() if line.startswith("#"): continue excludes.append(line) f.close() for a in args: includes.append(a.strip()) if not includes: includes.append("*") def is_ignored(path): for p in excludes: if match(path, p): return True return False def is_included(path): if is_ignored(path): return False for p in includes: if match(path, p): return True return False def is_smart(): return sys.stdout.isatty() and os.environ.get("TERM", "dumb") != "dumb" try: import fcntl, termios def width(): if is_smart(): s = struct.pack("HHHH", 0, 0, 0, 0) fd_stdout = sys.stdout.fileno() x = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s) rows, cols, xpx, ypx = struct.unpack("HHHH", x) return cols else: try: return int(os.environ.get("COLUMNS", "80")) except ValueError: return 80 WIDTH = width() def resize(sig, frm): global WIDTH WIDTH = width() import signal signal.signal(signal.SIGWINCH, resize) except ImportError: WIDTH = 80 def vt100_attrs(*attrs): return "\x1B[%sm" % ";".join(map(str, attrs)) vt100_reset = vt100_attrs(0) KEYWORDS = {"pass": (32,), "skip": (33,), "fail": (31,), "start": (34,), "total": (34,), "ignored": (33,), "selected": (34,), "elapsed": (34,), "average": (34,)} def colorize_word(word, text=None): if text is None: text = word return colorize(text, *KEYWORDS.get(word, ())) def colorize(text, *attrs): if attrs and (is_smart() or opts.always_colorize): return "%s%s%s" % (vt100_attrs(*attrs), text, vt100_reset) else: return text def indent(text): lines = text.split("\n") return " %s" % "\n ".join(lines) # Write a 'minimal' Junit xml style report file suitable for use by CI tools such as Jenkins. class JunitXmlStyleReporter: def __init__(self, file): self.f = open(file, "w"); def begin(self): self.f.write('\n') self.f.write('\n') def report(self, name, result): parts = name.split(".") method = parts[-1] module = '.'.join(parts[0:-1]) self.f.write('\n' % (module, method, result.time)) if result.failed: escaped_type = cgi.escape(str(result.exception_type)) escaped_message = cgi.escape(str(result.exception_message)) self.f.write('\n' % (escaped_type, escaped_message)) self.f.write('\n') self.f.write('\n') if result.skipped: self.f.write('\n') self.f.write('\n') def end(self): self.f.write('\n') self.f.close() class Interceptor: def __init__(self): self.newline = False self.indent = False self.passthrough = True self.dirty = False self.last = None def begin(self): self.newline = True self.indent = True self.passthrough = False self.dirty = False self.last = None def reset(self): self.newline = False self.indent = False self.passthrough = True class StreamWrapper: def __init__(self, interceptor, stream, prefix=" "): self.interceptor = interceptor self.stream = stream self.prefix = prefix def fileno(self): return self.stream.fileno() def isatty(self): return self.stream.isatty() def write(self, s): if self.interceptor.passthrough: self.stream.write(s) return if s: self.interceptor.dirty = True if self.interceptor.newline: self.interceptor.newline = False self.stream.write(" %s\n" % colorize_word("start")) self.interceptor.indent = True if self.interceptor.indent: self.stream.write(self.prefix) if s.endswith("\n"): s = s.replace("\n", "\n%s" % self.prefix)[:-2] self.interceptor.indent = True else: s = s.replace("\n", "\n%s" % self.prefix) self.interceptor.indent = False self.stream.write(s) if s: self.interceptor.last = s[-1] def flush(self): self.stream.flush() interceptor = Interceptor() out_wrp = StreamWrapper(interceptor, sys.stdout) err_wrp = StreamWrapper(interceptor, sys.stderr) out = sys.stdout err = sys.stderr sys.stdout = out_wrp sys.stderr = err_wrp class PatternFilter(Filter): def __init__(self, *patterns): Filter.__init__(self, patterns) self.patterns = patterns def filter(self, record): if not self.patterns: return True for p in self.patterns: if match(record.name, p): return True return False root = getLogger() handler = StreamHandler(sys.stdout) filter = PatternFilter(*config.log_categories) handler.addFilter(filter) handler.setFormatter(Formatter("%(asctime)s %(levelname)s %(message)s")) root.addHandler(handler) root.setLevel(WARN) log = getLogger("proton.test") PASS = "pass" SKIP = "skip" FAIL = "fail" class Runner: def __init__(self): self.exception = None self.exception_phase_name = None self.skip = False def passed(self): return not self.exception def skipped(self): return self.skip def failed(self): return self.exception and not self.skip def halt(self): """determines if the overall test execution should be allowed to continue to the next phase""" return self.exception or self.skip def run(self, phase_name, phase): """invokes a test-phase method (which can be the test method itself or a setup/teardown method). If the method raises an exception the exception is examined to see if the exception should be classified as a 'skipped' test""" # we don't try to catch exceptions for jython because currently a # jython bug will prevent the java portion of the stack being # stored with the exception info in the sys module if opts.bare: phase() else: try: phase() except KeyboardInterrupt: raise except: self.exception_phase_name = phase_name self.exception = sys.exc_info() exception_type = self.exception[0] self.skip = getattr(exception_type, "skipped", False) def status(self): if self.passed(): return PASS elif self.skipped(): return SKIP elif self.failed(): return FAIL else: return None def get_formatted_exception_trace(self): if self.exception: if self.skip: # format skipped tests without a traceback output = indent("".join(traceback.format_exception_only(*self.exception[:2]))).rstrip() else: output = "Error during %s:" % self.exception_phase_name lines = traceback.format_exception(*self.exception) val = self.exception[1] reflect = False if val and hasattr(val, "getStackTrace"): jlines = [] for frame in val.getStackTrace(): if reflect and frame.getClassName().startswith("org.python."): # this is a heuristic to eliminate the jython portion of # the java stack trace if not opts.javatrace: break jlines.append(" %s\n" % frame.toString()) if frame.getClassName().startswith("java.lang.reflect"): reflect = True else: reflect = False lines.extend(jlines) output += indent("".join(lines)).rstrip() return output def get_exception_type(self): if self.exception: return self.exception[0] else: return None def get_exception_message(self): if self.exception: return self.exception[1] else: return None ST_WIDTH = 8 def run_test(name, test, config): patterns = filter.patterns level = root.level filter.patterns = config.log_categories root.setLevel(config.log_level) parts = name.split(".") line = None output = "" for part in parts: if line: if len(line) + len(part) >= (WIDTH - ST_WIDTH - 1): output += "%s. \\\n" % line line = " %s" % part else: line = "%s.%s" % (line, part) else: line = part if line: output += "%s %s" % (line, (((WIDTH - ST_WIDTH) - len(line))*".")) sys.stdout.write(output) sys.stdout.flush() interceptor.begin() start = time.time() try: runner = test() finally: interceptor.reset() end = time.time() if interceptor.dirty: if interceptor.last != "\n": sys.stdout.write("\n") sys.stdout.write(output) print(" %s" % colorize_word(runner.status())) if runner.failed() or runner.skipped(): print(runner.get_formatted_exception_trace()) root.setLevel(level) filter.patterns = patterns return TestResult(end - start, runner.passed(), runner.skipped(), runner.failed(), runner.get_exception_type(), runner.get_exception_message(), runner.get_formatted_exception_trace()) class TestResult: def __init__(self, time, passed, skipped, failed, exception_type, exception_message, formatted_exception_trace): self.time = time self.passed = passed self.skipped = skipped self.failed = failed self.exception_type = exception_type self.exception_message = exception_message self.formatted_exception_trace = formatted_exception_trace class FunctionTest: def __init__(self, test): self.test = test def name(self): return "%s.%s" % (self.test.__module__, self.test.__name__) def run(self): return run_test(self.name(), self._run, config) def _run(self): runner = Runner() runner.run("test", lambda: self.test(config)) return runner def __repr__(self): return "FunctionTest(%r)" % self.test class MethodTest: def __init__(self, cls, method): self.cls = cls self.method = method def name(self): return "%s.%s.%s" % (self.cls.__module__, self.cls.__name__, self.method) def run(self): return run_test(self.name(), self._run, config) def _run(self): runner = Runner() inst = self.cls(self.method) test = getattr(inst, self.method) if hasattr(inst, "configure"): runner.run("configure", lambda: inst.configure(config)) if runner.halt(): return runner if hasattr(inst, "setUp"): runner.run("setup", inst.setUp) if runner.halt(): return runner if hasattr(inst, "setup"): runner.run("setup", inst.setup) if runner.halt(): return runner runner.run("test", test) if hasattr(inst, "teardown"): runner.run("teardown", inst.teardown) if hasattr(inst, "tearDown"): runner.run("teardown", inst.tearDown) return runner def __repr__(self): return "MethodTest(%r, %r)" % (self.cls, self.method) class PatternMatcher: def __init__(self, *patterns): self.patterns = patterns def matches(self, name): for p in self.patterns: if match(name, p): return True return False class FunctionScanner(PatternMatcher): def inspect(self, obj): return type(obj) == types.FunctionType and self.matches(obj.__name__) def descend(self, func): # the None is required for older versions of python return; yield None def extract(self, func): yield FunctionTest(func) class ClassScanner(PatternMatcher): def inspect(self, obj): return type(obj) in CLASS_TYPES and self.matches(obj.__name__) def descend(self, cls): # the None is required for older versions of python return; yield None def extract(self, cls): names = dir(cls) names.sort() for name in names: obj = getattr(cls, name) if hasattr(obj, '__call__') and name.startswith("test"): yield MethodTest(cls, name) class ModuleScanner: def inspect(self, obj): return type(obj) == types.ModuleType def descend(self, obj): names = dir(obj) names.sort() for name in names: yield getattr(obj, name) def extract(self, obj): # the None is required for older versions of python return; yield None class Harness: def __init__(self): self.scanners = [ ModuleScanner(), ClassScanner("*Test", "*Tests", "*TestCase"), FunctionScanner("test_*") ] self.tests = [] self.scanned = [] def scan(self, *roots): objects = list(roots) while objects: obj = objects.pop(0) for s in self.scanners: if s.inspect(obj): self.tests.extend(s.extract(obj)) for child in s.descend(obj): if not (child in self.scanned or child in objects): objects.append(child) self.scanned.append(obj) modules = opts.modules if not modules: modules.extend(["proton_tests"]) h = Harness() for name in modules: m = __import__(name, None, None, ["dummy"]) h.scan(m) filtered = [t for t in h.tests if is_included(t.name())] ignored = [t for t in h.tests if is_ignored(t.name())] total = len(filtered) + len(ignored) if opts.xml and not list_only: xmlr = JunitXmlStyleReporter(opts.xml); xmlr.begin(); else: xmlr = None def runthrough(): passed = 0 failed = 0 skipped = 0 start = time.time() for t in filtered: if list_only: print(t.name()) else: st = t.run() if xmlr: xmlr.report(t.name(), st) if st.passed: passed += 1 elif st.skipped: skipped += 1 elif st.failed: failed += 1 if opts.hoe: break end = time.time() run = passed + failed if not list_only: if passed: _pass = "pass" else: _pass = "fail" if failed: outcome = "fail" else: outcome = "pass" if ignored: ign = "ignored" else: ign = "pass" if skipped: skip = "skip" else: skip = "pass" sys.stdout.write(colorize("Totals: ", 1)) totals = [colorize_word("total", "%s tests" % total), colorize_word(_pass, "%s passed" % passed), colorize_word(skip, "%s skipped" % skipped), colorize_word(ign, "%s ignored" % len(ignored)), colorize_word(outcome, "%s failed" % failed)] sys.stdout.write(", ".join(totals)) if opts.hoe and failed > 0: print(" -- (halted after %s)" % run) else: print("") if opts.time and run > 0: sys.stdout.write(colorize("Timing:", 1)) timing = [colorize_word("elapsed", "%.2fs elapsed" % (end - start)), colorize_word("average", "%.2fs average" % ((end - start)/run))] print(", ".join(timing)) if xmlr: xmlr.end() return failed limit = opts.count count = 0 failures = False while limit == 0 or count < limit: count += 1 if runthrough(): failures = True if count > 1: print(" -- (failures after %s runthroughs)" % count) else: continue if failures: sys.exit(1) else: sys.exit(0) qpid-proton-0.10/tests/python/interop-generate0000775000000000000000000000632712562450203016466 0ustar #!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Generate encoded AMQP fragments for interop testing. import logging, optparse, os, struct, sys, time, traceback, types, cgi from proton import * def main(argv): def write(data, filename): f = open(filename+".amqp", 'w') f.write(data.encode()) f.close() # message m = Message() d = Data() d.put_string("hello") m.body = d.encode() write(m, "message") # null d = Data() d.put_null() write(d, "null") # primitive types d = Data() d.put_bool(True) d.put_bool(False) d.put_ubyte(42) d.put_ushort(42) d.put_short(-42) d.put_uint(12345) d.put_int(-12345) d.put_ulong(12345) d.put_long(-12345) d.put_float(0.125) d.put_double(0.125) write(d, "primitives") # string types d = Data() d.put_binary("abc\0defg") d.put_string("abcdefg") d.put_symbol("abcdefg") d.put_binary("") d.put_string("") d.put_symbol("") write(d, "strings") # described types d = Data() d.put_described() d.enter() d.put_symbol("foo-descriptor") d.put_string("foo-value") d.exit() d.put_described() d.enter() d.put_int(12) d.put_int(13) d.exit() write(d, "described") # described array d = Data() d.put_array(True, Data.INT) d.enter() d.put_symbol("int-array") for i in xrange(0,10): d.put_int(i) d.exit() write(d, "described_array") # Arrays # Integer array d = Data() d.put_array(False, Data.INT) d.enter() for i in xrange(0,100): d.put_int(i) d.exit() # String array d.put_array(False, Data.STRING) d.enter() for i in ["a", "b", "c"]: d.put_string(i) d.exit() # empty array d.put_array(False, Data.INT) write(d, "arrays") # List - mixed types d = Data() d.put_list() d.enter() d.put_int(32) d.put_string("foo") d.put_bool(True) d.exit() d.put_list() # Empty list write(d, "lists") # Maps d = Data() d.put_map() d.enter() for k,v in {"one":1, "two":2, "three":3}.items(): d.put_string(k) d.put_int(v) d.exit() d.put_map() d.enter() for k,v in {1:"one", 2:"two", 3:"three"}.items(): d.put_int(k) d.put_string(v) d.exit() d.put_map() # Empty map write(d, "maps") return 0 if __name__ == "__main__": sys.exit(main(sys.argv)) qpid-proton-0.10/tests/pom.xml0000664000000000000000000000750112562450203013257 0ustar 4.0.0 proton-tests proton-tests org.apache.qpid proton-project 0.10 The Proton system tests execute against either the Java or the C implementations, based on the chosen profile. To execute, "mvn test". Example of advanced usage (all of the -D flags are optional): mvn test \ -Dproton.pythontest.pattern='proton_tests.transport.TransportTest.*' \ -Dproton.pythontest.invocations=20 \ -Dproton.pythontest.always_colorize=true \ -Dproton-c-build-dir=/path/to/build/dir By default, the proton-jni profile looks for the JNI jar and native libraries under directory <basedir>/build/proton-c. http://svn.apache.org/viewvc/qpid/proton/ ${basedir}/target/surefire-reports java resources org.apache.maven.plugins maven-surefire-plugin ${basedir}/java/pythonTests.ignore ${basedir}/python ${basedir}/../proton-c/bindings/python ${basedir}/../proton-j/src/main/resources ${basedir}/python/proton-test ${testReportOutputDirectory} ${project.build.outputDirectory}/logging.properties ${testReportOutputDirectory} org.apache.qpid proton-j ${project.parent.version} org.bouncycastle bcpkix-jdk15on 1.47 org.python jython-standalone 2.5.3 test qpid-proton-0.10/tests/javascript/0000775000000000000000000000000012562450203014105 5ustar qpid-proton-0.10/tests/javascript/unittest.js0000664000000000000000000000276512562450203016334 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /** * The TestCase class provides a simple dependency-free Unit Test framework to * automagically invoke methods that start with "test" on classes that extend it. */ // TestCase Constructor var TestCase = function() {}; // Enumerate all functions of the class and invoke those beginning with "test". TestCase.prototype.run = function() { for (var property in this) { if ((typeof this[property] === 'function') && property.lastIndexOf('test', 0) === 0) { this.setUp(); this[property](); this.tearDown(); } } }; TestCase.prototype.setUp = function() {}; TestCase.prototype.tearDown = function() {}; module.exports.TestCase = TestCase; qpid-proton-0.10/tests/javascript/soak.js0000775000000000000000000000636412562450203015414 0ustar #!/usr/bin/env node /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ // Check if the environment is Node.js and if not log an error and exit. if (typeof process === 'object' && typeof require === 'function') { var proton = require("qpid-proton-messenger"); var addr = 'guest:guest@localhost:5673'; //var addr = 'localhost:5673'; var address = 'amqp://' + addr; console.log(address); var subscriptionQueue = ''; var count = 0; var start = 0; // Start Time. var message = new proton.Message(); var messenger = new proton.Messenger(); var pumpData = function() { while (messenger.incoming()) { // The second parameter forces Binary payloads to be decoded as strings // this is useful because the broker QMF Agent encodes strings as AMQP // binary, which is a right pain from an interoperability perspective. var t = messenger.get(message, true); //console.log("Address: " + message.getAddress()); //console.log("Content: " + message.body); messenger.accept(t); if (count % 1000 === 0) { var time = +new Date(); console.log("count = " + count + ", duration = " + (time - start) + ", rate = " + ((count*1000)/(time - start))); } sendMessage(); } if (messenger.isStopped()) { message.free(); messenger.free(); } }; var sendMessage = function() { var msgtext = "Message Number " + count; count++; message.setAddress(address + '/' + subscriptionQueue); message.body = msgtext; messenger.put(message); //messenger.settle(); }; messenger.on('error', function(error) {console.log(error);}); messenger.on('work', pumpData); messenger.on('subscription', function(subscription) { var subscriptionAddress = subscription.getAddress(); var splitAddress = subscriptionAddress.split('/'); subscriptionQueue = splitAddress[splitAddress.length - 1]; console.log("Subscription Queue: " + subscriptionQueue); start = +new Date(); sendMessage(); }); //messenger.setOutgoingWindow(1024); messenger.setIncomingWindow(1024); // The Java Broker seems to need this. messenger.recv(); // Receive as many messages as messenger can buffer. messenger.start(); messenger.subscribe('amqp://' + addr + '/#'); } else { console.error("soak.js should be run in Node.js"); } qpid-proton-0.10/tests/javascript/msgr-send.js0000775000000000000000000000736212562450203016355 0ustar #!/usr/bin/env node /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ // Check if the environment is Node.js and if not log an error and exit. if (typeof process === 'object' && typeof require === 'function') { var usage = 'Usage: msgr-send [OPTIONS]\n' + ' -a [,]* \tThe target address [amqp://~0.0.0.0]\n' + ' -c # \tNumber of messages to send before exiting [0=forever]\n' + ' -b # \tSize of message body in bytes [1024]\n' + ' -p # \tSend batches of # messages (wait for replies before sending next batch if -R) [1024]\n' + ' -w # \tSize for outgoing window [0]\n' + ' -e # \t# seconds to report statistics, 0 = end of test [0] *TBD*\n' + ' -R \tWait for a reply to each sent message\n' + ' -B # \tArgument to Messenger::recv(n) [-1]\n' + ' -N \tSet the container name to \n' + ' -V \tEnable debug logging\n'; // Increase the virtual heap available to the emscripten compiled C runtime. // This allows us to test a really big string. PROTON_TOTAL_MEMORY = 140000000; PROTON_TOTAL_STACK = 25000000; // Needs to be bigger than the biggest string. var proton = require("qpid-proton-messenger"); var benchmark = require("./msgr-send-common.js"); var opts = {}; opts.addresses = 'amqp://0.0.0.0'; opts.messageCount = 0; opts.messageSize = 1024; opts.recvCount = -1; opts.sendBatch = 1024; opts.outgoingWindow; opts.reportInterval = 0; opts.getReplies = false; opts.name; opts.verbose = false; var args = process.argv.slice(2); if (args.length > 0) { if (args[0] === '-h' || args[0] === '--help') { console.log(usage); process.exit(0); } for (var i = 0; i < args.length; i++) { var arg = args[i]; if (arg.charAt(0) === '-') { if (arg === '-V') { opts.verbose = true; } else if (arg === '-R') { opts.getReplies = true; } else { i++; var val = args[i]; if (arg === '-a') { opts.addresses = val; } else if (arg === '-c') { opts.messageCount = val; } else if (arg === '-b') { opts.messageSize = val; } else if (arg === '-B') { opts.recvCount = val; } else if (arg === '-p') { opts.sendBatch = val; } else if (arg === '-w') { opts.outgoingWindow = val; } else if (arg === '-e') { opts.reportInterval = val; } else if (arg === '-N') { opts.name = val; } } } } } var sender = new benchmark.MessengerSend(opts); sender.start(); } else { console.error("msgr-send.js should be run in Node.js"); } qpid-proton-0.10/tests/javascript/msgr-send.html0000664000000000000000000000747112562450203016703 0ustar Proton Messenger Send Benchmark
qpid-proton-0.10/tests/javascript/msgr-send-common.js0000664000000000000000000002242712562450203017637 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /** * This file is essentially a "module" that is common to msgr-send.js and msgr-send.html. * It defines the Statistics and MessengerSend classes and if the environment is Node.js * it will import qpid-proton-messenger and export MessengerSend for use in msgr-send.js. * Because it's really a module/library trying to execute msgr-send-common.js won't * itself do anything terribly exciting. */ var Statistics = function() { this.startTime = 0; this.latencySamples = 0; this.latencyTotal = 0; this.latencyMin = 0; this.latencyMax = 0; }; Statistics.prototype.start = function() { this.startTime = +new Date(); }; Statistics.prototype.messageReceived = function(msg) { var ts = +msg.getCreationTime(); // The + gets the value of the returned Data Object. if (ts) { var l = +new Date() - ts; if (l) { this.latencyTotal += l; this.latencySamples += 1; if (this.latencySamples === 1) { this.latencyMin = this.latencyMax = l; } else { if (this.latencyMin > l) { this.latencyMin = l; } if (this.latencyMax < l) { this.latencyMax = l; } } } } }; Statistics.prototype.report = function(sent, received) { var seconds = (+new Date() - this.startTime)/1000; console.log("Messages sent: " + sent + " received: " + received); console.log("Total time: " + seconds + " seconds"); if (seconds) { console.log("Throughput: " + (sent/seconds) + " msgs/sec sent"); console.log("Throughput: " + (received/seconds) + " msgs/sec received"); } if (this.latencySamples) { console.log("Latency (ms): " + this.latencyMin + " min " + this.latencyMax + " max " + (this.latencyTotal/this.latencySamples) + " avg"); } }; var MessengerSend = function(opts, callback) { //if (opts.verbose) { console.log("addresses = " + opts.addresses); console.log("messageCount = " + opts.messageCount); console.log("messageSize = " + opts.messageSize); console.log("recvCount = " + opts.recvCount); console.log("sendBatch = " + opts.sendBatch); console.log("outgoingWindow = " + opts.outgoingWindow); console.log("reportInterval = " + opts.reportInterval); console.log("getReplies = " + opts.getReplies); console.log("name = " + opts.name); console.log("verbose = " + opts.verbose); console.log(); //} var stats = new Statistics(); var targets = []; var running = true; // Used to avoid calling stop multiple times. var sent = 0; var received = 0; var message = new proton.Message(); var replyMessage = new proton.Message(); var messenger = new proton.Messenger(opts.name); // Retrieve replies and return the number of reply messages received. var processReplies = function() { var received = 0; if (opts.verbose) { console.log("Calling messenger.recv(" + opts.recvCount + ")"); } messenger.recv(opts.recvCount); if (opts.verbose) { console.log("Messages on incoming queue: " + messenger.incoming()); } while (messenger.incoming()) { messenger.get(replyMessage); received += 1; //console.log("Address: " + replyMessage.getAddress()); //console.log("Content: " + replyMessage.body); stats.messageReceived(replyMessage); } return received; }; // Send messages as fast as possible. This is analogous to the while loop in // the Python msgr-send.py but we wrap in a function in JavaScript so that // we can schedule on the JavaScript Event queue via setTimeout. This is needed // otherwise the JavaScript Event loop is blocked and no data gets sent. var sendData = function() { var delay = 0; while (opts.messageCount === 0 || (sent < opts.messageCount)) { // Check the amount of data buffered on the socket, if it's non-zero // exit the loop and call senData again after a short delay. This // will throttle the send rate if necessary. if (messenger.getBufferedAmount()) { console.log("messenger.getBufferedAmount() = " + messenger.getBufferedAmount()); delay = 100; break; // Exit loop to check for exit condition and schedule to Event queue. } var index = sent % targets.length; //console.log("sent = " + sent + ", index = " + index); message.setAddress(targets[index]); message.setCorrelationID(sent); message.setCreationTime(new Date()); messenger.put(message); sent += 1; if (opts.sendBatch && (messenger.outgoing() >= opts.sendBatch)) { if (opts.verbose) { console.log("Calling messenger.send()") } messenger.send(); if (opts.getReplies) { received += processReplies(); } break; // Exit loop to check for exit condition and yield to Event loop. } } // Check for exit condition. if (running && !(opts.messageCount === 0 || (sent < opts.messageCount))) { if (opts.getReplies && (received < sent)) { received += processReplies(); if (opts.verbose) { console.log("Messages sent = " + sent + ", received = " + received); } } else if (messenger.outgoing()) { if (opts.verbose) { console.log("Flushing pending sends"); } messenger.send(); } else { //console.log("******* calling stop") messenger.stop(); running = false; stats.report(sent, received); if (callback) { callback(stats); } } } if (messenger.isStopped()) { //console.log("-------------------- messenger.isStopped()"); message.free(); messenger.free(); } else { // schedule next call on the JavaScript Event queue. If we don't do this // our messages won't get sent because none of the internal JavaScript // network code will get any CPU. // If available we call setImmediate rather than setTimeout when the delay // is zero. setImmediate is more efficient, in particular I noticed that // with Node.js v0.10.18 I could get max throughput and max out CPU using // setTimeout, but when I upgraded to v0.10.33 my throughput dropped and // my CPU was hovering around 55% but using setImmediate the performance // improved again. My guess is that v0.10.18 was checking for zero delay // and calling setImmediate internally whereas v0.10.33 wasn't, but I // can't say for sure. TODO it's possible that some browsers might do a // better job with setImmediate too (given what I'm seeing with Node.js), // Chrome might be one such case, but it's not universally supported. // It might be worth adding a proper polyfill to handle this. if (delay === 0 && typeof setImmediate === 'function') { setImmediate(sendData); } else { setTimeout(sendData, delay); } } }; this.start = function() { message.body = Array(+opts.messageSize + 1).join('X'); message.setReplyTo('~'); messenger.on('error', function(error) { console.log(error); opts.messageCount = -1; // Force exit condition. }); if (opts.outgoingWindow) { messenger.setOutgoingWindow(opts.outgoingWindow); } messenger.start(); // Unpack targets that were specified using comma-separated list var addresses = opts.addresses.split(','); for (var i = 0; i < addresses.length; i++) { var address = addresses[i]; targets.push(address); } stats.start(); sendData(); }; }; // If running in Node.js import the proton library and export MessengerSend. if (typeof module === 'object') { var proton = require("qpid-proton-messenger"); module.exports.MessengerSend = MessengerSend; } qpid-proton-0.10/tests/javascript/msgr-recv.js0000775000000000000000000002244112562450203016356 0ustar #!/usr/bin/env node /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ var Statistics = function() { this.startTime = 0; this.latencySamples = 0; this.latencyTotal = 0; this.latencyMin = 0; this.latencyMax = 0; }; Statistics.prototype.start = function() { this.startTime = +new Date(); }; Statistics.prototype.messageReceived = function(msg) { var ts = +msg.getCreationTime(); // The + gets the value of the returned Data Object. if (ts) { var l = +new Date() - ts; if (l) { this.latencyTotal += l; this.latencySamples += 1; if (this.latencySamples === 1) { this.latencyMin = this.latencyMax = l; } else { if (this.latencyMin > l) { this.latencyMin = l; } if (this.latencyMax < l) { this.latencyMax = l; } } } } }; Statistics.prototype.report = function(sent, received) { var seconds = (+new Date() - this.startTime)/1000; console.log("Messages sent: " + sent + " received: " + received); console.log("Total time: " + seconds + " seconds"); if (seconds) { console.log("Throughput: " + (sent/seconds) + " msgs/sec sent"); console.log("Throughput: " + (received/seconds) + " msgs/sec received"); } if (this.latencySamples) { console.log("Latency (ms): " + this.latencyMin + " min " + this.latencyMax + " max " + (this.latencyTotal/this.latencySamples) + " avg"); } }; var MessengerReceive = function(opts, callback) { //if (opts.verbose) { console.log("subscriptions = " + opts.subscriptions); console.log("messageCount = " + opts.messageCount); console.log("recvCount = " + opts.recvCount); console.log("incomingWindow = " + opts.incomingWindow); console.log("reportInterval = " + opts.reportInterval); console.log("reply = " + opts.reply); console.log("forwardingTargets = " + opts.forwardingTargets); console.log("name = " + opts.name); console.log("readyText = " + opts.readyText); console.log("verbose = " + opts.verbose); console.log(); //} var stats = new Statistics(); var running = true; // Used to avoid calling stop multiple times. var sent = 0; var received = 0; var forwardingIndex = 0; var message = new proton.Message(); var messenger = new proton.Messenger(opts.name); var pumpData = function() { if (opts.verbose) { console.log("Calling messenger.recv(" + opts.recvCount + ")"); } messenger.recv(opts.recvCount); if (opts.verbose) { console.log("Messages on incoming queue: " + messenger.incoming()); } while (messenger.incoming()) { // start the timer only after receiving the first msg if (received === 0) { stats.start(); } messenger.get(message); received += 1; //console.log("Address: " + message.getAddress()); //console.log("CorrelationID: " + message.getCorrelationID()); //console.log("Content: " + message.body); stats.messageReceived(message); if (opts.reply) { var replyTo = message.getReplyTo(); if (replyTo) { if (opts.verbose) { console.log("Replying to: " + replyTo); } message.setAddress(replyTo); message.setCreationTime(new Date()); messenger.put(message); sent += 1; } } } // Check for exit condition. if (running && !(opts.messageCount === 0 || received < opts.messageCount)) { // Wait for outgoing to be zero before calling stop so pending sends // get flushed properly. if (messenger.outgoing()) { if (opts.verbose) { console.log("Flushing pending sends"); } } else { //console.log("******* messenger.stop()"); messenger.stop(); running = false; stats.report(sent, received); if (callback) { callback(stats); } } } if (messenger.isStopped()) { //console.log("-------------------- messenger.isStopped()"); message.free(); messenger.free(); } }; this.start = function() { messenger.on('error', function(error) {console.log("** error **"); console.log(error);}); messenger.on('work', pumpData); messenger.on('subscription', function(subscription) { // Hack to let test scripts know when the receivers are ready (so that the // senders may be started). console.log("****** subscription " + subscription.getAddress() + " succeeded") if (opts.readyText) { console.log(opts.readyText); } }); if (opts.incomingWindow) { messenger.setIncomingWindow(opts.incomingWindow); } messenger.start(); // Unpack addresses that were specified using comma-separated list var subscriptions = opts.subscriptions.split(','); for (var i = 0; i < subscriptions.length; i++) { var subscription = subscriptions[i]; if (opts.verbose) { console.log("Subscribing to " + subscription); } messenger.subscribe(subscription); } }; }; // Check if the environment is Node.js and if not log an error and exit. if (typeof process === 'object' && typeof require === 'function') { var usage = 'Usage: msgr-recv [OPTIONS]\n' + ' -a [,]* \tAddresses to listen on [amqp://~0.0.0.0]\n' + ' -c # \tNumber of messages to receive before exiting [0=forever]\n' + ' -b # \tArgument to Messenger::recv(n) [2048]\n' + ' -w # \tSize for incoming window [0]\n' + ' -e # \t# seconds to report statistics, 0 = end of test [0] *TBD*\n' + ' -R \tSend reply if \'reply-to\' present\n' + ' -F [,]* \tAddresses used for forwarding received messages\n' + ' -N \tSet the container name to \n' + ' -X \tPrint \'\\n\' to stdout after all subscriptions are created\n' + ' -V \tEnable debug logging\n'; // Increase the virtual heap available to the emscripten compiled C runtime. // This allows us to test a really big string. PROTON_TOTAL_MEMORY = 140000000; PROTON_TOTAL_STACK = 25000000; // Needs to be bigger than the biggest string. var proton = require("qpid-proton-messenger"); var opts = {}; opts.subscriptions = 'amqp://~0.0.0.0'; opts.messageCount = 0; opts.recvCount = -1; opts.incomingWindow; opts.reportInterval = 0; opts.reply = false; opts.forwardingTargets; opts.name; opts.readyText; opts.verbose = false; var args = process.argv.slice(2); if (args.length > 0) { if (args[0] === '-h' || args[0] === '--help') { console.log(usage); process.exit(0); } for (var i = 0; i < args.length; i++) { var arg = args[i]; if (arg.charAt(0) === '-') { if (arg === '-V') { opts.verbose = true; } else if (arg === '-R') { opts.reply = true; } else { i++; var val = args[i]; if (arg === '-a') { opts.subscriptions = val; } else if (arg === '-c') { opts.messageCount = val; } else if (arg === '-b') { opts.recvCount = val; } else if (arg === '-w') { opts.incomingWindow = val; } else if (arg === '-e') { opts.reportInterval = val; } else if (arg === '-F') { opts.forwardingTargets = val; } else if (arg === '-N') { opts.name = val; } else if (arg === '-X') { opts.readyText = val; } } } } } var receiver = new MessengerReceive(opts); receiver.start(); } else { console.error("msgr-recv.js should be run in Node.js"); } qpid-proton-0.10/tests/javascript/message.js0000775000000000000000000003156412562450203016103 0ustar #!/usr/bin/env node /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /** * This is a fairly literal JavaScript port of message.py used to unit test the * proton.Message wrapper class. */ // Check if the environment is Node.js and if not log an error and exit. if (typeof process === 'object' && typeof require === 'function') { var unittest = require("./unittest.js"); var assert = require("assert"); var proton = require("qpid-proton-messenger"); /** * JavaScript Implementation of Python's range() function taken from: * http://stackoverflow.com/questions/8273047/javascript-function-similar-to-python-range */ var range = function(start, stop, step) { if (typeof stop == 'undefined') { // one param defined stop = start; start = 0; }; if (typeof step == 'undefined') { step = 1; }; if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) { return []; }; var result = []; for (var i = start; step > 0 ? i < stop : i > stop; i += step) { result.push(i); }; return result; }; // Extend TestCase by creating a new Test class as we're using it in a few places. var Test = function() { // Test constructor. /** * The following call is the equivalent of "super" in Java. It's not necessary * here as the unittest.TestCase constructor doesn't set any state, but it * is the correct thing to do when implementing classical inheritance in * JavaScript so I've kept it here as a useful reminder of the "pattern". */ //unittest.TestCase.prototype.constructor.call(this); }; Test.prototype = new unittest.TestCase(); // Here's where the inheritance occurs. Test.prototype.constructor = Test; // Otherwise instances of Test would have a constructor of unittest.TestCase. Test.prototype.setUp = function() { this.msg = new proton.Message(); }; Test.prototype.tearDown = function() { this.msg.free(); this.msg = null; }; // Extend Test more simply by creating a prototype instance and adding test methods as properties. var AccessorsTest = new Test(); AccessorsTest._test = function(name, defaultValue, values) { /** * For the case of Binary values under test we retrieve their toString(). * This is because the methods under test "consume" the data, in other * words ownership of the underlying raw data transfers to the Message * object so the sent Binary object becomes "empty" after calling the setter. * In addition Binary values merely contain a "pointer" to the raw data * so even a "deepEqual" comparison won't accurately compare two Binaries. * For these tests we "cheat" and store an array of characters in the * Binary so that we can use their String forms for comparison tests. * * We also get the String value of Uuid for the case of setUserID because * that method transparently creates Binary values from the String form * of non-Binary data passed to it. It's a convenience method, but makes * testing somewhat more fiddly. */ // First get the values passed to the method. var values = Array.prototype.slice.apply(arguments, [2]); // If the first element of values is actually an Array then use the Array. // This scenario is what happens in the tests that use the range() function. values = (Object.prototype.toString.call(values[0]) === '[object Array]') ? values[0] : values; // Work out the accessor/mutator names noting that boolean accessors use "is" not "get". var setter = 'set' + name; var getter = (typeof defaultValue === 'boolean') ? 'is' + name : 'get' + name; // Get the message's default value first. var d = this.msg[getter](); d = (d instanceof proton.Data.Binary) ? d.toString() : d; // Compare the message's default with the expected default value passed in the test case. assert.deepEqual(d, defaultValue); for (var i = 0; i < values.length; i++) { var v = values[i]; var value = (v instanceof proton.Data.Binary || (name === 'UserID' && v instanceof proton.Data.Uuid)) ? v.toString() : v; value = (v instanceof Date) ? v.valueOf() : v; this.msg[setter](v); // This call will "consume" Binary data. var gotten = this.msg[getter](); gotten = (gotten instanceof proton.Data.Binary) ? gotten.toString() : gotten; gotten = (gotten instanceof Date) ? gotten.valueOf() : v; assert.deepEqual(value, gotten); } }; AccessorsTest._testString = function(name) { this._test(name, "", "asdf", "fdsa", ""); }; AccessorsTest._testTime = function(name) { // The ExpiryTime and CreationTime methods can take either a number or a Date Object. this._test(name, new Date(0), new Date(0), 123456789, new Date(987654321)); }; AccessorsTest.testID = function() { console.log("testID"); this._test("ID", null, "bytes", null, 123, "string", new proton.Data.Uuid(), new proton.Data.Binary("ВИÐÐРЫ")); console.log("OK\n"); }; AccessorsTest.testCorrelationID = function() { console.log("testCorrelationID"); this._test("CorrelationID", null, "bytes", null, 123, "string", new proton.Data.Uuid(), new proton.Data.Binary("ВИÐÐРЫ")); console.log("OK\n"); }; AccessorsTest.testDurable = function() { console.log("testDurable"); this._test("Durable", false, true, false); console.log("OK\n"); }; AccessorsTest.testPriority = function() { console.log("testPriority"); this._test("Priority", proton.Message.DEFAULT_PRIORITY, range(0, 256)); console.log("OK\n"); }; AccessorsTest.testTTL = function() { console.log("testTTL"); this._test("TTL", 0, range(12345, 54321)); console.log("OK\n"); }; AccessorsTest.testFirstAcquirer = function() { console.log("testFirstAcquirer"); this._test("FirstAcquirer", false, true, false); console.log("OK\n"); }; AccessorsTest.testDeliveryCount = function() { console.log("testDeliveryCount"); this._test("DeliveryCount", 0, range(0, 1024)); console.log("OK\n"); }; AccessorsTest.testUserID = function() { console.log("testUserID"); this._test("UserID", "", "asdf", "fdsa", 123, new proton.Data.Binary("ВИÐÐРЫ"), new proton.Data.Uuid(), ""); console.log("OK\n"); }; AccessorsTest.testAddress = function() { console.log("testAddress"); this._testString("Address"); console.log("OK\n"); }; AccessorsTest.testSubject = function() { console.log("testSubject"); this._testString("Subject"); console.log("OK\n"); }; AccessorsTest.testReplyTo = function() { console.log("testReplyTo"); this._testString("ReplyTo"); console.log("OK\n"); }; AccessorsTest.testContentType = function() { console.log("testContentType"); this._testString("ContentType"); console.log("OK\n"); }; AccessorsTest.testContentEncoding = function() { console.log("testContentEncoding"); this._testString("ContentEncoding"); console.log("OK\n"); }; AccessorsTest.testExpiryTime = function() { console.log("testExpiryTime"); this._testTime("ExpiryTime"); console.log("OK\n"); }; AccessorsTest.testCreationTime = function() { console.log("testCreationTime"); this._testTime("CreationTime"); console.log("OK\n"); }; AccessorsTest.testGroupID = function() { console.log("testGroupID"); this._testString("GroupID"); console.log("OK\n"); }; AccessorsTest.testGroupSequence = function() { console.log("testGroupSequence"); this._test("GroupSequence", 0, 0, -10, 10, 20, -20); console.log("OK\n"); }; AccessorsTest.testReplyToGroupID = function() { console.log("testReplyToGroupID"); this._testString("ReplyToGroupID"); console.log("OK\n"); }; var CodecTest = new Test(); CodecTest.testRoundTrip = function() { console.log("testRoundTrip"); this.msg.setID("asdf"); this.msg.setCorrelationID(new proton.Data.Uuid()); this.msg.setTTL(3); this.msg.setPriority(100); this.msg.setAddress("address"); this.msg.setSubject("subject"); this.msg.body = "Hello World!"; var data = this.msg.encode(); var msg2 = new proton.Message(); msg2.decode(data); assert(this.msg.getID() === msg2.getID()); assert(this.msg.getCorrelationID().toString() === msg2.getCorrelationID().toString()); assert(this.msg.getTTL() === msg2.getTTL()); assert(this.msg.getPriority() === msg2.getPriority()); assert(this.msg.getAddress() === msg2.getAddress()); assert(this.msg.getSubject() === msg2.getSubject()); assert(this.msg.body === msg2.body); msg2.free(); console.log("OK\n"); }; /** * This test tests the transparent serialisation and deserialisation of JavaScript * Objects using the AMQP type system (this is the default behaviour). */ CodecTest.testRoundTripBodyObject = function() { console.log("testRoundTripBodyObject"); this.msg.setAddress("address"); this.msg.body = {array: [1, 2, 3, 4], object: {name: "John Smith", age: 65}}; var data = this.msg.encode(); var msg2 = new proton.Message(); msg2.decode(data); assert(this.msg.getAddress() === msg2.getAddress()); assert(this.msg.getContentType() === msg2.getContentType()); assert.deepEqual(this.msg.body, msg2.body); msg2.free(); console.log("OK\n"); }; /** * This test tests the transparent serialisation and deserialisation of JavaScript * Objects as JSON. In this case the "on-the-wire" representation is an AMQP binary * stored in the AMQP data section. */ CodecTest.testRoundTripBodyObjectAsJSON = function() { console.log("testRoundTripBodyObjectAsJSON"); this.msg.setAddress("address"); this.msg.setContentType("application/json"); this.msg.body = {array: [1, 2, 3, 4], object: {name: "John Smith", age: 65}}; var data = this.msg.encode(); var msg2 = new proton.Message(); msg2.decode(data); assert(this.msg.getAddress() === msg2.getAddress()); assert(this.msg.getContentType() === msg2.getContentType()); assert.deepEqual(this.msg.body, msg2.body); msg2.free(); console.log("OK\n"); }; /** * By default the API will encode using the AMQP type system, but is the content-type * is set it will encode as an opaque Binary in an AMQP data section. For certain * types however this isn't the most useful thing. For application/json (see * previous test) we convert to and from JavaScript Objects and for text/* MIME * types the API will automatically convert the received Binary into a String. */ CodecTest.testRoundTripMIMETextObject = function() { console.log("testRoundTripMIMETextObject"); this.msg.setAddress("address"); this.msg.setContentType("text/plain"); this.msg.body = "some text"; var data = this.msg.encode(); var msg2 = new proton.Message(); msg2.decode(data); assert(this.msg.getAddress() === msg2.getAddress()); assert(this.msg.getContentType() === msg2.getContentType()); assert.deepEqual(this.msg.body, msg2.body); msg2.free(); console.log("OK\n"); }; // load and save are deprecated so not implemented in the JavaScript binding. AccessorsTest.run(); CodecTest.run(); } else { console.error("message.js should be run in Node.js"); } qpid-proton-0.10/tests/javascript/codec.js0000775000000000000000000005051312562450203015527 0ustar #!/usr/bin/env node /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /** * This is a fairly literal JavaScript port of codec.py used to unit test the * proton.Data wrapper class. This suite of tests is actually testing the low * level implementation methods used to access the AMQP type system and in * practice most normal users wouldn't need to call these directly, rather users * should simply use the putObject() and getObject() methods. */ // Check if the environment is Node.js and if not log an error and exit. if (typeof process === 'object' && typeof require === 'function') { var unittest = require("./unittest.js"); var assert = require("assert"); // Increase the virtual heap available to the emscripten compiled C runtime. // This allows us to test a really big string. PROTON_TOTAL_MEMORY = 140000000; PROTON_TOTAL_STACK = 25000000; // Needs to be bigger than the biggest string. var proton = require("qpid-proton-messenger"); // Extend TestCase by creating a prototype instance and adding test methods as properties. var DataTest = new unittest.TestCase(); DataTest.setUp = function() { this.data = new proton.Data(); }; DataTest.tearDown = function() { this.data.free(); this.data = null; }; DataTest.testTopLevelNext = function() { console.log("testTopLevelNext"); assert(this.data.next() === null); this.data.putNULL(); this.data.putBOOL(false); this.data.putINT(0); assert(this.data.next() === null); this.data.rewind(); assert(this.data.next() === proton.Data.NULL); assert(this.data.next() === proton.Data.BOOL); assert(this.data.next() === proton.Data.INT); assert(this.data.next() === null); console.log("OK\n"); }; DataTest.testNestedNext = function() { console.log("testNestedNext"); assert(this.data.next() === null); this.data.putNULL(); assert(this.data.next() === null); this.data.putLISTNODE(); assert(this.data.next() === null); this.data.putBOOL(false); assert(this.data.next() === null); this.data.rewind(); assert(this.data.next() === proton.Data.NULL); assert(this.data.next() === proton.Data.LIST); this.data.enter(); assert(this.data.next() === null); this.data.putUBYTE(0); assert(this.data.next() === null); this.data.putUINT(0); assert(this.data.next() === null); this.data.putINT(0); assert(this.data.next() === null); this.data.exit(); assert(this.data.next() === proton.Data.BOOL); assert(this.data.next() === null); this.data.rewind(); assert(this.data.next() === proton.Data.NULL); assert(this.data.next() === proton.Data.LIST); assert(this.data.enter()); assert(this.data.next() === proton.Data.UBYTE); assert(this.data.next() === proton.Data.UINT); assert(this.data.next() === proton.Data.INT); assert(this.data.next() === null); assert(this.data.exit()); assert(this.data.next() === proton.Data.BOOL); assert(this.data.next() === null); console.log("OK\n"); }; DataTest.testEnterExit = function() { console.log("testEnterExit"); assert(this.data.next() === null); assert(!this.data.enter()); this.data.putLISTNODE(); assert(this.data.enter()); assert(this.data.next() === null); this.data.putLISTNODE(); assert(this.data.enter()); this.data.putLISTNODE(); assert(this.data.enter()); assert(this.data.exit()); assert(this.data.getLISTNODE() === 0); assert(this.data.exit()); assert(this.data.getLISTNODE() === 1); assert(this.data.exit()); assert(this.data.getLISTNODE() === 1); assert(!this.data.exit()); assert(this.data.getLISTNODE() === 1); assert(this.data.next() === null); this.data.rewind(); assert(this.data.next() === proton.Data.LIST); assert(this.data.getLISTNODE() === 1); assert(this.data.enter()); assert(this.data.next() === proton.Data.LIST); assert(this.data.getLISTNODE() === 1); assert(this.data.enter()); assert(this.data.next() === proton.Data.LIST); assert(this.data.getLISTNODE() === 0); assert(this.data.enter()); assert(this.data.next() === null); assert(this.data.exit()); assert(this.data.getLISTNODE() === 0); assert(this.data.exit()); assert(this.data.getLISTNODE() === 1); assert(this.data.exit()); assert(this.data.getLISTNODE() === 1); assert(!this.data.exit()); console.log("OK\n"); }; /** * This tests the "low level" putARRAYNODE/getARRAYNODE methods. * In general though applications would create a proton.Data.Array and use the * higher level putARRAY/getARRAY */ DataTest._testArray = function(dtype, descriptor, atype, values) { var values = Array.prototype.slice.apply(arguments, [3]); dtype = (dtype == null) ? null : dtype.toUpperCase(); atype = atype.toUpperCase(); // Create an array node, enter it and put the descriptor (if present) and values. this.data.putARRAYNODE(dtype != null, proton.Data[atype]); this.data.enter(); if (dtype != null) { var putter = 'put' + dtype; this.data[putter](descriptor); } var putter = 'put' + atype; for (var i = 0; i < values.length; i++) { this.data[putter](values[i]); } this.data.exit(); // Check that we did indeed add an Array node this.data.rewind(); assert(this.data.next() === proton.Data.ARRAY); // Get the count, described and type metadata from the array node and compare // with the values we passed to putARRAYNODE. var metadata = this.data.getARRAYNODE(); var count = metadata.count; var described = metadata.described; var type = metadata.type; assert(count === values.length); if (dtype == null) { assert(described === false); } else { assert(described === true); } assert(type === proton.Data[atype]); // Enter the array node and compare the descriptor and values with those that // we put into the array. assert(this.data.enter()); if (described) { assert(this.data.next() === proton.Data[dtype]); var getter = 'get' + dtype; var gotten = this.data[getter](); assert(gotten.toString() === descriptor.toString()); } var getter = 'get' + atype; for (var i = 0; i < values.length; i++) { assert(this.data.next() === proton.Data[atype]); var gotten = this.data[getter](); assert(gotten.toString() === values[i].toString()); } assert(this.data.next() === null); assert(this.data.exit()); }; DataTest.testStringArray = function() { console.log("testStringArray"); this._testArray(null, null, "string", "one", "two", "three"); // Now try using the proton.Data.Array class. this.data.clear(); var put = new proton.Data.Array("STRING", ["four", "five", "six"]); this.data.putARRAY(put); var get = this.data.getARRAY(); assert(get.equals(put)); console.log("OK\n"); }; DataTest.testDescribedStringArray = function() { console.log("testDescribedStringArray"); this._testArray("symbol", "url", "string", "one", "two", "three"); // Now try using the proton.Data.Array class. this.data.clear(); var put = new proton.Data.Array("STRING", ["four", "five", "six"], new proton.Data.Symbol("url")); this.data.putARRAY(put); var get = this.data.getARRAY(); assert(get.equals(put)); console.log("OK\n"); }; DataTest.testIntArray = function() { console.log("testIntArray"); this._testArray(null, null, "int", 1, 2, 3); // Now try using the proton.Data.Array class. this.data.clear(); var put = new proton.Data.Array("INT", [4, 5, 6]); this.data.putARRAY(put); var get = this.data.getARRAY(); assert(get.equals(put)); console.log("OK\n"); }; DataTest.testUUIDArray = function() { console.log("testUUIDArray"); this._testArray(null, null, "uuid", new proton.Data.Uuid(), new proton.Data.Uuid(), new proton.Data.Uuid()); // Now try using the proton.Data.Array class. this.data.clear(); var put = new proton.Data.Array("UUID", [new proton.Data.Uuid(), new proton.Data.Uuid(), new proton.Data.Uuid()]); this.data.putARRAY(put); var get = this.data.getARRAY(); assert(get.equals(put)); console.log("OK\n"); }; DataTest.testEmptyArray = function() { console.log("testEmptyArray"); this._testArray(null, null, "null"); // Now try using the proton.Data.Array class. this.data.clear(); var put = new proton.Data.Array(); this.data.putARRAY(put); var get = this.data.getARRAY(); assert(get.equals(put)); console.log("OK\n"); }; DataTest.testDescribedEmptyArray = function() { console.log("testDescribedEmptyArray"); this._testArray("long", 0, "null"); // Now try using the proton.Data.Array class. this.data.clear(); var put = new proton.Data.Array((0).long()); this.data.putARRAY(put); var get = this.data.getARRAY(); assert(get.equals(put)); console.log("OK\n"); }; DataTest._test = function(dtype, values) { var values = Array.prototype.slice.apply(arguments, [1]); var lastValue = values[values.length - 1]; // Default equality function. Note that we use valueOf because some of the // types we are trying to compare (Symbol, Timestamp, Uuid etc.) are object // types and we want to compare their value not whether they are the same object. var eq = function(x, y) {return x.valueOf() === y.valueOf();}; if (typeof lastValue === 'function') { eq = values.pop(); } dtype = dtype.toUpperCase(); var ntype = proton.Data[dtype]; var putter = 'put' + dtype; var getter = 'get' + dtype; for (var i = 0; i < values.length; i++) { var v = values[i]; /* * Replace the array element with its value. We do this to make testing * simpler for Binary elements. In the case of Binary putBINARY "consumes" * the data, in other words ownership of the underlying raw data transfers * to the Data object so the v object becomes "empty" after calling the * putter. Calling its valueOf() happens to call its toString() which * provides a stringified version of the Binary whilst also working for * the other data types we want to test too. */ values[i] = v.valueOf(); this.data[putter](v); var gotten = this.data[getter](); assert(eq(gotten, values[i])); } this.data.rewind(); for (var i = 0; i < values.length; i++) { var v = values[i]; var vtype = this.data.next(); assert(vtype === ntype); var gotten = this.data[getter](); assert(eq(gotten, v)); } // Test encode and decode methods. var encoded = this.data.encode(); var copy = new proton.Data(); while (encoded) { encoded = copy.decode(encoded); } copy.rewind(); for (var i = 0; i < values.length; i++) { var v = values[i]; var vtype = copy.next(); assert(vtype === ntype); var gotten = copy[getter](); assert(eq(gotten, v)); } copy.free(); }; DataTest.testInt = function() { console.log("testInt"); this._test("int", 1, 2, 3, -1, -2, -3); console.log("OK\n"); }; DataTest.testString = function() { console.log("testString"); this._test("string", "one", "two", "three", "this is a test", ""); console.log("OK\n"); }; DataTest.testBigString = function() { // Try a 2MB string, this is about as big as we can cope with using the default // emscripten heap size. console.log("testBigString"); var data = ""; for (var i = 0; i < 2000000; i++) { data += "*"; } var string = "start\n" + data + "\nfinish\n"; this._test("string", string); console.log("OK\n"); }; /* TODO - currently emscripten isn't respecting Module['TOTAL_STACK'] so setting PROTON_TOTAL_STACK doesn't actually increase the stack size. DataTest.testReallyBigString = function() { // Try a 20MB string, this needs a bigger emscripten heap size and more stack // as the default stack is 5MB and strings are allocated on the stack. console.log("testReallyBigString"); var data = ""; for (var i = 0; i < 20000000; i++) { data += "*"; } var string = "start\n" + data + "\nfinish\n"; this._test("string", string); console.log("OK\n"); }; */ DataTest.testFloat = function() { console.log("testFloat"); // We have to use a special comparison here because JavaScript internally // only uses doubles and converting between floats and doubles is imprecise. this._test("float", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3, function(x, y) {return (x - y < 0.000001);}); console.log("OK\n"); }; DataTest.testDouble = function() { console.log("testDouble"); this._test("double", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3); console.log("OK\n"); }; DataTest.testBinary = function() { console.log("testBinary"); this._test("binary", new proton.Data.Binary(["t".char(), "h".char(), "i".char(), "s".char()]), new proton.Data.Binary("is"), new proton.Data.Binary("a"), new proton.Data.Binary("test"), new proton.Data.Binary("of"), new proton.Data.Binary("двоичные данные")); console.log("OK\n"); }; DataTest.testSymbol = function() { console.log("testSymbol"); this._test("symbol", new proton.Data.Symbol("this is a symbol test"), new proton.Data.Symbol("bleh"), new proton.Data.Symbol("blah")); console.log("OK\n"); }; DataTest.testTimestamp = function() { console.log("testTimestamp"); this._test("timestamp", new Date(0), new Date(12345), new Date(1000000)); console.log("OK\n"); }; DataTest.testChar = function() { console.log("testChar"); this._test("char", 'a', 'b', 'c', '\u1234'); console.log("OK\n"); }; DataTest.testUUID = function() { console.log("testUUID"); this._test("uuid", new proton.Data.Uuid(), new proton.Data.Uuid(), new proton.Data.Uuid()); console.log("OK\n"); }; /* TODO DataTest.testDecimal32 = function() { console.log("testDecimal32"); //this._test("decimal32", 0, 1, 2, 3, 4, Math.pow(2, 30)); }; DataTest.testDecimal64 = function() { console.log("testDecimal64"); //this._test("decimal64", 0, 1, 2, 3, 4, Math.pow(2, 60)); }; DataTest.testDecimal128 = function() { console.log("testDecimal128"); // TODO }; */ DataTest.testCopy = function() { console.log("testCopy"); this.data.putDESCRIBEDNODE(); this.data.enter(); this.data.putULONG(123); this.data.putMAPNODE(); this.data.enter(); this.data.putSTRING("pi"); this.data.putDOUBLE(3.14159265359); this.data.exit(); this.data.exit(); var dst = this.data.copy(); var copy = dst.format(); var orig = this.data.format(); assert(copy === orig); dst.free(); console.log("OK\n"); }; DataTest.testCopyNested = function() { console.log("testCopyNested"); var nested = [1, 2, 3, [4, 5, 6], 7, 8, 9]; this.data.putObject(nested); var dst = this.data.copy(); assert(dst.format() === this.data.format()); dst.free(); console.log("OK\n"); }; DataTest.testCopyNestedArray = function() { console.log("testCopyNestedArray"); var nested = [new proton.Data.Array("LIST", [ ["first", [new proton.Data.Array("INT", [1, 2, 3]), "this"]], ["second", [new proton.Data.Array("INT", [1, 2, 3]), "is"]], ["third", [new proton.Data.Array("INT", [1, 2, 3]), "fun"]] ]), "end"]; this.data.putObject(nested); var dst = this.data.copy(); assert(dst.format() === this.data.format()); dst.free(); console.log("OK\n"); }; DataTest.testRoundTrip = function() { console.log("testRoundTrip"); var obj = {key: new Date(1234), 123: "blah", c: "bleh", desc: new proton.Data.Described("http://example.org", new proton.Data.Symbol("url")), array: new proton.Data.Array("INT", [1, 2, 3]), list: [1, 2, 3, null, 4], boolean: true}; // Serialise obj into this.data. this.data.putObject(obj); // Encode this.data into a Binary representation. var enc = this.data.encode(); // Create a new Data instance and decode from the Binary representation // consuming the Binary contents in the process. var data = new proton.Data(); data.decode(enc); assert(data.format() === this.data.format()); // Deserialise from the copied Data instance into a new JavaScript Object. data.rewind(); assert(data.next()); var copy = data.getObject(); // Create yet another Data instance and serialise the new Object into that. var data1 = new proton.Data(); data1.putObject(copy); // Compare the round tripped Data with the original one. assert(data1.format() === this.data.format()); data.free(); data1.free(); console.log("OK\n"); }; DataTest.testLookup = function() { console.log("testLookup"); var obj = {key: "value", pi: 3.14159, list: [1, 2, 3, 4]}; // Serialise obj into this.data. this.data.putObject(obj); this.data.rewind(); this.data.next(); this.data.enter(); this.data.narrow(); assert(this.data.lookup("pi")); assert(this.data.getObject() === 3.14159); this.data.rewind(); assert(this.data.lookup("key")); assert(this.data.getObject() === "value"); this.data.rewind(); assert(this.data.lookup("list")); assert(this.data.getObject().toString() === "1,2,3,4"); this.data.widen(); this.data.rewind(); assert(!this.data.lookup("pi")); console.log("OK\n"); }; DataTest.run(); } else { console.error("codec.js should be run in Node.js"); } qpid-proton-0.10/tests/java/0000775000000000000000000000000012562450203012660 5ustar qpid-proton-0.10/tests/java/pythonTests.ignore0000664000000000000000000000025212562450203016430 0ustar proton_tests.reactor_interop.* proton_tests.soak.* proton_tests.ssl.SslTest.test_defaults_messenger_app proton_tests.ssl.SslTest.test_server_authentication_messenger_app qpid-proton-0.10/tests/java/org/0000775000000000000000000000000012562450203013447 5ustar qpid-proton-0.10/tests/java/org/apache/0000775000000000000000000000000012562450203014670 5ustar qpid-proton-0.10/tests/java/org/apache/qpid/0000775000000000000000000000000012562450203015625 5ustar qpid-proton-0.10/tests/java/org/apache/qpid/proton/0000775000000000000000000000000012562450203017146 5ustar qpid-proton-0.10/tests/java/org/apache/qpid/proton/ProtonJInterop.java0000664000000000000000000001565112562450203022755 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton; import java.io.IOException; import java.nio.BufferOverflowException; import org.apache.qpid.proton.amqp.messaging.AmqpValue; import org.apache.qpid.proton.amqp.transport.ErrorCondition; import org.apache.qpid.proton.engine.BaseHandler; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Event; import org.apache.qpid.proton.engine.Receiver; import org.apache.qpid.proton.engine.Sender; import org.apache.qpid.proton.engine.Session; import org.apache.qpid.proton.message.Message; import org.apache.qpid.proton.reactor.Acceptor; import org.apache.qpid.proton.reactor.FlowController; import org.apache.qpid.proton.reactor.Handshaker; import org.apache.qpid.proton.reactor.Reactor; public class ProtonJInterop { private static class SendHandler extends BaseHandler { private final String hostname; private int numMsgs; private int count = 0; private boolean result = false; private SendHandler(String hostname, int numMsgs) { this.hostname = hostname; this.numMsgs = numMsgs; add(new Handshaker()); } @Override public void onConnectionInit(Event event) { Connection conn = event.getConnection(); conn.setHostname(hostname); Session ssn = conn.session(); Sender snd = ssn.sender("sender"); conn.open(); ssn.open(); snd.open(); } @Override public void onLinkFlow(Event event) { Sender snd = (Sender)event.getLink(); if (snd.getCredit() > 0 && snd.getLocalState() != EndpointState.CLOSED) { Message message = Proton.message(); ++count; message.setBody(new AmqpValue("message-"+count)); byte[] msgData = new byte[1024]; int length; while(true) { try { length = message.encode(msgData, 0, msgData.length); break; } catch(BufferOverflowException e) { msgData = new byte[msgData.length * 2]; } } byte[] tag = String.valueOf(count).getBytes(); Delivery dlv = snd.delivery(tag); snd.send(msgData, 0, length); dlv.settle(); snd.advance(); if (count == numMsgs) { snd.close(); snd.getSession().close(); snd.getSession().getConnection().close(); result = true; } } } @Override public void onTransportError(Event event) { result = false; ErrorCondition condition = event.getTransport().getCondition(); if (condition != null) { System.err.println("Error: " + condition.getDescription()); } else { System.err.println("Error (no description returned)."); } } } private static class Send extends BaseHandler { private final SendHandler sendHandler; private Send(String hostname, int numMsgs) { sendHandler = new SendHandler(hostname, numMsgs); } @Override public void onReactorInit(Event event) { event.getReactor().connection(sendHandler); } public boolean getResult() { return sendHandler.result; } } private static class Recv extends BaseHandler { private final int port; private final int numMsgs; private int count = 0; private Acceptor acceptor = null; private Recv(int port, int numMsgs) { this.port = port; this.numMsgs = numMsgs; add(new Handshaker()); add(new FlowController()); } @Override public void onReactorInit(Event event) { try { acceptor = event.getReactor().acceptor("localhost", port); } catch(IOException ioException) { throw new RuntimeException(ioException); } } @Override public void onDelivery(Event event) { Receiver recv = (Receiver)event.getLink(); Delivery delivery = recv.current(); if (delivery.isReadable() && !delivery.isPartial()) { int size = delivery.pending(); byte[] buffer = new byte[size]; int read = recv.recv(buffer, 0, buffer.length); recv.advance(); Message msg = Proton.message(); msg.decode(buffer, 0, read); ++count; String msgBody = ((AmqpValue)msg.getBody()).getValue().toString(); String expected = "message-" + count; if (!expected.equals(msgBody)) { throw new RuntimeException("Received message body '" + msgBody + "', expected: '" + expected + "'"); } if (count == numMsgs) { recv.close(); recv.getSession().close(); recv.getSession().getConnection().close(); acceptor.close(); } } } } public static void main(String[] args) throws IOException { try { int port = Integer.valueOf(args[1]); int numMsgs = Integer.valueOf(args[2]); boolean result = false; if ("send".equalsIgnoreCase(args[0])) { Send send = new Send("localhost:" + port, numMsgs); Reactor r = Proton.reactor(send); r.run(); result = send.getResult(); } else { Reactor r = Proton.reactor(new Recv(port, numMsgs)); r.run(); result = true; } System.exit(result ? 0 : 1); } catch(Throwable t) { t.printStackTrace(); System.exit(1); } } }qpid-proton-0.10/tests/java/org/apache/qpid/proton/JythonTest.java0000664000000000000000000002410612562450203022127 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; import java.io.FileNotFoundException; import java.util.logging.Level; import java.util.logging.Logger; import org.junit.Test; import org.python.core.PyException; import org.python.core.PyString; import org.python.core.PySystemState; import org.python.util.PythonInterpreter; /** * Runs all the python tests, or just those that match the system property {@value #TEST_PATTERN_SYSTEM_PROPERTY} * if it exists. * Use {@value #TEST_INVOCATIONS_SYSTEM_PROPERTY} to specify the number of repetitions, or use 0 * for unlimited repetitions. */ public class JythonTest { private static final Logger LOGGER = Logger.getLogger(JythonTest.class.getName()); /* System properties expected to be defined in test/pom.xml */ private static final String PROTON_JYTHON_BINDING = "protonJythonBinding"; private static final String PROTON_JYTHON_SHIM = "protonJythonShim"; private static final String PROTON_JYTHON_TEST_ROOT = "protonJythonTestRoot"; private static final String PROTON_JYTHON_TEST_SCRIPT = "protonJythonTestScript"; private static final String PROTON_JYTHON_TESTS_XML_OUTPUT_DIRECTORY = "protonJythonTestXmlOutputDirectory"; private static final String PROTON_JYTHON_IGNORE_FILE = "protonJythonIgnoreFile"; /** Name of the junit style xml report to be written by the python test script */ private static final String XML_REPORT_NAME = "TEST-jython-test-results.xml"; public static final String TEST_PATTERN_SYSTEM_PROPERTY = "proton.pythontest.pattern"; public static final String IGNORE_FILE_SYSTEM_PROPERTY = "proton.pythontest.ignore_file"; /** The number of times to run the test, or forever if zero */ public static final String TEST_INVOCATIONS_SYSTEM_PROPERTY = "proton.pythontest.invocations"; public static final String ALWAYS_COLORIZE_SYSTEM_PROPERTY = "proton.pythontest.always_colorize"; @Test public void test() throws Exception { String testScript = getJythonTestScript(); String binding = getJythonBinding(); String shim = getJythonShim(); String testRoot = getJythonTestRoot(); String xmlReportFile = getOptionalXmlReportFilename(); String ignoreFile = getOptionalIgnoreFile(); PythonInterpreter interp = createInterpreterWithArgs(xmlReportFile, ignoreFile); interp.getSystemState().path.insert(0, new PyString(binding)); interp.getSystemState().path.insert(0, new PyString(shim)); interp.getSystemState().path.insert(0, new PyString(testRoot)); LOGGER.info("About to call Jython test script: '" + testScript + "' with '" + testRoot + "' added to Jython path"); int maxInvocations = Integer.getInteger(TEST_INVOCATIONS_SYSTEM_PROPERTY, 1); assertTrue("Number of invocations should be non-negative", maxInvocations >= 0); boolean loopForever = maxInvocations == 0; if(maxInvocations > 1) { LOGGER.info("Will invoke Python test " + maxInvocations + " times"); } if(loopForever) { LOGGER.info("Will repeatedly invoke Python test forever"); } int invocations = 1; while(loopForever || invocations++ <= maxInvocations) { runTestOnce(testScript, interp, invocations); } } private void runTestOnce(String testScript, PythonInterpreter interp, int invocationsSoFar) { try { interp.execfile(testScript); } catch (PyException e) { if( e.type.toString().equals("") && e.value.toString().equals("0") ) { // Build succeeded. } else { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "Jython interpreter failed. Test failures?", e); } // This unusual code is necessary because PyException toString() contains the useful Python traceback // and getMessage() is usually null fail("Caught PyException on invocation number " + invocationsSoFar + ": " + e.toString() + " with message: " + e.getMessage()); } } } private PythonInterpreter createInterpreterWithArgs(String xmlReportFile, String ignoreFile) { PySystemState systemState = new PySystemState(); if (xmlReportFile != null) { systemState.argv.append(new PyString("--xml")); systemState.argv.append(new PyString(xmlReportFile)); } if(ignoreFile == null) { ignoreFile = System.getProperty(IGNORE_FILE_SYSTEM_PROPERTY); } if(ignoreFile != null) { systemState.argv.append(new PyString("-I")); systemState.argv.append(new PyString(ignoreFile)); } String testPattern = System.getProperty(TEST_PATTERN_SYSTEM_PROPERTY); if(testPattern != null) { systemState.argv.append(new PyString(testPattern)); } if(Boolean.getBoolean(ALWAYS_COLORIZE_SYSTEM_PROPERTY)) { systemState.argv.append(new PyString("--always-colorize")); } PythonInterpreter interp = new PythonInterpreter(null, systemState); return interp; } private String getJythonTestScript() throws FileNotFoundException { String testScriptString = getNonNullSystemProperty(PROTON_JYTHON_TEST_SCRIPT, "System property '%s' must provide the location of the python test script"); File testScript = new File(testScriptString); if (!testScript.canRead()) { throw new FileNotFoundException("Can't read python test script " + testScript); } return testScript.getAbsolutePath(); } private String getJythonBinding() throws FileNotFoundException { String str = getNonNullSystemProperty(PROTON_JYTHON_BINDING, "System property '%s' must provide the location of the python test root"); File file = new File(str); if (!file.isDirectory()) { throw new FileNotFoundException("Binding location '" + file + "' should be a directory."); } return file.getAbsolutePath(); } private String getJythonShim() throws FileNotFoundException { String str = getNonNullSystemProperty(PROTON_JYTHON_SHIM, "System property '%s' must provide the location of the jythin shim"); File file = new File(str); if (!file.isDirectory()) { throw new FileNotFoundException("Shim location '" + file + "' should be a directory."); } return file.getAbsolutePath(); } private String getJythonTestRoot() throws FileNotFoundException { String testRootString = getNonNullSystemProperty(PROTON_JYTHON_TEST_ROOT, "System property '%s' must provide the location of the python test root"); File testRoot = new File(testRootString); if (!testRoot.isDirectory()) { throw new FileNotFoundException("Test root '" + testRoot + "' should be a directory."); } return testRoot.getAbsolutePath(); } private String getOptionalIgnoreFile() { String ignoreFile = System.getProperty(PROTON_JYTHON_IGNORE_FILE); if(ignoreFile != null) { File f = new File(ignoreFile); if(f.exists() && f.canRead()) { return ignoreFile; } else { LOGGER.info(PROTON_JYTHON_IGNORE_FILE + " system property set to " + ignoreFile + " but this cannot be read."); } } return null; } private String getOptionalXmlReportFilename() { String xmlOutputDirString = System.getProperty(PROTON_JYTHON_TESTS_XML_OUTPUT_DIRECTORY); if (xmlOutputDirString == null) { LOGGER.info(PROTON_JYTHON_TESTS_XML_OUTPUT_DIRECTORY + " system property not set; xml output will not be written"); } File xmlOutputDir = new File(xmlOutputDirString); createXmlOutputDirectoryIfNecessary(xmlOutputDirString, xmlOutputDir); return new File(xmlOutputDir, XML_REPORT_NAME).getAbsolutePath(); } private void createXmlOutputDirectoryIfNecessary(String xmlOutputDirString, File xmlOutputDir) { if (!xmlOutputDir.isDirectory()) { boolean success = xmlOutputDir.mkdirs(); if (!success) { LOGGER.warning("Failed to create directory " + xmlOutputDir + " Thread name :" + Thread.currentThread().getName()); } if (!xmlOutputDir.isDirectory()) { throw new RuntimeException("Failed to create one or more directories with path " + xmlOutputDirString); } } } private String getNonNullSystemProperty(String systemProperty, String messageWithStringFormatToken) { String testScriptString = System.getProperty(systemProperty); if (testScriptString == null) { String message = messageWithStringFormatToken; throw new IllegalStateException(String.format(message, systemProperty)); } return testScriptString; } } qpid-proton-0.10/tests/java/org/apache/qpid/proton/InteropTest.java0000664000000000000000000001476412562450203022305 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton; import org.apache.qpid.proton.TestDecoder; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.DescribedType; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.messaging.AmqpValue; import org.apache.qpid.proton.message.Message; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertArrayEquals; import org.junit.Test; import java.lang.System; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Vector; import java.util.List; import java.util.ArrayList; import java.util.Map; import java.util.HashMap; public class InteropTest { static private File findTestsInteropDir() { File f = new File(System.getProperty("user.dir")); while (f != null && !f.getName().equals("tests")) f = f.getParentFile(); if (f != null && f.isDirectory()) return new File(f, "interop"); else throw new Error("Cannot find tests/interop directory"); } static File testsInteropDir = findTestsInteropDir(); byte[] getBytes(String name) throws IOException { File f = new File(testsInteropDir, name + ".amqp"); byte[] data = new byte[(int) f.length()]; FileInputStream fi = new FileInputStream(f); assertEquals(f.length(), fi.read(data)); fi.close(); return data; } Message decodeMessage(String name) throws IOException { byte[] data = getBytes(name); Message m = Proton.message(); m.decode(data, 0, data.length); return m; } TestDecoder createDecoder(byte[] data) { TestDecoder td = new TestDecoder(data); return td; } @Test public void testMessage() throws IOException { Message m = decodeMessage("message"); Binary b = (Binary) (((AmqpValue) m.getBody()).getValue()); String s = createDecoder(b.getArray()).readString(); assertEquals("hello", s); } @Test public void testPrimitives() throws IOException { TestDecoder d = createDecoder(getBytes("primitives")); assertEquals(true, d.readBoolean()); assertEquals(false, d.readBoolean()); assertEquals(d.readUnsignedByte().intValue(), 42); assertEquals(42, d.readUnsignedShort().intValue()); assertEquals(-42, d.readShort().intValue()); assertEquals(12345, d.readUnsignedInteger().intValue()); assertEquals(-12345, d.readInteger().intValue()); assertEquals(12345, d.readUnsignedLong().longValue()); assertEquals(-12345, d.readLong().longValue()); assertEquals(0.125, d.readFloat().floatValue(), 0e-10); assertEquals(0.125, d.readDouble().doubleValue(), 0e-10); } @Test public void testStrings() throws IOException { TestDecoder d = createDecoder(getBytes("strings")); assertEquals(new Binary("abc\0defg".getBytes("UTF-8")), d.readBinary()); assertEquals("abcdefg", d.readString()); assertEquals(Symbol.valueOf("abcdefg"), d.readSymbol()); assertEquals(new Binary(new byte[0]), d.readBinary()); assertEquals("", d.readString()); assertEquals(Symbol.valueOf(""), d.readSymbol()); } @Test public void testDescribed() throws IOException { TestDecoder d = createDecoder(getBytes("described")); DescribedType dt = (DescribedType) (d.readObject()); assertEquals(Symbol.valueOf("foo-descriptor"), dt.getDescriptor()); assertEquals("foo-value", dt.getDescribed()); dt = (DescribedType) (d.readObject()); assertEquals(12, dt.getDescriptor()); assertEquals(13, dt.getDescribed()); } @Test public void testDescribedArray() throws IOException { TestDecoder d = createDecoder(getBytes("described_array")); DescribedType a[] = (DescribedType[]) (d.readArray()); for (int i = 0; i < 10; ++i) { assertEquals(Symbol.valueOf("int-array"), a[i].getDescriptor()); assertEquals(i, a[i].getDescribed()); } } @Test public void testArrays() throws IOException { TestDecoder d = createDecoder(getBytes("arrays")); // int array Vector ints = new Vector(); for (int i = 0; i < 100; ++i) ints.add(new Integer(i)); assertArrayEquals(ints.toArray(), d.readArray()); // String array String strings[] = { "a", "b", "c" }; assertArrayEquals(strings, d.readArray()); // Empty array assertArrayEquals(new Integer[0], d.readArray()); } @Test public void testLists() throws IOException { TestDecoder d = createDecoder(getBytes("lists")); List l = new ArrayList() { { add(new Integer(32)); add("foo"); add(new Boolean(true)); } }; assertEquals(l, d.readList()); l.clear(); assertEquals(l, d.readList()); } @SuppressWarnings({ "rawtypes", "unchecked" }) @Test public void testMaps() throws IOException { TestDecoder d = createDecoder(getBytes("maps")); Map map = new HashMap() { { put("one", 1); put("two", 2); put("three", 3); } }; assertEquals(map, d.readMap()); map = new HashMap() { { put(1, "one"); put(2, "two"); put(3, "three"); } }; assertEquals(map, d.readMap()); map = new HashMap(); assertEquals(map, d.readMap()); } } qpid-proton-0.10/tests/interop/0000775000000000000000000000000012562450203013417 5ustar qpid-proton-0.10/tests/interop/strings.amqp0000664000000000000000000000004212562450203015764 0ustar  abcdefg¡abcdefg£abcdefg ¡£qpid-proton-0.10/tests/interop/primitives.amqp0000664000000000000000000000006412562450203016472 0ustar ABP*`*aÿÖp09qÿÿÏÇ€09ÿÿÿÿÿÿÏÇr>‚?Àqpid-proton-0.10/tests/interop/null.amqp0000664000000000000000000000000112562450203015240 0ustar @qpid-proton-0.10/tests/interop/message.amqp0000664000000000000000000000011112562450203015714 0ustar SpÐ BP@BRSsÐ" @@@@@@@@ƒƒ@R@Sw ¡helloqpid-proton-0.10/tests/interop/maps.amqp0000664000000000000000000000011112562450203015230 0ustar Ñ¡threeT¡twoT¡oneTÑT¡oneT¡twoT¡threeÑqpid-proton-0.10/tests/interop/lists.amqp0000664000000000000000000000003212562450203015430 0ustar Ð T ¡fooAÐqpid-proton-0.10/tests/interop/described_array.amqp0000664000000000000000000000007612562450203017424 0ustar ð9 £ int-arrayq qpid-proton-0.10/tests/interop/described.amqp0000664000000000000000000000004112562450203016216 0ustar £foo-descriptor¡ foo-valueT T qpid-proton-0.10/tests/interop/arrays.amqp0000664000000000000000000000067512562450203015610 0ustar ð•dq  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcð±abcðqqpid-proton-0.10/proton-j/0000775000000000000000000000000012562450203012345 5ustar qpid-proton-0.10/proton-j/src/0000775000000000000000000000000012562450203013134 5ustar qpid-proton-0.10/proton-j/src/test/0000775000000000000000000000000012562450203014113 5ustar qpid-proton-0.10/proton-j/src/test/resources/0000775000000000000000000000000012562450203016125 5ustar qpid-proton-0.10/proton-j/src/test/resources/META-INF/0000775000000000000000000000000012562450203017265 5ustar qpid-proton-0.10/proton-j/src/test/resources/META-INF/services/0000775000000000000000000000000012562450203021110 5ustar ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootqpid-proton-0.10/proton-j/src/test/resources/META-INF/services/org.apache.qpid.proton.factoryloadertesting.DummyProtonFactoryqpid-proton-0.10/proton-j/src/test/resources/META-INF/services/org.apache.qpid.proton.factoryloadert0000664000000000000000000000017712562450203030344 0ustar org.apache.qpid.proton.factoryloadertesting.DummyProtonCFactory org.apache.qpid.proton.factoryloadertesting.DummyProtonJFactoryqpid-proton-0.10/proton-j/src/test/java/0000775000000000000000000000000012562450203015034 5ustar qpid-proton-0.10/proton-j/src/test/java/org/0000775000000000000000000000000012562450203015623 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/0000775000000000000000000000000012562450203017044 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/0000775000000000000000000000000012562450203020001 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/0000775000000000000000000000000012562450203021322 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/test/0000775000000000000000000000000012562450203022301 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/test/ProtonTestCase.java0000664000000000000000000000677312562450203026076 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.test; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.rules.TestName; public class ProtonTestCase { private static final Logger _logger = Logger.getLogger(ProtonTestCase.class.getName()); private final Map _propertiesSetForTest = new HashMap(); @Rule public TestName _testName = new TestName(); /** * Set a System property for duration of this test only. The tearDown will * guarantee to reset the property to its previous value after the test * completes. * * @param property The property to set * @param value the value to set it to, if null, the property will be cleared */ protected void setTestSystemProperty(final String property, final String value) { if (!_propertiesSetForTest.containsKey(property)) { // Record the current value so we can revert it later. _propertiesSetForTest.put(property, System.getProperty(property)); } if (value == null) { System.clearProperty(property); _logger.info("Set system property '" + property + "' to be cleared"); } else { System.setProperty(property, value); _logger.info("Set system property '" + property + "' to: '" + value + "'"); } } /** * Restore the System property values that were set by this test run. */ protected void revertTestSystemProperties() { if(!_propertiesSetForTest.isEmpty()) { for (String key : _propertiesSetForTest.keySet()) { String value = _propertiesSetForTest.get(key); if (value != null) { System.setProperty(key, value); _logger.info("Reverted system property '" + key + "' to: '" + value + "'"); } else { System.clearProperty(key); _logger.info("Reverted system property '" + key + "' to be cleared"); } } _propertiesSetForTest.clear(); } } @After public void tearDown() throws java.lang.Exception { _logger.info("========== tearDown " + getTestName() + " =========="); revertTestSystemProperties(); } @Before public void setUp() throws Exception { _logger.info("========== start " + getTestName() + " =========="); } protected String getTestName() { return getClass().getSimpleName() + "." +_testName.getMethodName(); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/0000775000000000000000000000000012562450203023731 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/0000775000000000000000000000000012562450203025176 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/TransportTest.java0000664000000000000000000000700012562450203030672 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.systemtests.engine; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; import org.junit.Ignore; import org.junit.Test; /** * TODO add test for 2.3.1 "The frame is malformed if the size is less than the size of the frame header (8 bytes)" * TODO add test using empty byte arrays (calling {@link Transport#input(byte[], int, int)} with empty byte array in Proton-j-impl currently throws "TransportException Unexpected EOS") */ public class TransportTest { private final Transport _transport = Proton.transport(); /** * Note that Proton does not yet give the application explicit control over protocol version negotiation * TODO does Proton give *visibility* of the negotiated protocol version? */ public void testReceiptOfHeaderContainingUnsupportedProtocolVersionNumber_causesAmqp10Response() { } @Test @Ignore("Reinstate once it is agreed how error condition will be reported by to use of API") public void testReceiptOfNonAmqpHeader_causesAmqp10Response() { byte[] nonAmqpHeader = "HTTP/1.0".getBytes(); try { _transport.input(nonAmqpHeader, 0, nonAmqpHeader.length); // TODO Proton-c gives rv PN_ERROR and a pn_transport_error "AMQP header mismatch: 'HTTP/1.0'" and then // jni layer turns this into a TransportException. // Proton-j just throws TransportException } catch (TransportException te) { // TODO - exception should not be thrown } byte[] buf = new byte[255]; int bytesWritten = _transport.output(buf, 0, buf.length); byte[] response = new byte[bytesWritten]; System.arraycopy(buf, 0, response, 0, bytesWritten); assertArrayEquals("AMQP\0\1\0\0".getBytes(), response); // how should further input be handled?? assertTransportRefusesFurtherInputOutput(_transport); } private void assertTransportRefusesFurtherInputOutput(Transport transport) { byte[] sourceBufferThatShouldBeUnread = "REFUSEME".getBytes(); int bytesConsumed = transport.input(sourceBufferThatShouldBeUnread, 0, sourceBufferThatShouldBeUnread.length); // assertEquals(-1, bytesConsumed); // TODO reinstate with testReceiptOfNonAmqpHeader_causesAmqp10Response byte[] destBufferThatShouldRemainUnwritten = new byte[255]; int bytesWritten = transport.output(destBufferThatShouldRemainUnwritten, 0, destBufferThatShouldRemainUnwritten.length); assertEquals(-1, bytesWritten); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/TransportPumper.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/TransportPumper.ja0000664000000000000000000000476612562450203030714 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.systemtests.engine; import static org.junit.Assert.assertEquals; import org.apache.qpid.proton.engine.Transport; public class TransportPumper { private static final String SERVER_ROLE = "server"; private static final String CLIENT_ROLE = "client"; private final Transport _clientTransport; private final Transport _serverTransport; public TransportPumper(Transport clientTransport, Transport serverTransport) { _clientTransport = clientTransport; _serverTransport = serverTransport; } public void pumpAll() { boolean bytesToTransfer = true; while(bytesToTransfer) { int clientOutputLength = pumpOnceFromClientToServer(); int serverOutputLength = pumpOnceFromServerToClient(); bytesToTransfer = clientOutputLength > 0 || serverOutputLength > 0; } } public int pumpOnceFromClientToServer() { return pumpOnce(_clientTransport, CLIENT_ROLE, _serverTransport, SERVER_ROLE); } public int pumpOnceFromServerToClient() { return pumpOnce(_serverTransport, SERVER_ROLE, _clientTransport, CLIENT_ROLE); } private int pumpOnce(Transport transportFrom, String fromRole, Transport transportTo, String toRole) { final byte[] output = new byte[1024]; int outputLength = transportFrom.output(output, 0, output.length); if (outputLength > 0) { int numberConsumedByServer = transportTo.input(output, 0, outputLength); assertEquals("Expecting " + toRole + " to consume all of " + fromRole + "'s output", outputLength, numberConsumedByServer); } return outputLength; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/ConnectionTest.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/engine/ConnectionTest.jav0000664000000000000000000006155312562450203030651 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests.engine; import static java.util.EnumSet.of; import static org.apache.qpid.proton.engine.EndpointState.ACTIVE; import static org.apache.qpid.proton.engine.EndpointState.CLOSED; import static org.apache.qpid.proton.engine.EndpointState.UNINITIALIZED; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assume.assumeTrue; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.transport.Close; import org.apache.qpid.proton.amqp.transport.ErrorCondition; import org.apache.qpid.proton.amqp.transport.Open; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.Endpoint; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Session; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; import org.apache.qpid.proton.engine.impl.AmqpFramer; import org.junit.Ignore; import org.junit.Test; /** * Implicitly tests both {@link Connection} and {@link Transport} (e.g. for stuff like the AMQP header exchange). * * TODO test that the connection properties, connection capability, and error info maps have keys that are exclusively of type Symbol. */ public class ConnectionTest { private static final String SERVER_CONTAINER = "serverContainer"; private static final String CLIENT_CONTAINER = "clientContainer"; private final Transport _clientTransport = Proton.transport(); private final Transport _serverTransport = Proton.transport(); private final TransportPumper _pumper = new TransportPumper(_clientTransport, _serverTransport); private final Connection _clientConnection = Proton.connection(); private final Connection _serverConnection = Proton.connection(); private final AmqpFramer _framer = new AmqpFramer(); // 2.4.1 Opening A Connection /** */ @Test public void testOpenConnection() { _pumper.pumpAll(); bindAndOpenConnections(); } /** Container id is a mandatory field so this should cause an error */ @Test public void testReceiptOfOpenWithoutContainerId_causesTODO() { _pumper.pumpAll(); Open openWithoutContainerId = new Open(); byte[] openFrameBuffer = _framer.generateFrame(0, openWithoutContainerId); int serverConsumed = _serverTransport.input(openFrameBuffer, 0, openFrameBuffer.length); assertEquals(openFrameBuffer.length, serverConsumed); assertEquals(_serverTransport.capacity(), Transport.END_OF_STREAM); } /** * "Prior to any explicit negotiation, the maximum frame size is 512 (MIN-MAX-FRAME-SIZE) and the maximum channel number is 0" * */ @Test public void testReceiptOfOpenExactlyDefaultMaximumFrameSize() { _pumper.pumpAll(); _serverTransport.bind(_serverConnection); assertEnpointState(_serverConnection, UNINITIALIZED, UNINITIALIZED); // containerId and extended header sized to give an open frame // exactly 512 bytes in length. String containerId = "12345678"; int extendedHeaderSize = 122 * 4; Open open = new Open(); open.setContainerId(containerId); byte[] openFrameBuffer = _framer.generateFrame(0, new byte[extendedHeaderSize], open); assertEquals("Test requires a frame of size MIN_MAX_FRAME_SIZE", Transport.MIN_MAX_FRAME_SIZE, openFrameBuffer.length); int serverConsumed = _serverTransport.input(openFrameBuffer, 0, openFrameBuffer.length); assertEquals(openFrameBuffer.length, serverConsumed); // Verify that the server has seen the Open arrive assertEnpointState(_serverConnection, UNINITIALIZED, ACTIVE); assertEquals(containerId, _serverConnection.getRemoteContainer()); } /** * "Prior to any explicit negotiation, the maximum frame size is 512 (MIN-MAX-FRAME-SIZE) and the maximum channel number is 0" */ @Test public void testReceiptOfOpenBiggerThanDefaultMaximumFrameSize_causesTODO() { _pumper.pumpAll(); _serverTransport.bind(_serverConnection); assertEnpointState(_serverConnection, UNINITIALIZED, UNINITIALIZED); // containerId and extended header sized to give an open frame // 1 byte larger the than 512 bytes permitted before negotiation by the AMQP spec. String containerId = "123456789"; int extendedHeaderSize = 122 * 4; Open bigOpen = new Open(); bigOpen.setContainerId(containerId); byte[] openFrameBuffer = _framer.generateFrame(0, new byte[extendedHeaderSize], bigOpen); assertEquals("Test requires a frame of size MIN_MAX_FRAME_SIZE + 1", Transport.MIN_MAX_FRAME_SIZE + 1, openFrameBuffer.length); int serverConsumed = _serverTransport.input(openFrameBuffer, 0, openFrameBuffer.length); assertEquals(openFrameBuffer.length, serverConsumed); // TODO server should indicate error but currently both implementations currently process // the larger frames. The following assertions should fail but currently pass. assertEnpointState(_serverConnection, UNINITIALIZED, ACTIVE); assertNotNull(_serverConnection.getRemoteContainer()); } @Test public void testReceiptOfSecondOpen_causesTODO() { bindAndOpenConnections(); Open secondOpen = new Open(); // erroneous secondOpen.setContainerId("secondOpen"); byte[] openFrameBuffer = _framer.generateFrame(0, secondOpen); int serverConsumed = _serverTransport.input(openFrameBuffer, 0, openFrameBuffer.length); assertEquals(openFrameBuffer.length, serverConsumed); // TODO server should indicate error but currently both implementation currently // allow this condition } /** "each peer MUST send an open frame before sending any other frames" * * @see ConnectionTest#testReceiptOfCloseBeforeOpen_causesTODO() */ public void testReceiptOfIntialFrameOtherThanOpen_causesTODO() { } /** * 2.4.5 "Implementations MUST be prepared to handle empty frames arriving on any valid channel" * * TODO consider moving to {@link TransportTest} once we have a less Connection-centric way of * checking health than calling {@link #bindAndOpenConnections()} */ @Test public void testReceiptOfInitialEmptyFrame_isAllowed() { _pumper.pumpAll(); byte[] emptyFrame = _framer.createEmptyFrame(0); int bytesConsumed = _serverTransport.input(emptyFrame, 0, emptyFrame.length); assertEquals(emptyFrame.length, bytesConsumed); bindAndOpenConnections(); } /** "The open frame can only be sent on channel 0" */ @Test @Ignore("Reinstate once it is agreed how error condition will be reported to user of API") public void testReceiptOfOpenOnNonZeroChannelNumber_causesTODO() { _pumper.pumpAll(); Open open = new Open(); open.setContainerId(SERVER_CONTAINER); int nonZeroChannelId = 1; byte[] buf = _framer.generateFrame(nonZeroChannelId, open); int rv = _serverTransport.input(buf, 0, buf.length); // TODO server should indicate error } /** * "After sending the open frame and reading its partner's open frame a peer MUST operate within * mutually acceptable limitations from this point forward" * see 2.7.1 "A peer that receives an oversized frame MUST close the connection with the framing-error error-code" */ public void testReceiptOfFrameLargerThanAgreedMaximumSize_causesTODO() { } public void testThatSentFramesAreWithinMaximumSizeLimit() { } // 2.4.2 Pipelined Open /** test that the other peer accepts the pipelined frames and creates an open connection */ @Test public void testReceiptOfOpenUsingPipelining() { _clientConnection.setContainer(CLIENT_CONTAINER); _clientTransport.bind(_clientConnection); _clientConnection.open(); _serverTransport.bind(_serverConnection); // when pipelining, we delay pumping until the connection is both bound and opened _pumper.pumpOnceFromClientToServer(); assertEnpointState(_clientConnection, ACTIVE, UNINITIALIZED); assertEnpointState(_serverConnection, UNINITIALIZED, ACTIVE); } /** test that the other peer accepts the pipelined frames and creates an already-closed connection */ @Test public void testReceiptOfOpenThenCloseUsingPipelining() { _clientConnection.setContainer(CLIENT_CONTAINER); _clientTransport.bind(_clientConnection); _clientConnection.open(); _clientConnection.close(); _serverTransport.bind(_serverConnection); _pumper.pumpOnceFromClientToServer(); assertEnpointState(_clientConnection, CLOSED, UNINITIALIZED); assertEnpointState(_serverConnection, UNINITIALIZED, CLOSED); } /** * Similar to {@link #testReceiptOfOpenUsingPipelining()} but opens both ends of the connection * so we can actually use it. */ @Test public void testOpenConnectionUsingPipelining() { _clientConnection.setContainer(CLIENT_CONTAINER); _clientTransport.bind(_clientConnection); _clientConnection.open(); _serverConnection.setContainer(SERVER_CONTAINER); _serverTransport.bind(_serverConnection); _serverConnection.open(); _pumper.pumpAll(); assertEnpointState(_clientConnection, ACTIVE, ACTIVE); assertEnpointState(_serverConnection, ACTIVE, ACTIVE); assertConnectionIsUsable(); } // 2.4.3 Closing A Connection and 2.7.9 Close /** * "each peer MUST write a close frame" * Omits the optional error field */ @Test public void testCloseConnection() { bindAndOpenConnections(); assertEnpointState(_clientConnection, ACTIVE, ACTIVE); assertEnpointState(_serverConnection, ACTIVE, ACTIVE); _clientConnection.close(); assertEnpointState(_clientConnection, CLOSED, ACTIVE); assertEnpointState(_serverConnection, ACTIVE, ACTIVE); _pumper.pumpAll(); assertEnpointState(_clientConnection, CLOSED, ACTIVE); assertEnpointState(_serverConnection, ACTIVE, CLOSED); _serverConnection.close(); assertEnpointState(_clientConnection, CLOSED, ACTIVE); assertEnpointState(_serverConnection, CLOSED, CLOSED); _pumper.pumpAll(); assertEnpointState(_clientConnection, CLOSED, CLOSED); assertEnpointState(_serverConnection, CLOSED, CLOSED); } /** * "each peer MUST write a close frame with a code indicating the reason for closing" * Also see 2.8.16 Connection Error */ @Test @SuppressWarnings({ "rawtypes", "unchecked" }) public void testCloseConnectionWithErrorCode_causesCloseFrameContainingErrorCodeToBeSent() { bindAndOpenConnections(); /* * TODO javadoc for {@link Connection#getCondition()} states null is returned if there is no condition, * this differs from the implementation of both Proton-c and Proton-j. */ assertNull(_clientConnection.getCondition().getCondition()); assertNull(_serverConnection.getCondition().getCondition()); assertNull(_clientConnection.getRemoteCondition().getCondition()); assertNull(_serverConnection.getRemoteCondition().getCondition()); ErrorCondition clientErrorCondition = new ErrorCondition(Symbol.getSymbol("myerror"), "mydescription"); Map info = new HashMap(); info.put(Symbol.getSymbol("simplevalue"), "value"); info.put(Symbol.getSymbol("list"), Arrays.asList("e1", "e2", "e3")); clientErrorCondition.setInfo(info); _clientConnection.setCondition(clientErrorCondition); _clientConnection.close(); _pumper.pumpAll(); assertEquals(clientErrorCondition, _serverConnection.getRemoteCondition()); assertNull(_serverConnection.getCondition().getCondition()); } /** * "each peer MUST write a close frame with a code indicating the reason for closing" */ public void testReceiptOfConnectionCloseContainingErrorCode_allowsErrorCodeToBeObserved() { } /** * A test for when the connection close frame contains a session error * rather than a connection error. This is allowed by the spec. */ public void testReceiptOfConnectionCloseContainingNonConnectionErrorCode_causesTODO() { } /** "This frame MUST be the last thing ever written onto a connection." */ public void testUsingProtonAfterClosingConnection_doesntCauseFrameToBeSent() { } /** "This frame MUST be the last thing ever written onto a connection." */ public void testReceiptOfFrameAfterClose_causesTODO() { } /** "A close frame MAY be received on any channel up to the maximum channel number negotiated in open" */ public void testReceiptOfCloseOnNonZeroChannelNumber_causesHappyPathTODO() { } /** * "each peer MUST send an open frame before sending any other frames" */ @Test public void testReceiptOfCloseBeforeOpen_causesTODO() { _pumper.pumpAll(); Close surprisingClose = new Close(); byte[] buf = _framer.generateFrame(0, surprisingClose); _serverTransport.input(buf, 0, buf.length); // TODO server should indicate error } // 2.4.4 Simultaneous Close /** "both endpoints MAY simultaneously" */ public void testPeersCloseConnectionSimultaneously() { } // 2.4.5 Idle Timeout Of A Connection public void testReceiptOfFrame_preventsIdleTimeoutOccurring() { } /** "If the threshold is exceeded, then a peer SHOULD try to gracefully close the connection using a close frame with an error explaining why" */ public void testReceiptOfFrameTooLate_causedIdleTimeoutToOccur() { } /** "Each peer has its own (independent) idle timeout." */ public void testPeersWithDifferentIdleTimeouts_timeOutAtTheCorrectTimes() { } /** * "If the value is not set, then the sender does not have an idle time-out. However, * senders doing this SHOULD be aware that implementations MAY choose to use an internal default * to efficiently manage a peer's resources." */ public void testReceiptOfFrameWithZeroIdleTimeout_causesNoIdleFramesToBeSent() { } /** * "If a peer can not, for any reason support a proposed idle timeout, * then it SHOULD close the connection using a close frame with an error explaining why" */ public void testReceiptOfOpenWithUnsupportedTimeout_causesCloseWithError() { } /** * implementations ... MUST use channel 0 if a maximum channel number has not yet been negotiated * (i.e., before an open frame has been received) */ public void testReceiptOfEmptyFrameOnNonZeroChannelBeforeMaximumChannelsNegotiated_causesTODO() { } // 2.4.7 State transitions /** * The DISCARDING state is a variant of the CLOSE_SENT state where the close is triggered by an error. * In this case any incoming frames on the connection MUST be silently discarded until the peer's close frame is received */ public void testReceiptOfFrameWhenInDiscardingState_isIgnored() { } // 2.7.1 Open public void testReceiptOfOpen_containerCanBeRetrieved() { } /** * The spec says: * "If no hostname is provided the receiving peer SHOULD select a default based on its own configuration" * but Proton's Engine layer does not do any defaulting - this is the responsibility * of other layers e.g. Messenger or Driver. */ public void testReceiptOfOpenWithoutHostname_nullHostnameIsRetrieved() { } public void testReceiptOfOpenWithHostname_hostnameCanBeRetrieved() { } /** * "Both peers MUST accept frames of up to 512 (MIN-MAX-FRAME-SIZE) octets." */ public void testReceiptOfOpenWithMaximumFramesizeLowerThanMinMaxFrameSize_causesTODO() { } public void testInitiatingPeerAndReceivingPeerUseDifferentMaxFrameSizes() { } public void testReceiptOfSessionBeginThatBreaksChannelMax_causesTODO() { } public void testCreationOfSessionThatBreaksChannelMax_causesTODO() { } public void testOpenConnectionWithPeersUsingUnequalChannelMax_enforcesLowerOfTwoValues() { } public void testOpenConnectionWithOnePeerUsingUnsetChannelMax_enforcesTheSetValue() { } public void testReceiptOfBeginWithInUseChannelId_causesTODO() { } /** "If a session is locally initiated, the remote-channel MUST NOT be set." */ public void testReceiptOfUnsolicitedBeginWithChannelId_causesTODO() { } /** * "When an endpoint responds to a remotely initiated session, the remote-channel MUST be set * to the channel on which the remote session sent the begin." */ public void testThatBeginResponseContainsChannelId() { } /** * I imagine we will want to begin ChannelMax number of sessions, then end * a session from the 'middle'. Then check we are correctly begin a new * channel. */ public void testEnd_channelNumberAvailableForReuse() { } public void testReceiptOfOpenWithOutgoingLocales_outgoingLocalesCanBeRetrieved() { } /** "A null value or an empty list implies that only en-US is supported. " */ public void testReceiptOfOpenWithNullOutgoingLocales_defaultOutgoingLocaleCanBeRetrieved() { } /** "A null value or an empty list implies that only en-US is supported. " */ public void testReceiptOfOpenWithEmptyListOfOutgoingLocales_defaultOutgoingLocaleCanBeRetrieved() { } public void testReceiptOfOpenWithIncomingLocales_incomingLocalesCanBeRetrieved() { } /** "A null value or an empty list implies that only en-US is supported. " */ public void testReceiptOfOpenWithNullIncomingLocales_defaultIncomingLocaleCanBeRetrieved() { } /** "A null value or an empty list implies that only en-US is supported. " */ public void testReceiptOfOpenWithEmptyListOfIncomingLocales_defaultIncomingLocaleCanBeRetrieved() { } // TODO It seems that currently Proton-j merely exposes the remote capabilities to // the user and is seems to be a end-user responsibility to enforce "If the receiver of the // offered-capabilities requires an extension capability which is not present in the // offered-capability list then it MUST close the connection.". However, i wonder if this // is an omission -- surely Proton could valid that request desirable capabilities are // offered by the remote??? public void testReceiptOfOpenWithOfferedCapabilities_offeredCapabilitiesCanBeRetrieved() { } public void testReceiptOfOpenWithDesiredCapabilities_desiredCapabilitiesCanBeRetrieved() { } public void testReceiptOfOpenWithProperties_propertiesCanBeRetrieved() { } // Transport/Connection related api-inspired tests /** * TODO is there a limit on the number of connections? * Also try closing them in a different order to their creation. */ public void testCreateMultipleConnections() { } public void testBindTwoConnectionsToATransport_causesTODO() { } public void testBindAConnectionToTwoTransports_causesTODO() { } /** * TODO possibly try to bind this "opened" connection too if it doesn't go pop before this. */ public void testOpenBeforeBind_causesTODO() { } public void testOpenTwice_throwsExceptionTODO() { } public void testOpenAfterClose_throwsExceptionTODO() { } // Connection.java-related api-inspired tests /** * also test that the session appears in the connection's session list */ public void testCreateSession() { } public void testSessionHeadWhenNoSessionsExist_returnsNull() { } public void testSessionHead_returnsSessionsMatchingCriteria() { } public void testLinkHeadWhenNoLinksExist_returnsNull() { } public void testLinkHead_returnsLinksMatchingCriteria() { } public void testGetWorkHeadWhenNoWork_returnsNull() { } public void testGetWorkHeadWhenOneDeliveryIsPending_returnsTheDelivery() { } /** * use a name that is longer than the limit of AMQShortString */ public void testSetContainerWithLongName_isAllowed() { } public void testSetContainerWithNullName_throwsException() { } public void testSetContainerWithEmptyName_throwsException() { } public void testSetContainerAfterOpeningConnection_throwsExceptionTODO() { } public void testOpenWithoutContainerName_throwsExceptionTODO() { } public void testGetRemoteContainerBeforeOpen_returnsNull() { } public void testGetRemoteContainerBeforeReceiptOfOpen_returnsNull() { } public void testSetHostnameWithLongName_isAllowed() { } /** * Proton does not require the conventional foo.bar.com format for hostnames. */ public void testSetHostnameWithNonstandardName_isAllowed() { } public void testSetHostnameAfterOpeningConnection_throwsExceptionTODO() { } public void testSetOfferedCapabilitiesAfterOpeningConnection_throwsExceptionTODO() { } public void testSetDesiredCapabilitiesAfterOpeningConnection_throwsExceptionTODO() { } public void testSetPropertiesAfterOpeningConnection_throwsExceptionTODO() { } // Endpoint api-inspired tests public void testGetLocalStateBeforeOpen_returnsUninitialised() { } public void testGetLocalStateAfterClose_returnsClosed() { } public void testGetRemoteStateBeforeReceiptOfOpen_returnsUninitialised() { } public void testGetRemoteStateAfterReceiptOfClose_returnsClosed() { } public void testFree_isAllowed() { } public void testSetContext_contextCanBeRetrieved() { } public void testGetContextWithoutSettingContext_returnsNull() { } private void assertConnectionIsUsable() { Session clientSesion = _clientConnection.session(); clientSesion.open(); _pumper.pumpAll(); Session serverSession = _serverConnection.sessionHead(of(UNINITIALIZED), of(ACTIVE)); serverSession.open(); _pumper.pumpAll(); assertEnpointState(clientSesion, ACTIVE, ACTIVE); assertEnpointState(serverSession, ACTIVE, ACTIVE); } private void bindAndOpenConnections() { // TODO should we be checking local and remote error conditions as part of this? _clientConnection.setContainer(CLIENT_CONTAINER); _serverConnection.setContainer(SERVER_CONTAINER); assertEnpointState(_clientConnection, UNINITIALIZED, UNINITIALIZED); assertEnpointState(_serverConnection, UNINITIALIZED, UNINITIALIZED); _clientTransport.bind(_clientConnection); _serverTransport.bind(_serverConnection); _clientConnection.open(); assertEnpointState(_clientConnection, ACTIVE, UNINITIALIZED); assertEnpointState(_serverConnection, UNINITIALIZED, UNINITIALIZED); _pumper.pumpAll(); assertEnpointState(_clientConnection, ACTIVE, UNINITIALIZED); assertEnpointState(_serverConnection, UNINITIALIZED, ACTIVE); _serverConnection.open(); assertEnpointState(_clientConnection, ACTIVE, UNINITIALIZED); assertEnpointState(_serverConnection, ACTIVE, ACTIVE); _pumper.pumpAll(); assertEnpointState(_clientConnection, ACTIVE, ACTIVE); assertEnpointState(_serverConnection, ACTIVE, ACTIVE); } private void assertEnpointState(Endpoint endpoint, EndpointState localState, EndpointState remoteState) { assertEquals("Unexpected local state", localState, endpoint.getLocalState()); assertEquals("Unexpected remote state", remoteState, endpoint.getRemoteState()); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/TestLoggingHelper.java0000664000000000000000000000540012562450203030161 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests; import java.nio.ByteBuffer; import java.util.logging.Logger; /** * Provides functions for Proton tests to produce readable logging. * Uses terminal colours if system property {@value #PROTON_TEST_TERMINAL_COLOURS_PROPERTY} * is true */ public class TestLoggingHelper { public static final String PROTON_TEST_TERMINAL_COLOURS_PROPERTY = "proton.test.terminal.colours"; private static final String COLOUR_RESET; private static final String SERVER_COLOUR; private static final String CLIENT_COLOUR; private static final String BOLD; static { if(Boolean.getBoolean(PROTON_TEST_TERMINAL_COLOURS_PROPERTY)) { BOLD = "\033[1m"; SERVER_COLOUR = "\033[34m"; // blue CLIENT_COLOUR = "\033[32m"; // green COLOUR_RESET = "\033[0m"; } else { BOLD = SERVER_COLOUR = CLIENT_COLOUR = COLOUR_RESET = ""; } } public static final String CLIENT_PREFIX = CLIENT_COLOUR + "CLIENT" + COLOUR_RESET; public static final String SERVER_PREFIX = SERVER_COLOUR + "SERVER" + COLOUR_RESET; public static final String MESSAGE_PREFIX = "MESSAGE"; private final BinaryFormatter _binaryFormatter = new BinaryFormatter(); private Logger _logger; public TestLoggingHelper(Logger logger) { _logger = logger; } public void prettyPrint(String prefix, byte[] bytes) { _logger.fine(prefix + " " + bytes.length + " byte(s) " + _binaryFormatter.format(bytes)); } /** * Note that ByteBuffer is assumed to be readable. Its state is unchanged by this operation. */ public void prettyPrint(String prefix, ByteBuffer buf) { byte[] bytes = new byte[buf.remaining()]; buf.duplicate().get(bytes); prettyPrint(prefix, bytes); } public static String bold(String string) { return BOLD + string + TestLoggingHelper.COLOUR_RESET; } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/SimpleTest.java0000664000000000000000000000323512562450203026670 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests; import static org.junit.Assert.assertEquals; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Transport; import org.junit.Test; public class SimpleTest { @Test public void test() { Connection connection1 = Proton.connection(); Connection connection2 = Proton.connection();; Transport transport1 = Proton.transport(); transport1.bind(connection1); Transport transport2 = Proton.transport(); transport2.bind(connection2); assertEquals(EndpointState.UNINITIALIZED, connection1.getLocalState()); assertEquals(EndpointState.UNINITIALIZED, connection1.getRemoteState()); connection1.open(); connection2.open(); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/SaslTest.java0000664000000000000000000000676112562450203026350 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests; import static org.apache.qpid.proton.systemtests.TestLoggingHelper.bold; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import java.util.logging.Logger; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.engine.Sasl; import org.junit.Test; public class SaslTest extends EngineTestBase { private static final Logger LOGGER = Logger.getLogger(SaslTest.class.getName()); @Test public void testSaslHostnamePropagationAndRetrieval() throws Exception { LOGGER.fine(bold("======== About to create transports")); getClient().transport = Proton.transport(); ProtocolTracerEnabler.setProtocolTracer(getClient().transport, TestLoggingHelper.CLIENT_PREFIX); Sasl clientSasl = getClient().transport.sasl(); clientSasl.client(); // Set the server hostname we are connecting to from the client String hostname = "my-remote-host-123"; clientSasl.setRemoteHostname(hostname); // Verify we can't get the hostname on the client try { clientSasl.getHostname(); fail("should have throw IllegalStateException"); } catch (IllegalStateException ise) { // expected } getServer().transport = Proton.transport(); ProtocolTracerEnabler.setProtocolTracer(getServer().transport, " " + TestLoggingHelper.SERVER_PREFIX); // Configure the server to do ANONYMOUS Sasl serverSasl = getServer().transport.sasl(); serverSasl.server(); serverSasl.setMechanisms("ANONYMOUS"); // Verify we can't set the hostname on the server try { serverSasl.setRemoteHostname("some-other-host"); fail("should have throw IllegalStateException"); } catch (IllegalStateException ise) { // expected } assertNull(serverSasl.getHostname()); assertArrayEquals(new String[0], clientSasl.getRemoteMechanisms()); pumpClientToServer(); pumpServerToClient(); // Verify we got the mechs, set the chosen mech, and verify the // server still doesnt know the hostname set/requested by the client assertArrayEquals(new String[] {"ANONYMOUS"} , clientSasl.getRemoteMechanisms()); clientSasl.setMechanisms("ANONYMOUS"); assertNull(serverSasl.getHostname()); pumpClientToServer(); // Verify the server now knows that the client set the hostname field assertEquals(hostname, serverSasl.getHostname()); } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/ProtonEngineExampleTest.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/ProtonEngineExampleTest.j0000664000000000000000000003117612562450203030677 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests; import static java.util.EnumSet.of; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.apache.qpid.proton.engine.EndpointState.ACTIVE; import static org.apache.qpid.proton.engine.EndpointState.CLOSED; import static org.apache.qpid.proton.engine.EndpointState.UNINITIALIZED; import static org.apache.qpid.proton.systemtests.TestLoggingHelper.bold; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import java.util.Arrays; import java.util.logging.Logger; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.amqp.messaging.Accepted; import org.apache.qpid.proton.amqp.messaging.AmqpValue; import org.apache.qpid.proton.amqp.messaging.Section; import org.apache.qpid.proton.amqp.messaging.Source; import org.apache.qpid.proton.amqp.messaging.Target; import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode; import org.apache.qpid.proton.amqp.transport.SenderSettleMode; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.engine.Receiver; import org.apache.qpid.proton.message.Message; import org.junit.Test; /** * Simple example to illustrate the use of the Engine and Message APIs. * * Implemented as a JUnit test for convenience, although the main purpose is to educate the reader * rather than test the code. * * To see the protocol trace, add the following line to test/resources/logging.properties: * * org.apache.qpid.proton.logging.LoggingProtocolTracer.sent.level = ALL * * and to see the byte level trace, add the following: * * org.apache.qpid.proton.systemtests.ProtonEngineExampleTest.level = ALL * * Does not illustrate use of the Messenger API. */ public class ProtonEngineExampleTest extends EngineTestBase { private static final Logger LOGGER = Logger.getLogger(ProtonEngineExampleTest.class.getName()); private static final int BUFFER_SIZE = 4096; private final String _targetAddress = getServer().containerId + "-link1-target"; @Test public void test() throws Exception { LOGGER.fine(bold("======== About to create transports")); getClient().transport = Proton.transport(); ProtocolTracerEnabler.setProtocolTracer(getClient().transport, TestLoggingHelper.CLIENT_PREFIX); getServer().transport = Proton.transport(); ProtocolTracerEnabler.setProtocolTracer(getServer().transport, " " + TestLoggingHelper.SERVER_PREFIX); doOutputInputCycle(); getClient().connection = Proton.connection(); getClient().transport.bind(getClient().connection); getServer().connection = Proton.connection(); getServer().transport.bind(getServer().connection); LOGGER.fine(bold("======== About to open connections")); getClient().connection.open(); getServer().connection.open(); doOutputInputCycle(); LOGGER.fine(bold("======== About to open sessions")); getClient().session = getClient().connection.session(); getClient().session.open(); pumpClientToServer(); getServer().session = getServer().connection.sessionHead(of(UNINITIALIZED), of(ACTIVE)); assertEndpointState(getServer().session, UNINITIALIZED, ACTIVE); getServer().session.open(); assertEndpointState(getServer().session, ACTIVE, ACTIVE); pumpServerToClient(); assertEndpointState(getClient().session, ACTIVE, ACTIVE); LOGGER.fine(bold("======== About to create sender")); getClient().source = new Source(); getClient().source.setAddress(null); getClient().target = new Target(); getClient().target.setAddress(_targetAddress); getClient().sender = getClient().session.sender("link1"); getClient().sender.setTarget(getClient().target); getClient().sender.setSource(getClient().source); // Exactly once delivery semantics getClient().sender.setSenderSettleMode(SenderSettleMode.UNSETTLED); getClient().sender.setReceiverSettleMode(ReceiverSettleMode.SECOND); assertEndpointState(getClient().sender, UNINITIALIZED, UNINITIALIZED); getClient().sender.open(); assertEndpointState(getClient().sender, ACTIVE, UNINITIALIZED); pumpClientToServer(); LOGGER.fine(bold("======== About to set up implicitly created receiver")); // A real application would be interested in more states than simply ACTIVE, as there // exists the possibility that the link could have moved to another state already e.g. CLOSED. // (See pipelining). getServer().receiver = (Receiver) getServer().connection.linkHead(of(UNINITIALIZED), of(ACTIVE)); // Accept the settlement modes suggested by the client getServer().receiver.setSenderSettleMode(getServer().receiver.getRemoteSenderSettleMode()); getServer().receiver.setReceiverSettleMode(getServer().receiver.getRemoteReceiverSettleMode()); org.apache.qpid.proton.amqp.transport.Target serverRemoteTarget = getServer().receiver.getRemoteTarget(); assertTerminusEquals(getClient().target, serverRemoteTarget); getServer().receiver.setTarget(applicationDeriveTarget(serverRemoteTarget)); assertEndpointState(getServer().receiver, UNINITIALIZED, ACTIVE); getServer().receiver.open(); assertEndpointState(getServer().receiver, ACTIVE, ACTIVE); pumpServerToClient(); assertEndpointState(getClient().sender, ACTIVE, ACTIVE); getServer().receiver.flow(1); pumpServerToClient(); LOGGER.fine(bold("======== About to create a message and send it to the server")); getClient().message = Proton.message(); Section messageBody = new AmqpValue("Hello"); getClient().message.setBody(messageBody); getClient().messageData = new byte[BUFFER_SIZE]; int lengthOfEncodedMessage = getClient().message.encode(getClient().messageData, 0, BUFFER_SIZE); getTestLoggingHelper().prettyPrint(TestLoggingHelper.MESSAGE_PREFIX, Arrays.copyOf(getClient().messageData, lengthOfEncodedMessage)); byte[] deliveryTag = "delivery1".getBytes(); getClient().delivery = getClient().sender.delivery(deliveryTag); int numberOfBytesAcceptedBySender = getClient().sender.send(getClient().messageData, 0, lengthOfEncodedMessage); assertEquals("For simplicity, assume the sender can accept all the data", lengthOfEncodedMessage, numberOfBytesAcceptedBySender); assertNull(getClient().delivery.getLocalState()); boolean senderAdvanced = getClient().sender.advance(); assertTrue("sender has not advanced", senderAdvanced); pumpClientToServer(); LOGGER.fine(bold("======== About to process the message on the server")); getServer().delivery = getServer().connection.getWorkHead(); assertEquals("The received delivery should be on our receiver", getServer().receiver, getServer().delivery.getLink()); assertNull(getServer().delivery.getLocalState()); assertNull(getServer().delivery.getRemoteState()); assertFalse(getServer().delivery.isPartial()); assertTrue(getServer().delivery.isReadable()); getServer().messageData = new byte[BUFFER_SIZE]; int numberOfBytesProducedByReceiver = getServer().receiver.recv(getServer().messageData, 0, BUFFER_SIZE); assertEquals(numberOfBytesAcceptedBySender, numberOfBytesProducedByReceiver); getServer().message = Proton.message(); getServer().message.decode(getServer().messageData, 0, numberOfBytesProducedByReceiver); boolean messageProcessed = applicationProcessMessage(getServer().message); assertTrue(messageProcessed); getServer().delivery.disposition(Accepted.getInstance()); assertEquals(Accepted.getInstance(), getServer().delivery.getLocalState()); pumpServerToClient(); assertEquals(Accepted.getInstance(), getClient().delivery.getRemoteState()); LOGGER.fine(bold("======== About to accept and settle the message on the client")); Delivery clientDelivery = getClient().connection.getWorkHead(); assertEquals(getClient().delivery, clientDelivery); assertTrue(clientDelivery.isUpdated()); assertEquals(getClient().sender, clientDelivery.getLink()); clientDelivery.disposition(clientDelivery.getRemoteState()); assertEquals(Accepted.getInstance(), getClient().delivery.getLocalState()); clientDelivery.settle(); assertNull("Now we've settled, the delivery should no longer be in the work list", getClient().connection.getWorkHead()); pumpClientToServer(); LOGGER.fine(bold("======== About to settle the message on the server")); assertEquals(Accepted.getInstance(), getServer().delivery.getRemoteState()); Delivery serverDelivery = getServer().connection.getWorkHead(); assertEquals(getServer().delivery, serverDelivery); assertTrue(serverDelivery.isUpdated()); assertTrue("Client should have already settled", serverDelivery.remotelySettled()); serverDelivery.settle(); assertTrue(serverDelivery.isSettled()); assertNull("Now we've settled, the delivery should no longer be in the work list", getServer().connection.getWorkHead()); // Increment the receiver's credit so its ready for another message. // When using proton-c, this call is required in order to generate a Flow frame // (proton-j sends one even without it to eagerly restore the session incoming window). getServer().receiver.flow(1); pumpServerToClient(); LOGGER.fine(bold("======== About to close client's sender")); getClient().sender.close(); pumpClientToServer(); LOGGER.fine(bold("======== Server about to process client's link closure")); assertSame(getServer().receiver, getServer().connection.linkHead(of(ACTIVE), of(CLOSED))); getServer().receiver.close(); pumpServerToClient(); LOGGER.fine(bold("======== About to close client's session")); getClient().session.close(); pumpClientToServer(); LOGGER.fine(bold("======== Server about to process client's session closure")); assertSame(getServer().session, getServer().connection.sessionHead(of(ACTIVE), of(CLOSED))); getServer().session.close(); pumpServerToClient(); LOGGER.fine(bold("======== About to close client's connection")); getClient().connection.close(); pumpClientToServer(); LOGGER.fine(bold("======== Server about to process client's connection closure")); assertEquals(CLOSED, getServer().connection.getRemoteState()); getServer().connection.close(); pumpServerToClient(); LOGGER.fine(bold("======== Checking client has nothing more to pump")); assertClientHasNothingToOutput(); LOGGER.fine(bold("======== Done!")); } /** * Simulates creating a local terminus using the properties supplied by the remote link endpoint. * * In a broker you'd usually overlay serverRemoteTarget (eg its filter properties) onto * an existing object (which eg contains whether it's a queue or a topic), creating a new one from that * overlay. Also if this is link recovery then you'd fetch the unsettled map too. */ private org.apache.qpid.proton.amqp.transport.Target applicationDeriveTarget(org.apache.qpid.proton.amqp.transport.Target serverRemoteTarget) { return serverRemoteTarget; } /** * Simulates processing a message. */ private boolean applicationProcessMessage(Message message) { Object messageBody = ((AmqpValue)message.getBody()).getValue(); return "Hello".equals(messageBody); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/ProtonContainer.java0000664000000000000000000000331012562450203027715 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests; import org.apache.qpid.proton.amqp.messaging.Source; import org.apache.qpid.proton.amqp.messaging.Target; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.engine.Receiver; import org.apache.qpid.proton.engine.Sender; import org.apache.qpid.proton.engine.Session; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.message.Message; /** * Simple "struct" class used to hold related Engine objects */ public class ProtonContainer { String containerId; Connection connection; Transport transport; Session session; Sender sender; Receiver receiver; Source source; Target target; Delivery delivery; Message message; byte[] messageData; public ProtonContainer(String containerId) { this.containerId = containerId; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/ProtocolTracerEnabler.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/ProtocolTracerEnabler.jav0000664000000000000000000000536212562450203030674 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.logging.Logger; import org.apache.qpid.proton.engine.Transport; public class ProtocolTracerEnabler { private static final Logger LOGGER = Logger.getLogger(ProtocolTracerEnabler.class.getName()); private static final String LOGGING_PROTOCOL_TRACER_CLASS_NAME = "org.apache.qpid.proton.logging.LoggingProtocolTracer"; /** * Attempts to set up a {@value #LOGGING_PROTOCOL_TRACER_CLASS_NAME} on the supplied transport. * Uses reflection so this code can be run without a compile-time dependency on proton-j-impl. */ public static void setProtocolTracer(Transport transport, String prefix) { try { Class loggingProtocolTracerClass = Class.forName(LOGGING_PROTOCOL_TRACER_CLASS_NAME); Constructor loggingProtocolTracerConstructor = loggingProtocolTracerClass.getConstructor(String.class); Object newLoggingProtocolTracer = loggingProtocolTracerConstructor.newInstance(prefix); Class protocolTracerClass = Class.forName("org.apache.qpid.proton.engine.impl.ProtocolTracer"); Method setPrococolTracerMethod = transport.getClass().getMethod("setProtocolTracer", protocolTracerClass); setPrococolTracerMethod.invoke(transport, newLoggingProtocolTracer); } catch(Exception e) { if(e instanceof ClassNotFoundException || e instanceof NoSuchMethodException) { LOGGER.fine("Protocol tracing disabled because unable to reflectively set a " + LOGGING_PROTOCOL_TRACER_CLASS_NAME + " instance on the supplied transport which is a: " + transport.getClass().getName()); } else { throw new RuntimeException("Unable to set up protocol tracing", e); } } } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/FreeTest.java0000664000000000000000000002177712562450203026333 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests; import static java.util.EnumSet.of; import static org.apache.qpid.proton.engine.EndpointState.ACTIVE; import static org.apache.qpid.proton.engine.EndpointState.UNINITIALIZED; import static org.apache.qpid.proton.systemtests.TestLoggingHelper.bold; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import java.util.logging.Logger; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.amqp.messaging.Source; import org.apache.qpid.proton.amqp.messaging.Target; import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode; import org.apache.qpid.proton.amqp.transport.SenderSettleMode; import org.apache.qpid.proton.engine.Receiver; import org.apache.qpid.proton.engine.Sender; import org.apache.qpid.proton.engine.Session; import org.junit.Test; public class FreeTest extends EngineTestBase { private static final Logger LOGGER = Logger.getLogger(FreeTest.class.getName()); @Test public void testFreeConnectionWithMultipleSessionsAndSendersAndReceiversDoesNotThrowCME() throws Exception { LOGGER.fine(bold("======== About to create transports")); getClient().transport = Proton.transport(); ProtocolTracerEnabler.setProtocolTracer(getClient().transport, TestLoggingHelper.CLIENT_PREFIX); getServer().transport = Proton.transport(); ProtocolTracerEnabler.setProtocolTracer(getServer().transport, " " + TestLoggingHelper.SERVER_PREFIX); getClient().connection = Proton.connection(); getClient().transport.bind(getClient().connection); getServer().connection = Proton.connection(); getServer().transport.bind(getServer().connection); LOGGER.fine(bold("======== About to open connections")); getClient().connection.open(); getServer().connection.open(); doOutputInputCycle(); LOGGER.fine(bold("======== About to open sessions")); getClient().session = getClient().connection.session(); getClient().session.open(); Session clientSession2 = getClient().connection.session(); clientSession2.open(); pumpClientToServer(); getServer().session = getServer().connection.sessionHead(of(UNINITIALIZED), of(ACTIVE)); assertEndpointState(getServer().session, UNINITIALIZED, ACTIVE); getServer().session.open(); assertEndpointState(getServer().session, ACTIVE, ACTIVE); Session serverSession2 = getServer().connection.sessionHead(of(UNINITIALIZED), of(ACTIVE)); assertNotNull("Engine did not return expected second server session", serverSession2); assertNotSame("Engine did not return expected second server session", serverSession2, getServer().session); serverSession2.open(); pumpServerToClient(); assertEndpointState(getClient().session, ACTIVE, ACTIVE); assertEndpointState(clientSession2, ACTIVE, ACTIVE); LOGGER.fine(bold("======== About to create client senders")); getClient().source = new Source(); getClient().source.setAddress(null); getClient().target = new Target(); getClient().target.setAddress("myQueue"); getClient().sender = getClient().session.sender("sender1"); getClient().sender.setTarget(getClient().target); getClient().sender.setSource(getClient().source); getClient().sender.setSenderSettleMode(SenderSettleMode.UNSETTLED); getClient().sender.setReceiverSettleMode(ReceiverSettleMode.FIRST); assertEndpointState(getClient().sender, UNINITIALIZED, UNINITIALIZED); getClient().sender.open(); assertEndpointState(getClient().sender, ACTIVE, UNINITIALIZED); Sender clientSender2 = getClient().session.sender("sender2"); clientSender2.setTarget(getClient().target); clientSender2.setSource(getClient().source); clientSender2.setSenderSettleMode(SenderSettleMode.UNSETTLED); clientSender2.setReceiverSettleMode(ReceiverSettleMode.FIRST); assertEndpointState(clientSender2, UNINITIALIZED, UNINITIALIZED); clientSender2.open(); assertEndpointState(clientSender2, ACTIVE, UNINITIALIZED); pumpClientToServer(); LOGGER.fine(bold("======== About to set up server receivers")); getServer().receiver = (Receiver) getServer().connection.linkHead(of(UNINITIALIZED), of(ACTIVE)); // Accept the settlement modes suggested by the client getServer().receiver.setSenderSettleMode(getServer().receiver.getRemoteSenderSettleMode()); getServer().receiver.setReceiverSettleMode(getServer().receiver.getRemoteReceiverSettleMode()); org.apache.qpid.proton.amqp.transport.Target serverRemoteTarget = getServer().receiver.getRemoteTarget(); assertTerminusEquals(getClient().target, serverRemoteTarget); getServer().receiver.setTarget(serverRemoteTarget); assertEndpointState(getServer().receiver, UNINITIALIZED, ACTIVE); getServer().receiver.open(); assertEndpointState(getServer().receiver, ACTIVE, ACTIVE); Receiver serverReceiver2 = (Receiver) getServer().connection.linkHead(of(UNINITIALIZED), of(ACTIVE)); serverReceiver2.open(); assertEndpointState(serverReceiver2, ACTIVE, ACTIVE); pumpServerToClient(); assertEndpointState(getClient().sender, ACTIVE, ACTIVE); assertEndpointState(clientSender2, ACTIVE, ACTIVE); LOGGER.fine(bold("======== About to create client receivers")); Source src = new Source(); src.setAddress("myQueue"); Target tgt1 = new Target(); tgt1.setAddress("receiver1"); getClient().receiver = getClient().session.receiver("receiver1"); getClient().receiver.setSource(src); getClient().receiver.setTarget(tgt1); getClient().receiver.setSenderSettleMode(SenderSettleMode.UNSETTLED); getClient().receiver.setReceiverSettleMode(ReceiverSettleMode.FIRST); assertEndpointState(getClient().receiver, UNINITIALIZED, UNINITIALIZED); getClient().receiver.open(); assertEndpointState(getClient().receiver, ACTIVE, UNINITIALIZED); Target tgt2 = new Target(); tgt1.setAddress("receiver2"); Receiver clientReceiver2 = getClient().session.receiver("receiver2"); clientReceiver2.setSource(src); clientReceiver2.setTarget(tgt2); clientReceiver2.setSenderSettleMode(SenderSettleMode.UNSETTLED); clientReceiver2.setReceiverSettleMode(ReceiverSettleMode.FIRST); assertEndpointState(clientReceiver2, UNINITIALIZED, UNINITIALIZED); clientReceiver2.open(); assertEndpointState(clientReceiver2, ACTIVE, UNINITIALIZED); pumpClientToServer(); LOGGER.fine(bold("======== About to set up server senders")); getServer().sender = (Sender) getServer().connection.linkHead(of(UNINITIALIZED), of(ACTIVE)); // Accept the settlement modes suggested by the client getServer().sender.setSenderSettleMode(getServer().sender.getRemoteSenderSettleMode()); getServer().sender.setReceiverSettleMode(getServer().sender.getRemoteReceiverSettleMode()); org.apache.qpid.proton.amqp.transport.Target serverRemoteTarget2 = getServer().sender.getRemoteTarget(); assertTerminusEquals(tgt1, serverRemoteTarget2); getServer().sender.setTarget(serverRemoteTarget2); assertEndpointState(getServer().sender, UNINITIALIZED, ACTIVE); getServer().sender.open(); assertEndpointState(getServer().sender, ACTIVE, ACTIVE); Sender serverSender2 = (Sender) getServer().connection.linkHead(of(UNINITIALIZED), of(ACTIVE)); serverRemoteTarget2 = serverSender2.getRemoteTarget(); assertTerminusEquals(tgt2, serverRemoteTarget2); serverSender2.setTarget(serverRemoteTarget2); serverSender2.open(); assertEndpointState(serverSender2, ACTIVE, ACTIVE); pumpServerToClient(); assertEndpointState(getClient().receiver, ACTIVE, ACTIVE); assertEndpointState(clientReceiver2, ACTIVE, ACTIVE); LOGGER.fine(bold("======== About to close and free client's connection")); getClient().connection.close(); getClient().connection.free(); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/EngineTestBase.java0000664000000000000000000000763412562450203027446 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; import java.nio.ByteBuffer; import java.util.logging.Logger; import org.apache.qpid.proton.amqp.messaging.Target; import org.apache.qpid.proton.engine.Endpoint; import org.apache.qpid.proton.engine.EndpointState; public abstract class EngineTestBase { private static final Logger LOGGER = Logger.getLogger(EngineTestBase.class.getName()); private final TestLoggingHelper _testLoggingHelper = new TestLoggingHelper(LOGGER); private final ProtonContainer _client = new ProtonContainer("clientContainer"); private final ProtonContainer _server = new ProtonContainer("serverContainer"); protected TestLoggingHelper getTestLoggingHelper() { return _testLoggingHelper; } protected ProtonContainer getClient() { return _client; } protected ProtonContainer getServer() { return _server; } protected void assertClientHasNothingToOutput() { assertEquals(0, getClient().transport.getOutputBuffer().remaining()); getClient().transport.outputConsumed(); } protected void pumpServerToClient() { ByteBuffer serverBuffer = getServer().transport.getOutputBuffer(); getTestLoggingHelper().prettyPrint(" <<<" + TestLoggingHelper.SERVER_PREFIX + " ", serverBuffer); assertTrue("Server expected to produce some output", serverBuffer.hasRemaining()); ByteBuffer clientBuffer = getClient().transport.getInputBuffer(); clientBuffer.put(serverBuffer); assertEquals("Client expected to consume all server's output", 0, serverBuffer.remaining()); getClient().transport.processInput().checkIsOk(); getServer().transport.outputConsumed(); } protected void pumpClientToServer() { ByteBuffer clientBuffer = getClient().transport.getOutputBuffer(); getTestLoggingHelper().prettyPrint(TestLoggingHelper.CLIENT_PREFIX + ">>> ", clientBuffer); assertTrue("Client expected to produce some output", clientBuffer.hasRemaining()); ByteBuffer serverBuffer = getServer().transport.getInputBuffer(); serverBuffer.put(clientBuffer); assertEquals("Server expected to consume all client's output", 0, clientBuffer.remaining()); getClient().transport.outputConsumed(); getServer().transport.processInput().checkIsOk(); } protected void doOutputInputCycle() throws Exception { pumpClientToServer(); pumpServerToClient(); } protected void assertEndpointState(Endpoint endpoint, EndpointState localState, EndpointState remoteState) { assertEquals(localState, endpoint.getLocalState()); assertEquals(remoteState, endpoint.getRemoteState()); } protected void assertTerminusEquals(org.apache.qpid.proton.amqp.transport.Target expectedTarget, org.apache.qpid.proton.amqp.transport.Target actualTarget) { assertEquals( ((Target)expectedTarget).getAddress(), ((Target)actualTarget).getAddress()); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/DefaultDeliveryStateTest.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/DefaultDeliveryStateTest.0000664000000000000000000002624112562450203030670 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests; import static java.util.EnumSet.of; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.apache.qpid.proton.engine.EndpointState.ACTIVE; import static org.apache.qpid.proton.engine.EndpointState.CLOSED; import static org.apache.qpid.proton.engine.EndpointState.UNINITIALIZED; import static org.apache.qpid.proton.systemtests.TestLoggingHelper.bold; import static org.junit.Assert.assertNull; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.logging.Logger; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.amqp.messaging.Accepted; import org.apache.qpid.proton.amqp.messaging.AmqpValue; import org.apache.qpid.proton.amqp.messaging.Modified; import org.apache.qpid.proton.amqp.messaging.Released; import org.apache.qpid.proton.amqp.messaging.Source; import org.apache.qpid.proton.amqp.messaging.Target; import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode; import org.apache.qpid.proton.amqp.transport.SenderSettleMode; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.engine.Sender; import org.apache.qpid.proton.message.Message; import org.junit.Test; public class DefaultDeliveryStateTest extends EngineTestBase { private static final Logger LOGGER = Logger.getLogger(DefaultDeliveryStateTest.class.getName()); private static final int BUFFER_SIZE = 4096; private final String _sourceAddress = getServer().containerId + "-link1-source"; @Test public void testDefaultDeliveryState() throws Exception { LOGGER.fine(bold("======== About to create transports")); getClient().transport = Proton.transport(); ProtocolTracerEnabler.setProtocolTracer(getClient().transport, TestLoggingHelper.CLIENT_PREFIX); getServer().transport = Proton.transport(); ProtocolTracerEnabler.setProtocolTracer(getServer().transport, " " + TestLoggingHelper.SERVER_PREFIX); doOutputInputCycle(); getClient().connection = Proton.connection(); getClient().transport.bind(getClient().connection); getServer().connection = Proton.connection(); getServer().transport.bind(getServer().connection); LOGGER.fine(bold("======== About to open connections")); getClient().connection.open(); getServer().connection.open(); doOutputInputCycle(); LOGGER.fine(bold("======== About to open sessions")); getClient().session = getClient().connection.session(); getClient().session.open(); pumpClientToServer(); getServer().session = getServer().connection.sessionHead(of(UNINITIALIZED), of(ACTIVE)); assertEndpointState(getServer().session, UNINITIALIZED, ACTIVE); getServer().session.open(); assertEndpointState(getServer().session, ACTIVE, ACTIVE); pumpServerToClient(); assertEndpointState(getClient().session, ACTIVE, ACTIVE); LOGGER.fine(bold("======== About to create reciever")); getClient().source = new Source(); getClient().source.setAddress(_sourceAddress); getClient().target = new Target(); getClient().target.setAddress(null); getClient().receiver = getClient().session.receiver("link1"); getClient().receiver.setTarget(getClient().target); getClient().receiver.setSource(getClient().source); getClient().receiver.setReceiverSettleMode(ReceiverSettleMode.FIRST); getClient().receiver.setSenderSettleMode(SenderSettleMode.UNSETTLED); assertEndpointState(getClient().receiver, UNINITIALIZED, UNINITIALIZED); getClient().receiver.open(); assertEndpointState(getClient().receiver, ACTIVE, UNINITIALIZED); pumpClientToServer(); LOGGER.fine(bold("======== About to set up implicitly created sender")); getServer().sender = (Sender) getServer().connection.linkHead(of(UNINITIALIZED), of(ACTIVE)); getServer().sender.setReceiverSettleMode(getServer().sender.getRemoteReceiverSettleMode()); getServer().sender.setSenderSettleMode(getServer().sender.getRemoteSenderSettleMode()); org.apache.qpid.proton.amqp.transport.Source serverRemoteSource = getServer().sender.getRemoteSource(); getServer().sender.setSource(serverRemoteSource); assertEndpointState(getServer().sender, UNINITIALIZED, ACTIVE); getServer().sender.open(); assertEndpointState(getServer().sender, ACTIVE, ACTIVE); pumpServerToClient(); assertEndpointState(getClient().receiver, ACTIVE, ACTIVE); int messagCount = 3; getClient().receiver.flow(messagCount); pumpClientToServer(); LOGGER.fine(bold("======== About to create messages and send to the client")); Delivery serverDelivery1 = sendMessageToClient("delivery1", "Msg1"); Delivery serverDelivery2 = sendMessageToClient("delivery2", "Msg2"); Delivery serverDelivery3 = sendMessageToClient("delivery3", "Msg3"); pumpServerToClient(); assertNull(serverDelivery1.getLocalState()); assertNull(serverDelivery2.getLocalState()); assertNull(serverDelivery3.getLocalState()); assertNull(serverDelivery1.getRemoteState()); assertNull(serverDelivery2.getRemoteState()); assertNull(serverDelivery3.getRemoteState()); LOGGER.fine(bold("======== About to process the messages on the client")); Delivery clientDelivery1 = receiveMessageFromServer("delivery1", "Msg1"); Delivery clientDelivery2 = receiveMessageFromServer("delivery2", "Msg2"); Delivery clientDelivery3 = receiveMessageFromServer("delivery3", "Msg3"); // Give them some default state clientDelivery1.setDefaultDeliveryState(Released.getInstance()); clientDelivery2.setDefaultDeliveryState(Released.getInstance()); clientDelivery3.setDefaultDeliveryState(Released.getInstance()); assertEquals(Released.getInstance(), clientDelivery1.getDefaultDeliveryState()); assertEquals(Released.getInstance(), clientDelivery2.getDefaultDeliveryState()); assertEquals(Released.getInstance(), clientDelivery3.getDefaultDeliveryState()); // Check the default state doesn't influence the actual state assertNull(clientDelivery1.getLocalState()); assertNull(clientDelivery2.getLocalState()); assertNull(clientDelivery3.getLocalState()); assertNull(clientDelivery1.getRemoteState()); assertNull(clientDelivery2.getRemoteState()); assertNull(clientDelivery3.getRemoteState()); // Accept one for real, update default on another, leave last untouched clientDelivery1.disposition(Accepted.getInstance()); clientDelivery2.setDefaultDeliveryState(new Modified()); // Confirm default and actual states have or have not changed as expected assertEquals(Released.getInstance(), clientDelivery1.getDefaultDeliveryState()); assertTrue(clientDelivery2.getDefaultDeliveryState() instanceof Modified); assertEquals(Released.getInstance(), clientDelivery3.getDefaultDeliveryState()); assertEquals(Accepted.getInstance(), clientDelivery1.getLocalState()); assertNull(clientDelivery2.getLocalState()); assertNull(clientDelivery3.getLocalState()); // Verify the server gets intended state changes pumpClientToServer(); assertEquals(Accepted.getInstance(), serverDelivery1.getRemoteState()); assertNull(serverDelivery2.getRemoteState()); assertNull(serverDelivery3.getRemoteState()); // Confirm server sees the default states for second and third // messages when they get settled during link free getClient().receiver.close(); assertEndpointState(getClient().receiver, CLOSED, ACTIVE); pumpClientToServer(); assertEndpointState(getServer().sender, ACTIVE, CLOSED); getServer().sender.close(); assertEndpointState(getServer().sender, CLOSED, CLOSED); pumpServerToClient(); getClient().receiver.free(); assertEndpointState(getClient().receiver, CLOSED, CLOSED); pumpClientToServer(); assertEquals(Accepted.getInstance(), serverDelivery1.getRemoteState()); assertTrue(serverDelivery2.getRemoteState() instanceof Modified); assertEquals(Released.getInstance(), serverDelivery3.getRemoteState()); } private Delivery receiveMessageFromServer(String deliveryTag, String messageContent) { Delivery delivery = getClient().connection.getWorkHead(); assertTrue(Arrays.equals(deliveryTag.getBytes(StandardCharsets.UTF_8), delivery.getTag())); assertEquals("The received delivery should be on our receiver", getClient().receiver, delivery.getLink()); assertNull(delivery.getLocalState()); assertNull(delivery.getRemoteState()); assertFalse(delivery.isPartial()); assertTrue(delivery.isReadable()); byte[] received = new byte[BUFFER_SIZE]; int len = getClient().receiver.recv(received, 0, BUFFER_SIZE); assertTrue("given array was too small", len < BUFFER_SIZE); Message m = Proton.message(); m.decode(received, 0, len); Object messageBody = ((AmqpValue)m.getBody()).getValue(); assertEquals("Unexpected message content", messageContent, messageBody); boolean receiverAdvanced = getClient().receiver.advance(); assertTrue("receiver has not advanced", receiverAdvanced); return delivery; } private Delivery sendMessageToClient(String deliveryTag, String messageBody) { byte[] tag = deliveryTag.getBytes(StandardCharsets.UTF_8); Message m = Proton.message(); m.setBody(new AmqpValue(messageBody)); byte[] encoded = new byte[BUFFER_SIZE]; int len = m.encode(encoded, 0, BUFFER_SIZE); assertTrue("given array was too small", len < BUFFER_SIZE); Delivery serverDelivery = getServer().sender.delivery(tag); int sent = getServer().sender.send(encoded, 0, len); assertEquals("sender unable to send all data at once as assumed for simplicity", len, sent); boolean senderAdvanced = getServer().sender.advance(); assertTrue("sender has not advanced", senderAdvanced); return serverDelivery; } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/BinaryFormatterTest.java0000664000000000000000000000375412562450203030555 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests; import static org.junit.Assert.*; import org.junit.Test; public class BinaryFormatterTest { private BinaryFormatter _binaryFormatter = new BinaryFormatter(); @Test public void testSingleCharacter() { assertEquals("[ A ]", _binaryFormatter.format("A".getBytes())); } @Test public void testSingleSmallNonCharacter() { byte[] bytes = new byte[] { (byte)0x1 }; assertEquals("[x01]", _binaryFormatter.format(bytes)); } @Test public void testSingleLargeNonCharacter() { int numberToUse = 0xa2; byte byteToUse = (byte)numberToUse; byte[] bytes = new byte[] { byteToUse }; assertEquals("[xa2]", _binaryFormatter.format(bytes)); } @Test public void testComplex() { byte[] binaryData = new byte[4]; System.arraycopy("ABC".getBytes(), 0, binaryData, 0, 3); binaryData[3] = (byte)0xff; String formattedString = _binaryFormatter.format(binaryData); String expected = "[ A ][ B ][ C ][xff]"; assertEquals(expected, formattedString); } public void testFormatSubArray() { fail("TODO"); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/systemtests/BinaryFormatter.java0000664000000000000000000000305612562450203027710 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.systemtests; public class BinaryFormatter { public String format(byte[] binaryData) { StringBuilder stringBuilder = new StringBuilder(); for(int i = 0; i < binaryData.length; i++) { byte theByte = binaryData[i]; String formattedByte = formatByte(theByte); stringBuilder.append(formattedByte); } return stringBuilder.toString(); } private String formatByte(byte theByte) { final String retVal; if(Character.isLetterOrDigit(theByte)) { retVal = String.format("[ %c ]", theByte); } else { retVal = String.format("[x%02x]", theByte); } return retVal; } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/reactor/0000775000000000000000000000000012562450203022761 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/reactor/impl/0000775000000000000000000000000012562450203023722 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/reactor/impl/LeakTestReactor.java0000664000000000000000000001035412562450203027624 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; import java.io.IOException; import java.nio.channels.Pipe; import java.nio.channels.Pipe.SinkChannel; import java.nio.channels.Pipe.SourceChannel; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.HashMap; import java.util.Map.Entry; import junit.framework.AssertionFailedError; // Extends the Reactor to substitute a unit-test implementation of the // IO class. This detects, and reports, situations where the reactor code // fails to close one of the Java I/O related resources that it has created. public class LeakTestReactor extends ReactorImpl { private static class TestIO implements IO { private final HashMap resources = new HashMap(); @Override public Pipe pipe() throws IOException { Pipe pipe = Pipe.open(); resources.put(pipe.source(), new Exception()); resources.put(pipe.sink(), new Exception()); return pipe; } @Override public Selector selector() throws IOException { Selector selector = Selector.open(); resources.put(selector, new Exception()); return selector; } @Override public ServerSocketChannel serverSocketChannel() throws IOException { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); resources.put(serverSocketChannel, new Exception()); return serverSocketChannel; } @Override public SocketChannel socketChannel() throws IOException { SocketChannel socketChannel = SocketChannel.open(); resources.put(socketChannel, new Exception()); return socketChannel; } private boolean isOpen(Object resource) { if (resource instanceof SourceChannel) { return ((SourceChannel)resource).isOpen(); } else if (resource instanceof SinkChannel) { return ((SinkChannel)resource).isOpen(); } else if (resource instanceof Selector) { return ((Selector)resource).isOpen(); } else if (resource instanceof ServerSocketChannel) { return ((ServerSocketChannel)resource).isOpen(); } else if (resource instanceof SocketChannel) { return ((SocketChannel)resource).isOpen(); } else { throw new AssertionFailedError("Don't know how to check if this type is open: " + resource.getClass()); } } protected void assertNoLeaks() throws AssertionFailedError { boolean fail = false; for (Entry entry : resources.entrySet()) { if (isOpen(entry.getKey())) { System.out.println("Leaked an instance of '" + entry.getKey() + "' from:"); entry.getValue().printStackTrace(System.out); fail = true; } } if (fail) { throw new AssertionFailedError("Resources leaked"); } resources.clear(); } } private final TestIO testIO; public LeakTestReactor() throws IOException { super(new TestIO()); testIO = (TestIO)getIO(); } public void assertNoLeaks() throws AssertionFailedError { testIO.assertNoLeaks(); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/reactor/impl/AcceptorImplTest.java0000664000000000000000000000707612562450203030021 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; import java.io.IOException; import java.nio.channels.ServerSocketChannel; import org.apache.qpid.proton.reactor.ReactorChild; import org.apache.qpid.proton.reactor.Selectable.Callback; import org.junit.Test; import org.mockito.Mockito; public class AcceptorImplTest { /** * Tests that if ServerSocketChannel.accept() throws an IOException the Acceptor will * call Selectable.error() on it's underlying selector. * @throws IOException */ @Test public void acceptThrowsException() throws IOException { final Callback mockCallback = Mockito.mock(Callback.class); final SelectableImpl selectable = new SelectableImpl(); selectable.onError(mockCallback); ReactorImpl mockReactor = Mockito.mock(ReactorImpl.class); class MockIO extends IOImpl { @Override public ServerSocketChannel serverSocketChannel() throws IOException { ServerSocketChannel result = Mockito.mock(ServerSocketChannel.class); Mockito.when(result.accept()).thenThrow(new IOException()); return result; } } IO mockIO = new MockIO(); Mockito.when(mockReactor.getIO()).thenReturn(mockIO); Mockito.when(mockReactor.selectable(Mockito.any(ReactorChild.class))).thenReturn(selectable); new AcceptorImpl(mockReactor, "host", 1234, null); selectable.readable(); Mockito.verify(mockCallback).run(selectable); } /** * Tests that if ServerSocketChannel.accept() returns null the Acceptor will * throw a ReactorInternalException (because the acceptor's underlying selectable should * not have been marked as readable, if there is no connection to accept). * @throws IOException */ @Test(expected=ReactorInternalException.class) public void acceptReturnsNull() throws IOException { final Callback mockCallback = Mockito.mock(Callback.class); final SelectableImpl selectable = new SelectableImpl(); selectable.onError(mockCallback); ReactorImpl mockReactor = Mockito.mock(ReactorImpl.class); class MockIO extends IOImpl { @Override public ServerSocketChannel serverSocketChannel() throws IOException { ServerSocketChannel result = Mockito.mock(ServerSocketChannel.class); Mockito.when(result.accept()).thenReturn(null); return result; } } IO mockIO = new MockIO(); Mockito.when(mockReactor.getIO()).thenReturn(mockIO); Mockito.when(mockReactor.selectable(Mockito.any(ReactorChild.class))).thenReturn(selectable); new AcceptorImpl(mockReactor, "host", 1234, null); selectable.readable(); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/reactor/ReactorTest.java0000664000000000000000000005206412562450203026072 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.net.ServerSocket; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import junit.framework.AssertionFailedError; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.engine.BaseHandler; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.engine.Event; import org.apache.qpid.proton.engine.Event.Type; import org.apache.qpid.proton.engine.Handler; import org.apache.qpid.proton.engine.HandlerException; import org.apache.qpid.proton.engine.Sender; import org.apache.qpid.proton.engine.Session; import org.apache.qpid.proton.reactor.impl.AcceptorImpl; import org.apache.qpid.proton.reactor.impl.LeakTestReactor; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public class ReactorTest { public ReactorFactory reactorFactory; private Reactor reactor; private static interface ReactorFactory { Reactor newReactor() throws IOException; } // Parameterize the tests, and run them once with a reactor obtained by calling // 'Proton.reactor()' and once with the LeakTestReactor. @Parameters public static Collection data() throws IOException { ReactorFactory classicReactor = new ReactorFactory() { @Override public Reactor newReactor() throws IOException { return Proton.reactor(); } }; ReactorFactory newLeakDetection = new ReactorFactory() { @Override public Reactor newReactor() throws IOException { return new LeakTestReactor(); } }; return Arrays.asList(new ReactorFactory[][]{{classicReactor}, {newLeakDetection}}); } public ReactorTest(ReactorFactory reactorFactory) { this.reactorFactory = reactorFactory; } @Before public void before() throws IOException { reactor = reactorFactory.newReactor(); } private void checkForLeaks() { if (reactor instanceof LeakTestReactor) { ((LeakTestReactor)reactor).assertNoLeaks(); } } @After public void after() { checkForLeaks(); } /** * Tests that creating a reactor and running it: *
    *
  • Doesn't throw any exceptions.
  • *
  • Returns immediately from the run method (as there is no more work to do).
  • *
* @throws IOException */ @Test public void runEmpty() throws IOException { assertNotNull(reactor); reactor.run(); reactor.free(); } private static class TestHandler extends BaseHandler { private final ArrayList actual = new ArrayList(); @Override public void onUnhandled(Event event) { actual.add(event.getType()); } public void assertEvents(Type...expected) { assertArrayEquals(expected, actual.toArray()); } } /** * Tests adding a handler to a reactor and running the reactor. The * expected behaviour is for the reactor to return, and a number of reactor- * related events to have been delivered to the handler. * @throws IOException */ @Test public void handlerRun() throws IOException { Handler handler = reactor.getHandler(); assertNotNull(handler); TestHandler testHandler = new TestHandler(); handler.add(testHandler); reactor.run(); reactor.free(); testHandler.assertEvents(Type.REACTOR_INIT, Type.SELECTABLE_INIT, Type.SELECTABLE_UPDATED, Type.SELECTABLE_FINAL, Type.REACTOR_FINAL); } /** * Tests basic operation of the Reactor.connection method by creating a * connection from a reactor, then running the reactor. The expected behaviour * is for: *
    *
  • The reactor to end immediately.
  • *
  • The handler associated with the connection receives an init event.
  • *
  • The connection is one of the reactor's children.
  • *
* @throws IOException */ @Test public void connection() throws IOException { TestHandler connectionHandler = new TestHandler(); Connection connection = reactor.connection(connectionHandler); assertNotNull(connection); assertTrue("connection should be one of the reactor's children", reactor.children().contains(connection)); TestHandler reactorHandler = new TestHandler(); reactor.getHandler().add(reactorHandler); reactor.run(); reactor.free(); reactorHandler.assertEvents(Type.REACTOR_INIT, Type.SELECTABLE_INIT, Type.SELECTABLE_UPDATED, Type.SELECTABLE_FINAL, Type.REACTOR_FINAL); connectionHandler.assertEvents(Type.CONNECTION_INIT); } /** * Tests operation of the Reactor.acceptor method by creating an acceptor * which is immediately closed by the reactor. The expected behaviour is for: *
    *
  • The reactor to end immediately (as it has no more work to process).
  • *
  • The handler, associated with the acceptor, to receive no events.
  • *
  • For it's lifetime, the acceptor is one of the reactor's children.
  • *
* @throws IOException */ @Test public void acceptor() throws IOException { final Acceptor acceptor = reactor.acceptor("127.0.0.1", 0); assertNotNull(acceptor); assertTrue("acceptor should be one of the reactor's children", reactor.children().contains(acceptor)); TestHandler acceptorHandler = new TestHandler(); BaseHandler.setHandler(acceptor, acceptorHandler); reactor.getHandler().add(new BaseHandler() { @Override public void onReactorInit(Event event) { acceptor.close(); } }); reactor.run(); reactor.free(); acceptorHandler.assertEvents(); assertFalse("acceptor should have been removed from the reactor's children", reactor.children().contains(acceptor)); } private static class ServerHandler extends TestHandler { private Acceptor acceptor; public void setAcceptor(Acceptor acceptor) { this.acceptor = acceptor; } @Override public void onConnectionRemoteOpen(Event event) { super.onConnectionRemoteOpen(event); event.getConnection().open(); } @Override public void onConnectionRemoteClose(Event event) { super.onConnectionRemoteClose(event); acceptor.close(); event.getConnection().close(); event.getConnection().free(); } } /** * Tests end to end behaviour of the reactor by creating an acceptor and then * a connection (which connects to the port the acceptor is listening on). * As soon as the connection is established, both the acceptor and connection * are closed. The events generated by the acceptor and the connection are * compared to a set of expected events. * @throws IOException */ @Test public void connect() throws IOException { ServerHandler sh = new ServerHandler(); Acceptor acceptor = reactor.acceptor("127.0.0.1", 0, sh); final int listeningPort = ((AcceptorImpl)acceptor).getPortNumber(); sh.setAcceptor(acceptor); class ClientHandler extends TestHandler { @Override public void onConnectionInit(Event event) { super.onConnectionInit(event); event.getConnection().setHostname("127.0.0.1:" + listeningPort); event.getConnection().open(); } @Override public void onConnectionRemoteOpen(Event event) { super.onConnectionRemoteOpen(event); event.getConnection().close(); } @Override public void onConnectionRemoteClose(Event event) { super.onConnectionRemoteClose(event); event.getConnection().free(); } } ClientHandler ch = new ClientHandler(); Connection connection = reactor.connection(ch); assertTrue("acceptor should be one of the reactor's children", reactor.children().contains(acceptor)); assertTrue("connection should be one of the reactor's children", reactor.children().contains(connection)); reactor.run(); reactor.free(); assertFalse("acceptor should have been removed from the reactor's children", reactor.children().contains(acceptor)); assertFalse("connection should have been removed from the reactor's children", reactor.children().contains(connection)); sh.assertEvents(Type.CONNECTION_INIT, Type.CONNECTION_BOUND, // XXX: proton-c generates a PN_TRANSPORT event here Type.CONNECTION_REMOTE_OPEN, Type.CONNECTION_LOCAL_OPEN, Type.TRANSPORT, Type.CONNECTION_REMOTE_CLOSE, Type.TRANSPORT_TAIL_CLOSED, Type.CONNECTION_LOCAL_CLOSE, Type.TRANSPORT, Type.TRANSPORT_HEAD_CLOSED, Type.TRANSPORT_CLOSED, Type.CONNECTION_UNBOUND, Type.CONNECTION_FINAL); ch.assertEvents(Type.CONNECTION_INIT, Type.CONNECTION_LOCAL_OPEN, Type.CONNECTION_BOUND, // XXX: proton-c generates two PN_TRANSPORT events here Type.CONNECTION_REMOTE_OPEN, Type.CONNECTION_LOCAL_CLOSE, Type.TRANSPORT, Type.TRANSPORT_HEAD_CLOSED, Type.CONNECTION_REMOTE_CLOSE, Type.TRANSPORT_TAIL_CLOSED, Type.TRANSPORT_CLOSED, Type.CONNECTION_UNBOUND, Type.CONNECTION_FINAL); } private static class SinkHandler extends BaseHandler { protected int received = 0; @Override public void onDelivery(Event event) { Delivery dlv = event.getDelivery(); if (!dlv.isPartial()) { dlv.settle(); ++received; } } } private static class SourceHandler extends BaseHandler { private int remaining; private final int port; protected SourceHandler(int count, int port) { remaining = count; this.port = port; } @Override public void onConnectionInit(Event event) { Connection conn = event.getConnection(); conn.setHostname("127.0.0.1:" + port); Session ssn = conn.session(); Sender snd = ssn.sender("sender"); conn.open(); ssn.open(); snd.open(); } @Override public void onLinkFlow(Event event) { Sender link = (Sender)event.getLink(); while (link.getCredit() > 0 && remaining > 0) { Delivery dlv = link.delivery(new byte[0]); assertNotNull(dlv); dlv.settle(); link.advance(); --remaining; } if (remaining == 0) { event.getConnection().close(); } } @Override public void onConnectionRemoteClose(Event event) { event.getConnection().free(); } } private void transfer(int count, int window) throws IOException { reactor = reactorFactory.newReactor(); ServerHandler sh = new ServerHandler(); Acceptor acceptor = reactor.acceptor("127.0.0.1", 0, sh); sh.setAcceptor(acceptor); sh.add(new Handshaker()); // XXX: a window of 1 doesn't work unless the flowcontroller is // added after the thing that settles the delivery sh.add(new FlowController(window)); SinkHandler snk = new SinkHandler(); sh.add(snk); SourceHandler src = new SourceHandler(count, ((AcceptorImpl)acceptor).getPortNumber()); reactor.connection(src); reactor.run(); reactor.free(); assertEquals("Did not receive the expected number of messages", count, snk.received); checkForLeaks(); } @Test public void transfer_0to64_2() throws IOException { for (int i = 0; i < 64; ++i) { transfer(i, 2); } } @Test public void transfer_1024_64() throws IOException { transfer(1024, 64); } @Test public void transfer_4096_1024() throws IOException { transfer(4*1024, 1024); } @Test public void schedule() throws IOException { TestHandler reactorHandler = new TestHandler(); reactor.getHandler().add(reactorHandler); TestHandler taskHandler = new TestHandler(); reactor.schedule(0, taskHandler); reactor.run(); reactor.free(); reactorHandler.assertEvents(Type.REACTOR_INIT, Type.SELECTABLE_INIT, Type.SELECTABLE_UPDATED, Type.REACTOR_QUIESCED, Type.SELECTABLE_UPDATED, Type.SELECTABLE_FINAL, Type.REACTOR_FINAL); taskHandler.assertEvents(Type.TIMER_TASK); } private class BarfException extends RuntimeException { private static final long serialVersionUID = -5891140258375562884L; } private class BarfOnSomethingHandler extends BaseHandler { protected final BarfException exception; protected BarfOnSomethingHandler(BarfException exception) { this.exception = exception; } } private class BarfOnReactorInit extends BarfOnSomethingHandler { protected BarfOnReactorInit(BarfException exception) { super(exception); } @Override public void onReactorInit(Event e) { throw exception; } } private class BarfOnReactorFinal extends BarfOnSomethingHandler { protected BarfOnReactorFinal(BarfException exception) { super(exception); } @Override public void onReactorFinal(Event event) { throw exception; } } private class BarfOnConnectionInit extends BarfOnSomethingHandler { protected BarfOnConnectionInit(BarfException exception) { super(exception); } @Override public void onConnectionInit(Event e) { throw exception; } } private class BarfOnSessionInit extends BarfOnSomethingHandler { protected BarfOnSessionInit(BarfException exception) { super(exception); } @Override public void onSessionInit(Event e) { throw exception; } } private class BarfOnLinkInit extends BarfOnSomethingHandler { protected BarfOnLinkInit(BarfException exception) { super(exception); } @Override public void onLinkInit(Event e) { throw exception; } } private class BarfOnTask extends BarfOnSomethingHandler { protected BarfOnTask(BarfException exception) { super(exception); } @Override public void onTimerTask(Event e) { throw exception; } } private void assertReactorRunBarfsOnHandler(Reactor reactor, BarfException expectedException, Handler expectedHandler) { try { reactor.run(); throw new AssertionFailedError("Reactor.run() should have thrown an exception"); } catch(HandlerException handlerException) { assertSame("Linked exception does not match expected exception", expectedException, handlerException.getCause()); assertSame("Handler in exception does not match expected handler", expectedHandler, handlerException.getHandler()); } } @Test public void barfInReactorFinal() throws IOException { BarfException expectedBarf = new BarfException(); Handler expectedHandler = new BarfOnReactorFinal(expectedBarf); reactor.getGlobalHandler().add(expectedHandler); assertReactorRunBarfsOnHandler(reactor, expectedBarf, expectedHandler); reactor.free(); } @Test public void barfOnGlobalSet() throws IOException { BarfException expectedBarf = new BarfException(); Handler expectedHandler = new BarfOnReactorInit(expectedBarf); reactor.setGlobalHandler(expectedHandler); assertReactorRunBarfsOnHandler(reactor, expectedBarf, expectedHandler); reactor.free(); } @Test public void barfOnGlobalAdd() throws IOException { BarfException expectedBarf = new BarfException(); Handler expectedHandler = new BarfOnReactorInit(expectedBarf); reactor.getGlobalHandler().add(expectedHandler); assertReactorRunBarfsOnHandler(reactor, expectedBarf, expectedHandler); reactor.free(); } @Test public void barfOnReactorSet() throws IOException { BarfException expectedBarf = new BarfException(); Handler expectedHandler = new BarfOnReactorInit(expectedBarf); reactor.setHandler(expectedHandler); assertReactorRunBarfsOnHandler(reactor, expectedBarf, expectedHandler); reactor.free(); } @Test public void barfOnReactorAdd() throws IOException { BarfException expectedBarf = new BarfException(); Handler expectedHandler = new BarfOnReactorInit(expectedBarf); reactor.getHandler().add(expectedHandler); assertReactorRunBarfsOnHandler(reactor, expectedBarf, expectedHandler); reactor.free(); } @Test public void barfOnConnection() throws IOException { BarfException expectedBarf = new BarfException(); Handler expectedHandler = new BarfOnConnectionInit(expectedBarf); reactor.connection(expectedHandler); assertReactorRunBarfsOnHandler(reactor, expectedBarf, expectedHandler); reactor.free(); } @Test public void barfOnSession() throws IOException { BarfException expectedBarf = new BarfException(); Handler expectedHandler = new BarfOnSessionInit(expectedBarf); reactor.connection(expectedHandler).session(); assertReactorRunBarfsOnHandler(reactor, expectedBarf, expectedHandler); reactor.free(); } @Test public void barfOnLink() throws IOException { BarfException expectedBarf = new BarfException(); Handler expectedHandler = new BarfOnLinkInit(expectedBarf); reactor.connection(expectedHandler).session().sender("barf"); assertReactorRunBarfsOnHandler(reactor, expectedBarf, expectedHandler); reactor.free(); } @Test public void barfOnSchedule() throws IOException { BarfException expectedBarf = new BarfException(); Handler expectedHandler = new BarfOnTask(expectedBarf); reactor.schedule(0, expectedHandler); assertReactorRunBarfsOnHandler(reactor, expectedBarf, expectedHandler); reactor.free(); } @Test public void connectionRefused() throws IOException { final ServerSocket serverSocket = new ServerSocket(0, 0); class ConnectionHandler extends TestHandler { @Override public void onConnectionInit(Event event) { super.onConnectionInit(event); Connection connection = event.getConnection(); connection.setHostname("127.0.0.1:" + serverSocket.getLocalPort()); connection.open(); try { serverSocket.close(); } catch(IOException e) { AssertionFailedError afe = new AssertionFailedError(); afe.initCause(e); throw afe; } } } TestHandler connectionHandler = new ConnectionHandler(); reactor.connection(connectionHandler); reactor.run(); reactor.free(); serverSocket.close(); connectionHandler.assertEvents(Type.CONNECTION_INIT, Type.CONNECTION_LOCAL_OPEN, Type.CONNECTION_BOUND, Type.TRANSPORT_ERROR, Type.TRANSPORT_TAIL_CLOSED, Type.TRANSPORT_HEAD_CLOSED, Type.TRANSPORT_CLOSED, Type.CONNECTION_UNBOUND, Type.TRANSPORT); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/messenger/0000775000000000000000000000000012562450203023312 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/messenger/impl/0000775000000000000000000000000012562450203024253 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/messenger/impl/AddressTest.java0000664000000000000000000000774612562450203027361 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.qpid.proton.messenger.impl; import static org.junit.Assert.*; import org.junit.Test; public class AddressTest { private void testParse(String url, String scheme, String user, String pass, String host, String port, String name) { Address address = new Address(url); assertEquals(scheme, address.getScheme()); assertEquals(user, address.getUser()); assertEquals(pass, address.getPass()); assertEquals(host, address.getHost()); assertEquals(port, address.getPort()); assertEquals(url, address.toString()); } @Test public void addressTests() { testParse("host", null, null, null, "host", null, null); testParse("host:423", null, null, null, "host", "423", null); testParse("user@host", null, "user", null, "host", null, null); testParse("user:1243^&^:pw@host:423", null, "user", "1243^&^:pw", "host", "423", null); testParse("user:1243^&^:pw@host:423/Foo.bar:90087", null, "user", "1243^&^:pw", "host", "423", "Foo.bar:90087"); testParse("user:1243^&^:pw@host:423/Foo.bar:90087@somewhere", null, "user", "1243^&^:pw", "host", "423", "Foo.bar:90087@somewhere"); testParse("[::1]", null, null, null, "::1", null, null); testParse("[::1]:amqp", null, null, null, "::1", "amqp", null); testParse("user@[::1]", null, "user", null, "::1", null, null); testParse("user@[::1]:amqp", null, "user", null, "::1", "amqp", null); testParse("user:1243^&^:pw@[::1]:amqp", null, "user", "1243^&^:pw", "::1", "amqp", null); testParse("user:1243^&^:pw@[::1]:amqp/Foo.bar:90087", null, "user", "1243^&^:pw", "::1", "amqp", "Foo.bar:90087"); testParse("user:1243^&^:pw@[::1:amqp/Foo.bar:90087", null, "user", "1243^&^:pw", "[", ":1:amqp", "Foo.bar:90087"); testParse("user:1243^&^:pw@::1]:amqp/Foo.bar:90087", null, "user", "1243^&^:pw", "", ":1]:amqp", "Foo.bar:90087"); testParse("amqp://user@[::1]", "amqp", "user", null, "::1", null, null); testParse("amqp://user@[::1]:amqp", "amqp", "user", null, "::1", "amqp", null); testParse("amqp://user@[1234:52:0:1260:f2de:f1ff:fe59:8f87]:amqp", "amqp", "user", null, "1234:52:0:1260:f2de:f1ff:fe59:8f87", "amqp", null); testParse("amqp://user:1243^&^:pw@[::1]:amqp", "amqp", "user", "1243^&^:pw", "::1", "amqp", null); testParse("amqp://user:1243^&^:pw@[::1]:amqp/Foo.bar:90087", "amqp", "user", "1243^&^:pw", "::1", "amqp", "Foo.bar:90087"); testParse("amqp://host", "amqp", null, null, "host", null, null); testParse("amqp://user@host", "amqp", "user", null, "host", null, null); testParse("amqp://user@host/path:%", "amqp", "user", null, "host", null, "path:%"); testParse("amqp://user@host:5674/path:%", "amqp", "user", null, "host", "5674", "path:%"); testParse("amqp://user@host/path:%", "amqp", "user", null, "host", null, "path:%"); testParse("amqp://bigbird@host/queue@host", "amqp", "bigbird", null, "host", null, "queue@host"); testParse("amqp://host/queue@host", "amqp", null, null, "host", null, "queue@host"); testParse("amqp://host:9765/queue@host", "amqp", null, null, "host", "9765", "queue@host"); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/0000775000000000000000000000000012562450203022567 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/0000775000000000000000000000000012562450203023530 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/0000775000000000000000000000000012562450203024331 5ustar ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SslHandshakeSniffingTransportWrapperTest.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SslHandshakeSniffingT0000664000000000000000000001515112562450203030437 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import static org.apache.qpid.proton.engine.impl.TransportTestHelper.assertByteBufferContentEquals; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.nio.ByteBuffer; import org.apache.qpid.proton.engine.TransportException; import org.apache.qpid.proton.engine.impl.TransportWrapper; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; public class SslHandshakeSniffingTransportWrapperTest { private static final byte[] EXAMPLE_SSL_V3_HANDSHAKE_BYTES = new byte[] {0x16, 0x03, 0x02, 0x00, 0x31}; private static final byte[] EXAMPLE_SSL_V2_HANDSHAKE_BYTES = new byte[] {0x00, 0x00, 0x01, 0x03, 0x00}; private SslTransportWrapper _secureTransportWrapper = mock(SslTransportWrapper.class); private TransportWrapper _plainTransportWrapper = mock(TransportWrapper.class); private SslTransportWrapper _sniffingWrapper = new SslHandshakeSniffingTransportWrapper(_secureTransportWrapper, _plainTransportWrapper); @Rule public ExpectedException _expectedException = ExpectedException.none(); @Test public void testGetInputBufferGetOutputBufferWithNonSsl() { testInputAndOutput("INPUT".getBytes(), _plainTransportWrapper); } @Test public void testWithSSLv2() { testInputAndOutput(EXAMPLE_SSL_V2_HANDSHAKE_BYTES, _secureTransportWrapper); } @Test public void testWithSSLv3TLS() { testInputAndOutput(EXAMPLE_SSL_V3_HANDSHAKE_BYTES, _secureTransportWrapper); } private void testInputAndOutput(byte[] input, TransportWrapper transportThatShouldBeUsed) { byte[] output = "OUTPUT".getBytes(); ByteBuffer underlyingInputBuffer = ByteBuffer.allocate(1024); ByteBuffer underlyingOutputBuffer = ByteBuffer.wrap(output); // set up underlying transport when(transportThatShouldBeUsed.tail()).thenReturn(underlyingInputBuffer); when(transportThatShouldBeUsed.head()).thenReturn(underlyingOutputBuffer); // do input and verify underlying calls were made ByteBuffer inputBuffer = _sniffingWrapper.tail(); inputBuffer.put(input); _sniffingWrapper.process(); verify(transportThatShouldBeUsed).tail(); verify(transportThatShouldBeUsed).process(); // check the wrapped input actually received the expected bytes underlyingInputBuffer.flip(); assertByteBufferContentEquals(input, underlyingInputBuffer); // do output and check we get the correct transport's output ByteBuffer outputBuffer = _sniffingWrapper.head(); verify(transportThatShouldBeUsed).head(); assertByteBufferContentEquals(output, outputBuffer); int consumed = outputBuffer.position(); _sniffingWrapper.pop(consumed); verify(transportThatShouldBeUsed).pop(consumed); verifyZeroInteractionsWithOtherTransport(transportThatShouldBeUsed); } @Test public void testTooFewBytesToMakeDetermination() { byte[] sourceBuffer = new byte[] {0x00}; try { _sniffingWrapper.tail().put(sourceBuffer); _sniffingWrapper.close_tail(); _expectedException.expect(TransportException.class); _sniffingWrapper.process(); } finally { verifyZeroInteractions(_secureTransportWrapper, _plainTransportWrapper); } } @Test public void testGetSslAttributesWhenProtocolIsNotYetDetermined_returnNull() { assertEquals("Cipher name should be null", null, _sniffingWrapper.getCipherName()); assertEquals("Protocol name should be null", null, _sniffingWrapper.getProtocolName()); verifyZeroInteractions(_secureTransportWrapper, _plainTransportWrapper); } @Test public void testGetSslAttributesWhenUsingNonSsl_returnNull() { testGetSslAttributes("INPUT".getBytes(), _plainTransportWrapper, null, null); } /** * Tests {@link SslHandshakeSniffingTransportWrapper#getCipherName()} * and {@link SslHandshakeSniffingTransportWrapper#getProtocolName()}. */ @Test public void testGetSslAttributesWhenUsingSsl() { String cipherName = "testCipherName"; String protocolName = "testProtocolName"; when(_secureTransportWrapper.getCipherName()).thenReturn(cipherName); when(_secureTransportWrapper.getProtocolName()).thenReturn(protocolName); testGetSslAttributes(EXAMPLE_SSL_V2_HANDSHAKE_BYTES, _secureTransportWrapper, cipherName, protocolName); } private void testGetSslAttributes( byte[] input, TransportWrapper transportThatShouldBeUsed, String expectedCipherName, String expectedProtocolName) { ByteBuffer underlyingInputBuffer = ByteBuffer.allocate(1024); when(transportThatShouldBeUsed.tail()).thenReturn(underlyingInputBuffer); _sniffingWrapper.tail().put(input); _sniffingWrapper.process(); assertEquals(expectedCipherName, _sniffingWrapper.getCipherName()); assertEquals(expectedProtocolName, _sniffingWrapper.getProtocolName()); verifyZeroInteractionsWithOtherTransport(transportThatShouldBeUsed); } private void verifyZeroInteractionsWithOtherTransport(TransportWrapper transportThatShouldBeUsed) { final TransportWrapper transportThatShouldNotBeUsed; if(transportThatShouldBeUsed == _plainTransportWrapper) { transportThatShouldNotBeUsed = _secureTransportWrapper; } else { transportThatShouldNotBeUsed = _plainTransportWrapper; } verifyZeroInteractions(transportThatShouldNotBeUsed); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapperTest.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWra0000664000000000000000000001742612562450203030570 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import static org.apache.qpid.proton.engine.impl.ByteBufferUtils.pour; import static org.apache.qpid.proton.engine.impl.TransportTestHelper.assertByteBufferContentEquals; import static org.apache.qpid.proton.engine.impl.TransportTestHelper.pourBufferToString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.nio.ByteBuffer; import javax.net.ssl.SSLException; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; /** * TODO unit test handshaking * TODO unit test closing * TODO unit test graceful handling of SSLEngine.wrap throwing an SSLException */ public class SimpleSslTransportWrapperTest { private RememberingTransportInput _underlyingInput = new RememberingTransportInput(); private CannedTransportOutput _underlyingOutput = new CannedTransportOutput(); private SimpleSslTransportWrapper _sslWrapper; private CapitalisingDummySslEngine _dummySslEngine = new CapitalisingDummySslEngine(); @Rule public ExpectedException _expectedException = ExpectedException.none(); @Before public void setUp() { _sslWrapper = new SimpleSslTransportWrapper(_dummySslEngine, _underlyingInput, _underlyingOutput); } @Test public void testInputDecodesOnePacket() { String encodedBytes = "<-A->"; putBytesIntoTransport(encodedBytes); assertEquals("a_", _underlyingInput.getAcceptedInput()); } @Test public void testInputWithMultiplePackets() { String encodedBytes = "<-A-><-B-><-C-><>"; putBytesIntoTransport(encodedBytes); assertEquals("a_b_c_z_", _underlyingInput.getAcceptedInput()); } @Test public void testInputIncompletePacket_isNotPassedToUnderlyingInputUntilCompleted() { String incompleteEncodedBytes = "<-A-><-B-><-C"; // missing the trailing '>' to cause the underflow String remainingEncodedBytes = "-><-D->"; putBytesIntoTransport(incompleteEncodedBytes); assertEquals("a_b_", _underlyingInput.getAcceptedInput()); putBytesIntoTransport(remainingEncodedBytes); assertEquals("a_b_c_d_", _underlyingInput.getAcceptedInput()); } /** * As per {@link #testInputIncompletePacket_isNotPassedToUnderlyingInputUntilCompleted()} * but this time it takes TWO chunks to complete the "dangling" packet. */ @Test public void testInputIncompletePacketInThreeParts() { String firstEncodedBytes = "<-A-><-B-><-"; String secondEncodedBytes = "C"; // Sending this causes the impl to have to hold the data without producing more input yet String thirdEncodedBytes = "-><-D->"; putBytesIntoTransport(firstEncodedBytes); assertEquals("a_b_", _underlyingInput.getAcceptedInput()); putBytesIntoTransport(secondEncodedBytes); assertEquals("a_b_", _underlyingInput.getAcceptedInput()); putBytesIntoTransport(thirdEncodedBytes); assertEquals("a_b_c_d_", _underlyingInput.getAcceptedInput()); } @Test public void testUnderlyingInputUsingSmallBuffer_receivesAllDecodedInput() throws Exception { _underlyingInput.setInputBufferSize(1); putBytesIntoTransport("<-A->"); assertEquals("a_", _underlyingInput.getAcceptedInput()); } @Test public void testSslUnwrapThrowsException_returnsErrorResultAndRefusesFurtherInput() throws Exception { SSLException sslException = new SSLException("unwrap exception"); _dummySslEngine.rejectNextEncodedPacket(sslException); _sslWrapper.tail().put("<-A->".getBytes()); _sslWrapper.process(); assertEquals(_sslWrapper.capacity(), Transport.END_OF_STREAM); } @Test public void testUnderlyingInputReturnsErrorResult_returnsErrorResultAndRefusesFurtherInput() throws Exception { String underlyingErrorDescription = "dummy underlying error"; _underlyingInput.rejectNextInput(underlyingErrorDescription); _sslWrapper.tail().put("<-A->".getBytes()); try { _sslWrapper.process(); fail("no exception"); } catch (TransportException e) { assertEquals(underlyingErrorDescription, e.getMessage()); } } @Test public void testHeadIsReadOnly() { _underlyingOutput.setOutput(""); assertTrue(_sslWrapper.head().isReadOnly()); } @Test public void testOutputEncodesOnePacket() { _underlyingOutput.setOutput("a_"); ByteBuffer outputBuffer = _sslWrapper.head(); assertByteBufferContentEquals("<-A->".getBytes(), outputBuffer); } @Test public void testOutputEncodesMultiplePackets() { _underlyingOutput.setOutput("a_b_c_"); assertEquals("<-A-><-B-><-C->", getAllBytesFromTransport()); } @Test public void testOutputEncodesMultiplePacketsOfVaryingSize() { _underlyingOutput.setOutput("z_a_b_"); assertEquals("<><-A-><-B->", getAllBytesFromTransport()); } @Test public void testClientConsumesEncodedOutputInMultipleChunks() { _underlyingOutput.setOutput("a_b_"); { ByteBuffer buffer = _sslWrapper.head(); String output = pourBufferToString(buffer, 2); assertEquals("<-", output); _sslWrapper.pop(buffer.position()); } { ByteBuffer buffer = _sslWrapper.head(); String output = pourBufferToString(buffer, 3); assertEquals("A->", output); _sslWrapper.pop(buffer.position()); } assertEquals("<-B->", getAllBytesFromTransport()); } @Test public void testNoOutputToEncode() { _underlyingOutput.setOutput(""); assertFalse(_sslWrapper.head().hasRemaining()); } private void putBytesIntoTransport(String encodedBytes) { ByteBuffer byteBuffer = ByteBuffer.wrap(encodedBytes.getBytes()); while(byteBuffer.hasRemaining()) { int numberPoured = pour(byteBuffer, _sslWrapper.tail()); assertTrue("We should be able to pour some bytes into the input buffer", numberPoured > 0); _sslWrapper.process(); } } private String getAllBytesFromTransport() { StringBuilder readBytes = new StringBuilder(); while (true) { int pending = _sslWrapper.pending(); if (pending > 0) { ByteBuffer buffer = _sslWrapper.head(); readBytes.append(pourBufferToString(buffer)); _sslWrapper.pop(pending); continue; } else { break; } } return readBytes.toString(); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/RememberingTransportInput.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/RememberingTransportI0000664000000000000000000000471612562450203030546 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import java.nio.ByteBuffer; import org.apache.qpid.proton.engine.TransportException; import org.apache.qpid.proton.engine.impl.TransportInput; class RememberingTransportInput implements TransportInput { private StringBuilder _receivedInput = new StringBuilder(); private String _nextError; private int _inputBufferSize = 1024; private ByteBuffer _buffer = ByteBuffer.allocate(_inputBufferSize); String getAcceptedInput() { return _receivedInput.toString(); } @Override public String toString() { return "[RememberingTransportInput receivedInput (length " + _receivedInput.length() + ") is:" + _receivedInput.toString() + "]"; } @Override public int capacity() { return _buffer.remaining(); } @Override public int position() { return _buffer.position(); } @Override public ByteBuffer tail() { return _buffer; } @Override public void process() throws TransportException { if(_nextError != null) { throw new TransportException(_nextError); } _buffer.flip(); byte[] receivedInputBuffer = new byte[_buffer.remaining()]; _buffer.get(receivedInputBuffer); _buffer.compact(); _receivedInput.append(new String(receivedInputBuffer)); } @Override public void close_tail() { // do nothing } public void rejectNextInput(String nextError) { _nextError = nextError; } public void setInputBufferSize(int inputBufferSize) { _inputBufferSize = inputBufferSize; } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/CapitalisingDummySslEngine.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/CapitalisingDummySslE0000664000000000000000000002006612562450203030472 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.nio.ByteBuffer; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.Status; import javax.net.ssl.SSLException; /** * A simpler implementation of an SSLEngine that has predictable human-readable output, and that allows us to * easily trigger {@link Status#BUFFER_OVERFLOW} and {@link Status#BUFFER_UNDERFLOW}. * * Using a true SSLEngine for this would be impractical. */ public class CapitalisingDummySslEngine implements ProtonSslEngine { static final int SHORT_ENCODED_CHUNK_SIZE = 2; private static final int MAX_ENCODED_CHUNK_SIZE = 5; private static final char ENCODED_TEXT_BEGIN = '<'; private static final char ENCODED_TEXT_END = '>'; private static final char ENCODED_TEXT_INNER_CHAR = '-'; private static final int CLEAR_CHUNK_SIZE = 2; private static final char CLEARTEXT_PADDING = '_'; private SSLException _nextException; /** * Converts a_ to <-A->. z_ is special and encodes as <> (to give us packets of different lengths). * If dst is not sufficiently large ({@value #SHORT_ENCODED_CHUNK_SIZE} in our encoding), we return * {@link Status#BUFFER_OVERFLOW}, and the src and dst ByteBuffers are unchanged. */ @Override public SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException { int consumed = 0; int produced = 0; final Status resultStatus; if (src.remaining() >= CLEAR_CHUNK_SIZE) { src.mark(); char uncapitalisedChar = (char) src.get(); char underscore = (char) src.get(); validateClear(uncapitalisedChar, underscore); boolean useShortEncoding = uncapitalisedChar == 'z'; int encodingLength = useShortEncoding ? SHORT_ENCODED_CHUNK_SIZE : MAX_ENCODED_CHUNK_SIZE; boolean overflow = dst.remaining() < encodingLength; if (overflow) { src.reset(); resultStatus = Status.BUFFER_OVERFLOW; } else { consumed = CLEAR_CHUNK_SIZE; char capitalisedChar = Character.toUpperCase(uncapitalisedChar); dst.put((byte)ENCODED_TEXT_BEGIN); if (!useShortEncoding) { dst.put((byte)ENCODED_TEXT_INNER_CHAR); dst.put((byte)capitalisedChar); dst.put((byte)ENCODED_TEXT_INNER_CHAR); } dst.put((byte)ENCODED_TEXT_END); produced = encodingLength; resultStatus = Status.OK; } } else { resultStatus = Status.OK; } return new SSLEngineResult(resultStatus, HandshakeStatus.NOT_HANDSHAKING, consumed, produced); } /** * Converts <-A-><-B-><-C-> to a_. <> is special and decodes as z_ * Input such as "= SHORT_ENCODED_CHUNK_SIZE) { src.mark(); char begin = (char)src.get(); char nextChar = (char)src.get(); // Could be - or > final int readSoFar = 2; final char capitalisedChar; if (nextChar != ENCODED_TEXT_END) { int remainingBytesForMaxLengthPacket = MAX_ENCODED_CHUNK_SIZE - readSoFar; if (src.remaining() < remainingBytesForMaxLengthPacket ) { src.reset(); resultStatus = Status.BUFFER_UNDERFLOW; return new SSLEngineResult(resultStatus, HandshakeStatus.NOT_HANDSHAKING, 0, 0); } else { char beginInner = nextChar; capitalisedChar = (char)src.get(); char endInner = (char)src.get(); char end = (char)src.get(); consumed = MAX_ENCODED_CHUNK_SIZE; validateEncoded(begin, beginInner, capitalisedChar, endInner, end); } } else { assertEquals("Unexpected begin", Character.toString(ENCODED_TEXT_BEGIN), Character.toString(begin)); capitalisedChar = 'Z'; consumed = SHORT_ENCODED_CHUNK_SIZE;; } char lowerCaseChar = Character.toLowerCase(capitalisedChar); dst.put((byte)lowerCaseChar); dst.put((byte)CLEARTEXT_PADDING); produced = CLEAR_CHUNK_SIZE; resultStatus = Status.OK; } else { resultStatus = Status.BUFFER_UNDERFLOW; consumed = 0; produced = 0; } return new SSLEngineResult(resultStatus, HandshakeStatus.NOT_HANDSHAKING, consumed, produced); } @Override public int getEffectiveApplicationBufferSize() { return getApplicationBufferSize(); } private int getApplicationBufferSize() { return CLEAR_CHUNK_SIZE; } @Override public int getPacketBufferSize() { return MAX_ENCODED_CHUNK_SIZE; } @Override public String getProtocol() { throw new UnsupportedOperationException(); } @Override public HandshakeStatus getHandshakeStatus() { throw new UnsupportedOperationException(); } @Override public Runnable getDelegatedTask() { throw new UnsupportedOperationException(); } @Override public String getCipherSuite() { throw new UnsupportedOperationException(); } private void validateEncoded(char begin, char beginInner, char capitalisedChar, char endInner, char end) { assertEquals("Unexpected begin", Character.toString(ENCODED_TEXT_BEGIN), Character.toString(begin)); assertEquals("Unexpected begin inner", Character.toString(ENCODED_TEXT_INNER_CHAR), Character.toString(beginInner)); assertEquals("Unexpected end inner", Character.toString(ENCODED_TEXT_INNER_CHAR), Character.toString(endInner)); assertEquals("Unexpected end", Character.toString(ENCODED_TEXT_END), Character.toString(end)); assertTrue("Encoded character " + capitalisedChar + " must be capital", Character.isUpperCase(capitalisedChar)); } private void validateClear(char uncapitalisedChar, char underscore) { assertTrue("Clear text character " + uncapitalisedChar + " must be lowercase", Character.isLowerCase(uncapitalisedChar)); assertEquals("Unexpected clear text pad", Character.toString(CLEARTEXT_PADDING), Character.toString(underscore)); } @Override public boolean getUseClientMode() { return true; } public void rejectNextEncodedPacket(SSLException nextException) { _nextException = nextException; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/CannedTransportOutput.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/ssl/CannedTransportOutput0000664000000000000000000000340212562450203030601 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import java.nio.ByteBuffer; import org.apache.qpid.proton.engine.impl.TransportOutput; public class CannedTransportOutput implements TransportOutput { private ByteBuffer _cannedOutput; private ByteBuffer _head; private int _popped; public CannedTransportOutput() { } public CannedTransportOutput(String output) { setOutput(output); } public void setOutput(String output) { _cannedOutput = ByteBuffer.wrap(output.getBytes()); _head = _cannedOutput.asReadOnlyBuffer(); _popped = 0; } @Override public int pending() { return _head.remaining(); } @Override public ByteBuffer head() { return _head; } @Override public void pop(int bytes) { _popped += bytes; _head.position(_popped); } @Override public void close_head() { // do nothing } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportTestHelper.java0000664000000000000000000000420212562450203030365 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine.impl; import static org.junit.Assert.assertEquals; import java.nio.ByteBuffer; public class TransportTestHelper { public static void assertByteArrayContentEquals(byte[] expectedBytes, byte[] actualBytes) { assertEquals(new String(expectedBytes), new String(actualBytes)); } public static void assertByteBufferContentEquals(byte[] expectedBytes, ByteBuffer actualByteBuffer) { ByteBuffer myByteBuffer = actualByteBuffer.duplicate(); byte[] actualBytes = new byte[myByteBuffer.remaining()]; myByteBuffer.get(actualBytes); assertByteArrayContentEquals(expectedBytes, actualBytes); } public static String pourBufferToString(ByteBuffer source) { return pourBufferToString(source, source.remaining()); } public static String pourBufferToString(ByteBuffer source, int sizeRequested) { byte[] buf = new byte[sizeRequested]; int numberRead = ByteBufferUtils.pourBufferToArray(source, buf, 0, sizeRequested); return new String(buf, 0, numberRead); } public static String stringOfLength(String value, int repeat) { StringBuilder builder = new StringBuilder(); for(int i = 0 ; i < repeat; i++) { builder.append(value); } return builder.toString(); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportOutputAdaptorTest.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportOutputAdaptorTes0000664000000000000000000001254212562450203030663 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine.impl; import static java.util.Arrays.copyOfRange; import static org.apache.qpid.proton.engine.impl.TransportTestHelper.assertByteArrayContentEquals; import static org.apache.qpid.proton.engine.impl.TransportTestHelper.assertByteBufferContentEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.apache.qpid.proton.engine.TransportException; import java.nio.ByteBuffer; import org.junit.Test; public class TransportOutputAdaptorTest { private final CannedTransportOutputWriter _transportOutputWriter = new CannedTransportOutputWriter(); private final TransportOutput _transportOutput = new TransportOutputAdaptor(_transportOutputWriter, 1024); @Test public void testThatOutputBufferIsReadOnly() { assertTrue(_transportOutput.head().isReadOnly()); } @Test public void testGetOutputBuffer_containsCorrectBytes() { byte[] testBytes = "testbytes".getBytes(); _transportOutputWriter.setNextCannedOutput(testBytes); assertEquals(testBytes.length, _transportOutput.pending()); final ByteBuffer outputBuffer = _transportOutput.head(); assertEquals(testBytes.length, outputBuffer.remaining()); byte[] outputBytes = new byte[testBytes.length]; outputBuffer.get(outputBytes); assertByteArrayContentEquals(testBytes, outputBytes); _transportOutput.pop(outputBuffer.position()); final ByteBuffer outputBuffer2 = _transportOutput.head(); assertEquals(0, outputBuffer2.remaining()); } @Test public void testClientConsumesOutputInMultipleChunks() { byte[] testBytes = "testbytes".getBytes(); _transportOutputWriter.setNextCannedOutput(testBytes); // sip the first two bytes into a small byte array int chunk1Size = 2; int chunk2Size = testBytes.length - chunk1Size; { final ByteBuffer outputBuffer1 = _transportOutput.head(); byte[] byteArray1 = new byte[chunk1Size]; outputBuffer1.get(byteArray1); assertEquals(chunk2Size, outputBuffer1.remaining()); assertByteArrayContentEquals(copyOfRange(testBytes, 0, chunk1Size), byteArray1); _transportOutput.pop(outputBuffer1.position()); } { final ByteBuffer outputBuffer2 = _transportOutput.head(); int chunk2Offset = chunk1Size; assertByteBufferContentEquals(copyOfRange(testBytes, chunk2Offset, testBytes.length), outputBuffer2); } } @Test public void testClientConsumesOutputInMultipleChunksWithAdditionalTransportWriterOutput() { byte[] initialBytes = "abcd".getBytes(); _transportOutputWriter.setNextCannedOutput(initialBytes); // sip the first two bytes into a small byte array int chunk1Size = 2; int initialRemaining = initialBytes.length - chunk1Size; { final ByteBuffer outputBuffer1 = _transportOutput.head(); byte[] byteArray1 = new byte[chunk1Size]; outputBuffer1.get(byteArray1); assertEquals(initialRemaining, outputBuffer1.remaining()); assertByteArrayContentEquals(copyOfRange(initialBytes, 0, chunk1Size), byteArray1); _transportOutput.pop(outputBuffer1.position()); } byte[] additionalBytes = "wxyz".getBytes(); _transportOutputWriter.setNextCannedOutput(additionalBytes); { final ByteBuffer outputBuffer2 = _transportOutput.head(); byte[] expectedBytes = "cdwxyz".getBytes(); assertByteBufferContentEquals(expectedBytes, outputBuffer2); } } private static final class CannedTransportOutputWriter implements TransportOutputWriter { byte[] _cannedOutput = new byte[0]; @Override public boolean writeInto(ByteBuffer outputBuffer) { int bytesWritten = ByteBufferUtils.pourArrayToBuffer(_cannedOutput, 0, _cannedOutput.length, outputBuffer); if(bytesWritten < _cannedOutput.length) { fail("Unable to write all " + _cannedOutput.length + " bytes of my canned output to the provided output buffer: " + outputBuffer); } _cannedOutput = new byte[0]; return false; } void setNextCannedOutput(byte[] cannedOutput) { _cannedOutput = cannedOutput; } public void closed(TransportException error) { // do nothing } } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportImplTest.java0000664000000000000000000003037412562450203030060 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import static org.apache.qpid.proton.engine.impl.AmqpHeader.HEADER; import static org.apache.qpid.proton.engine.impl.TransportTestHelper.stringOfLength; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.nio.ByteBuffer; import java.util.LinkedList; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.transport.Attach; import org.apache.qpid.proton.amqp.transport.Begin; import org.apache.qpid.proton.amqp.transport.FrameBody; import org.apache.qpid.proton.amqp.transport.Open; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; import org.apache.qpid.proton.framing.TransportFrame; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; public class TransportImplTest { @SuppressWarnings("deprecation") private TransportImpl _transport = new TransportImpl(); private static final int CHANNEL_ID = 1; private static final TransportFrame TRANSPORT_FRAME_BEGIN = new TransportFrame(CHANNEL_ID, new Begin(), null); private static final TransportFrame TRANSPORT_FRAME_OPEN = new TransportFrame(CHANNEL_ID, new Open(), null); @Rule public ExpectedException _expectedException = ExpectedException.none(); @Test public void testInput() { ByteBuffer buffer = _transport.getInputBuffer(); buffer.put(HEADER); _transport.processInput().checkIsOk(); assertNotNull(_transport.getInputBuffer()); } @Test public void testInitialProcessIsNoop() { _transport.process(); } @Test public void testProcessIsIdempotent() { _transport.process(); _transport.process(); } /** * Empty input is always allowed by {@link Transport#getInputBuffer()} and * {@link Transport#processInput()}, in contrast to the old API. * * @see TransportImplTest#testEmptyInputBeforeBindUsingOldApi_causesTransportException() */ @Test public void testEmptyInput_isAllowed() { _transport.getInputBuffer(); _transport.processInput().checkIsOk(); } /** * Tests the end-of-stream behaviour specified by {@link Transport#input(byte[], int, int)}. */ @Test public void testEmptyInputBeforeBindUsingOldApi_causesTransportException() { _expectedException.expect(TransportException.class); _expectedException.expectMessage("Unexpected EOS when remote connection not closed: connection aborted"); _transport.input(new byte [0], 0, 0); } /** * TODO it's not clear why empty input is specifically allowed in this case. */ @Test public void testEmptyInputWhenRemoteConnectionIsClosedUsingOldApi_isAllowed() { @SuppressWarnings("deprecation") ConnectionImpl connection = new ConnectionImpl(); _transport.bind(connection); connection.setRemoteState(EndpointState.CLOSED); _transport.input(new byte [0], 0, 0); } @Test public void testOutupt() { { // TransportImpl's underlying output spontaneously outputs the AMQP header final ByteBuffer outputBuffer = _transport.getOutputBuffer(); assertEquals(HEADER.length, outputBuffer.remaining()); byte[] outputBytes = new byte[HEADER.length]; outputBuffer.get(outputBytes); assertArrayEquals(HEADER, outputBytes); _transport.outputConsumed(); } { final ByteBuffer outputBuffer = _transport.getOutputBuffer(); assertEquals(0, outputBuffer.remaining()); _transport.outputConsumed(); } } @Test public void testTransportInitiallyHandlesFrames() { assertTrue(_transport.isHandlingFrames()); } @Test public void testBoundTransport_continuesToHandleFrames() { @SuppressWarnings("deprecation") Connection connection = new ConnectionImpl(); assertTrue(_transport.isHandlingFrames()); _transport.bind(connection); assertTrue(_transport.isHandlingFrames()); _transport.handleFrame(TRANSPORT_FRAME_OPEN); assertTrue(_transport.isHandlingFrames()); } @Test public void testUnboundTransport_stopsHandlingFrames() { assertTrue(_transport.isHandlingFrames()); _transport.handleFrame(TRANSPORT_FRAME_OPEN); assertFalse(_transport.isHandlingFrames()); } @Test public void testHandleFrameWhenNotHandling_throwsIllegalStateException() { assertTrue(_transport.isHandlingFrames()); _transport.handleFrame(TRANSPORT_FRAME_OPEN); assertFalse(_transport.isHandlingFrames()); _expectedException.expect(IllegalStateException.class); _transport.handleFrame(TRANSPORT_FRAME_BEGIN); } @Test public void testOutputTooBigToBeWrittenInOneGo() { int smallMaxFrameSize = 512; _transport = new TransportImpl(smallMaxFrameSize); @SuppressWarnings("deprecation") Connection conn = new ConnectionImpl(); _transport.bind(conn); // Open frame sized in order to produce a frame that will almost fill output buffer conn.setHostname(stringOfLength("x", 500)); conn.open(); // Close the connection to generate a Close frame which will cause an overflow // internally - we'll get the remaining bytes on the next interaction. conn.close(); ByteBuffer buf = _transport.getOutputBuffer(); assertEquals("Expecting buffer to be full", smallMaxFrameSize, buf.remaining()); buf.position(buf.limit()); _transport.outputConsumed(); buf = _transport.getOutputBuffer(); assertTrue("Expecting second buffer to have bytes", buf.remaining() > 0); assertTrue("Expecting second buffer to not be full", buf.remaining() < Transport.MIN_MAX_FRAME_SIZE); } @Test public void testAttemptToInitiateSaslAfterProcessingBeginsCausesIllegalStateException() { _transport.process(); try { _transport.sasl(); } catch(IllegalStateException ise) { //expected, sasl must be initiated before processing begins } } private class MockTransportImpl extends TransportImpl { LinkedList writes = new LinkedList(); @Override protected void writeFrame(int channel, FrameBody frameBody, ByteBuffer payload, Runnable onPayloadTooLarge) { super.writeFrame(channel, frameBody, payload, onPayloadTooLarge); writes.addLast(frameBody); } } @Test public void testTickRemoteTimeout() { MockTransportImpl transport = new MockTransportImpl(); Connection connection = Proton.connection(); transport.bind(connection); int timeout = 4000; Open open = new Open(); open.setIdleTimeOut(new UnsignedInteger(4000)); TransportFrame openFrame = new TransportFrame(CHANNEL_ID, open, null); transport.handleFrame(openFrame); while(transport.pending() > 0) transport.pop(transport.head().remaining()); long deadline = transport.tick(0); assertEquals("Expected to be returned a deadline of 2000", 2000, deadline); // deadline = 4000 / 2 deadline = transport.tick(1000); // Wait for less than the deadline with no data - get the same value assertEquals("When the deadline hasn't been reached tick() should return the previous deadline", 2000, deadline); assertEquals("When the deadline hasn't been reached tick() shouldn't write data", 0, transport.writes.size()); deadline = transport.tick(timeout/2); // Wait for the deadline - next deadline should be (4000/2)*2 assertEquals("When the deadline has been reached expected a new deadline to be returned 4000", 4000, deadline); assertEquals("tick() should have written data", 1, transport.writes.size()); assertEquals("tick() should have written an empty frame", null, transport.writes.get(0)); transport.writeFrame(CHANNEL_ID, new Begin(), null, null); while(transport.pending() > 0) transport.pop(transport.head().remaining()); int framesWrittenBeforeTick = transport.writes.size(); deadline = transport.tick(3000); assertEquals("Writing data resets the deadline", 5000, deadline); assertEquals("When the deadline is reset tick() shouldn't write an empty frame", 0, transport.writes.size() - framesWrittenBeforeTick); transport.writeFrame(CHANNEL_ID, new Attach(), null, null); assertTrue(transport.pending() > 0); framesWrittenBeforeTick = transport.writes.size(); deadline = transport.tick(4000); assertEquals("Having pending data does not reset the deadline", 5000, deadline); assertEquals("Having pending data prevents tick() from sending an empty frame", 0, transport.writes.size() - framesWrittenBeforeTick); } @Test public void testTickLocalTimeout() { MockTransportImpl transport = new MockTransportImpl(); transport.setIdleTimeout(4000); Connection connection = Proton.connection(); transport.bind(connection); transport.handleFrame(TRANSPORT_FRAME_OPEN); connection.open(); while(transport.pending() > 0) transport.pop(transport.head().remaining()); long deadline = transport.tick(0); assertEquals("Expected to be returned a deadline of 4000", 4000, deadline); int framesWrittenBeforeTick = transport.writes.size(); deadline = transport.tick(1000); // Wait for less than the deadline with no data - get the same value assertEquals("When the deadline hasn't been reached tick() should return the previous deadline", 4000, deadline); assertEquals("Reading data should never result in a frame being written", 0, transport.writes.size() - framesWrittenBeforeTick); // Protocol header + empty frame ByteBuffer data = ByteBuffer.wrap(new byte[] {'A', 'M', 'Q', 'P', 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00}); while (data.remaining() > 0) { int origLimit = data.limit(); int amount = Math.min(transport.tail().remaining(), data.remaining()); data.limit(data.position() + amount); transport.tail().put(data); data.limit(origLimit); transport.process(); } framesWrittenBeforeTick = transport.writes.size(); deadline = transport.tick(2000); assertEquals("Reading data data resets the deadline", 6000, deadline); assertEquals("Reading data should never result in a frame being written", 0, transport.writes.size() - framesWrittenBeforeTick); assertEquals("Reading data before the deadline should keep the connection open", EndpointState.ACTIVE, connection.getLocalState()); framesWrittenBeforeTick = transport.writes.size(); deadline = transport.tick(7000); assertEquals("Calling tick() after the deadline should result in the connection being closed", EndpointState.CLOSED, connection.getLocalState()); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/StringUtilsTest.java0000664000000000000000000001247412562450203027532 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import static org.junit.Assert.*; import org.apache.qpid.proton.amqp.Binary; import org.junit.Test; public class StringUtilsTest { @Test public void testNullBinary() { assertEquals("unexpected result", "\"\"", StringUtils.toQuotedString(null, 10, true)); } @Test public void testEmptyBinaryEmptyArray() { Binary bin = new Binary(new byte[0]); assertEquals("unexpected result", "\"\"", StringUtils.toQuotedString(bin, 10, true)); } @Test public void testEmptyBinaryNonEmptyArray() { byte[] bytes = new byte[] {(byte) 0, (byte) 0, (byte) 0}; Binary bin = new Binary(bytes, 0, 0); assertEquals("unexpected result", "\"\"", StringUtils.toQuotedString(bin, 10, true)); } @Test public void testEmptyBinaryNonEmptyArrayWithOffset() { byte[] bytes = new byte[] {(byte) 0, (byte) 0, (byte) 0}; Binary bin = new Binary(bytes, 1, 0); assertEquals("unexpected result", "\"\"", StringUtils.toQuotedString(bin, 10, true)); } @Test public void testBinaryStringifiedSmallerThanGivenMaxLength() { byte[] bytes = new byte[] {(byte) 0, (byte) 1, (byte) 3, (byte) 65, (byte) 152}; String expected = "\"\\x00\\x01\\x03A\\x98\""; Binary bin = new Binary(bytes); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 100, true)); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 100, false)); } @Test public void testBinaryStringifiedSmallerThanGivenMaxLengthWithOffset() { byte[] bytes = new byte[] {(byte) 0, (byte) 1, (byte) 3, (byte) 65, (byte) 152}; String expected = "\"\\x01\\x03A\\x98\""; Binary bin = new Binary(bytes, 1, 4); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 100, true)); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 100, false)); } @Test public void testBinaryStringifiedEqualToGivenMaxLength() { byte[] bytes = new byte[] {(byte) 0, (byte) 1, (byte) 3, (byte) 65}; String expected = "\"\\x00\\x01\\x03A\""; Binary bin = new Binary(bytes); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 15, true)); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 15, false)); bytes = new byte[] {(byte) 0, (byte) 1, (byte) 65, (byte) 3}; expected = "\"\\x00\\x01A\\x03\""; bin = new Binary(bytes); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 15, true)); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 15, false)); } @Test public void testBinaryStringifiedEqualToGivenMaxLengthWithOffset() { byte[] bytes = new byte[] {(byte) 0, (byte) 1, (byte) 3, (byte) 65}; String expected = "\"\\x01\\x03A\""; Binary bin = new Binary(bytes, 1, 3); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 11, true)); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 11, false)); bytes = new byte[] {(byte) 0, (byte) 1, (byte) 65, (byte) 3}; expected = "\"\\x01A\\x03\""; bin = new Binary(bytes, 1, 3); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 11, true)); assertEquals("unexpected result", expected, StringUtils.toQuotedString(bin, 11, false)); } @Test public void testBinaryStringifiedLargerThanGivenMaxLength() { byte[] bytes = new byte[] {(byte) 0, (byte) 1, (byte) 3}; String expected1 = "\"\\x00\\x01\""; Binary bin = new Binary(bytes); assertEquals("unexpected result", expected1, StringUtils.toQuotedString(bin, 10, false)); String expected2 = "\"\\x00\\x01\"...(truncated)"; assertEquals("unexpected result", expected2, StringUtils.toQuotedString(bin, 10, true)); } @Test public void testBinaryStringifiedLargerThanGivenMaxLengthWithOffset() { byte[] bytes = new byte[] {(byte) 0, (byte) 1, (byte) 3}; String expected1 = "\"\\x00\\x01\""; Binary bin = new Binary(bytes); assertEquals("unexpected result", expected1, StringUtils.toQuotedString(bin, 10, false)); String expected2 = "\"\\x00\\x01\"...(truncated)"; assertEquals("unexpected result", expected2, StringUtils.toQuotedString(bin, 10, true)); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/SaslFrameParserTest.java0000664000000000000000000001227712562450203030276 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine.impl; import static org.mockito.Mockito.*; import static org.junit.Assert.*; import static org.junit.matchers.JUnitMatchers.containsString; import java.nio.ByteBuffer; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.security.SaslFrameBody; import org.apache.qpid.proton.amqp.security.SaslInit; import org.apache.qpid.proton.amqp.transport.FrameBody; import org.apache.qpid.proton.amqp.transport.Open; import org.apache.qpid.proton.codec.AMQPDefinedTypes; import org.apache.qpid.proton.codec.ByteBufferDecoder; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.DecoderImpl; import org.apache.qpid.proton.codec.EncoderImpl; import org.apache.qpid.proton.engine.TransportException; import org.junit.Test; /** * TODO test case where header is malformed * TODO test case where input provides frame and half etc */ public class SaslFrameParserTest { private final SaslFrameHandler _mockSaslFrameHandler = mock(SaslFrameHandler.class); private final ByteBufferDecoder _mockDecoder = mock(ByteBufferDecoder.class); private final SaslFrameParser _frameParser; private final SaslFrameParser _frameParserWithMockDecoder = new SaslFrameParser(_mockSaslFrameHandler, _mockDecoder); private final AmqpFramer _amqpFramer = new AmqpFramer(); private final SaslInit _saslFrameBody; private final ByteBuffer _saslFrameBytes; public SaslFrameParserTest() { DecoderImpl decoder = new DecoderImpl(); EncoderImpl encoder = new EncoderImpl(decoder); AMQPDefinedTypes.registerAllTypes(decoder,encoder); _frameParser = new SaslFrameParser(_mockSaslFrameHandler, decoder); _saslFrameBody = new SaslInit(); _saslFrameBody.setMechanism(Symbol.getSymbol("unused")); _saslFrameBytes = ByteBuffer.wrap(_amqpFramer.generateSaslFrame(0, new byte[0], _saslFrameBody)); } @Test public void testInputOfValidFrame() { sendAmqpSaslHeader(_frameParser); when(_mockSaslFrameHandler.isDone()).thenReturn(false); _frameParser.input(_saslFrameBytes); verify(_mockSaslFrameHandler).handle(isA(SaslInit.class), (Binary)isNull()); } @Test public void testInputOfInvalidFrame_causesErrorAndRefusesFurtherInput() { sendAmqpSaslHeader(_frameParserWithMockDecoder); String exceptionMessage = "dummy decode exception"; when(_mockDecoder.readObject()).thenThrow(new DecodeException(exceptionMessage)); // We send a valid frame but the mock decoder has been configured to reject it try { _frameParserWithMockDecoder.input(_saslFrameBytes); fail("expected exception"); } catch (TransportException e) { assertThat(e.getMessage(), containsString(exceptionMessage)); } verify(_mockSaslFrameHandler, never()).handle(any(SaslFrameBody.class), any(Binary.class)); // Check that any further interaction causes an error TransportResult. try { _frameParserWithMockDecoder.input(ByteBuffer.wrap("".getBytes())); fail("expected exception"); } catch (TransportException e) { // this is expected } } @Test public void testInputOfNonSaslFrame_causesErrorAndRefusesFurtherInput() { sendAmqpSaslHeader(_frameParserWithMockDecoder); FrameBody nonSaslFrame = new Open(); when(_mockDecoder.readObject()).thenReturn(nonSaslFrame); // We send a valid frame but the mock decoder has been configured to reject it try { _frameParserWithMockDecoder.input(_saslFrameBytes); fail("expected exception"); } catch (TransportException e) { assertThat(e.getMessage(), containsString("Unexpected frame type encountered.")); } verify(_mockSaslFrameHandler, never()).handle(any(SaslFrameBody.class), any(Binary.class)); // Check that any further interaction causes an error TransportResult. try { _frameParserWithMockDecoder.input(ByteBuffer.wrap("".getBytes())); fail("expected exception"); } catch (TransportException e) { // this is expected } } private void sendAmqpSaslHeader(SaslFrameParser saslFrameParser) { saslFrameParser.input(ByteBuffer.wrap(AmqpHeader.SASL_HEADER)); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/FrameParserTest.java0000664000000000000000000002555312562450203027454 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine.impl; import static org.apache.qpid.proton.engine.Transport.DEFAULT_MAX_FRAME_SIZE; import static org.apache.qpid.proton.engine.impl.AmqpHeader.HEADER; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.junit.matchers.JUnitMatchers.containsString; import static org.mockito.Matchers.any; import static org.mockito.Matchers.argThat; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.nio.ByteBuffer; import org.apache.qpid.proton.amqp.transport.Close; import org.apache.qpid.proton.amqp.transport.FrameBody; import org.apache.qpid.proton.amqp.transport.Open; import org.apache.qpid.proton.codec.AMQPDefinedTypes; import org.apache.qpid.proton.codec.DecoderImpl; import org.apache.qpid.proton.codec.EncoderImpl; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; import org.apache.qpid.proton.engine.TransportResult; import org.apache.qpid.proton.engine.TransportResult.Status; import org.apache.qpid.proton.framing.TransportFrame; import org.hamcrest.Description; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.ArgumentMatcher; import org.mockito.InOrder; // TODO test a frame with a payload (potentially followed by another frame) public class FrameParserTest { private FrameHandler _mockFrameHandler = mock(FrameHandler.class); private DecoderImpl _decoder = new DecoderImpl(); private EncoderImpl _encoder = new EncoderImpl(_decoder); private final FrameParser _frameParser = new FrameParser(_mockFrameHandler, _decoder, DEFAULT_MAX_FRAME_SIZE); private final AmqpFramer _amqpFramer = new AmqpFramer(); @Before public void setUp() { AMQPDefinedTypes.registerAllTypes(_decoder, _encoder); when(_mockFrameHandler.isHandlingFrames()).thenReturn(true); } @Test public void testInputOfInvalidProtocolHeader_causesErrorAndRefusesFurtherInput() { String headerMismatchMessage = "AMQP header mismatch"; ByteBuffer buffer = _frameParser.tail(); buffer.put("hello".getBytes()); _frameParser.process(); assertEquals(_frameParser.capacity(), Transport.END_OF_STREAM); } @Test public void testInputOfValidProtocolHeader() { ByteBuffer buffer = _frameParser.tail(); buffer.put(HEADER); _frameParser.process(); assertNotNull(_frameParser.tail()); } @Test public void testInputOfValidProtocolHeaderInMultipleChunks() { { ByteBuffer buffer = _frameParser.tail(); buffer.put(HEADER, 0, 2); _frameParser.process(); } { ByteBuffer buffer = _frameParser.tail(); buffer.put(HEADER, 2, HEADER.length - 2); _frameParser.process(); } assertNotNull(_frameParser.tail()); } @Test public void testInputOfValidFrame_invokesFrameTransportCallback() { sendHeader(); // now send an open frame ByteBuffer buffer = _frameParser.tail(); Open openFrame = generateOpenFrame(); int channel = 0; byte[] frame = _amqpFramer.generateFrame(channel, openFrame); buffer.put(frame); _frameParser.process(); verify(_mockFrameHandler).handleFrame(frameMatching(channel, openFrame)); } @Test public void testInputOfFrameInMultipleChunks_invokesFrameTransportCallback() { sendHeader(); Open openFrame = generateOpenFrame(); int channel = 0; byte[] frame = _amqpFramer.generateFrame(channel, openFrame); int lengthOfFirstChunk = 2; int lengthOfSecondChunk = (frame.length - lengthOfFirstChunk)/2; int lengthOfThirdChunk = frame.length - lengthOfFirstChunk - lengthOfSecondChunk; // send the first chunk { ByteBuffer buffer = _frameParser.tail(); buffer.put(frame, 0, lengthOfFirstChunk); _frameParser.process(); verify(_mockFrameHandler, never()).handleFrame(any(TransportFrame.class)); } // send the second chunk { ByteBuffer buffer = _frameParser.tail(); int secondChunkOffset = lengthOfFirstChunk; buffer.put(frame, secondChunkOffset, lengthOfSecondChunk); _frameParser.process(); verify(_mockFrameHandler, never()).handleFrame(any(TransportFrame.class)); } // send the third and final chunk { ByteBuffer buffer = _frameParser.tail(); int thirdChunkOffset = lengthOfFirstChunk + lengthOfSecondChunk; buffer.put(frame, thirdChunkOffset, lengthOfThirdChunk); _frameParser.process(); verify(_mockFrameHandler).handleFrame(frameMatching(channel, openFrame)); } } @Test public void testInputOfTwoFrames_invokesFrameTransportTwice() { sendHeader(); int channel = 0; Open openFrame = generateOpenFrame(); byte[] openFrameBytes = _amqpFramer.generateFrame(channel, openFrame); Close closeFrame = generateCloseFrame(); byte[] closeFrameBytes = _amqpFramer.generateFrame(channel, closeFrame); _frameParser.tail() .put(openFrameBytes) .put(closeFrameBytes); _frameParser.process(); InOrder inOrder = inOrder(_mockFrameHandler); inOrder.verify(_mockFrameHandler).handleFrame(frameMatching(channel, openFrame)); inOrder.verify(_mockFrameHandler).handleFrame(frameMatching(channel, closeFrame)); } @Test public void testFrameTransportTemporarilyRefusesOpenFrame() { when(_mockFrameHandler.isHandlingFrames()).thenReturn(false); sendHeader(); // now send an open frame int channel = 0; Open openFrame = generateOpenFrame(); { ByteBuffer buffer = _frameParser.tail(); byte[] frame = _amqpFramer.generateFrame(channel, openFrame); buffer.put(frame); _frameParser.process(); } verify(_mockFrameHandler, never()).handleFrame(any(TransportFrame.class)); when(_mockFrameHandler.isHandlingFrames()).thenReturn(true); // now ensure that the held frame gets sent on second input Close closeFrame = generateCloseFrame(); { ByteBuffer buffer = _frameParser.tail(); byte[] frame = _amqpFramer.generateFrame(channel, closeFrame); buffer.put(frame); _frameParser.process(); } InOrder inOrder = inOrder(_mockFrameHandler); inOrder.verify(_mockFrameHandler).handleFrame(frameMatching(channel, openFrame)); inOrder.verify(_mockFrameHandler).handleFrame(frameMatching(channel, closeFrame)); } @Test public void testFrameTransportTemporarilyRefusesOpenAndCloseFrame() { when(_mockFrameHandler.isHandlingFrames()).thenReturn(false); sendHeader(); // now send an open frame int channel = 0; Open openFrame = generateOpenFrame(); { ByteBuffer buffer = _frameParser.tail(); byte[] frame = _amqpFramer.generateFrame(channel, openFrame); buffer.put(frame); _frameParser.process(); } verify(_mockFrameHandler, never()).handleFrame(any(TransportFrame.class)); // now send a close frame Close closeFrame = generateCloseFrame(); { ByteBuffer buffer = _frameParser.tail(); byte[] frame = _amqpFramer.generateFrame(channel, closeFrame); buffer.put(frame); _frameParser.process(); } verify(_mockFrameHandler, never()).handleFrame(any(TransportFrame.class)); when(_mockFrameHandler.isHandlingFrames()).thenReturn(true); _frameParser.flush(); InOrder inOrder = inOrder(_mockFrameHandler); inOrder.verify(_mockFrameHandler).handleFrame(frameMatching(channel, openFrame)); inOrder.verify(_mockFrameHandler).handleFrame(frameMatching(channel, closeFrame)); } private void sendHeader() throws TransportException { ByteBuffer buffer = _frameParser.tail(); buffer.put(HEADER); _frameParser.process(); } private Open generateOpenFrame() { Open open = new Open(); open.setContainerId("containerid"); return open; } private Close generateCloseFrame() { Close close = new Close(); return close; } private TransportFrame frameMatching(int channel, FrameBody frameBody) { return argThat(new TransportFrameMatcher(channel, frameBody)); } private class TransportFrameMatcher extends ArgumentMatcher { private final TransportFrame _expectedTransportFrame; TransportFrameMatcher(int expectedChannel, FrameBody expectedFrameBody) { _expectedTransportFrame = new TransportFrame(expectedChannel, expectedFrameBody, null); } @Override public boolean matches(Object transportFrameObj) { if(transportFrameObj == null) { return false; } TransportFrame transportFrame = (TransportFrame)transportFrameObj; FrameBody actualFrame = transportFrame.getBody(); int _expectedChannel = _expectedTransportFrame.getChannel(); FrameBody expectedFrame = _expectedTransportFrame.getBody(); return _expectedChannel == transportFrame.getChannel() && expectedFrame.getClass().equals(actualFrame.getClass()); } @Override public void describeTo(Description description) { super.describeTo(description); description.appendText("Expected: " + _expectedTransportFrame); } } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/AmqpFramer.java0000664000000000000000000000736112562450203026435 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import static org.junit.Assert.assertEquals; import java.nio.ByteBuffer; import org.apache.qpid.proton.amqp.security.SaslFrameBody; import org.apache.qpid.proton.amqp.transport.FrameBody; import org.apache.qpid.proton.codec.AMQPDefinedTypes; import org.apache.qpid.proton.codec.DecoderImpl; import org.apache.qpid.proton.codec.EncoderImpl; import org.apache.qpid.proton.codec.WritableBuffer; /** * Generates frames as per section 2.3.1 of the AMQP spec */ public class AmqpFramer { // My test data is generated by the decoder and encoder from proton-j // although at run-time the Engine internally uses its own implementation. private DecoderImpl _decoder = new DecoderImpl(); private EncoderImpl _encoder = new EncoderImpl(_decoder); public AmqpFramer() { AMQPDefinedTypes.registerAllTypes(_decoder, _encoder); } public byte[] createEmptyFrame(int channel) { byte[] emptyFrame = generateFrame(channel, null); return emptyFrame; } public byte[] generateFrame(int channel, FrameBody frameBody) { byte[] emptyExtendedHeader = new byte[] {}; return generateFrame(channel, emptyExtendedHeader, frameBody); } public byte[] generateFrame(int channel, byte[] extendedHeader, FrameBody frameBody) { return generateFrame(channel, extendedHeader, frameBody, (byte)0); } public byte[] generateSaslFrame(int channel, byte[] extendedHeader, SaslFrameBody frameBody) { return generateFrame(channel, extendedHeader, frameBody, (byte)1); } /** * @param amqpFrameType indicates either AMQP or SASL * @param frameBody is currently expected to be a {@link FrameBody} or a {@link SaslFrameBody} */ public byte[] generateFrame(int channel, byte[] extendedHeader, Object frameBody, byte amqpFrameType) { assertEquals("Extended header must be multiple of 4 bytes", 0, extendedHeader.length % 4); int numberOfExtendedHeaderFourByteWords = extendedHeader.length / 4; ByteBuffer buffer = ByteBuffer.allocate(1024); buffer.position(8); // leave hole for frame header _encoder.setByteBuffer(new WritableBuffer.ByteBufferWrapper(buffer)); // write extended header - maybe empty buffer.put(extendedHeader); // write frame body if (frameBody != null) { _encoder.writeObject(frameBody); } int frameSize = buffer.position(); int framePreambleSizeInFourByteWords = 2; byte dataOffsetFourByteWords = (byte)(framePreambleSizeInFourByteWords + numberOfExtendedHeaderFourByteWords); buffer.rewind(); buffer.putInt(frameSize); buffer.put(dataOffsetFourByteWords); buffer.put(amqpFrameType); buffer.putShort((short)channel); byte[] target = new byte[frameSize]; buffer.rewind(); buffer.get(target, 0, frameSize); return target; } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/codec/0000775000000000000000000000000012562450203022377 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/codec/impl/0000775000000000000000000000000012562450203023340 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/codec/impl/DataImplTest.java0000664000000000000000000000565112562450203026545 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.impl; import static org.junit.Assert.*; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.codec.Data; import org.junit.Test; public class DataImplTest { @Test public void testEncodeDecodeSymbolArrayUsingPutArray() { Symbol symbol1 = Symbol.valueOf("testRoundtripSymbolArray1"); Symbol symbol2 = Symbol.valueOf("testRoundtripSymbolArray2"); Data data1 = new DataImpl(); data1.putArray(false, Data.DataType.SYMBOL); data1.enter(); data1.putSymbol(symbol1); data1.putSymbol(symbol2); data1.exit(); Binary encoded = data1.encode(); encoded.asByteBuffer(); Data data2 = new DataImpl(); data2.decode(encoded.asByteBuffer()); assertEquals("unexpected array length", 2, data2.getArray()); assertEquals("unexpected array length", Data.DataType.SYMBOL, data2.getArrayType()); Object[] array = data2.getJavaArray(); assertNotNull("Array should not be null", array); assertEquals("Expected a Symbol array", Symbol[].class, array.getClass()); assertEquals("unexpected array length", 2, array.length); assertEquals("unexpected value", symbol1, array[0]); assertEquals("unexpected value", symbol2, array[1]); } @Test public void testEncodeDecodeSymbolArrayUsingPutObject() { Symbol symbol1 = Symbol.valueOf("testRoundtripSymbolArray1"); Symbol symbol2 = Symbol.valueOf("testRoundtripSymbolArray2"); Symbol[] input = new Symbol[]{symbol1, symbol2}; Data data1 = new DataImpl(); data1.putObject(input); Binary encoded = data1.encode(); encoded.asByteBuffer(); Data data2 = new DataImpl(); data2.decode(encoded.asByteBuffer()); assertEquals("unexpected array length", 2, data2.getArray()); assertEquals("unexpected array length", Data.DataType.SYMBOL, data2.getArrayType()); Object[] array = data2.getJavaArray(); assertArrayEquals("Array not as expected", input, array); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedLongTypeTest.java0000664000000000000000000000513212562450203027341 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec; import static org.junit.Assert.*; import java.math.BigInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.codec.UnsignedLongType.UnsignedLongEncoding; import org.junit.Test; public class UnsignedLongTypeTest { @Test public void testGetEncodingWithZero() { DecoderImpl decoder = new DecoderImpl(); EncoderImpl encoder = new EncoderImpl(decoder); UnsignedLongType ult = new UnsignedLongType(encoder, decoder); //values of 0 are encoded as a specific type UnsignedLongEncoding encoding = ult.getEncoding(UnsignedLong.valueOf(0L)); assertEquals("incorrect encoding returned", EncodingCodes.ULONG0, encoding.getEncodingCode()); } @Test public void testGetEncodingWithSmallPositiveValue() { DecoderImpl decoder = new DecoderImpl(); EncoderImpl encoder = new EncoderImpl(decoder); UnsignedLongType ult = new UnsignedLongType(encoder, decoder); //values between 0 and 255 are encoded as a specific 'small' type using a single byte UnsignedLongEncoding encoding = ult.getEncoding(UnsignedLong.valueOf(1L)); assertEquals("incorrect encoding returned", EncodingCodes.SMALLULONG, encoding.getEncodingCode()); } @Test public void testGetEncodingWithTwoToSixtyThree() { DecoderImpl decoder = new DecoderImpl(); EncoderImpl encoder = new EncoderImpl(decoder); UnsignedLongType ult = new UnsignedLongType(encoder, decoder); BigInteger bigInt = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); UnsignedLongEncoding encoding = ult.getEncoding(UnsignedLong.valueOf(bigInt)); assertEquals("incorrect encoding returned", EncodingCodes.ULONG, encoding.getEncodingCode()); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/codec/UnsignedIntegerTypeTest.java0000664000000000000000000000507412562450203030044 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec; import static org.junit.Assert.*; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.codec.UnsignedIntegerType.UnsignedIntegerEncoding; import org.junit.Test; public class UnsignedIntegerTypeTest { @Test public void testGetEncodingWithZero() { DecoderImpl decoder = new DecoderImpl(); EncoderImpl encoder = new EncoderImpl(decoder); UnsignedIntegerType ult = new UnsignedIntegerType(encoder, decoder); //values of 0 are encoded as a specific type UnsignedIntegerEncoding encoding = ult.getEncoding(UnsignedInteger.valueOf(0L)); assertEquals("incorrect encoding returned", EncodingCodes.UINT0, encoding.getEncodingCode()); } @Test public void testGetEncodingWithSmallPositiveValue() { DecoderImpl decoder = new DecoderImpl(); EncoderImpl encoder = new EncoderImpl(decoder); UnsignedIntegerType ult = new UnsignedIntegerType(encoder, decoder); //values between 0 and 255 are encoded as a specific 'small' type using a single byte UnsignedIntegerEncoding encoding = ult.getEncoding(UnsignedInteger.valueOf(1L)); assertEquals("incorrect encoding returned", EncodingCodes.SMALLUINT, encoding.getEncodingCode()); } @Test public void testGetEncodingWithTwoToThirtyOne() { DecoderImpl decoder = new DecoderImpl(); EncoderImpl encoder = new EncoderImpl(decoder); UnsignedIntegerType ult = new UnsignedIntegerType(encoder, decoder); long val = Integer.MAX_VALUE + 1L; UnsignedIntegerEncoding encoding = ult.getEncoding(UnsignedInteger.valueOf(val)); assertEquals("incorrect encoding returned", EncodingCodes.UINT, encoding.getEncodingCode()); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/codec/StringTypeTest.java0000664000000000000000000001537712562450203026227 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec; import static org.junit.Assert.assertEquals; import java.lang.Character.UnicodeBlock; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.apache.qpid.proton.amqp.messaging.AmqpValue; import org.junit.Test; /** * Test the encoding and decoding of {@link StringType} values. */ public class StringTypeTest { private static final Charset CHARSET_UTF8 = Charset.forName("UTF-8"); private static final List TEST_DATA = generateTestData(); /** * Loop over all the chars in given {@link UnicodeBlock}s and return a * {@link Set } containing all the possible values as their * {@link String} values. * * @param blocks the {@link UnicodeBlock}s to loop over * @return a {@link Set } containing all the possible values as * {@link String} values */ private static Set getAllStringsFromUnicodeBlocks(final UnicodeBlock... blocks) { final Set blockSet = new HashSet(Arrays.asList(blocks)); final Set strings = new HashSet(); for (int codePoint = 0; codePoint <= Character.MAX_CODE_POINT; codePoint++) { if (blockSet.contains(UnicodeBlock.of(codePoint))) { final int charCount = Character.charCount(codePoint); final StringBuilder sb = new StringBuilder( charCount); if (charCount == 1) { sb.append(String.valueOf((char) codePoint)); } else if (charCount == 2) { //TODO: use Character.highSurrogate(codePoint) and Character.lowSurrogate(codePoint) when Java 7 is baseline char highSurrogate = (char) ((codePoint >>> 10) + ('\uD800' - (0x010000 >>> 10))); char lowSurrogate = (char) ((codePoint & 0x3ff) + '\uDC00'); sb.append(highSurrogate); sb.append(lowSurrogate); } else { throw new IllegalArgumentException("Character.charCount of " + charCount + " not supported."); } strings.add(sb.toString()); } } return strings; } /** * Test the encoding and decoding of various complicated Unicode characters * which will end up as "surrogate pairs" when encoded to UTF-8 */ @Test public void calculateUTF8Length() { for (final String input : TEST_DATA) { assertEquals("Incorrect string length calculated for string '"+input+"'",input.getBytes(CHARSET_UTF8).length, StringType.calculateUTF8Length(input)); } } /** * Test the encoding and decoding of various Unicode characters */ @Test public void encodeDecodeStrings() { final DecoderImpl decoder = new DecoderImpl(); final EncoderImpl encoder = new EncoderImpl(decoder); AMQPDefinedTypes.registerAllTypes(decoder, encoder); final ByteBuffer bb = ByteBuffer.allocate(16); for (final String input : TEST_DATA) { bb.clear(); final AmqpValue inputValue = new AmqpValue(input); encoder.setByteBuffer(bb); encoder.writeObject(inputValue); bb.clear(); decoder.setByteBuffer(bb); final AmqpValue outputValue = (AmqpValue) decoder.readObject(); assertEquals("Failed to round trip String correctly: ", input, outputValue.getValue()); } } // build up some test data with a set of suitable Unicode characters private static List generateTestData() { return new LinkedList() { private static final long serialVersionUID = 7331717267070233454L; { // non-surrogate pair blocks addAll(getAllStringsFromUnicodeBlocks(UnicodeBlock.BASIC_LATIN, UnicodeBlock.LATIN_1_SUPPLEMENT, UnicodeBlock.GREEK, UnicodeBlock.LETTERLIKE_SYMBOLS)); // blocks with surrogate pairs //TODO: restore others when Java 7 is baseline addAll(getAllStringsFromUnicodeBlocks(UnicodeBlock.LINEAR_B_SYLLABARY, /*UnicodeBlock.MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS,*/ UnicodeBlock.MUSICAL_SYMBOLS, /*UnicodeBlock.EMOTICONS,*/ /*UnicodeBlock.PLAYING_CARDS,*/ UnicodeBlock.BOX_DRAWING, UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS, UnicodeBlock.PRIVATE_USE_AREA, UnicodeBlock.SUPPLEMENTARY_PRIVATE_USE_AREA_A, UnicodeBlock.SUPPLEMENTARY_PRIVATE_USE_AREA_B)); // some additional combinations of characters that could cause problems to the encoder String[] boxDrawing = getAllStringsFromUnicodeBlocks(UnicodeBlock.BOX_DRAWING).toArray(new String[0]); String[] halfFullWidthForms = getAllStringsFromUnicodeBlocks(UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS).toArray(new String[0]); for (int i = 0; i < halfFullWidthForms.length; i++) { add(halfFullWidthForms[i] + boxDrawing[i % boxDrawing.length]); } } }; } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/amqp/0000775000000000000000000000000012562450203022260 5ustar qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/amqp/transport/0000775000000000000000000000000012562450203024314 5ustar ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/amqp/transport/ErrorConditionTest.javaqpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/amqp/transport/ErrorConditionTest.jav0000664000000000000000000001055312562450203030622 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.amqp.transport; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import java.util.Collections; import org.apache.qpid.proton.amqp.Symbol; import org.junit.Test; public class ErrorConditionTest { @Test public void testEqualityOfNewlyConstructed() { ErrorCondition new1 = new ErrorCondition(); ErrorCondition new2 = new ErrorCondition(); assertErrorConditionsEqual(new1, new2); } @Test public void testSameObject() { ErrorCondition error = new ErrorCondition(); assertErrorConditionsEqual(error, error); } @Test public void testConditionEquality() { String symbolValue = "symbol"; ErrorCondition same1 = new ErrorCondition(); same1.setCondition(Symbol.getSymbol(new String(symbolValue))); ErrorCondition same2 = new ErrorCondition(); same2.setCondition(Symbol.getSymbol(new String(symbolValue))); assertErrorConditionsEqual(same1, same2); ErrorCondition different = new ErrorCondition(); different.setCondition(Symbol.getSymbol("other")); assertErrorConditionsNotEqual(same1, different); } @Test public void testConditionAndDescriptionEquality() { String symbolValue = "symbol"; String descriptionValue = "description"; ErrorCondition same1 = new ErrorCondition(); same1.setCondition(Symbol.getSymbol(new String(symbolValue))); same1.setDescription(new String(descriptionValue)); ErrorCondition same2 = new ErrorCondition(); same2.setCondition(Symbol.getSymbol(new String(symbolValue))); same2.setDescription(new String(descriptionValue)); assertErrorConditionsEqual(same1, same2); ErrorCondition different = new ErrorCondition(); different.setCondition(Symbol.getSymbol(symbolValue)); different.setDescription("other"); assertErrorConditionsNotEqual(same1, different); } @Test public void testConditionDescriptionInfoEquality() { String symbolValue = "symbol"; String descriptionValue = "description"; ErrorCondition same1 = new ErrorCondition(); same1.setCondition(Symbol.getSymbol(new String(symbolValue))); same1.setDescription(new String(descriptionValue)); same1.setInfo(Collections.singletonMap(Symbol.getSymbol("key"), "value")); ErrorCondition same2 = new ErrorCondition(); same2.setCondition(Symbol.getSymbol(new String(symbolValue))); same2.setDescription(new String(descriptionValue)); same2.setInfo(Collections.singletonMap(Symbol.getSymbol("key"), "value")); assertErrorConditionsEqual(same1, same2); ErrorCondition different = new ErrorCondition(); different.setCondition(Symbol.getSymbol(symbolValue)); different.setDescription(new String(descriptionValue)); different.setInfo(Collections.singletonMap(Symbol.getSymbol("other"), "value")); assertErrorConditionsNotEqual(same1, different); } private void assertErrorConditionsNotEqual(ErrorCondition error1, ErrorCondition error2) { assertThat(error1, is(not(error2))); assertThat(error2, is(not(error1))); } private void assertErrorConditionsEqual(ErrorCondition error1, ErrorCondition error2) { assertEquals(error1, error2); assertEquals(error2, error1); assertEquals(error1.hashCode(), error2.hashCode()); } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/amqp/UnsignedLongTest.java0000664000000000000000000001130312562450203026355 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.amqp; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.math.BigInteger; import org.junit.Test; public class UnsignedLongTest { private static final byte[] TWO_TO_64_PLUS_ONE_BYTES = new byte[] { (byte) 1, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 1 }; private static final byte[] TWO_TO_64_MINUS_ONE_BYTES = new byte[] {(byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1 }; @Test public void testValueOfStringWithNegativeNumberThrowsNFE() throws Exception { try { UnsignedLong.valueOf("-1"); fail("Expected exception was not thrown"); } catch(NumberFormatException nfe) { //expected } } @Test public void testValueOfBigIntegerWithNegativeNumberThrowsNFE() throws Exception { try { UnsignedLong.valueOf(BigInteger.valueOf(-1L)); fail("Expected exception was not thrown"); } catch(NumberFormatException nfe) { //expected } } @Test public void testValuesOfStringWithinRangeSucceed() throws Exception { //check 0 (min) to confirm success UnsignedLong min = UnsignedLong.valueOf("0"); assertEquals("unexpected value", 0, min.longValue()); //check 2^64 -1 (max) to confirm success BigInteger onLimit = new BigInteger(TWO_TO_64_MINUS_ONE_BYTES); String onlimitString = onLimit.toString(); UnsignedLong max = UnsignedLong.valueOf(onlimitString); assertEquals("unexpected value", onLimit, max.bigIntegerValue()); } @Test public void testValuesOfBigIntegerWithinRangeSucceed() throws Exception { //check 0 (min) to confirm success UnsignedLong min = UnsignedLong.valueOf(BigInteger.ZERO); assertEquals("unexpected value", 0, min.longValue()); //check 2^64 -1 (max) to confirm success BigInteger onLimit = new BigInteger(TWO_TO_64_MINUS_ONE_BYTES); UnsignedLong max = UnsignedLong.valueOf(onLimit); assertEquals("unexpected value", onLimit, max.bigIntegerValue()); //check Long.MAX_VALUE to confirm success UnsignedLong longMax = UnsignedLong.valueOf(BigInteger.valueOf(Long.MAX_VALUE)); assertEquals("unexpected value", Long.MAX_VALUE, longMax.longValue()); } @Test public void testValueOfStringAboveMaxValueThrowsNFE() throws Exception { //2^64 + 1 (value 2 over max) BigInteger aboveLimit = new BigInteger(TWO_TO_64_PLUS_ONE_BYTES); try { UnsignedLong.valueOf(aboveLimit.toString()); fail("Expected exception was not thrown"); } catch(NumberFormatException nfe) { //expected } //2^64 (value 1 over max) aboveLimit = aboveLimit.subtract(BigInteger.ONE); try { UnsignedLong.valueOf(aboveLimit.toString()); fail("Expected exception was not thrown"); } catch(NumberFormatException nfe) { //expected } } @Test public void testValueOfBigIntegerAboveMaxValueThrowsNFE() throws Exception { //2^64 + 1 (value 2 over max) BigInteger aboveLimit = new BigInteger(TWO_TO_64_PLUS_ONE_BYTES); try { UnsignedLong.valueOf(aboveLimit); fail("Expected exception was not thrown"); } catch(NumberFormatException nfe) { //expected } //2^64 (value 1 over max) aboveLimit = aboveLimit.subtract(BigInteger.ONE); try { UnsignedLong.valueOf(aboveLimit); fail("Expected exception was not thrown"); } catch(NumberFormatException nfe) { //expected } } } qpid-proton-0.10/proton-j/src/test/java/org/apache/qpid/proton/amqp/BinaryTest.java0000664000000000000000000000643512562450203025217 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.amqp; import static org.junit.Assert.*; import java.util.Arrays; import org.junit.Test; public class BinaryTest { @Test public void testNotEqualsWithDifferentTypeObject() { Binary bin = createSteppedValueBinary(10); assertFalse("Objects should not be equal with different type", bin.equals("not-a-Binary")); } @Test public void testEqualsWithItself() { Binary bin = createSteppedValueBinary(10); assertTrue("Object should be equal to itself", bin.equals(bin)); } @Test public void testEqualsWithDifferentBinaryOfSameLengthAndContent() { int length = 10; Binary bin1 = createSteppedValueBinary(length); Binary bin2 = createSteppedValueBinary(length); assertTrue("Objects should be equal", bin1.equals(bin2)); assertTrue("Objects should be equal", bin2.equals(bin1)); } @Test public void testEqualsWithDifferentLengthBinaryOfDifferentBytes() { int length1 = 10; Binary bin1 = createSteppedValueBinary(length1); Binary bin2 = createSteppedValueBinary(length1 + 1); assertFalse("Objects should not be equal", bin1.equals(bin2)); assertFalse("Objects should not be equal", bin2.equals(bin1)); } @Test public void testEqualsWithDifferentLengthBinaryOfSameByte() { Binary bin1 = createNewRepeatedValueBinary(10, (byte) 1); Binary bin2 = createNewRepeatedValueBinary(123, (byte) 1); assertFalse("Objects should not be equal", bin1.equals(bin2)); assertFalse("Objects should not be equal", bin2.equals(bin1)); } @Test public void testEqualsWithDifferentContentBinary() { int length = 10; Binary bin1 = createNewRepeatedValueBinary(length, (byte) 1); Binary bin2 = createNewRepeatedValueBinary(length, (byte) 1); bin2.getArray()[5] = (byte) 0; assertFalse("Objects should not be equal", bin1.equals(bin2)); assertFalse("Objects should not be equal", bin2.equals(bin1)); } private Binary createSteppedValueBinary(int length) { byte[] bytes = new byte[length]; for (int i = 0; i < length; i++) { bytes[i] = (byte) (length - i); } return new Binary(bytes); } private Binary createNewRepeatedValueBinary(int length, byte repeatedByte){ byte[] bytes = new byte[length]; Arrays.fill(bytes, repeatedByte); return new Binary(bytes); } } qpid-proton-0.10/proton-j/src/main/0000775000000000000000000000000012562450203014060 5ustar qpid-proton-0.10/proton-j/src/main/resources/0000775000000000000000000000000012562450203016072 5ustar qpid-proton-0.10/proton-j/src/main/resources/curl.py0000664000000000000000000000321612562450203017413 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License # from org.apache.qpid.proton.messenger.impl import Address def pn_url(): return Address() def pn_url_parse(urlstr): return Address(urlstr) def pn_url_free(url): pass def pn_url_clear(url): url.clear(); def pn_url_str(url): return url.toString() def pn_url_get_scheme(url): return url.getScheme() def pn_url_get_username(url): return url.getUser() def pn_url_get_password(url): return url.getPass() def pn_url_get_host(url): return url.getHost() or None def pn_url_get_port(url): return url.getPort() def pn_url_get_path(url): return url.getName() def pn_url_set_scheme(url, value): url.setScheme(value) def pn_url_set_username(url, value): url.setUser(value) def pn_url_set_password(url, value): url.setPass(value) def pn_url_set_host(url, value): url.setHost(value) def pn_url_set_port(url, value): url.setPort(value) def pn_url_set_path(url, value): url.setName(value) qpid-proton-0.10/proton-j/src/main/resources/ctypes.py0000664000000000000000000000151112562450203017751 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # from proton/types.h PN_MILLIS_MAX = 4294967295 qpid-proton-0.10/proton-j/src/main/resources/cssl.py0000664000000000000000000000620712562450203017415 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from org.apache.qpid.proton import Proton from org.apache.qpid.proton.engine import SslDomain from cerror import * # from proton/ssl.h PN_SSL_MODE_CLIENT = 1 PN_SSL_MODE_SERVER = 2 PN_SSL_RESUME_UNKNOWN = 0 PN_SSL_RESUME_NEW = 1 PN_SSL_RESUME_REUSED = 2 PN_SSL_VERIFY_NULL=0 PN_SSL_VERIFY_PEER=1 PN_SSL_ANONYMOUS_PEER=2 PN_SSL_VERIFY_PEER_NAME=3 PN_SSL_MODE_J2P = { SslDomain.Mode.CLIENT: PN_SSL_MODE_CLIENT, SslDomain.Mode.SERVER: PN_SSL_MODE_SERVER } PN_SSL_MODE_P2J = { PN_SSL_MODE_CLIENT: SslDomain.Mode.CLIENT, PN_SSL_MODE_SERVER: SslDomain.Mode.SERVER } def pn_ssl_present(): return True def pn_ssl_domain(mode): domain = Proton.sslDomain() domain.init(PN_SSL_MODE_P2J[mode]) return domain def pn_ssl_domain_set_credentials(domain, certificate_file, private_key_file, password): domain.setCredentials(certificate_file, private_key_file, password) return 0 def pn_ssl_domain_set_trusted_ca_db(domain, trusted_db): domain.setTrustedCaDb(trusted_db) return 0 PN_VERIFY_MODE_J2P = { None: PN_SSL_VERIFY_NULL, SslDomain.VerifyMode.VERIFY_PEER: PN_SSL_VERIFY_PEER, SslDomain.VerifyMode.VERIFY_PEER_NAME: PN_SSL_VERIFY_PEER_NAME, SslDomain.VerifyMode.ANONYMOUS_PEER: PN_SSL_ANONYMOUS_PEER } PN_VERIFY_MODE_P2J = { PN_SSL_VERIFY_NULL: None, PN_SSL_VERIFY_PEER: SslDomain.VerifyMode.VERIFY_PEER, PN_SSL_VERIFY_PEER_NAME: SslDomain.VerifyMode.VERIFY_PEER_NAME, PN_SSL_ANONYMOUS_PEER: SslDomain.VerifyMode.ANONYMOUS_PEER } def pn_ssl_domain_set_peer_authentication(domain, mode, trusted=None): domain.setPeerAuthentication(PN_VERIFY_MODE_P2J[mode]) if trusted: domain.setTrustedCaDb(trusted) return 0 def pn_ssl_domain_allow_unsecured_client(domain): domain.allowUnsecuredClient(True) return 0 class pn_ssl_wrapper: def __init__(self, transport): self.impl = None self.transport = transport def pn_ssl(transport): if getattr(transport, "ssl", None) is not None: return transport.ssl else: transport.ssl = pn_ssl_wrapper(transport) return transport.ssl def pn_ssl_init(ssl, domain, session_id): # XXX: session_id ssl.impl = ssl.transport.impl.ssl(domain, None) def pn_ssl_resume_status(ssl): raise Skipped() def pn_ssl_get_cipher_name(ssl, size): name = ssl.impl.getCipherName() return (bool(name), name) def pn_ssl_get_protocol_name(ssl, size): name = ssl.impl.getProtocolName() return (bool(name), name) qpid-proton-0.10/proton-j/src/main/resources/csasl.py0000664000000000000000000000461112562450203017553 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from org.apache.qpid.proton.engine import Sasl from compat import array, zeros from cerror import * # from proton/sasl.h PN_SASL_NONE=-1 PN_SASL_OK=0 PN_SASL_AUTH=1 PN_SASL_SYS=2 PN_SASL_PERM=3 PN_SASL_TEMP=4 def pn_sasl_extended(): return False def pn_sasl(tp): sasl = tp.impl.sasl() if tp.server: sasl.server() else: sasl.client() return sasl SASL_OUTCOMES_P2J = { PN_SASL_NONE: Sasl.PN_SASL_NONE, PN_SASL_OK: Sasl.PN_SASL_OK, PN_SASL_AUTH: Sasl.PN_SASL_AUTH, PN_SASL_SYS: Sasl.PN_SASL_SYS, PN_SASL_PERM: Sasl.PN_SASL_PERM, PN_SASL_TEMP: Sasl.PN_SASL_TEMP, } SASL_OUTCOMES_J2P = { Sasl.PN_SASL_NONE: PN_SASL_NONE, Sasl.PN_SASL_OK: PN_SASL_OK, Sasl.PN_SASL_AUTH: PN_SASL_AUTH, Sasl.PN_SASL_SYS: PN_SASL_SYS, Sasl.PN_SASL_PERM: PN_SASL_PERM, Sasl.PN_SASL_TEMP: PN_SASL_TEMP, } def pn_transport_require_auth(transport, require): raise Skipped('Not supported in Proton-J') # TODO: Placeholders def pn_transport_is_authenticated(transport): raise Skipped('Not supported in Proton-J') def pn_transport_is_encrypted(transport): raise Skipped('Not supported in Proton-J') def pn_transport_get_user(transport): raise Skipped('Not supported in Proton-J') def pn_connection_set_user(connection, user): pass def pn_connection_set_password(connection, password): pass def pn_sasl_allowed_mechs(sasl, mechs): sasl.setMechanisms(*mechs.split()) def pn_sasl_set_allow_insecure_mechs(sasl, insecure): raise Skipped('Not supported in Proton-J') def pn_sasl_done(sasl, outcome): sasl.done(SASL_OUTCOMES_P2J[outcome]) def pn_sasl_outcome(sasl): return SASL_OUTCOMES_J2P[sasl.getOutcome()] qpid-proton-0.10/proton-j/src/main/resources/creactor.py0000664000000000000000000000553312562450203020254 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from cerror import Skipped from cengine import wrap, pn_connection_wrapper from org.apache.qpid.proton.reactor import Reactor from org.apache.qpid.proton.engine import BaseHandler # from proton/reactor.h def pn_reactor(): return Reactor.Factory.create() def pn_reactor_attachments(r): return r.attachments() def pn_reactor_get_global_handler(r): return r.getGlobalHandler() def pn_reactor_set_global_handler(r, h): r.setGlobalHandler(h) def pn_reactor_get_handler(r): return r.getHandler() def pn_reactor_set_handler(r, h): r.setHandler(h) def pn_reactor_set_timeout(r, t): r.setTimeout(t) def pn_reactor_get_timeout(r): return r.getTimeout() def pn_reactor_schedule(r, t, h): return r.schedule(t, h) def pn_reactor_yield(r): getattr(r, "yield")() def pn_reactor_start(r): r.start() def pn_reactor_process(r): return r.process() def pn_reactor_stop(r): return r.stop() def pn_reactor_selectable(r): return r.selectable() def pn_reactor_connection(r, h): return wrap(r.connection(h), pn_connection_wrapper) def pn_reactor_acceptor(r, host, port, handler): return r.acceptor(host, int(port), handler) def pn_reactor_mark(r): return r.mark() def pn_reactor_wakeup(r): return r.wakeup() def pn_handler_add(h, c): h.add(c) def pn_handler_dispatch(h, ev, et): ev.impl.dispatch(h) def pn_record_set_handler(r, h): BaseHandler.setHandler(r, h) def pn_record_get_handler(r): return BaseHandler.getHandler(r) def pn_task_attachments(t): return t.attachments() def pn_selectable_attachments(s): return s.attachments() def pn_selectable_set_fd(s, fd): s.setChannel(fd.getChannel()) def pn_acceptor_close(a): a.close() def pn_task_cancel(t): t.cancel() def pn_object_reactor(o): if hasattr(o, "impl"): if hasattr(o.impl, "getSession"): return o.impl.getSession().getConnection().getReactor() elif hasattr(o.impl, "getConnection"): return o.impl.getConnection().getReactor() else: return o.impl.getReactor() else: return o.getReactor() qpid-proton-0.10/proton-j/src/main/resources/cproton.py0000664000000000000000000000327412562450203020136 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # """ The cproton module defines a java implementation of the C interface as exposed to python via swig. This allows tests defined in python to run against both the C and Java protocol implementations. """ # @todo(kgiusti) dynamically set these via filters in the pom.xml file PN_VERSION_MAJOR = 0 PN_VERSION_MINOR = 0 from ctypes import * from cobject import * from cerror import * from ccodec import * from cengine import * from csasl import * from cssl import * from cdriver import * from cmessenger import * from cmessage import * from curl import * from creactor import * from chandlers import * # XXX: this is for compatibility, apparently the version of jython we # use doesn't have next, we should remove this when we upgrade _DEF = object() def next(iter, default=_DEF): try: return iter.next() except StopIteration: if default is _DEF: raise else: return default qpid-proton-0.10/proton-j/src/main/resources/compat.py0000664000000000000000000000171512562450203017733 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import sys from jarray import zeros, array as _array if (sys.version_info[0] == 2 and sys.version_info[1] == 5): array = _array else: def array(obj, code): return obj qpid-proton-0.10/proton-j/src/main/resources/cobject.py0000664000000000000000000000347712562450203020070 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # def pn_class_name(cls): return cls def pn_void2py(obj): return obj def pn_py2void(obj): return obj def pn_cast_pn_connection(obj): return obj def pn_cast_pn_session(obj): return obj def pn_cast_pn_link(obj): return obj def pn_cast_pn_delivery(obj): return obj def pn_cast_pn_transport(obj): return obj def pn_cast_pn_reactor(obj): return obj def pn_cast_pn_task(obj): return obj def pn_cast_pn_selectable(obj): return obj PN_PYREF = None def pn_record_def(record, key, clazz): pass from java.lang import Object def pn_record_get(record, key): return record.get(key, Object) def pn_record_set(record, key, value): record.set(key, Object, value) def pn_incref(obj): pass def pn_decref(obj): pass def pn_free(obj): pass from java.lang import StringBuilder def pn_string(st): sb = StringBuilder() if st: sb.append(st) return sb def pn_string_get(sb): return sb.toString() def pn_inspect(obj, st): if obj is None: st.append("null") else: st.append(repr(obj)) return 0 qpid-proton-0.10/proton-j/src/main/resources/cmessenger.py0000664000000000000000000001207112562450203020600 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from org.apache.qpid.proton import Proton from org.apache.qpid.proton.messenger import Messenger, Status from org.apache.qpid.proton import InterruptException, TimeoutException from cerror import * # from proton/messenger.h PN_STATUS_UNKNOWN = 0 PN_STATUS_PENDING = 1 PN_STATUS_ACCEPTED = 2 PN_STATUS_REJECTED = 3 PN_STATUS_RELEASED = 4 PN_STATUS_MODIFIED = 5 PN_STATUS_ABORTED = 6 PN_STATUS_SETTLED = 7 PN_CUMULATIVE = 1 class pn_messenger_wrapper: def __init__(self, impl): self.impl = impl self.error = pn_error(0, None) def pn_messenger(name): if name is None: return pn_messenger_wrapper(Proton.messenger()) else: return pn_messenger_wrapper(Proton.messenger(name)) def pn_messenger_error(m): return m.error def pn_messenger_set_timeout(m, t): m.impl.setTimeout(t) return 0 def pn_messenger_set_blocking(m, b): m.impl.setBlocking(b) return 0 def pn_messenger_set_certificate(m, c): m.impl.setCertificate(c) return 0 def pn_messenger_set_private_key(m, p): m.impl.setPrivateKey(p) return 0 def pn_messenger_set_password(m, p): m.impl.setPassword(p) return 0 def pn_messenger_set_trusted_certificates(m, t): m.impl.setTrustedCertificates(t) return 0 def pn_messenger_set_incoming_window(m, w): m.impl.setIncomingWindow(w) return 0 def pn_messenger_set_outgoing_window(m, w): m.impl.setOutgoingWindow(w) return 0 def pn_messenger_start(m): m.impl.start() return 0 # XXX: ??? def pn_messenger_work(m, t): try: if m.impl.work(t): return 1 else: return PN_TIMEOUT except InterruptException, e: return PN_INTR class pn_subscription: def __init__(self): pass def pn_messenger_subscribe(m, source): m.impl.subscribe(source) return pn_subscription() def pn_messenger_route(m, pattern, address): m.impl.route(pattern, address) return 0 def pn_messenger_rewrite(m, pattern, address): m.impl.rewrite(pattern, address) return 0 def pn_messenger_interrupt(m): m.impl.interrupt() return 0 def pn_messenger_buffered(m, t): raise Skipped() from org.apache.qpid.proton.engine import TransportException def pn_messenger_stop(m): m.impl.stop() return 0 def pn_messenger_stopped(m): return m.impl.stopped() def pn_messenger_put(m, msg): msg.pre_encode() m.impl.put(msg.impl) return 0 def pn_messenger_outgoing_tracker(m): return m.impl.outgoingTracker() def pn_messenger_send(m, n): try: m.impl.send(n) return 0 except InterruptException, e: return PN_INTR except TimeoutException, e: return PN_TIMEOUT def pn_messenger_recv(m, n): try: m.impl.recv(n) return 0 except InterruptException, e: return PN_INTR except TimeoutException, e: return PN_TIMEOUT def pn_messenger_receiving(m): return m.impl.receiving() def pn_messenger_incoming(m): return m.impl.incoming() def pn_messenger_outgoing(m): return m.impl.outgoing() def pn_messenger_get(m, msg): mimpl = m.impl.get() if msg: msg.decode(mimpl) return 0 def pn_messenger_incoming_tracker(m): return m.impl.incomingTracker() def pn_messenger_accept(m, tracker, flags): if flags: m.impl.accept(tracker, Messenger.CUMULATIVE) else: m.impl.accept(tracker, 0) return 0 def pn_messenger_reject(m, tracker, flags): if flags: m.impl.reject(tracker, Messenger.CUMULATIVE) else: m.impl.reject(tracker, 0) return 0 def pn_messenger_settle(m, tracker, flags): if flags: m.impl.settle(tracker, Messenger.CUMULATIVE) else: m.impl.settle(tracker, 0) return 0 STATUS_P2J = { PN_STATUS_UNKNOWN: Status.UNKNOWN, PN_STATUS_PENDING: Status.PENDING, PN_STATUS_ACCEPTED: Status.ACCEPTED, PN_STATUS_REJECTED: Status.REJECTED, PN_STATUS_RELEASED: Status.RELEASED, PN_STATUS_MODIFIED: Status.MODIFIED, PN_STATUS_ABORTED: Status.ABORTED, PN_STATUS_SETTLED: Status.SETTLED } STATUS_J2P = { Status.UNKNOWN: PN_STATUS_UNKNOWN, Status.PENDING: PN_STATUS_PENDING, Status.ACCEPTED: PN_STATUS_ACCEPTED, Status.REJECTED: PN_STATUS_REJECTED, Status.RELEASED: PN_STATUS_RELEASED, Status.MODIFIED: PN_STATUS_MODIFIED, Status.ABORTED: PN_STATUS_ABORTED, Status.SETTLED: PN_STATUS_SETTLED } def pn_messenger_status(m, tracker): return STATUS_J2P[m.impl.getStatus(tracker)] def pn_messenger_set_passive(m, passive): raise Skipped() def pn_messenger_selectable(m): raise Skipped() qpid-proton-0.10/proton-j/src/main/resources/cmessage.py0000664000000000000000000001517712562450203020246 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from org.apache.qpid.proton import Proton from org.apache.qpid.proton.amqp.messaging import AmqpValue, AmqpSequence, \ Data as DataSection from org.apache.qpid.proton.message import MessageFormat from ccodec import * from cerror import * # from proton/message.h PN_DATA = 0 PN_TEXT = 1 PN_AMQP = 2 PN_JSON = 3 PN_DEFAULT_PRIORITY = 4 class pn_message_wrapper: def __init__(self): self.inferred = False self.impl = Proton.message() self.id = pn_data(0) self.correlation_id = pn_data(0) self.instructions = pn_data(0) self.annotations = pn_data(0) self.properties = pn_data(0) self.body = pn_data(0) def decode(self, impl): self.impl = impl self.post_decode() def post_decode(self): obj2dat(self.impl.getMessageId(), self.id) self.id.next() obj2dat(self.impl.getCorrelationId(), self.correlation_id) self.correlation_id.next() obj2dat(self.impl.getDeliveryAnnotations(), self.instructions) obj2dat(self.impl.getMessageAnnotations(), self.annotations) obj2dat(self.impl.getApplicationProperties(), self.properties) bod = self.impl.getBody() if bod is not None: bod = bod.getValue() obj2dat(bod, self.body) def pre_encode(self): self.impl.setMessageId(dat2obj(self.id)) self.impl.setCorrelationId(dat2obj(self.correlation_id)) self.impl.setDeliveryAnnotations(dat2obj(self.instructions)) self.impl.setMessageAnnotations(dat2obj(self.annotations)) self.impl.setApplicationProperties(dat2obj(self.properties)) bod = dat2obj(self.body) if self.inferred: if isinstance(bod, bytes): bod = DataSection(Binary(array(bod, 'b'))) elif isinstance(bod, list): bod = AmqpSequence(bod) else: bod = AmqpValue(bod) else: bod = AmqpValue(bod) self.impl.setBody(bod) def __repr__(self): return self.impl.toString() def pn_message(): return pn_message_wrapper() def pn_message_id(msg): return msg.id def pn_message_correlation_id(msg): return msg.correlation_id def pn_message_get_address(msg): return msg.impl.getAddress() def pn_message_set_address(msg, address): msg.impl.setAddress(address) return 0 def pn_message_get_reply_to(msg): return msg.impl.getReplyTo() def pn_message_set_reply_to(msg, address): msg.impl.setReplyTo(address) return 0 def pn_message_get_reply_to_group_id(msg): return msg.impl.getReplyToGroupId() def pn_message_set_reply_to_group_id(msg, id): msg.impl.setReplyToGroupId(id) return 0 def pn_message_get_group_sequence(msg): return msg.impl.getGroupSequence() def pn_message_set_group_sequence(msg, seq): msg.impl.setGroupSequence(seq) return 0 def pn_message_get_group_id(msg): return msg.impl.getGroupId() def pn_message_set_group_id(msg, id): msg.impl.setGroupId(id) return 0 def pn_message_is_first_acquirer(msg): return msg.impl.isFirstAcquirer() def pn_message_set_first_acquirer(msg, b): msg.impl.setFirstAcquirer(b) return 0 def pn_message_is_durable(msg): return msg.impl.isDurable() def pn_message_set_durable(msg, b): msg.impl.setDurable(b) return 0 def pn_message_get_delivery_count(msg): return msg.impl.getDeliveryCount() def pn_message_set_delivery_count(msg, c): msg.impl.setDeliveryCount(c) return 0 def pn_message_get_creation_time(msg): return msg.impl.getCreationTime() def pn_message_set_creation_time(msg, t): msg.impl.setCreationTime(t) return 0 def pn_message_get_expiry_time(msg): return msg.impl.getExpiryTime() def pn_message_set_expiry_time(msg, t): msg.impl.setExpiryTime(t) return 0 def pn_message_get_content_type(msg): return msg.impl.getContentType() def pn_message_set_content_type(msg, ct): msg.impl.setContentType(ct) return 0 def pn_message_get_content_encoding(msg): return msg.impl.getContentEncoding() def pn_message_set_content_encoding(msg, ct): msg.impl.setContentEncoding(ct) return 0 def pn_message_get_subject(msg): return msg.impl.getSubject() def pn_message_set_subject(msg, value): msg.impl.setSubject(value) return 0 def pn_message_get_priority(msg): return msg.impl.getPriority() def pn_message_set_priority(msg, p): msg.impl.setPriority(p) return 0 def pn_message_get_ttl(msg): return msg.impl.getTtl() def pn_message_set_ttl(msg, ttl): msg.impl.setTtl(ttl) return 0 def pn_message_get_user_id(msg): uid = msg.impl.getUserId() if uid is None: return "" else: return uid.tostring() def pn_message_set_user_id(msg, uid): msg.impl.setUserId(uid) return 0 def pn_message_instructions(msg): return msg.instructions def pn_message_annotations(msg): return msg.annotations def pn_message_properties(msg): return msg.properties def pn_message_body(msg): return msg.body def pn_message_decode(msg, data): n = msg.impl.decode(array(data, 'b'), 0, len(data)) msg.post_decode() return n from java.nio import BufferOverflowException def pn_message_encode(msg, size): msg.pre_encode() ba = zeros(size, 'b') # XXX: shouldn't have to use the try/catch try: n = msg.impl.encode(ba, 0, size) if n >= 0: return n, ba[:n].tostring() else: return n except BufferOverflowException, e: return PN_OVERFLOW, None MESSAGE_FORMAT_J2P = { MessageFormat.DATA: PN_DATA, MessageFormat.TEXT: PN_TEXT, MessageFormat.AMQP: PN_AMQP, MessageFormat.JSON: PN_JSON } MESSAGE_FORMAT_P2J = { PN_DATA: MessageFormat.DATA, PN_TEXT: MessageFormat.TEXT, PN_AMQP: MessageFormat.AMQP, PN_JSON: MessageFormat.JSON } def pn_message_set_format(msg, format): msg.impl.setMessageFormat(MESSAGE_FORMAT_P2J[format]) return 0 def pn_message_clear(msg): msg.impl.clear() def pn_message_load(msg, data): msg.impl.load(data) return 0 from array import array as array_type def pn_message_save(msg, size): data = msg.impl.save() if data is None: return 0, "" elif isinstance(data, array_type): return 0, data.tostring() else: return 0, data qpid-proton-0.10/proton-j/src/main/resources/chandlers.py0000664000000000000000000000271612562450203020415 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import sys from cerror import Skipped from org.apache.qpid.proton.reactor import FlowController, Handshaker from org.apache.qpid.proton.engine import BaseHandler, HandlerException # from proton/handlers.h def pn_flowcontroller(window): return FlowController(window) def pn_handshaker(): return Handshaker() def pn_iohandler(): raise Skipped() from cengine import pn_event, pn_event_type class pn_pyhandler(BaseHandler): def __init__(self, pyobj): self.pyobj = pyobj def onUnhandled(self, event): ev = pn_event(event) try: self.pyobj.dispatch(ev, pn_event_type(ev)) except: self.pyobj.exception(*sys.exc_info()) qpid-proton-0.10/proton-j/src/main/resources/cerror.py0000664000000000000000000000236612562450203017747 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # from proton/error.h PN_EOS = -1 PN_ERR = -2 PN_OVERFLOW = -3 PN_UNDERFLOW = -4 PN_STATE_ERR = -5 PN_ARG_ERR = -6 PN_TIMEOUT =-7 PN_INTR = -8 PN_INPROGRESS =-9 class pn_error: def __init__(self, code, text): self.code = code self.text = text def set(self, code, text): self.code = code self.text = text return self.code def pn_error_code(err): return err.code def pn_error_text(err): return err.text class Skipped(Exception): skipped = True qpid-proton-0.10/proton-j/src/main/resources/cengine.py0000664000000000000000000007137112562450203020065 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from org.apache.qpid.proton import Proton from org.apache.qpid.proton.amqp import Symbol from org.apache.qpid.proton.amqp.messaging import Source, Target, \ TerminusDurability, TerminusExpiryPolicy, Received, Accepted, \ Rejected, Released, Modified from org.apache.qpid.proton.amqp.transaction import Coordinator from org.apache.qpid.proton.amqp.transport import ErrorCondition, \ SenderSettleMode, ReceiverSettleMode from org.apache.qpid.proton.engine import EndpointState, Sender, \ Receiver, Transport as _Transport, TransportException from java.util import EnumSet from compat import array, zeros from cerror import * from ccodec import * # from proton/engine.h PN_LOCAL_UNINIT = 1 PN_LOCAL_ACTIVE = 2 PN_LOCAL_CLOSED = 4 PN_REMOTE_UNINIT = 8 PN_REMOTE_ACTIVE = 16 PN_REMOTE_CLOSED = 32 PN_SND_UNSETTLED = 0 PN_SND_SETTLED = 1 PN_SND_MIXED = 2 PN_RCV_FIRST = 0 PN_RCV_SECOND = 1 PN_UNSPECIFIED = 0 PN_SOURCE = 1 PN_TARGET = 2 PN_COORDINATOR = 3 PN_NONDURABLE = 0 PN_CONFIGURATION = 1 PN_DELIVERIES = 2 PN_EXPIRE_WITH_LINK = 0 PN_EXPIRE_WITH_SESSION = 1 PN_EXPIRE_WITH_CONNECTION = 2 PN_EXPIRE_NEVER = 3 PN_DIST_MODE_UNSPECIFIED = 0 PN_DIST_MODE_COPY = 1 PN_DIST_MODE_MOVE = 2 PN_RECEIVED = (0x0000000000000023) PN_ACCEPTED = (0x0000000000000024) PN_REJECTED = (0x0000000000000025) PN_RELEASED = (0x0000000000000026) PN_MODIFIED = (0x0000000000000027) PN_TRACE_OFF = _Transport.TRACE_OFF PN_TRACE_RAW = _Transport.TRACE_RAW PN_TRACE_FRM = _Transport.TRACE_FRM PN_TRACE_DRV = _Transport.TRACE_DRV def wrap(obj, wrapper): if obj: ctx = obj.getContext() if not ctx: ctx = wrapper(obj) obj.setContext(ctx) return ctx class pn_condition: def __init__(self): self.name = None self.description = None self.info = pn_data(0) def decode(self, impl): if impl is None: self.name = None self.description = None self.info.clear() else: cond = impl.getCondition() if cond is None: self.name = None else: self.name = cond.toString() self.description = impl.getDescription() obj2dat(impl.getInfo(), self.info) def encode(self): if self.name is None: return None else: impl = ErrorCondition() impl.setCondition(Symbol.valueOf(self.name)) impl.setDescription(self.description) impl.setInfo(dat2obj(self.info)) return impl def pn_condition_is_set(cond): return bool(cond.name) def pn_condition_get_name(cond): return cond.name def pn_condition_set_name(cond, name): cond.name = name def pn_condition_get_description(cond): return cond.description def pn_condition_set_description(cond, description): cond.description = description def pn_condition_clear(cond): cond.name = None cond.description = None cond.info.clear() def pn_condition_info(cond): return cond.info class endpoint_wrapper: def __init__(self, impl): self.impl = impl self.condition = pn_condition() self.remote_condition = pn_condition() def on_close(self): cond = self.condition.encode() if cond: self.impl.setCondition(cond) def remote_condition(self): self.remote_condition.decode(self.impl.getRemoteCondition()) return self.remote_condition class pn_connection_wrapper(endpoint_wrapper): def __init__(self, impl): endpoint_wrapper.__init__(self, impl) self.properties = pn_data(0) self.offered_capabilities = pn_data(0) self.desired_capabilities = pn_data(0) def pn_connection(): return wrap(Proton.connection(), pn_connection_wrapper) def set2mask(local, remote): mask = 0 if local.contains(EndpointState.UNINITIALIZED): mask |= PN_LOCAL_UNINIT if local.contains(EndpointState.ACTIVE): mask |= PN_LOCAL_ACTIVE if local.contains(EndpointState.CLOSED): mask |= PN_LOCAL_CLOSED if remote.contains(EndpointState.UNINITIALIZED): mask |= PN_REMOTE_UNINIT if remote.contains(EndpointState.ACTIVE): mask |= PN_REMOTE_ACTIVE if remote.contains(EndpointState.CLOSED): mask |= PN_REMOTE_CLOSED return mask def endpoint_state(impl): return set2mask(EnumSet.of(impl.getLocalState()), EnumSet.of(impl.getRemoteState())) def pn_connection_state(conn): return endpoint_state(conn.impl) def pn_connection_condition(conn): return conn.condition def pn_connection_remote_condition(conn): return remote_condition(conn) def pn_connection_properties(conn): return conn.properties def pn_connection_remote_properties(conn): return obj2dat(conn.impl.getRemoteProperties()) def pn_connection_offered_capabilities(conn): return conn.offered_capabilities def pn_connection_remote_offered_capabilities(conn): return array2dat(conn.impl.getRemoteOfferedCapabilities(), PN_SYMBOL) def pn_connection_desired_capabilities(conn): return conn.desired_capabilities def pn_connection_remote_desired_capabilities(conn): return array2dat(conn.impl.getRemoteDesiredCapabilities(), PN_SYMBOL) def pn_connection_attachments(conn): return conn.impl.attachments() def pn_connection_set_container(conn, name): conn.impl.setContainer(name) def pn_connection_get_container(conn): return conn.impl.getContainer() def pn_connection_remote_container(conn): return conn.impl.getRemoteContainer() def pn_connection_get_hostname(conn): return conn.impl.getHostname() def pn_connection_set_hostname(conn, name): conn.impl.setHostname(name) def pn_connection_remote_hostname(conn): return conn.impl.getRemoteHostname() def pn_connection_open(conn): props = dat2obj(conn.properties) offered = dat2obj(conn.offered_capabilities) desired = dat2obj(conn.desired_capabilities) if props: conn.impl.setProperties(props) if offered: conn.impl.setOfferedCapabilities(array(list(offered), Symbol)) if desired: conn.impl.setDesiredCapabilities(array(list(desired), Symbol)) conn.impl.open() def pn_connection_close(conn): conn.on_close() conn.impl.close() def pn_connection_release(conn): conn.impl.free() def pn_connection_transport(conn): return wrap(conn.impl.getTransport(), pn_transport_wrapper) class pn_session_wrapper(endpoint_wrapper): pass def pn_session(conn): return wrap(conn.impl.session(), pn_session_wrapper) def pn_session_attachments(ssn): return ssn.impl.attachments() def pn_session_state(ssn): return endpoint_state(ssn.impl) def pn_session_get_incoming_capacity(ssn): return ssn.impl.getIncomingCapacity() def pn_session_set_incoming_capacity(ssn, capacity): ssn.impl.setIncomingCapacity(capacity) def pn_session_incoming_bytes(ssn): return ssn.impl.getIncomingBytes() def pn_session_outgoing_bytes(ssn): return ssn.impl.getOutgoingBytes() def pn_session_get_outgoing_window(ssn): return ssn.impl.getOutgoingWindow() def pn_session_set_outgoing_window(ssn, window): ssn.impl.setOutgoingWindow(window) def pn_session_condition(ssn): return ssn.condition def pn_session_remote_condition(ssn): return remote_condition(ssn) def pn_session_open(ssn): ssn.impl.open() def pn_session_close(ssn): ssn.on_close() ssn.impl.close() def mask2set(mask): local = [] remote = [] if PN_LOCAL_UNINIT & mask: local.append(EndpointState.UNINITIALIZED) if PN_LOCAL_ACTIVE & mask: local.append(EndpointState.ACTIVE) if PN_LOCAL_CLOSED & mask: local.append(EndpointState.CLOSED) if PN_REMOTE_UNINIT & mask: remote.append(EndpointState.UNINITIALIZED) if PN_REMOTE_ACTIVE & mask: remote.append(EndpointState.ACTIVE) if PN_REMOTE_CLOSED & mask: remote.append(EndpointState.CLOSED) if local: local = EnumSet.of(*local) else: local = None if remote: remote = EnumSet.of(*remote) else: remote = None return local, remote def pn_session_head(conn, mask): local, remote = mask2set(mask) return wrap(conn.impl.sessionHead(local, remote), pn_session_wrapper) def pn_session_connection(ssn): return wrap(ssn.impl.getConnection(), pn_connection_wrapper) def pn_sender(ssn, name): return wrap(ssn.impl.sender(name), pn_link_wrapper) def pn_receiver(ssn, name): return wrap(ssn.impl.receiver(name), pn_link_wrapper) def pn_session_free(ssn): ssn.impl.free() TERMINUS_TYPES_J2P = { Source: PN_SOURCE, Target: PN_TARGET, Coordinator: PN_COORDINATOR, None.__class__: PN_UNSPECIFIED } TERMINUS_TYPES_P2J = { PN_SOURCE: Source, PN_TARGET: Target, PN_COORDINATOR: Coordinator, PN_UNSPECIFIED: lambda: None } DURABILITY_P2J = { PN_NONDURABLE: TerminusDurability.NONE, PN_CONFIGURATION: TerminusDurability.CONFIGURATION, PN_DELIVERIES: TerminusDurability.UNSETTLED_STATE } DURABILITY_J2P = { TerminusDurability.NONE: PN_NONDURABLE, TerminusDurability.CONFIGURATION: PN_CONFIGURATION, TerminusDurability.UNSETTLED_STATE: PN_DELIVERIES } EXPIRY_POLICY_P2J = { PN_EXPIRE_WITH_LINK: TerminusExpiryPolicy.LINK_DETACH, PN_EXPIRE_WITH_SESSION: TerminusExpiryPolicy.SESSION_END, PN_EXPIRE_WITH_CONNECTION: TerminusExpiryPolicy.CONNECTION_CLOSE, PN_EXPIRE_NEVER: TerminusExpiryPolicy.NEVER } EXPIRY_POLICY_J2P = { TerminusExpiryPolicy.LINK_DETACH: PN_EXPIRE_WITH_LINK, TerminusExpiryPolicy.SESSION_END: PN_EXPIRE_WITH_SESSION, TerminusExpiryPolicy.CONNECTION_CLOSE: PN_EXPIRE_WITH_CONNECTION, TerminusExpiryPolicy.NEVER: PN_EXPIRE_NEVER } DISTRIBUTION_MODE_P2J = { PN_DIST_MODE_UNSPECIFIED: None, PN_DIST_MODE_COPY: Symbol.valueOf("copy"), PN_DIST_MODE_MOVE: Symbol.valueOf("move") } DISTRIBUTION_MODE_J2P = { None: PN_DIST_MODE_UNSPECIFIED, Symbol.valueOf("copy"): PN_DIST_MODE_COPY, Symbol.valueOf("move"): PN_DIST_MODE_MOVE } class pn_terminus: def __init__(self, type): self.type = type self.address = None self.durability = PN_NONDURABLE self.expiry_policy = PN_EXPIRE_WITH_SESSION self.distribution_mode = PN_DIST_MODE_UNSPECIFIED self.timeout = 0 self.dynamic = False self.properties = pn_data(0) self.capabilities = pn_data(0) self.outcomes = pn_data(0) self.filter = pn_data(0) def copy(self, src): self.type = src.type self.address = src.address self.durability = src.durability self.expiry_policy = src.expiry_policy self.timeout = src.timeout self.dynamic = src.dynamic self.properties = src.properties self.capabilities = src.capabilities self.outcomes = src.outcomes self.filter = src.filter def decode(self, impl): if impl is not None: self.type = TERMINUS_TYPES_J2P[impl.__class__] if self.type in (PN_SOURCE, PN_TARGET): self.address = impl.getAddress() self.durability = DURABILITY_J2P[impl.getDurable()] self.expiry_policy = EXPIRY_POLICY_J2P[impl.getExpiryPolicy()] self.timeout = impl.getTimeout().longValue() self.dynamic = impl.getDynamic() obj2dat(impl.getDynamicNodeProperties(), self.properties) array2dat(impl.getCapabilities(), PN_SYMBOL, self.capabilities) if self.type == PN_SOURCE: self.distribution_mode = DISTRIBUTION_MODE_J2P[impl.getDistributionMode()] array2dat(impl.getOutcomes(), PN_SYMBOL, self.outcomes) obj2dat(impl.getFilter(), self.filter) def encode(self): impl = TERMINUS_TYPES_P2J[self.type]() if self.type in (PN_SOURCE, PN_TARGET): impl.setAddress(self.address) impl.setDurable(DURABILITY_P2J[self.durability]) impl.setExpiryPolicy(EXPIRY_POLICY_P2J[self.expiry_policy]) impl.setTimeout(UnsignedInteger.valueOf(self.timeout)) impl.setDynamic(self.dynamic) props = dat2obj(self.properties) caps = dat2obj(self.capabilities) if props: impl.setDynamicNodeProperties(props) if caps: impl.setCapabilities(*array(list(caps), Symbol)) if self.type == PN_SOURCE: impl.setDistributionMode(DISTRIBUTION_MODE_P2J[self.distribution_mode]) outcomes = dat2obj(self.outcomes) filter = dat2obj(self.filter) if outcomes: impl.setOutcomes(outcomes) if filter: impl.setFilter(filter) return impl def pn_terminus_get_type(terminus): return terminus.type def pn_terminus_set_type(terminus, type): terminus.type = type return 0 def pn_terminus_get_address(terminus): return terminus.address def pn_terminus_set_address(terminus, address): terminus.address = address return 0 def pn_terminus_get_durability(terminus): return terminus.durability def pn_terminus_get_expiry_policy(terminus): return terminus.expiry_policy def pn_terminus_set_timeout(terminus, timeout): terminus.timeout = timeout return 0 def pn_terminus_get_timeout(terminus): return terminus.timeout def pn_terminus_get_distribution_mode(terminus): return terminus.distribution_mode def pn_terminus_set_distribution_mode(terminus, mode): terminus.distribution_mode = mode return 0 def pn_terminus_is_dynamic(terminus): return terminus.dynamic def pn_terminus_set_dynamic(terminus, dynamic): terminus.dynamic = dynamic return 0 def pn_terminus_properties(terminus): return terminus.properties def pn_terminus_capabilities(terminus): return terminus.capabilities def pn_terminus_outcomes(terminus): return terminus.outcomes def pn_terminus_filter(terminus): return terminus.filter def pn_terminus_copy(terminus, src): terminus.copy(src) return 0 class pn_link_wrapper(endpoint_wrapper): def __init__(self, impl): endpoint_wrapper.__init__(self, impl) self.source = pn_terminus(PN_SOURCE) self.remote_source = pn_terminus(PN_UNSPECIFIED) self.target = pn_terminus(PN_TARGET) self.remote_target = pn_terminus(PN_UNSPECIFIED) def on_open(self): self.impl.setSource(self.source.encode()) self.impl.setTarget(self.target.encode()) def pn_link_attachments(link): return link.impl.attachments() def pn_link_source(link): link.source.decode(link.impl.getSource()) return link.source def pn_link_remote_source(link): link.remote_source.decode(link.impl.getRemoteSource()) return link.remote_source def pn_link_target(link): link.target.decode(link.impl.getTarget()) return link.target def pn_link_remote_target(link): link.remote_target.decode(link.impl.getRemoteTarget()) return link.remote_target def pn_link_condition(link): return link.condition def pn_link_remote_condition(link): return remote_condition(link) SND_SETTLE_MODE_P2J = { PN_SND_UNSETTLED: SenderSettleMode.UNSETTLED, PN_SND_SETTLED: SenderSettleMode.SETTLED, PN_SND_MIXED: SenderSettleMode.MIXED, None: None } SND_SETTLE_MODE_J2P = { SenderSettleMode.UNSETTLED: PN_SND_UNSETTLED, SenderSettleMode.SETTLED: PN_SND_SETTLED, SenderSettleMode.MIXED: PN_SND_MIXED, None: None } def pn_link_set_snd_settle_mode(link, mode): link.impl.setSenderSettleMode(SND_SETTLE_MODE_P2J[mode]) def pn_link_snd_settle_mode(link): return SND_SETTLE_MODE_J2P[link.impl.getSenderSettleMode()] def pn_link_remote_snd_settle_mode(link): return SND_SETTLE_MODE_J2P[link.impl.getRemoteSenderSettleMode()] RCV_SETTLE_MODE_P2J = { PN_RCV_FIRST: ReceiverSettleMode.FIRST, PN_RCV_SECOND: ReceiverSettleMode.SECOND, None: None } RCV_SETTLE_MODE_J2P = { ReceiverSettleMode.FIRST: PN_RCV_FIRST, ReceiverSettleMode.SECOND: PN_RCV_SECOND, None: None } def pn_link_set_rcv_settle_mode(link, mode): link.impl.setReceiverSettleMode(RCV_SETTLE_MODE_P2J[mode]) def pn_link_rcv_settle_mode(link): return RCV_SETTLE_MODE_J2P[link.impl.getReceiverSettleMode()] def pn_link_remote_rcv_settle_mode(link): return RCV_SETTLE_MODE_J2P[link.impl.getRemoteReceiverSettleMode()] def pn_link_is_sender(link): return isinstance(link.impl, Sender) def pn_link_is_receiver(link): return isinstance(link.impl, Receiver) def pn_link_head(conn, mask): local, remote = mask2set(mask) return wrap(conn.impl.linkHead(local, remote), pn_link_wrapper) def pn_link_next(link, mask): local, remote = mask2set(mask) return wrap(link.impl.next(local, remote), pn_link_wrapper) def pn_link_session(link): return wrap(link.impl.getSession(), pn_session_wrapper) def pn_link_state(link): return endpoint_state(link.impl) def pn_link_name(link): return link.impl.getName() def pn_link_open(link): link.on_open() link.impl.open() def pn_link_close(link): link.on_close() link.impl.close() def pn_link_detach(link): link.on_close() link.impl.detach() def pn_link_flow(link, n): link.impl.flow(n) def pn_link_drain(link, n): link.impl.drain(n) def pn_link_drained(link): return link.impl.drained() def pn_link_draining(link): return link.impl.draining() def pn_link_credit(link): return link.impl.getCredit() def pn_link_queued(link): return link.impl.getQueued() def pn_link_unsettled(link): return link.impl.getUnsettled() def pn_link_send(link, bytes): return link.impl.send(array(bytes, 'b'), 0, len(bytes)) def pn_link_recv(link, limit): ary = zeros(limit, 'b') n = link.impl.recv(ary, 0, limit) if n >= 0: bytes = ary[:n].tostring() else: bytes = None return n, bytes def pn_link_advance(link): return link.impl.advance() def pn_link_current(link): return wrap(link.impl.current(), pn_delivery_wrapper) def pn_link_free(link): link.impl.free() def pn_work_head(conn): return wrap(conn.impl.getWorkHead(), pn_delivery_wrapper) def pn_work_next(dlv): return wrap(dlv.impl.getWorkNext(), pn_delivery_wrapper) DELIVERY_STATES = { Received: PN_RECEIVED, Accepted: PN_ACCEPTED, Rejected: PN_REJECTED, Released: PN_RELEASED, Modified: PN_MODIFIED, None.__class__: 0 } DISPOSITIONS = { PN_RECEIVED: Received, PN_ACCEPTED: Accepted, PN_REJECTED: Rejected, PN_RELEASED: Released, PN_MODIFIED: Modified, 0: lambda: None } class pn_disposition: def __init__(self): self.type = 0 self.data = pn_data(0) self.failed = False self.undeliverable = False self.annotations = pn_data(0) self.condition = pn_condition() self.section_number = 0 self.section_offset = 0 def decode(self, impl): self.type = DELIVERY_STATES[impl.__class__] if self.type == PN_REJECTED: self.condition.decode(impl.getError()) else: pn_condition_clear(self.condition) if self.type == PN_MODIFIED: self.failed = impl.getDeliveryFailed() self.undeliverable = impl.getUndeliverableHere() obj2dat(impl.getMessageAnnotations(), self.annotations) else: self.failed = False self.undeliverable = False pn_data_clear(self.annotations) if self.type == PN_RECEIVED: self.section_number = impl.getSectionNumber().longValue() self.section_offset = impl.getSectionOffset().longValue() else: self.section_number = 0 self.section_offset = 0 self.data.clear() if impl: # XXX #self.data.putObject(impl) pass self.data.rewind() def encode(self): if self.type not in DISPOSITIONS: raise Skipped() impl = DISPOSITIONS[self.type]() if impl is None: return impl if self.type == PN_REJECTED: impl.setError(self.condition.encode()) if self.type == PN_MODIFIED: impl.setDeliveryFailed(self.failed) impl.setUndeliverableHere(self.undeliverable) ann = dat2obj(self.annotations) if ann: impl.setMessageAnnotations(ann) if self.type == PN_RECEIVED: if self.section_number: impl.setSectionNumber(UnsignedInteger.valueOf(self.section_number)) if self.section_offset: impl.setSectionOffset(UnsignedLong.valueOf(self.section_offset)) return impl def pn_disposition_type(dsp): return dsp.type def pn_disposition_is_failed(dsp): return dsp.failed def pn_disposition_set_failed(dsp, failed): dsp.failed = failed def pn_disposition_is_undeliverable(dsp): return dsp.undeliverable def pn_disposition_set_undeliverable(dsp, undeliverable): dsp.undeliverable = undeliverable def pn_disposition_data(dsp): return dsp.data def pn_disposition_annotations(dsp): return dsp.annotations def pn_disposition_condition(dsp): return dsp.condition def pn_disposition_get_section_number(dsp): return dsp.section_number def pn_disposition_set_section_number(dsp, number): dsp.section_number = number def pn_disposition_get_section_offset(dsp): return dsp.section_offset def pn_disposition_set_section_offset(dsp, offset): dsp.section_offset = offset class pn_delivery_wrapper: def __init__(self, impl): self.impl = impl self.local = pn_disposition() self.remote = pn_disposition() def pn_delivery(link, tag): return wrap(link.impl.delivery(array(tag, 'b')), pn_delivery_wrapper) def pn_delivery_tag(dlv): return dlv.impl.getTag().tostring() def pn_delivery_attachments(dlv): return dlv.impl.attachments() def pn_delivery_partial(dlv): return dlv.impl.isPartial() def pn_delivery_pending(dlv): return dlv.impl.pending() def pn_delivery_writable(dlv): return dlv.impl.isWritable() def pn_delivery_readable(dlv): return dlv.impl.isReadable() def pn_delivery_updated(dlv): return dlv.impl.isUpdated() def pn_delivery_settled(dlv): return dlv.impl.remotelySettled() def pn_delivery_local(dlv): dlv.local.decode(dlv.impl.getLocalState()) return dlv.local def pn_delivery_local_state(dlv): dlv.local.decode(dlv.impl.getLocalState()) return dlv.local.type def pn_delivery_remote(dlv): dlv.remote.decode(dlv.impl.getRemoteState()) return dlv.remote def pn_delivery_remote_state(dlv): dlv.remote.decode(dlv.impl.getRemoteState()) return dlv.remote.type def pn_delivery_update(dlv, state): dlv.local.type = state dlv.impl.disposition(dlv.local.encode()) def pn_delivery_link(dlv): return wrap(dlv.impl.getLink(), pn_link_wrapper) def pn_delivery_settle(dlv): dlv.impl.settle() class pn_transport_wrapper: def __init__(self, impl): self.impl = impl self.server = False self.condition = pn_condition() def pn_transport(): return wrap(Proton.transport(), pn_transport_wrapper) def pn_transport_get_pytracer(trans): raise Skipped() def pn_transport_attachments(trans): return trans.impl.attachments() def pn_transport_set_server(trans): trans.server = True; def pn_transport_get_max_frame(trans): return trans.impl.getMaxFrameSize() def pn_transport_set_max_frame(trans, value): trans.impl.setMaxFrameSize(value) def pn_transport_get_remote_max_frame(trans): return trans.impl.getRemoteMaxFrameSize() def pn_transport_set_idle_timeout(trans, value): trans.impl.setIdleTimeout(value); def pn_transport_get_idle_timeout(trans): return trans.impl.getIdleTimeout() def pn_transport_get_remote_idle_timeout(trans): return trans.impl.getRemoteIdleTimeout() def pn_transport_get_frames_input(trans): return trans.impl.getFramesInput() def pn_transport_get_frames_output(trans): return trans.impl.getFramesOutput() def pn_transport_set_channel_max(trans, n): trans.impl.setChannelMax(n) def pn_transport_get_channel_max(trans): return trans.impl.getChannelMax() def pn_transport_remote_channel_max(trans): return trans.impl.getRemoteChannelMax() def pn_transport_tick(trans, now): return trans.impl.tick(now); def pn_transport_bind(trans, conn): trans.impl.bind(conn.impl) return 0 def pn_transport_unbind(trans): trans.impl.unbind() return 0 def pn_transport_trace(trans, n): trans.impl.trace(n) def pn_transport_pending(trans): return trans.impl.pending() def pn_transport_peek(trans, size): size = min(trans.impl.pending(), size) ba = zeros(size, 'b') if size: bb = trans.impl.head() bb.get(ba) bb.position(0) return 0, ba.tostring() def pn_transport_pop(trans, size): trans.impl.pop(size) def pn_transport_capacity(trans): return trans.impl.capacity() def pn_transport_push(trans, input): result = 0 while input: cap = pn_transport_capacity(trans) if cap < 0: return cap elif len(input) > cap: trimmed = input[:cap] else: trimmed = input bb = trans.impl.tail() bb.put(array(trimmed, 'b')) trans.impl.process() input = input[cap:] result += len(trimmed) return result def pn_transport_close_head(trans): trans.impl.close_head() return 0 def pn_transport_close_tail(trans): trans.impl.close_tail() return 0 def pn_transport_closed(trans): return trans.impl.isClosed() def pn_transport_condition(trans): trans.condition.decode(trans.impl.getCondition()) return trans.condition from org.apache.qpid.proton.engine import Event PN_REACTOR_INIT = Event.Type.REACTOR_INIT PN_REACTOR_QUIESCED = Event.Type.REACTOR_QUIESCED PN_REACTOR_FINAL = Event.Type.REACTOR_FINAL PN_TIMER_TASK = Event.Type.TIMER_TASK PN_CONNECTION_INIT = Event.Type.CONNECTION_INIT PN_CONNECTION_BOUND = Event.Type.CONNECTION_BOUND PN_CONNECTION_UNBOUND = Event.Type.CONNECTION_UNBOUND PN_CONNECTION_LOCAL_OPEN = Event.Type.CONNECTION_LOCAL_OPEN PN_CONNECTION_REMOTE_OPEN = Event.Type.CONNECTION_REMOTE_OPEN PN_CONNECTION_LOCAL_CLOSE = Event.Type.CONNECTION_LOCAL_CLOSE PN_CONNECTION_REMOTE_CLOSE = Event.Type.CONNECTION_REMOTE_CLOSE PN_CONNECTION_FINAL = Event.Type.CONNECTION_FINAL PN_SESSION_INIT = Event.Type.SESSION_INIT PN_SESSION_LOCAL_OPEN = Event.Type.SESSION_LOCAL_OPEN PN_SESSION_REMOTE_OPEN = Event.Type.SESSION_REMOTE_OPEN PN_SESSION_LOCAL_CLOSE = Event.Type.SESSION_LOCAL_CLOSE PN_SESSION_REMOTE_CLOSE = Event.Type.SESSION_REMOTE_CLOSE PN_SESSION_FINAL = Event.Type.SESSION_FINAL PN_LINK_INIT = Event.Type.LINK_INIT PN_LINK_LOCAL_OPEN = Event.Type.LINK_LOCAL_OPEN PN_LINK_REMOTE_OPEN = Event.Type.LINK_REMOTE_OPEN PN_LINK_LOCAL_CLOSE = Event.Type.LINK_LOCAL_CLOSE PN_LINK_REMOTE_CLOSE = Event.Type.LINK_REMOTE_CLOSE PN_LINK_LOCAL_DETACH = Event.Type.LINK_LOCAL_DETACH PN_LINK_REMOTE_DETACH = Event.Type.LINK_REMOTE_DETACH PN_LINK_FLOW = Event.Type.LINK_FLOW PN_LINK_FINAL = Event.Type.LINK_FINAL PN_DELIVERY = Event.Type.DELIVERY PN_TRANSPORT = Event.Type.TRANSPORT PN_TRANSPORT_ERROR = Event.Type.TRANSPORT_ERROR PN_TRANSPORT_HEAD_CLOSED = Event.Type.TRANSPORT_HEAD_CLOSED PN_TRANSPORT_TAIL_CLOSED = Event.Type.TRANSPORT_TAIL_CLOSED PN_TRANSPORT_CLOSED = Event.Type.TRANSPORT_CLOSED PN_SELECTABLE_INIT = Event.Type.SELECTABLE_INIT PN_SELECTABLE_UPDATED = Event.Type.SELECTABLE_UPDATED PN_SELECTABLE_READABLE = Event.Type.SELECTABLE_READABLE PN_SELECTABLE_WRITABLE = Event.Type.SELECTABLE_WRITABLE PN_SELECTABLE_EXPIRED = Event.Type.SELECTABLE_EXPIRED PN_SELECTABLE_ERROR = Event.Type.SELECTABLE_ERROR PN_SELECTABLE_FINAL = Event.Type.SELECTABLE_FINAL def pn_collector(): return Proton.collector() def pn_connection_collect(conn, coll): conn.impl.collect(coll) class pn_event: def __init__(self, impl): self.impl = impl def pn_collector_peek(coll): ev = coll.peek() if ev: return pn_event(ev.copy()) else: return None def pn_collector_pop(coll): coll.pop() def pn_collector_free(coll): pass def pn_event_reactor(event): return event.impl.getReactor() def pn_event_connection(event): return wrap(event.impl.getConnection(), pn_connection_wrapper) def pn_event_session(event): return wrap(event.impl.getSession(), pn_session_wrapper) def pn_event_link(event): return wrap(event.impl.getLink(), pn_link_wrapper) def pn_event_delivery(event): return wrap(event.impl.getDelivery(), pn_delivery_wrapper) def pn_event_transport(event): return wrap(event.impl.getTransport(), pn_transport_wrapper) from org.apache.qpid.proton.engine.impl import ConnectionImpl, SessionImpl, \ SenderImpl, ReceiverImpl, DeliveryImpl, TransportImpl from org.apache.qpid.proton.reactor.impl import TaskImpl, SelectableImpl J2C = { ConnectionImpl: "pn_connection", SessionImpl: "pn_session", SenderImpl: "pn_link", ReceiverImpl: "pn_link", DeliveryImpl: "pn_delivery", TransportImpl: "pn_transport", TaskImpl: "pn_task", SelectableImpl: "pn_selectable" } wrappers = { "pn_connection": lambda x: wrap(x, pn_connection_wrapper), "pn_session": lambda x: wrap(x, pn_session_wrapper), "pn_link": lambda x: wrap(x, pn_link_wrapper), "pn_delivery": lambda x: wrap(x, pn_delivery_wrapper), "pn_transport": lambda x: wrap(x, pn_transport_wrapper), "pn_task": lambda x: x, "pn_selectable": lambda x: x, "pn_void": lambda x: x } def pn_event_class(event): ctx = event.impl.getContext() return J2C.get(ctx.getClass(), "pn_void") def pn_event_context(event): return wrappers[pn_event_class(event)](event.impl.getContext()) def pn_event_type(event): return event.impl.getType() def pn_event_type_name(etype): return str(etype) def pn_event_category(event): return event.impl.getCategory() def pn_event_attachments(event): return event.impl.attachments() qpid-proton-0.10/proton-j/src/main/resources/cdriver.py0000664000000000000000000000347212562450203020110 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from org.apache.qpid.proton import Proton # from proton/driver.h def pn_driver(): return Proton.driver() def pn_driver_wait(drv, t): drv.doWait(t) def pn_driver_listener(drv): return drv.listener() def pn_driver_connector(drv): return drv.connector() def pn_listener(drv, host, port, ctx): return drv.createListener(host, int(port), ctx) def pn_listener_context(l): return l.getContext() def pn_listener_set_context(l, v): l.setContext(v) def pn_listener_accept(l): return l.accept() def pn_connector(drv, host, port, ctx): return drv.createConnector(host, int(port), ctx) def pn_connector_context(c): return c.getContext() def pn_connector_set_context(c, v): c.setContext(v) def pn_connector_set_connection(c, conn): c.setConnection(conn.impl) def pn_connector_connection(c): return wrap(c.getConnection(), pn_connection_wrapper) def pn_connector_transport(c): return wrap(c.getTransport(), pn_transport_wrapper) def pn_connector_process(c): return c.process() def pn_connector_closed(c): return c.isClosed() qpid-proton-0.10/proton-j/src/main/resources/ccodec.py0000664000000000000000000001713712562450203017675 0ustar # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from org.apache.qpid.proton import Proton from org.apache.qpid.proton.amqp import Symbol, UnsignedByte, UnsignedInteger, \ UnsignedLong, Decimal32, Decimal64, Decimal128 from org.apache.qpid.proton.codec.Data import DataType from java.util import UUID as JUUID, Date as JDate from java.nio import ByteBuffer from compat import array, zeros # from proton/codec.h PN_NULL = 1 PN_BOOL = 2 PN_UBYTE = 3 PN_BYTE = 4 PN_USHORT = 5 PN_SHORT = 6 PN_UINT = 7 PN_INT = 8 PN_CHAR = 9 PN_ULONG = 10 PN_LONG = 11 PN_TIMESTAMP = 12 PN_FLOAT = 13 PN_DOUBLE = 14 PN_DECIMAL32 = 15 PN_DECIMAL64 = 16 PN_DECIMAL128 = 17 PN_UUID = 18 PN_BINARY = 19 PN_STRING = 20 PN_SYMBOL = 21 PN_DESCRIBED = 22 PN_ARRAY = 23 PN_LIST = 24 PN_MAP = 25 DATA_TYPES_J2P = {} DATA_TYPES_P2J = {} def DATA_TYPES(jtype, ptype): DATA_TYPES_J2P[jtype] = ptype DATA_TYPES_P2J[ptype] = jtype DATA_TYPES(DataType.NULL, PN_NULL) DATA_TYPES(DataType.BOOL, PN_BOOL) DATA_TYPES(DataType.BYTE, PN_BYTE) DATA_TYPES(DataType.UBYTE, PN_UBYTE) DATA_TYPES(DataType.USHORT, PN_USHORT) DATA_TYPES(DataType.UINT, PN_UINT) DATA_TYPES(DataType.ULONG, PN_ULONG) DATA_TYPES(DataType.SHORT, PN_SHORT) DATA_TYPES(DataType.INT, PN_INT) DATA_TYPES(DataType.LONG, PN_LONG) DATA_TYPES(DataType.CHAR, PN_CHAR) DATA_TYPES(DataType.TIMESTAMP, PN_TIMESTAMP) DATA_TYPES(DataType.FLOAT, PN_FLOAT) DATA_TYPES(DataType.DOUBLE, PN_DOUBLE) DATA_TYPES(DataType.DECIMAL32, PN_DECIMAL32) DATA_TYPES(DataType.DECIMAL64, PN_DECIMAL64) DATA_TYPES(DataType.DECIMAL128, PN_DECIMAL128) DATA_TYPES(DataType.BINARY, PN_BINARY) DATA_TYPES(DataType.STRING, PN_STRING) DATA_TYPES(DataType.SYMBOL, PN_SYMBOL) DATA_TYPES(DataType.UUID, PN_UUID) DATA_TYPES(DataType.LIST, PN_LIST) DATA_TYPES(DataType.MAP, PN_MAP) DATA_TYPES(DataType.ARRAY, PN_ARRAY) DATA_TYPES(DataType.DESCRIBED, PN_DESCRIBED) def pn_data(capacity): return Proton.data(capacity) def pn_data_put_null(data): data.putNull() return 0 def pn_data_put_bool(data, b): data.putBoolean(b) return 0 def pn_data_get_bool(data): return data.getBoolean() def pn_data_get_byte(data): return data.getByte() def pn_data_put_byte(data, u): data.putByte(u) return 0 def pn_data_get_ubyte(data): return data.getUnsignedByte().longValue() def pn_data_put_ubyte(data, u): data.putUnsignedByte(UnsignedByte.valueOf(u)) return 0 def pn_data_get_ushort(data): return data.getUnsignedShort().longValue() def pn_data_put_ushort(data, u): data.putUnsignedShort(UnsignedShort.valueOf(u)) return 0 def pn_data_get_uint(data): return data.getUnsignedInteger().longValue() def pn_data_put_uint(data, u): data.putUnsignedInteger(UnsignedInteger.valueOf(u)) return 0 def pn_data_put_ulong(data, u): data.putUnsignedLong(UnsignedLong.valueOf(u)) return 0 BITS_64 = 2**64 - 1; def pn_data_get_ulong(data): value = data.getUnsignedLong().longValue() if value < 0: return value & BITS_64; return value def pn_data_get_short(data): return data.getShort() def pn_data_put_short(data, s): data.putShort(s) return 0 def pn_data_put_int(data, i): data.putInt(i) return 0 def pn_data_get_int(data): return data.getInt() def pn_data_put_long(data, l): data.putLong(l) return 0 def pn_data_get_long(data): return data.getLong() def pn_data_put_char(data, c): data.putChar(c) return 0 def pn_data_get_char(data): return data.getChar() def pn_data_put_timestamp(data, t): data.putTimestamp(JDate(t)) return 0 def pn_data_get_timestamp(data): return data.getTimestamp().getTime() def pn_data_put_float(data, f): data.putFloat(f) return 0 def pn_data_get_float(data): return data.getFloat() def pn_data_put_double(data, d): data.putDouble(d) return 0 def pn_data_get_double(data): return data.getDouble() def pn_data_put_decimal32(data, d): data.putDecimal32(Decimal32(d)) return 0 def pn_data_get_decimal32(data): return data.getDecimal32().getBits() def pn_data_put_decimal64(data, d): data.putDecimal64(Decimal64(d)) return 0 def pn_data_get_decimal64(data): return data.getDecimal64().getBits() def pn_data_put_decimal128(data, d): data.putDecimal128(Decimal128(array(d, 'b'))) return 0 def pn_data_get_decimal128(data): return data.getDecimal128().asBytes().tostring() def pn_data_put_binary(data, b): data.putBinary(array(b, 'b')) return 0 def pn_data_get_binary(data): return data.getBinary().getArray().tostring() def pn_data_put_string(data, s): data.putString(s) return 0 def pn_data_get_string(data): return data.getString() def pn_data_put_symbol(data, s): data.putSymbol(Symbol.valueOf(s)) return 0 def pn_data_get_symbol(data): return data.getSymbol().toString() def pn_data_put_uuid(data, u): bb = ByteBuffer.wrap(array(u, 'b')) first = bb.getLong() second = bb.getLong() data.putUUID(JUUID(first, second)) return 0 def pn_data_get_uuid(data): u = data.getUUID() ba = zeros(16, 'b') bb = ByteBuffer.wrap(ba) bb.putLong(u.getMostSignificantBits()) bb.putLong(u.getLeastSignificantBits()) return ba.tostring() def pn_data_put_list(data): data.putList() return 0 def pn_data_get_list(data): return data.getList() def pn_data_put_map(data): data.putMap() return 0 def pn_data_put_array(data, described, type): data.putArray(described, DATA_TYPES_P2J[type]) return 0 def pn_data_get_array(data): return data.getArray() def pn_data_is_array_described(data): return data.isArrayDescribed() def pn_data_get_array_type(data): return DATA_TYPES_J2P[data.getArrayType()] def pn_data_put_described(data): data.putDescribed() return 0 def pn_data_rewind(data): data.rewind() def pn_data_next(data): t = data.next() return t != None def pn_data_enter(data): return data.enter() def pn_data_exit(data): return data.exit() def pn_data_type(data): t = data.type() if t is None: return -1 else: return DATA_TYPES_J2P[t] def pn_data_encode(data, size): enc = data.encode().getArray().tostring() if len(enc) > size: return PN_OVERFLOW, None else: return len(enc), enc def pn_data_encoded_size(data): return data.encodedSize() def pn_data_decode(data, encoded): return data.decode(ByteBuffer.wrap(array(encoded, 'b'))) def pn_data_narrow(data): data.narrow() def pn_data_widen(data): data.widen() def pn_data_copy(data, src): data.copy(src) def pn_data_format(data, n): return 0, data.format() def pn_data_clear(data): data.clear() def pn_data_free(data): pass def dat2obj(dat): dat.rewind() if dat.next(): return dat.getObject() else: return None def obj2dat(obj, dat=None): if dat is None: dat = pn_data(0) else: dat.clear() if obj: dat.putObject(obj) dat.rewind() return dat def array2dat(ary, atype, dat=None): if dat is None: dat = pn_data(0) else: dat.clear() if ary: pn_data_put_array(dat, False, atype) pn_data_enter(dat) for o in ary: dat.putObject(o) dat.rewind() return dat qpid-proton-0.10/proton-j/src/main/resources/META-INF/0000775000000000000000000000000012562450203017232 5ustar qpid-proton-0.10/proton-j/src/main/resources/META-INF/services/0000775000000000000000000000000012562450203021055 5ustar ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootqpid-proton-0.10/proton-j/src/main/resources/META-INF/services/org.apache.qpid.proton.messenger.MessengerFactoryqpid-proton-0.10/proton-j/src/main/resources/META-INF/services/org.apache.qpid.proton.messenger.Mess0000664000000000000000000000007212562450203030157 0ustar org.apache.qpid.proton.messenger.impl.MessengerFactoryImpl././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootqpid-proton-0.10/proton-j/src/main/resources/META-INF/services/org.apache.qpid.proton.message.MessageFactoryqpid-proton-0.10/proton-j/src/main/resources/META-INF/services/org.apache.qpid.proton.message.Messag0000664000000000000000000000006612562450203030126 0ustar org.apache.qpid.proton.message.impl.MessageFactoryImpl././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootqpid-proton-0.10/proton-j/src/main/resources/META-INF/services/org.apache.qpid.proton.engine.EngineFactoryqpid-proton-0.10/proton-j/src/main/resources/META-INF/services/org.apache.qpid.proton.engine.EngineF0000664000000000000000000000006412562450203030041 0ustar org.apache.qpid.proton.engine.impl.EngineFactoryImpl././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootqpid-proton-0.10/proton-j/src/main/resources/META-INF/services/org.apache.qpid.proton.driver.DriverFactoryqpid-proton-0.10/proton-j/src/main/resources/META-INF/services/org.apache.qpid.proton.driver.DriverF0000664000000000000000000000006412562450203030115 0ustar org.apache.qpid.proton.driver.impl.DriverFactoryImpl././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootqpid-proton-0.10/proton-j/src/main/resources/META-INF/services/org.apache.qpid.proton.codec.DataFactoryqpid-proton-0.10/proton-j/src/main/resources/META-INF/services/org.apache.qpid.proton.codec.DataFact0000664000000000000000000000006112562450203030002 0ustar org.apache.qpid.proton.codec.impl.DataFactoryImplqpid-proton-0.10/proton-j/src/main/java/0000775000000000000000000000000012562450203015001 5ustar qpid-proton-0.10/proton-j/src/main/java/org/0000775000000000000000000000000012562450203015570 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/0000775000000000000000000000000012562450203017011 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/0000775000000000000000000000000012562450203017746 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/0000775000000000000000000000000012562450203021267 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/0000775000000000000000000000000012562450203022726 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/0000775000000000000000000000000012562450203023667 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/Timer.java0000664000000000000000000000444112562450203025615 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; import java.util.PriorityQueue; import org.apache.qpid.proton.engine.Collector; import org.apache.qpid.proton.engine.Event.Type; import org.apache.qpid.proton.engine.impl.CollectorImpl; import org.apache.qpid.proton.reactor.Task; public class Timer { private CollectorImpl collector; private PriorityQueue tasks = new PriorityQueue(); public Timer(Collector collector) { this.collector = (CollectorImpl)collector; } Task schedule(long deadline) { TaskImpl task = new TaskImpl(deadline); tasks.add(task); return task; } long deadline() { flushCancelled(); if (tasks.size() > 0) { Task task = tasks.peek(); return task.deadline(); } else { return 0; } } private void flushCancelled() { while (!tasks.isEmpty()) { TaskImpl task = tasks.peek(); if (task.isCancelled()) tasks.poll(); else break; } } void tick(long now) { while(!tasks.isEmpty()) { TaskImpl task = tasks.peek(); if (now >= task.deadline()) { tasks.poll(); if (!task.isCancelled()) collector.put(Type.TIMER_TASK, task); } else { break; } } } int tasks() { flushCancelled(); return tasks.size(); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/TaskImpl.java0000664000000000000000000000442012562450203026256 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; import java.util.concurrent.atomic.AtomicInteger; import org.apache.qpid.proton.engine.Record; import org.apache.qpid.proton.engine.impl.RecordImpl; import org.apache.qpid.proton.reactor.Reactor; import org.apache.qpid.proton.reactor.Task; public class TaskImpl implements Task, Comparable { private final long deadline; private final int counter; private boolean cancelled = false; private final AtomicInteger count = new AtomicInteger(); private Record attachments = new RecordImpl(); private Reactor reactor; public TaskImpl(long deadline) { this.deadline = deadline; this.counter = count.getAndIncrement(); } @Override public int compareTo(TaskImpl other) { int result; if (deadline < other.deadline) { result = -1; } else if (deadline > other.deadline) { result = 1; } else { result = counter - other.counter; } return result; } @Override public long deadline() { return deadline; } public boolean isCancelled() { return cancelled; } @Override public void cancel() { cancelled = true; } public void setReactor(Reactor reactor) { this.reactor = reactor; } @Override public Reactor getReactor() { return reactor; } @Override public Record attachments() { return attachments; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/SelectorImpl.java0000664000000000000000000001710212562450203027135 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; import java.io.IOException; import java.nio.channels.SelectionKey; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.HashSet; import java.util.Iterator; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.transport.ErrorCondition; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.reactor.Selectable; import org.apache.qpid.proton.reactor.Selector; class SelectorImpl implements Selector { private final java.nio.channels.Selector selector; private final HashSet selectables = new HashSet(); private final HashSet readable = new HashSet(); private final HashSet writeable = new HashSet(); private final HashSet expired = new HashSet(); private final HashSet error = new HashSet(); protected SelectorImpl(IO io) throws IOException { selector = io.selector(); } @Override public void add(Selectable selectable) throws IOException { // Selectable can be 'null' - if this is the case it can only ever receive expiry events. if (selectable.getChannel() != null) { selectable.getChannel().configureBlocking(false); SelectionKey key = selectable.getChannel().register(selector, 0); key.attach(selectable); } selectables.add(selectable); update(selectable); } @Override public void update(Selectable selectable) { if (selectable.getChannel() != null) { int interestedOps = 0; if (selectable.getChannel() instanceof SocketChannel && ((SocketChannel)selectable.getChannel()).isConnectionPending()) { interestedOps |= SelectionKey.OP_CONNECT; } else { if (selectable.isReading()) { if (selectable.getChannel() instanceof ServerSocketChannel) { interestedOps |= SelectionKey.OP_ACCEPT; } else { interestedOps |= SelectionKey.OP_READ; } } if (selectable.isWriting()) interestedOps |= SelectionKey.OP_WRITE; } SelectionKey key = selectable.getChannel().keyFor(selector); key.interestOps(interestedOps); } } @Override public void remove(Selectable selectable) { if (selectable.getChannel() != null) { SelectionKey key = selectable.getChannel().keyFor(selector); if (key != null) { key.cancel(); key.attach(null); } } selectables.remove(selectable); } @Override public void select(long timeout) throws IOException { long now = System.currentTimeMillis(); if (timeout > 0) { long deadline = 0; // XXX: Note: this differs from the C code which requires a call to update() to make deadline changes take affect for (Selectable selectable : selectables) { long d = selectable.getDeadline(); if (d > 0) { deadline = (deadline == 0) ? d : Math.min(deadline, d); } } if (deadline > 0) { long delta = deadline - now; if (delta < 0) { timeout = 0; } else if (delta < timeout) { timeout = delta; } } } error.clear(); long awoken = 0; if (timeout > 0) { long remainingTimeout = timeout; while(remainingTimeout > 0) { selector.select(remainingTimeout); awoken = System.currentTimeMillis(); for (Iterator iterator = selector.selectedKeys().iterator(); iterator.hasNext();) { SelectionKey key = iterator.next(); if (key.isConnectable()) { try { ((SocketChannel)key.channel()).finishConnect(); update((Selectable)key.attachment()); } catch(IOException ioException) { SelectableImpl selectable = (SelectableImpl)key.attachment(); ErrorCondition condition = new ErrorCondition(); condition.setCondition(Symbol.getSymbol("proton:io")); condition.setDescription(ioException.getMessage()); Transport transport = selectable.getTransport(); if (transport != null) { transport.setCondition(condition); transport.close_tail(); transport.close_head(); transport.pop(transport.pending()); } error.add(selectable); } iterator.remove(); } } if (!selector.selectedKeys().isEmpty()) { break; } remainingTimeout = remainingTimeout - (awoken - now); } } else { selector.selectNow(); awoken = System.currentTimeMillis(); } readable.clear(); writeable.clear(); expired.clear(); for (SelectionKey key : selector.selectedKeys()) { Selectable selectable = (Selectable)key.attachment(); if (key.isReadable()) readable.add(selectable); if (key.isAcceptable()) readable.add(selectable); if (key.isWritable()) writeable.add(selectable); } selector.selectedKeys().clear(); // XXX: Note: this is different to the C code which evaluates expiry at the point the selectable is iterated over. for (Selectable selectable : selectables) { long deadline = selectable.getDeadline(); if (deadline > 0 && awoken >= deadline) { expired.add(selectable); } } } @Override public Iterator readable() { return readable.iterator(); } @Override public Iterator writeable() { return writeable.iterator(); } @Override public Iterator expired() { return expired.iterator(); } @Override public Iterator error() { return error.iterator(); } @Override public void free() { try { selector.close(); } catch(IOException ioException) { // Ignore } } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/SelectableImpl.java0000664000000000000000000001327712562450203027431 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; import java.nio.channels.SelectableChannel; import org.apache.qpid.proton.engine.Collector; import org.apache.qpid.proton.engine.Event.Type; import org.apache.qpid.proton.engine.Record; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.impl.CollectorImpl; import org.apache.qpid.proton.engine.impl.RecordImpl; import org.apache.qpid.proton.reactor.Reactor; import org.apache.qpid.proton.reactor.Selectable; public class SelectableImpl implements Selectable { private Callback readable; private Callback writable; private Callback error; private Callback expire; private Callback release; private Callback free; private boolean reading = false; private boolean writing = false; private long deadline = 0; private SelectableChannel channel; private Record attachments = new RecordImpl(); private boolean registered; private Reactor reactor; private Transport transport; private boolean terminal; private boolean terminated; @Override public boolean isReading() { return reading; } @Override public boolean isWriting() { return writing; } @Override public long getDeadline() { return deadline; } @Override public void setReading(boolean reading) { this.reading = reading; } @Override public void setWriting(boolean writing) { this.writing = writing; } @Override public void setDeadline(long deadline) { this.deadline = deadline; } @Override public void onReadable(Callback runnable) { this.readable = runnable; } @Override public void onWritable(Callback runnable) { this.writable = runnable; } @Override public void onExpired(Callback runnable) { this.expire = runnable; } @Override public void onError(Callback runnable) { this.error = runnable; } @Override public void onRelease(Callback runnable) { this.release = runnable; } @Override public void onFree(Callback runnable) { this.free = runnable; } @Override public void readable() { if (readable != null) { readable.run(this); } } @Override public void writeable() { if (writable != null) { writable.run(this); } } @Override public void expired() { if (expire != null) { expire.run(this); } } @Override public void error() { if (error != null) { error.run(this); } } @Override public void release() { if (release != null) { release.run(this); } } @Override public void free() { if (free != null) { free.run(this); } } @Override public void setChannel(SelectableChannel channel) { this.channel = channel; } @Override public SelectableChannel getChannel() { return channel; } @Override public boolean isRegistered() { return registered; } @Override public void setRegistered(boolean registered) { this.registered = registered; } @Override public void setCollector(final Collector collector) { final CollectorImpl collectorImpl = (CollectorImpl)collector; onReadable(new Callback() { @Override public void run(Selectable selectable) { collectorImpl.put(Type.SELECTABLE_READABLE, selectable); } }); onWritable(new Callback() { @Override public void run(Selectable selectable) { collectorImpl.put(Type.SELECTABLE_WRITABLE, selectable); } }); onExpired(new Callback() { @Override public void run(Selectable selectable) { collectorImpl.put(Type.SELECTABLE_EXPIRED, selectable); } }); onError(new Callback() { @Override public void run(Selectable selectable) { collectorImpl.put(Type.SELECTABLE_ERROR, selectable); } }); } @Override public Reactor getReactor() { return reactor; } @Override public void terminate() { terminal = true; } @Override public boolean isTerminal() { return terminal; } protected Transport getTransport() { return transport; } protected void setTransport(Transport transport) { this.transport = transport; } protected void setReactor(Reactor reactor) { this.reactor = reactor; } @Override public Record attachments() { return attachments; } public boolean isTerminated() { return terminated; } public void terminated() { terminated = true; } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/ReactorInternalException.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/ReactorInternalException0000664000000000000000000000263112562450203030567 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; /** * Thrown by the reactor when it encounters an internal error condition. * This is analogous to an assertion failure in the proton-c reactor * implementation. */ class ReactorInternalException extends RuntimeException { private static final long serialVersionUID = 8979674526584642454L; protected ReactorInternalException(String msg) { super(msg); } protected ReactorInternalException(Throwable cause) { super(cause); } protected ReactorInternalException(String msg, Throwable cause) { super(msg, cause); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/ReactorImpl.java0000664000000000000000000003035312562450203026757 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.Pipe; import java.util.HashSet; import java.util.Set; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.engine.BaseHandler; import org.apache.qpid.proton.engine.Collector; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.Event; import org.apache.qpid.proton.engine.Event.Type; import org.apache.qpid.proton.engine.Extendable; import org.apache.qpid.proton.engine.Handler; import org.apache.qpid.proton.engine.HandlerException; import org.apache.qpid.proton.engine.Record; import org.apache.qpid.proton.engine.impl.CollectorImpl; import org.apache.qpid.proton.engine.impl.ConnectionImpl; import org.apache.qpid.proton.engine.impl.RecordImpl; import org.apache.qpid.proton.reactor.Acceptor; import org.apache.qpid.proton.reactor.Reactor; import org.apache.qpid.proton.reactor.ReactorChild; import org.apache.qpid.proton.reactor.Selectable; import org.apache.qpid.proton.reactor.Selectable.Callback; import org.apache.qpid.proton.reactor.Selector; import org.apache.qpid.proton.reactor.Task; public class ReactorImpl implements Reactor, Extendable { private CollectorImpl collector; private long now; private long timeout; private Handler global; private Handler handler; private Set children; private int selectables; private boolean yield; private Selectable selectable; private Type previous; private Timer timer; private final Pipe wakeup; private Selector selector; private Record attachments; private final IO io; @Override public long mark() { now = System.currentTimeMillis(); return now; } @Override public long now() { return now; } protected ReactorImpl(IO io) throws IOException { collector = (CollectorImpl)Proton.collector(); global = new IOHandler(); handler = new BaseHandler(); children = new HashSet(); selectables = 0; timer = new Timer(collector); this.io = io; wakeup = this.io.pipe(); mark(); attachments = new RecordImpl(); } public ReactorImpl() throws IOException { this(new IOImpl()); } @Override public void free() { if (wakeup.source().isOpen()) { try { wakeup.source().close(); } catch(IOException e) { // Ignore. } } if (wakeup.sink().isOpen()) { try { wakeup.sink().close(); } catch(IOException e) { // Ignore } } if (selector != null) { selector.free(); } for (ReactorChild child : children) { child.free(); } } @Override public Record attachments() { return attachments; } @Override public long getTimeout() { return timeout; } @Override public void setTimeout(long timeout) { this.timeout = timeout; } @Override public Handler getGlobalHandler() { return global; } @Override public void setGlobalHandler(Handler handler) { global = handler; } @Override public Handler getHandler() { return handler; } @Override public void setHandler(Handler handler) { this.handler = handler; } @Override public Set children() { return children; } @Override public Collector collector() { return collector; } private class ReleaseCallback implements Callback { private final ReactorImpl reactor; private final ReactorChild child; public ReleaseCallback(ReactorImpl reactor, ReactorChild child) { this.reactor = reactor; this.child = child; } @Override public void run(Selectable selectable) { if (reactor.children.remove(child)) { --reactor.selectables; child.free(); } } } @Override public Selectable selectable() { return selectable(null); } public SelectableImpl selectable(ReactorChild child) { SelectableImpl result = new SelectableImpl(); result.setCollector(collector); collector.put(Type.SELECTABLE_INIT, result); result.setReactor(this); children.add(child == null ? result : child); result.onRelease(new ReleaseCallback(this, child == null ? result : child)); ++selectables; return result; } @Override public void update(Selectable selectable) { SelectableImpl selectableImpl = (SelectableImpl)selectable; if (!selectableImpl.isTerminated()) { if (selectableImpl.isTerminal()) { selectableImpl.terminated(); collector.put(Type.SELECTABLE_FINAL, selectable); } else { collector.put(Type.SELECTABLE_UPDATED, selectable); } } } // pn_event_handler private Handler eventHandler(Event event) { Handler result; if (event.getLink() != null) { result = BaseHandler.getHandler(event.getLink()); if (result != null) return result; } if (event.getSession() != null) { result = BaseHandler.getHandler(event.getSession()); if (result != null) return result; } if (event.getConnection() != null) { result = BaseHandler.getHandler(event.getConnection()); if (result != null) return result; } if (event.getTask() != null) { result = BaseHandler.getHandler(event.getTask()); if (result != null) return result; } if (event.getSelectable() != null) { result = BaseHandler.getHandler(event.getSelectable()); if (result != null) return result; } return handler; } @Override public void yield() { yield = true; } @Override public boolean quiesced() { Event event = collector.peek(); if (event == null) return true; if (collector.more()) return false; return event.getType() == Type.REACTOR_QUIESCED; } @Override public boolean process() throws HandlerException { mark(); Type previous = null; while (true) { Event event = collector.peek(); if (event != null) { if (yield) { yield = false; return true; } Handler handler = eventHandler(event); event.dispatch(handler); event.dispatch(global); if (event.getType() == Type.CONNECTION_FINAL) { children.remove(event.getConnection()); } this.previous = event.getType(); previous = this.previous; collector.pop(); } else { if (more()) { if (previous != Type.REACTOR_QUIESCED && this.previous != Type.REACTOR_FINAL) { collector.put(Type.REACTOR_QUIESCED, this); } else { return true; } } else { if (selectable != null) { selectable.terminate(); update(selectable); selectable = null; } else { return false; } } } } } @Override public void wakeup() { try { wakeup.sink().write(ByteBuffer.allocate(1)); } catch(ClosedChannelException channelClosedException) { // Ignore - pipe already closed by reactor being shutdown. } catch(IOException ioException) { throw new ReactorInternalException(ioException); } } @Override public void start() { collector.put(Type.REACTOR_INIT, this); selectable = timerSelectable(); } @Override public void stop() throws HandlerException { collector.put(Type.REACTOR_FINAL, this); // (Comment from C code) XXX: should consider removing this from stop to avoid reentrance process(); collector = null; } private boolean more() { return timer.tasks() > 0 || selectables > 1; } @Override public void run() throws HandlerException { setTimeout(3141); start(); while(process()) {} stop(); } // pn_reactor_schedule from reactor.c @Override public Task schedule(int delay, Handler handler) { Task task = timer.schedule(now + delay); ((TaskImpl)task).setReactor(this); BaseHandler.setHandler(task, handler); if (selectable != null) { selectable.setDeadline(timer.deadline()); update(selectable); } return task; } private void expireSelectable(Selectable selectable) { ReactorImpl reactor = (ReactorImpl) selectable.getReactor(); reactor.timer.tick(reactor.now); selectable.setDeadline(reactor.timer.deadline()); reactor.update(selectable); } private class TimerReadable implements Callback { @Override public void run(Selectable selectable) { try { wakeup.source().read(ByteBuffer.allocate(64)); } catch (IOException e) { throw new RuntimeException(e); } expireSelectable(selectable); } } private class TimerExpired implements Callback { @Override public void run(Selectable selectable) { expireSelectable(selectable); } } // pni_timer_finalize from reactor.c private class TimerFree implements Callback { @Override public void run(Selectable selectable) { try { selectable.getChannel().close(); } catch(IOException ioException) { // Ignore } } } private Selectable timerSelectable() { Selectable sel = selectable(); sel.setChannel(wakeup.source()); sel.onReadable(new TimerReadable()); sel.onExpired(new TimerExpired()); sel.onFree(new TimerFree()); sel.setReading(true); sel.setDeadline(timer.deadline()); update(sel); return sel; } protected Selector getSelector() { return selector; } protected void setSelector(Selector selector) { this.selector = selector; } // pn_reactor_connection from connection.c @Override public Connection connection(Handler handler) { Connection connection = Proton.connection(); BaseHandler.setHandler(connection, handler); connection.collect(collector); children.add(connection); ((ConnectionImpl)connection).setReactor(this); return connection; } @Override public Acceptor acceptor(String host, int port) throws IOException { return this.acceptor(host, port, null); } @Override public Acceptor acceptor(String host, int port, Handler handler) throws IOException { return new AcceptorImpl(this, host, port, handler); } public IO getIO() { return io; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOImpl.java0000664000000000000000000000300112562450203025655 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; import java.io.IOException; import java.nio.channels.Pipe; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; public class IOImpl implements IO { @Override public Pipe pipe() throws IOException { return Pipe.open(); } @Override public Selector selector() throws IOException { return Selector.open(); } @Override public ServerSocketChannel serverSocketChannel() throws IOException { return ServerSocketChannel.open(); } @Override public SocketChannel socketChannel() throws IOException { return SocketChannel.open(); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IOHandler.java0000664000000000000000000003224412562450203026344 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.nio.channels.Channel; import java.nio.channels.SocketChannel; import java.util.Iterator; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.transport.ErrorCondition; import org.apache.qpid.proton.engine.BaseHandler; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Event; import org.apache.qpid.proton.engine.Sasl; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.impl.TransportImpl; import org.apache.qpid.proton.reactor.Reactor; import org.apache.qpid.proton.reactor.Selectable; import org.apache.qpid.proton.reactor.Selectable.Callback; import org.apache.qpid.proton.reactor.Selector; public class IOHandler extends BaseHandler { // pni_handle_quiesced from connection.c private void handleQuiesced(Reactor reactor, Selector selector) throws IOException { // check if we are still quiesced, other handlers of // PN_REACTOR_QUIESCED could have produced more events to process if (!reactor.quiesced()) return; selector.select(reactor.getTimeout()); reactor.mark(); Iterator selectables = selector.readable(); while(selectables.hasNext()) { selectables.next().readable(); } selectables = selector.writeable(); while(selectables.hasNext()) { selectables.next().writeable(); } selectables = selector.expired(); while(selectables.hasNext()) { selectables.next().expired(); } selectables = selector.error(); while(selectables.hasNext()) { selectables.next().error(); } reactor.yield(); } // pni_handle_open(...) from connection.c private void handleOpen(Event event) { Connection connection = event.getConnection(); if (connection.getRemoteState() != EndpointState.UNINITIALIZED) { return; } Transport transport = Proton.transport(); Sasl sasl = transport.sasl(); sasl.client(); sasl.setMechanisms("ANONYMOUS"); transport.bind(connection); } // pni_handle_bound(...) from connection.c private void handleBound(Reactor reactor, Event event) { Connection connection = event.getConnection(); String hostname = connection.getHostname(); if (hostname == null || hostname.equals("")) { return; } int colonIndex = hostname.indexOf(':'); int port = 5672; if (colonIndex >= 0) { try { port = Integer.parseInt(hostname.substring(colonIndex+1)); } catch(NumberFormatException nfe) { throw new IllegalArgumentException("Not a valid host: " + hostname, nfe); } hostname = hostname.substring(0, colonIndex); } Transport transport = event.getConnection().getTransport(); Socket socket = null; // In this case, 'null' is the proton-j equivalent of PN_INVALID_SOCKET try { SocketChannel socketChannel = ((ReactorImpl)reactor).getIO().socketChannel(); socketChannel.configureBlocking(false); socketChannel.connect(new InetSocketAddress(hostname, port)); socket = socketChannel.socket(); } catch(IOException ioException) { ErrorCondition condition = new ErrorCondition(); condition.setCondition(Symbol.getSymbol("proton:io")); condition.setDescription(ioException.getMessage()); transport.setCondition(condition); transport.close_tail(); transport.close_head(); transport.pop(transport.pending()); // Force generation of TRANSPORT_HEAD_CLOSE (not in C code) } selectableTransport(reactor, socket, transport); } // pni_connection_capacity from connection.c private static int capacity(Selectable selectable) { Transport transport = ((SelectableImpl)selectable).getTransport(); int capacity = transport.capacity(); if (capacity < 0) { if (transport.isClosed()) { selectable.terminate(); } } return capacity; } // pni_connection_pending from connection.c private static int pending(Selectable selectable) { Transport transport = ((SelectableImpl)selectable).getTransport(); int pending = transport.pending(); if (pending < 0) { if (transport.isClosed()) { selectable.terminate(); } } return pending; } // pni_connection_deadline from connection.c private static long deadline(SelectableImpl selectable) { Reactor reactor = selectable.getReactor(); Transport transport = selectable.getTransport(); long deadline = transport.tick(reactor.now()); return deadline; } // pni_connection_update from connection.c private static void update(Selectable selectable) { SelectableImpl selectableImpl = (SelectableImpl)selectable; int c = capacity(selectableImpl); int p = pending(selectableImpl); selectable.setReading(c > 0); selectable.setWriting(p > 0); selectable.setDeadline(deadline(selectableImpl)); } // pni_connection_readable from connection.c private static Callback connectionReadable = new Callback() { @Override public void run(Selectable selectable) { Reactor reactor = selectable.getReactor(); Transport transport = ((SelectableImpl)selectable).getTransport(); int capacity = transport.capacity(); if (capacity > 0) { SocketChannel socketChannel = (SocketChannel)selectable.getChannel(); try { int n = socketChannel.read(transport.tail()); if (n == -1) { transport.close_tail(); } else { transport.process(); } } catch (IOException e) { ErrorCondition condition = new ErrorCondition(); condition.setCondition(Symbol.getSymbol("proton:io")); condition.setDescription(e.getMessage()); transport.setCondition(condition); transport.close_tail(); } } // (Comment from C code:) occasionally transport events aren't // generated when expected, so the following hack ensures we // always update the selector update(selectable); reactor.update(selectable); } }; // pni_connection_writable from connection.c private static Callback connectionWritable = new Callback() { @Override public void run(Selectable selectable) { Reactor reactor = selectable.getReactor(); Transport transport = ((SelectableImpl)selectable).getTransport(); int pending = transport.pending(); if (pending > 0) { SocketChannel channel = (SocketChannel)selectable.getChannel(); try { int n = channel.write(transport.head()); if (n < 0) { transport.close_head(); } else { transport.pop(n); } } catch(IOException ioException) { ErrorCondition condition = new ErrorCondition(); condition.setCondition(Symbol.getSymbol("proton:io")); condition.setDescription(ioException.getMessage()); transport.setCondition(condition); transport.close_head(); } } int newPending = transport.pending(); if (newPending != pending) { update(selectable); reactor.update(selectable); } } }; // pni_connection_error from connection.c private static Callback connectionError = new Callback() { @Override public void run(Selectable selectable) { Reactor reactor = selectable.getReactor(); selectable.terminate(); reactor.update(selectable); } }; // pni_connection_expired from connection.c private static Callback connectionExpired = new Callback() { @Override public void run(Selectable selectable) { Reactor reactor = selectable.getReactor(); Transport transport = ((SelectableImpl)selectable).getTransport(); long deadline = transport.tick(reactor.now()); selectable.setDeadline(deadline); int c = capacity(selectable); int p = pending(selectable); selectable.setReading(c > 0); selectable.setWriting(p > 0); reactor.update(selectable); } }; private static Callback connectionFree = new Callback() { @Override public void run(Selectable selectable) { Channel channel = selectable.getChannel(); if (channel != null) { try { channel.close(); } catch(IOException ioException) { // Ignore } } } }; // pn_reactor_selectable_transport // Note the socket argument can, validly be 'null' this is the equivalent of proton-c's PN_INVALID_SOCKET protected static Selectable selectableTransport(Reactor reactor, Socket socket, Transport transport) { Selectable selectable = reactor.selectable(); selectable.setChannel(socket != null ? socket.getChannel() : null); selectable.onReadable(connectionReadable); selectable.onWritable(connectionWritable); selectable.onError(connectionError); selectable.onExpired(connectionExpired); selectable.onFree(connectionFree); ((SelectableImpl)selectable).setTransport(transport); ((TransportImpl)transport).setSelectable(selectable); ((TransportImpl)transport).setReactor(reactor); update(selectable); reactor.update(selectable); return selectable; } private void handleTransport(Reactor reactor, Event event) { TransportImpl transport = (TransportImpl)event.getTransport(); Selectable selectable = transport.getSelectable(); if (selectable != null && !selectable.isTerminal()) { update(selectable); reactor.update(selectable); } } @Override public void onUnhandled(Event event) { try { ReactorImpl reactor = (ReactorImpl)event.getReactor(); Selector selector = reactor.getSelector(); if (selector == null) { selector = new SelectorImpl(reactor.getIO()); reactor.setSelector(selector); } Selectable selectable; switch(event.getType()) { case SELECTABLE_INIT: selectable = event.getSelectable(); selector.add(selectable); break; case SELECTABLE_UPDATED: selectable = event.getSelectable(); selector.update(selectable); break; case SELECTABLE_FINAL: selectable = event.getSelectable(); selector.remove(selectable); selectable.release(); break; case CONNECTION_LOCAL_OPEN: handleOpen(event); break; case CONNECTION_BOUND: handleBound(reactor, event); break; case TRANSPORT: handleTransport(reactor, event); break; case TRANSPORT_CLOSED: event.getTransport().unbind(); break; case REACTOR_QUIESCED: handleQuiesced(reactor, selector); break; default: break; } } catch(IOException ioException) { // XXX: Might not be the right exception type, but at least the exception isn't being swallowed throw new ReactorInternalException(ioException); } } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/IO.java0000664000000000000000000000301112562450203025034 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; import java.io.IOException; import java.nio.channels.Pipe; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; // Java equivalent to pn_io. // This is, currently, in the reactor.impl package because it is not // used elsewhere in the proton-j codebase. Instead it is present to // facilitate mocking of various Java I/O related resources so that // the unit tests can check for leaks. public interface IO { Pipe pipe() throws IOException; Selector selector() throws IOException; ServerSocketChannel serverSocketChannel() throws IOException; SocketChannel socketChannel() throws IOException; } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/impl/AcceptorImpl.java0000664000000000000000000001120712562450203027115 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor.impl; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.engine.BaseHandler; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.Handler; import org.apache.qpid.proton.engine.Record; import org.apache.qpid.proton.engine.Sasl; import org.apache.qpid.proton.engine.Sasl.SaslOutcome; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.impl.RecordImpl; import org.apache.qpid.proton.reactor.Acceptor; import org.apache.qpid.proton.reactor.Reactor; import org.apache.qpid.proton.reactor.Selectable; import org.apache.qpid.proton.reactor.Selectable.Callback; public class AcceptorImpl implements Acceptor { private Record attachments = new RecordImpl(); private final SelectableImpl sel; private class AcceptorReadable implements Callback { @Override public void run(Selectable selectable) { Reactor reactor = selectable.getReactor(); try { SocketChannel socketChannel = ((ServerSocketChannel)selectable.getChannel()).accept(); if (socketChannel == null) { throw new ReactorInternalException("Selectable readable, but no socket to accept"); } Handler handler = BaseHandler.getHandler(AcceptorImpl.this); if (handler == null) { handler = reactor.getHandler(); } Connection conn = reactor.connection(handler); Transport trans = Proton.transport(); Sasl sasl = trans.sasl(); sasl.server(); sasl.setMechanisms("ANONYMOUS"); sasl.done(SaslOutcome.PN_SASL_OK); trans.bind(conn); IOHandler.selectableTransport(reactor, socketChannel.socket(), trans); } catch(IOException ioException) { sel.error(); } } } private class AcceptorFree implements Callback { @Override public void run(Selectable selectable) { try { if (selectable.getChannel() != null) { selectable.getChannel().close(); } } catch(IOException ioException) { // Ignore - as we can't make the channel any more closed... } } } protected AcceptorImpl(Reactor reactor, String host, int port, Handler handler) throws IOException { ServerSocketChannel ssc = ((ReactorImpl)reactor).getIO().serverSocketChannel(); ssc.bind(new InetSocketAddress(host, port)); sel = ((ReactorImpl)reactor).selectable(this); sel.setChannel(ssc); sel.onReadable(new AcceptorReadable()); sel.onFree(new AcceptorFree()); sel.setReactor(reactor); BaseHandler.setHandler(this, handler); sel.setReading(true); reactor.update(sel); } @Override public void close() { if (!sel.isTerminal()) { Reactor reactor = sel.getReactor(); try { sel.getChannel().close(); } catch(IOException ioException) { // Ignore. } sel.setChannel(null); sel.terminate(); reactor.update(sel); } } // Used for unit tests, where acceptor is bound to an ephemeral port public int getPortNumber() throws IOException { ServerSocketChannel ssc = (ServerSocketChannel)sel.getChannel(); return ((InetSocketAddress)ssc.getLocalAddress()).getPort(); } @Override public void free() { sel.free(); } @Override public Record attachments() { return attachments; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/Task.java0000664000000000000000000000315412562450203024476 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor; import org.apache.qpid.proton.engine.Event.Type; import org.apache.qpid.proton.engine.Extendable; import org.apache.qpid.proton.engine.Handler; /** * Represents work scheduled with a {@link Reactor} for execution at * some point in the future. *

* Tasks are created using the {@link Reactor#schedule(int, Handler)} * method. */ public interface Task extends Extendable { /** * @return the deadline at which the handler associated with the scheduled * task should be delivered a {@link Type#TIMER_TASK} event. */ long deadline(); /** @return the reactor that created this task. */ Reactor getReactor(); /** * Cancel the execution of this task. No-op if invoked after the task was already executed. */ void cancel(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/Selector.java0000664000000000000000000001011012562450203025342 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor; import java.io.IOException; import java.util.Iterator; /** * A multiplexor of instances of {@link Selectable}. *

* Many instances of Selectable can be added to a selector, and * the {@link #select(long)} method used to block the calling thread until * one of the Selectables becomes read to perform an operation. *

* This class is not thread safe, so only one thread should be manipulating the * contents of the selector, or running the {@link #select(long)} method at * any given time. */ public interface Selector { /** * Adds a selectable to the selector. * @param selectable * @throws IOException */ void add(Selectable selectable) throws IOException; /** * Updates the selector to reflect any changes interest by the specified * selectable. This is achieved by calling the * {@link Selectable#isReading()} and {@link Selectable#isWriting()} * methods. * @param selectable */ void update(Selectable selectable); /** * Removes a selectable from the selector. * @param selectable */ void remove(Selectable selectable); /** * Waits for the specified timeout period for one or more selectables to * become ready for an operation. Selectables that become ready are * returned by the {@link #readable()}, {@link #writeable()}, * {@link #expired()}, or {@link #error()} methods. * * @param timeout the maximum number of milliseconds to block the calling * thread waiting for a selectable to become ready for an * operation. The value zero is interpreted as check but * don't block. * @throws IOException */ void select(long timeout) throws IOException; /** * @return the selectables that have become readable since the last call * to {@link #select(long)}. Calling select clears * any previous values in this set before adding new values * corresponding to those selectables that have become readable. */ Iterator readable(); /** * @return the selectables that have become writable since the last call * to {@link #select(long)}. Calling select clears * any previous values in this set before adding new values * corresponding to those selectables that have become writable. */ Iterator writeable(); /** * @return the selectables that have expired since the last call * to {@link #select(long)}. Calling select clears * any previous values in this set before adding new values * corresponding to those selectables that have now expired. */ Iterator expired(); /** * @return the selectables that have encountered an error since the last * call to {@link #select(long)}. Calling select * clears any previous values in this set before adding new values * corresponding to those selectables that have encountered an * error. */ Iterator error() ; /** Frees the resources used by this selector. */ void free(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/Selectable.java0000664000000000000000000001705712562450203025646 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor; import java.nio.channels.SelectableChannel; import org.apache.qpid.proton.engine.Collector; import org.apache.qpid.proton.engine.Extendable; /** * An entity that can be multiplexed using a {@link Selector}. *

* Every selectable is associated with exactly one {@link SelectableChannel}. * Selectables may be interested in three kinds of events: read events, write * events, and timer events. A selectable will express its interest in these * events through the {@link #isReading()}, {@link #isWriting()}, and * {@link #getDeadline()} methods. *

* When a read, write, or timer event occurs, the selectable must be notified by * calling {@link #readable()}, {@link #writeable()}, or {@link #expired()} as * appropriate. * * Once a selectable reaches a terminal state (see {@link #isTerminal()}, it * will never be interested in events of any kind. When this occurs it should be * removed from the Selector and discarded using {@link #free()}. */ public interface Selectable extends ReactorChild, Extendable { /** * A callback that can be passed to the various "on" methods of the * selectable - to allow code to be run when the selectable becomes ready * for the associated operation. */ interface Callback { void run(Selectable selectable); } /** * @return true if the selectable is interested in receiving * notification (via the {@link #readable()} method that indicate * that the associated {@link SelectableChannel} has data ready * to be read from it. */ boolean isReading(); /** * @return true if the selectable is interested in receiving * notifications (via the {@link #writeable()} method that indicate * that the associated {@link SelectableChannel} is ready to be * written to. */ boolean isWriting(); /** * @return a deadline after which this selectable can expect to receive * a notification (via the {@link #expired()} method that indicates * that the deadline has past. The deadline is expressed in the * same format as {@link System#currentTimeMillis()}. Returning * a deadline of zero (or a negative number) indicates that the * selectable does not wish to be notified of expiry. */ long getDeadline(); /** * Sets the value that will be returned by {@link #isReading()}. * @param reading */ void setReading(boolean reading); /** * Sets the value that will be returned by {@link #isWriting()}. * @param writing */ void setWriting(boolean writing); /** * Sets the value that will be returned by {@link #getDeadline()}. * @param deadline */ void setDeadline(long deadline); /** * Registers a callback that will be run when the selectable becomes ready * for reading. * @param runnable the callback to register. Any previously registered * callback will be replaced. */ void onReadable(Callback runnable); /** * Registers a callback that will be run when the selectable becomes ready * for writing. * @param runnable the callback to register. Any previously registered * callback will be replaced. */ void onWritable(Callback runnable); /** * Registers a callback that will be run when the selectable expires. * @param runnable the callback to register. Any previously registered * callback will be replaced. */ void onExpired(Callback runnable); /** * Registers a callback that will be run when the selectable is notified of * an error. * @param runnable the callback to register. Any previously registered * callback will be replaced. */ void onError(Callback runnable); /** * Registers a callback that will be run when the selectable is notified * that it has been released. * @param runnable the callback to register. Any previously registered * callback will be replaced. */ void onRelease(Callback runnable); /** * Registers a callback that will be run when the selectable is notified * that it has been free'd. * @param runnable the callback to register. Any previously registered * callback will be replaced. */ void onFree(Callback runnable); /** * Notify the selectable that the underlying {@link SelectableChannel} is * ready for a read operation. */ void readable(); /** * Notify the selectable that the underlying {@link SelectableChannel} is * ready for a write operation. */ void writeable(); /** Notify the selectable that it has expired. */ void expired(); /** Notify the selectable that an error has occurred. */ void error(); /** Notify the selectable that it has been released. */ void release(); /** Notify the selectable that it has been free'd. */ @Override void free(); /** * Associates a {@link SelectableChannel} with this selector. * @param channel */ void setChannel(SelectableChannel channel); // This is the equivalent to pn_selectable_set_fd(...) /** @return the {@link SelectableChannel} associated with this selector. */ SelectableChannel getChannel(); // This is the equivalent to pn_selectable_get_fd(...) /** * Check if a selectable is registered. This can be used for tracking * whether a given selectable has been registerd with an external event * loop. *

* Note: the reactor code, currently, does not use this flag. * @return trueif the selectable is registered. */ boolean isRegistered(); // XXX: unused in C reactor code /** * Set the registered flag for a selectable. *

* Note: the reactor code, currently, does not use this flag. * @param registered the value returned by {@link #isRegistered()} */ void setRegistered(boolean registered); // XXX: unused in C reactor code /** * Configure a selectable with a set of callbacks that emit readable, * writable, and expired events into the supplied collector. * @param collector */ void setCollector(final Collector collector); /** @return the reactor to which this selectable is a child. */ Reactor getReactor() ; /** * Terminates the selectable. Once a selectable reaches a terminal state * it will never be interested in events of any kind. */ public void terminate() ; /** * @return true if the selectable has reached a terminal state. */ boolean isTerminal(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/ReactorChild.java0000664000000000000000000000202712562450203026135 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor; /** * Interface used to identify classes that can be a child of a reactor. */ public interface ReactorChild { /** Frees any resources associated with this child. */ void free(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/Reactor.java0000664000000000000000000002466612562450203025206 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor; import java.io.IOException; import java.util.Set; import org.apache.qpid.proton.engine.BaseHandler; import org.apache.qpid.proton.engine.Collector; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.Event.Type; import org.apache.qpid.proton.engine.Handler; import org.apache.qpid.proton.engine.HandlerException; import org.apache.qpid.proton.engine.Record; import org.apache.qpid.proton.reactor.impl.ReactorImpl; /** * The proton reactor provides a general purpose event processing * library for writing reactive programs. A reactive program is defined * by a set of event handlers. An event handler is just any class or * object that extends the Handler interface. For convenience, a class * can extend {@link BaseHandler} and only handle the events that it cares to * implement methods for. *

* This class is not thread safe (with the exception of the {@link #wakeup()} * method) and should only be used by a single thread at any given time. */ public interface Reactor { public static final class Factory { public static Reactor create() throws IOException { return new ReactorImpl(); } } /** * Updates the last time that the reactor's state has changed, potentially * resulting in events being generated. * @return the current time in milliseconds * {@link System#currentTimeMillis()}. */ long mark(); /** @return the last time that {@link #mark()} was called. */ long now(); /** @return an instance of {@link Record} that can be used to associate * other objects (attachments) with this instance of the * Reactor class. */ Record attachments(); /** * @param timeout a timeout value, to associate with this instance of * the reactor. This can be retrieved using the * {@link #getTimeout()} method. */ void setTimeout(long timeout); /** * @return the value previously set using {@link #setTimeout(long)} or * 0 if no previous value has been set. */ long getTimeout(); /** * @return the global handler for this reactor. Every event the reactor * sees is dispatched to the global handler. To receive every * event generated by the reactor, associate a child handler * with the global handler. For example: *

     *            getGlobalHandler().add(yourHandler);
     *         
*/ Handler getGlobalHandler(); /** * Sets a new global handler. You probably don't want to do this and * would be better adding a handler to the value returned by the * {{@link #getGlobalHandler()} method. * @param handler the new global handler. */ void setGlobalHandler(Handler handler); /** * @return the handler for this reactor. Every event the reactor sees, * which is not handled by a child of the reactor (such as a * timer, connection, acceptor, or selector) is passed to this * handler. To receive these events, it is recommend that you * associate a child handler with the handler returned by this * method. For example: *
     *           getHandler().add(yourHandler);
     *         
*/ Handler getHandler(); /** * Sets a new handler, that will receive any events not handled by a child * of the reactor. Note that setting a handler via this method replaces * the previous handler, and will result in no further events being * dispatched to the child handlers associated with the previous handler. * For this reason it is recommended that you do not use this method and * instead add child handlers to the value returned by the * {@link #getHandler()} method. * @param handler the new handler for this reactor. */ void setHandler(Handler handler); /** * @return a set containing the child objects associated wit this reactor. * This will contain any active instances of: {@link Task} - created * using the {@link #schedule(int, Handler)} method, * {@link Connection} - created using the * {@link #connection(Handler)} method, {@link Acceptor} - * created using the {@link #acceptor(String, int)} method. * {@link #acceptor(String, int, Handler)} method, or * {@link Selectable} - created using the {@link #selectable()} * method. */ Set children(); /** * @return the Collector used to gather events generated by this reactor. */ Collector collector(); /** * Creates a new Selectable as a child of this reactor. * @return the newly created Selectable. */ Selectable selectable(); /** * Updates the specified Selectable either emitting a * {@link Type#SELECTABLE_UPDATED} event if the selectable is not terminal, * or {@link Type#SELECTABLE_FINAL} if the selectable is terminal and has * not already emitted a {@link Type#SELECTABLE_FINAL} event. * @param selectable */ void update(Selectable selectable); /** * Yields, causing the next call to {@link #process()} to return * successfully - without processing any events. If multiple calls * can be made to yield and only the next invocation of * {@link #process()} will be affected. */ void yield() ; /** * @return true if the reactor is in quiesced state (e.g. has * no events to process). false is returned otherwise. */ boolean quiesced(); /** * Process any events pending for this reactor. Events are dispatched to * the handlers registered with the reactor, or child objects associated * with the reactor. This method blocks until the reactor has no more work * to do (and no more work pending, in terms of scheduled tasks or open * selectors to process). * @return true if the reactor may have more events in the * future. For example: if there are scheduled tasks, or open * selectors. false is returned if the reactor has * (and will have) no more events to process. * @throws HandlerException if an unchecked exception is thrown by one of * the handlers - it will be re-thrown attached to an instance of * HandlerException. */ boolean process() throws HandlerException; /** * Wakes up the thread (if any) blocked in the {@link #process()} method. * This is the only method of this class that is thread safe, in that it * can be used at the same time as another thread is using the reactor. */ void wakeup(); /** * Starts the reactor. This method should be invoked before the first call * to {@link #process()}. */ void start(); /** * Stops the reactor. This method should be invoked after the last call to * {@link #process()}. * @throws HandlerException */ void stop() throws HandlerException; /** * Simplifies the use of the reactor by wrapping the use of * start, run, and stop method * calls. *

* Logically the implementation of this method is: *

     *   start();
     *   while(process()) {}
     *   stop();
     * 
* @throws HandlerException if an unchecked exception is thrown by one of * the handlers - it will be re-thrown attached to an instance of * HandlerException. */ void run() throws HandlerException; /** * Schedules execution of a task to take place at some point in the future. * @param delay the number of milliseconds, in the future, to schedule the * task for. * @param handler a handler to associate with the task. This is notified * when the deadline for the task is reached. * @return an object representing the task that has been scheduled. */ Task schedule(int delay, Handler handler); /** * Creates a new out-bound connection. * @param handler a handler that is notified when events occur for the * connection. Typically the host and port to connect to * would be supplied to the connection object inside the * logic which handles the {@link Type#CONNECTION_INIT} * event. * @return the newly created connection object. */ Connection connection(Handler handler); /** * Creates a new acceptor. This is equivalent to calling: *
     *   acceptor(host, port, null);
     * 
* @param host * @param port * @return the newly created acceptor object. * @throws IOException */ Acceptor acceptor(String host, int port) throws IOException; /** * Creates a new acceptor. This acceptor listens for in-bound connections. * @param host the host name or address of the NIC to listen on. * @param port the port number to listen on. * @param handler if non-null this handler is registered with * each new connection accepted by the acceptor. * @return the newly created acceptor object. * @throws IOException */ Acceptor acceptor(String host, int port, Handler handler) throws IOException; /** * Frees any resources (such as sockets and selectors) held by the reactor * or its children. */ void free(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/Handshaker.java0000664000000000000000000000454312562450203025647 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor; import org.apache.qpid.proton.engine.BaseHandler; import org.apache.qpid.proton.engine.Endpoint; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Event; /** * A handler that mirrors the actions of the remote end of a connection. This * handler responds in kind when the remote end of the connection is opened and * closed. Likewise if the remote end of the connection opens or closes * sessions and links, this handler responds by opening or closing the local end * of the session or link. */ public class Handshaker extends BaseHandler { private void open(Endpoint endpoint) { if (endpoint.getLocalState() == EndpointState.UNINITIALIZED) { endpoint.open(); } } private void close(Endpoint endpoint) { if (endpoint.getLocalState() != EndpointState.CLOSED) { endpoint.close(); } } @Override public void onConnectionRemoteOpen(Event event) { open(event.getConnection()); } @Override public void onSessionRemoteOpen(Event event) { open(event.getSession()); } @Override public void onLinkRemoteOpen(Event event) { open(event.getLink()); } @Override public void onConnectionRemoteClose(Event event) { close(event.getConnection()); } @Override public void onSessionRemoteClose(Event event) { close(event.getSession()); } @Override public void onLinkRemoteClose(Event event) { close(event.getLink()); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/FlowController.java0000664000000000000000000000446012562450203026550 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor; import org.apache.qpid.proton.engine.BaseHandler; import org.apache.qpid.proton.engine.Event; import org.apache.qpid.proton.engine.Link; import org.apache.qpid.proton.engine.Receiver; /** * A handler that applies flow control to a connection. This handler tops-up * link credit each time credit is expended by the receipt of messages. */ public class FlowController extends BaseHandler { private int drained; private int window; public FlowController(int window) { // XXX: a window of 1 doesn't work because we won't necessarily get // notified when the one allowed delivery is settled if (window <= 1) throw new IllegalArgumentException(); this.window = window; this.drained = 0; } public FlowController() { this(1024); } private void topup(Receiver link, int window) { int delta = window - link.getCredit(); link.flow(delta); } @Override public void onUnhandled(Event event) { int window = this.window; Link link = event.getLink(); switch(event.getType()) { case LINK_LOCAL_OPEN: case LINK_REMOTE_OPEN: case LINK_FLOW: case DELIVERY: if (link instanceof Receiver) { this.drained += link.drained(); if (this.drained == 0) { topup((Receiver)link, window); } } break; default: break; } } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/reactor/Acceptor.java0000664000000000000000000000240512562450203025332 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.reactor; import org.apache.qpid.proton.engine.Extendable; /** * Acceptors are children of a {@link Reactor} that accept in-bound network * connections. */ public interface Acceptor extends ReactorChild, Extendable { /** * Closes the acceptor, stopping it accepting any further in-bound * connections. Already accepted connections continue to be processed by * the associated reactor. */ void close(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/0000775000000000000000000000000012562450203023257 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/impl/0000775000000000000000000000000012562450203024220 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/impl/Transform.java0000664000000000000000000001055312562450203027042 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.messenger.impl; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Transform * */ class Transform { private class Rule { String _pattern; String _substitution; Pattern _compiled; StringBuilder _sb = new StringBuilder(); boolean _matched = false; String _result = null; Rule(String pattern, String substitution) { _pattern = pattern; _substitution = substitution; _compiled = Pattern.compile(_pattern.replace("*", "(.*)").replace("%", "([^/]*)")); } boolean apply(String src) { _matched = false; _result = null; Matcher m = _compiled.matcher(src); if (m.matches()) { _matched = true; if (_substitution != null) { _sb.setLength(0); int limit = _substitution.length(); int idx = 0; while (idx < limit) { char c = _substitution.charAt(idx); switch (c) { case '$': idx++; if (idx < limit) { c = _substitution.charAt(idx); } else { throw new IllegalStateException("substition index truncated"); } if (c == '$') { _sb.append(c); idx++; } else { int num = 0; while (Character.isDigit(c)) { num *= 10; num += c - '0'; idx++; c = idx < limit ? _substitution.charAt(idx) : '\0'; } if (num > 0) { _sb.append(m.group(num)); } else { throw new IllegalStateException ("bad substitution index at character[" + idx + "]: " + _substitution); } } break; default: _sb.append(c); idx++; break; } } _result = _sb.toString(); } } return _matched; } boolean matched() { return _matched; } String result() { return _result; } } private List _rules = new ArrayList(); private Rule _matched = null; public void rule(String pattern, String substitution) { _rules.add(new Rule(pattern, substitution)); } public boolean apply(String src) { _matched = null; for (Rule rule: _rules) { if (rule.apply(src)) { _matched = rule; break; } } return _matched != null; } public boolean matched() { return _matched != null; } public String result() { return _matched != null ? _matched.result() : null; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/impl/TrackerImpl.java0000664000000000000000000000262512562450203027305 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.messenger.impl; import org.apache.qpid.proton.messenger.Tracker; class TrackerImpl implements Tracker { public enum Type { OUTGOING, INCOMING } private Type _type; private int _sequence; TrackerImpl(Type type, int sequence) { _type = type; _sequence = sequence; } boolean isOutgoing() { return _type == Type.OUTGOING; } int getSequence() { return _sequence; } public String toString() { return (isOutgoing() ? "O:" : "I:") + Integer.toString(_sequence); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/impl/StoreEntry.java0000664000000000000000000001043212562450203027201 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.messenger.impl; import org.apache.qpid.proton.messenger.Tracker; import org.apache.qpid.proton.messenger.Status; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.amqp.messaging.Accepted; import org.apache.qpid.proton.amqp.messaging.Modified; import org.apache.qpid.proton.amqp.messaging.Rejected; import org.apache.qpid.proton.amqp.messaging.Released; import org.apache.qpid.proton.amqp.messaging.Received; import org.apache.qpid.proton.amqp.transport.DeliveryState; class StoreEntry { private Store _store; private Integer _id; private String _address; private byte[] _encodedMsg; private int _encodedLength; private Delivery _delivery; private Status _status = Status.UNKNOWN; private Object _context; private boolean _inStore = false; public StoreEntry(Store store, String address) { _store = store; _address = address; } public Store getStore() { return _store; } public boolean isStored() { return _inStore; } public void stored() { _inStore = true; } public void notStored() { _inStore = false; } public String getAddress() { return _address; } public byte[] getEncodedMsg() { return _encodedMsg; } public int getEncodedLength() { return _encodedLength; } public void setEncodedMsg( byte[] encodedMsg, int length ) { _encodedMsg = encodedMsg; _encodedLength = length; } public void setId(int id) { _id = new Integer(id); } public Integer getId() { return _id; } public void setDelivery( Delivery d ) { if (_delivery != null) { _delivery.setContext(null); } _delivery = d; if (_delivery != null) { _delivery.setContext(this); } updated(); } public Delivery getDelivery() { return _delivery; } public Status getStatus() { return _status; } public void setStatus(Status status) { _status = status; } private static Status _disp2status(DeliveryState disp) { if (disp == null) return Status.PENDING; if (disp instanceof Received) return Status.PENDING; if (disp instanceof Accepted) return Status.ACCEPTED; if (disp instanceof Rejected) return Status.REJECTED; if (disp instanceof Released) return Status.RELEASED; if (disp instanceof Modified) return Status.MODIFIED; assert(false); return null; } public void updated() { if (_delivery != null) { if (_delivery.getRemoteState() != null) { _status = _disp2status(_delivery.getRemoteState()); } else if (_delivery.remotelySettled()) { DeliveryState disp = _delivery.getLocalState(); if (disp == null) { _status = Status.SETTLED; } else { _status = _disp2status(_delivery.getLocalState()); } } else { _status = Status.PENDING; } } } public void setContext(Object context) { _context = context; } public Object getContext() { return _context; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/impl/Store.java0000664000000000000000000001347212562450203026166 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.messenger.impl; import java.util.List; import java.util.LinkedList; import java.util.Map; import java.util.HashMap; import java.util.Collection; import java.util.Iterator; import org.apache.qpid.proton.messenger.Status; import org.apache.qpid.proton.messenger.Messenger; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.amqp.messaging.Accepted; import org.apache.qpid.proton.amqp.messaging.Rejected; class Store { private static final Accepted ACCEPTED = Accepted.getInstance(); private static final Rejected REJECTED = new Rejected(); private LinkedList _store = new LinkedList(); private HashMap> _stream = new HashMap>(); // for incoming/outgoing window tracking int _window; int _lwm; int _hwm; private HashMap _tracked = new HashMap(); Store() { } private boolean isTracking( Integer id ) { return id != null && (id.intValue() - _lwm >= 0) && (_hwm - id.intValue() > 0); } int size() { return _store.size(); } int getWindow() { return _window; } void setWindow(int window) { _window = window; } StoreEntry put(String address) { if (address == null) address = ""; StoreEntry entry = new StoreEntry(this, address); _store.add( entry ); LinkedList list = _stream.get( address ); if (list != null) { list.add( entry ); } else { list = new LinkedList(); list.add( entry ); _stream.put( address, list ); } entry.stored(); return entry; } StoreEntry get(String address) { if (address != null) { LinkedList list = _stream.get( address ); if (list != null) return list.peekFirst(); } else { return _store.peekFirst(); } return null; } StoreEntry getEntry(int id) { return _tracked.get(id); } Iterator trackedEntries() { return _tracked.values().iterator(); } void freeEntry(StoreEntry entry) { if (entry.isStored()) { _store.remove( entry ); LinkedList list = _stream.get( entry.getAddress() ); if (list != null) list.remove( entry ); entry.notStored(); } // note well: may still be in _tracked map if still in window! } public int trackEntry(StoreEntry entry) { assert( entry.getStore() == this ); entry.setId(_hwm++); _tracked.put(entry.getId(), entry); slideWindow(); return entry.getId(); } private void slideWindow() { if (_window >= 0) { while (_hwm - _lwm > _window) { StoreEntry old = getEntry(_lwm); if (old != null) { _tracked.remove( old.getId() ); Delivery d = old.getDelivery(); if (d != null) { if (d.getLocalState() == null) d.disposition(ACCEPTED); d.settle(); } } _lwm++; } } } int update(int id, Status status, int flags, boolean settle, boolean match ) { if (!isTracking(id)) return 0; int start = (Messenger.CUMULATIVE & flags) != 0 ? _lwm : id; for (int i = start; (id - i) >= 0; i++) { StoreEntry e = getEntry(i); if (e != null) { Delivery d = e.getDelivery(); if (d != null) { if (d.getLocalState() == null) { if (match) { d.disposition(d.getRemoteState()); } else { switch (status) { case ACCEPTED: d.disposition(ACCEPTED); break; case REJECTED: d.disposition(REJECTED); break; default: break; } } e.updated(); } } if (settle) { if (d != null) { d.settle(); } _tracked.remove(e.getId()); } } } while (_hwm - _lwm > 0 && !_tracked.containsKey(_lwm)) { _lwm++; } return 0; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/impl/MessengerImpl.java0000664000000000000000000013227212562450203027644 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.messenger.impl; import java.io.IOException; import java.util.ArrayList; import java.util.EnumSet; import java.util.Iterator; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.InterruptException; import org.apache.qpid.proton.TimeoutException; import org.apache.qpid.proton.driver.Connector; import org.apache.qpid.proton.driver.Driver; import org.apache.qpid.proton.driver.Listener; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Link; import org.apache.qpid.proton.engine.Receiver; import org.apache.qpid.proton.engine.Sasl; import org.apache.qpid.proton.engine.Sender; import org.apache.qpid.proton.engine.Session; import org.apache.qpid.proton.engine.SslDomain; import org.apache.qpid.proton.engine.Ssl; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.message.Message; import org.apache.qpid.proton.messenger.Messenger; import org.apache.qpid.proton.messenger.MessengerException; import org.apache.qpid.proton.messenger.Status; import org.apache.qpid.proton.messenger.Tracker; import org.apache.qpid.proton.amqp.messaging.Source; import org.apache.qpid.proton.amqp.messaging.Target; import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode; import org.apache.qpid.proton.amqp.transport.SenderSettleMode; import org.apache.qpid.proton.amqp.Binary; public class MessengerImpl implements Messenger { private enum LinkCreditMode { // method for replenishing credit LINK_CREDIT_EXPLICIT, // recv(N) LINK_CREDIT_AUTO; // recv() } private static final EnumSet UNINIT = EnumSet.of(EndpointState.UNINITIALIZED); private static final EnumSet ACTIVE = EnumSet.of(EndpointState.ACTIVE); private static final EnumSet CLOSED = EnumSet.of(EndpointState.CLOSED); private static final EnumSet ANY = EnumSet.allOf(EndpointState.class); private final Logger _logger = Logger.getLogger("proton.messenger"); private final String _name; private long _timeout = -1; private boolean _blocking = true; private long _nextTag = 1; private Driver _driver; private LinkCreditMode _credit_mode = LinkCreditMode.LINK_CREDIT_EXPLICIT; private final int _credit_batch = 1024; // credit_mode == LINK_CREDIT_AUTO private int _credit; // available private int _distributed; // outstanding credit private int _receivers; // total # receiver Links private int _draining; // # Links in drain state private List _credited = new ArrayList(); private List _blocked = new ArrayList(); private long _next_drain; private TrackerImpl _incomingTracker; private TrackerImpl _outgoingTracker; private Store _incomingStore = new Store(); private Store _outgoingStore = new Store(); private List _awaitingDestruction = new ArrayList(); private int _sendThreshold; private Transform _routes = new Transform(); private Transform _rewrites = new Transform(); private String _certificate; private String _privateKey; private String _password; private String _trustedDb; /** * @deprecated This constructor's visibility will be reduced to the default scope in a future release. * Client code outside this module should use a {@link MessengerFactory} instead */ @Deprecated public MessengerImpl() { this(java.util.UUID.randomUUID().toString()); } /** * @deprecated This constructor's visibility will be reduced to the default scope in a future release. * Client code outside this module should use a {@link MessengerFactory} instead */ @Deprecated public MessengerImpl(String name) { _name = name; } public void setTimeout(long timeInMillis) { _timeout = timeInMillis; } public long getTimeout() { return _timeout; } public boolean isBlocking() { return _blocking; } public void setBlocking(boolean b) { _blocking = b; } public void setCertificate(String certificate) { _certificate = certificate; } public String getCertificate() { return _certificate; } public void setPrivateKey(String privateKey) { _privateKey = privateKey; } public String getPrivateKey() { return _privateKey; } public void setPassword(String password) { _password = password; } public String getPassword() { return _password; } public void setTrustedCertificates(String trusted) { _trustedDb = trusted; } public String getTrustedCertificates() { return _trustedDb; } public void start() throws IOException { _driver = Proton.driver(); } public void stop() { if (_driver != null) { if(_logger.isLoggable(Level.FINE)) { _logger.fine(this + " about to stop"); } //close all connections for (Connector c : _driver.connectors()) { Connection connection = c.getConnection(); connection.close(); } //stop listeners for (Listener l : _driver.listeners()) { try { l.close(); } catch (IOException e) { _logger.log(Level.WARNING, "Error while closing listener", e); } } waitUntil(_allClosed); } } public boolean stopped() { return _allClosed.test(); } public boolean work(long timeout) throws TimeoutException { if (_driver == null) { return false; } _worked = false; return waitUntil(_workPred, timeout); } public void interrupt() { if (_driver != null) { _driver.wakeup(); } } private String defaultRewrite(String address) { if (address != null && address.contains("@")) { Address addr = new Address(address); String scheme = addr.getScheme(); String host = addr.getHost(); String port = addr.getPort(); String name = addr.getName(); StringBuilder sb = new StringBuilder(); if (scheme != null) { sb.append(scheme).append("://"); } if (host != null) { sb.append(host); } if (port != null) { sb.append(":").append(port); } if (name != null) { sb.append("/").append(name); } return sb.toString(); } else { return address; } } private String _original; private void rewriteMessage(Message m) { _original = m.getAddress(); if (_rewrites.apply(_original)) { m.setAddress(_rewrites.result()); } else { m.setAddress(defaultRewrite(_original)); } } private void restoreMessage(Message m) { m.setAddress(_original); } private String routeAddress(String addr) { if (_routes.apply(addr)) { return _routes.result(); } else { return addr; } } public void put(Message m) throws MessengerException { if (_driver == null) { throw new IllegalStateException("cannot put while messenger is stopped"); } if(_logger.isLoggable(Level.FINE)) { _logger.fine(this + " about to put message: " + m); } StoreEntry entry = _outgoingStore.put( m.getAddress() ); _outgoingTracker = new TrackerImpl(TrackerImpl.Type.OUTGOING, _outgoingStore.trackEntry(entry)); String routedAddress = routeAddress(m.getAddress()); Address address = new Address(routedAddress); if (address.getHost() == null) { throw new MessengerException("unable to send to address: " + routedAddress); } rewriteMessage(m); try { adjustReplyTo(m); int encoded; byte[] buffer = new byte[5*1024]; while (true) { try { encoded = m.encode(buffer, 0, buffer.length); break; } catch (java.nio.BufferOverflowException e) { buffer = new byte[buffer.length*2]; } } entry.setEncodedMsg( buffer, encoded ); } finally { restoreMessage(m); } Sender sender = getLink(address, new SenderFinder(address.getName())); pumpOut(m.getAddress(), sender); } private void reclaimLink(Link link) { if (link instanceof Receiver) { int credit = link.getCredit(); if (credit > 0) { _credit += credit; _distributed -= credit; } } Delivery delivery = link.head(); while (delivery != null) { StoreEntry entry = (StoreEntry) delivery.getContext(); if (entry != null) { entry.setDelivery(null); if (delivery.isBuffered()) { entry.setStatus(Status.ABORTED); } } delivery = delivery.next(); } linkRemoved(link); } private int pumpOut( String address, Sender sender ) { StoreEntry entry = _outgoingStore.get( address ); if (entry == null) { sender.drained(); return 0; } byte[] tag = String.valueOf(_nextTag++).getBytes(); Delivery delivery = sender.delivery(tag); entry.setDelivery( delivery ); _logger.log(Level.FINE, "Sending on delivery: " + delivery); int n = sender.send( entry.getEncodedMsg(), 0, entry.getEncodedLength()); if (n < 0) { _outgoingStore.freeEntry( entry ); _logger.log(Level.WARNING, "Send error: " + n); return n; } else { sender.advance(); _outgoingStore.freeEntry( entry ); return 0; } } public void send() throws TimeoutException { send(-1); } public void send(int n) throws TimeoutException { if (_driver == null) { throw new IllegalStateException("cannot send while messenger is stopped"); } if(_logger.isLoggable(Level.FINE)) { _logger.fine(this + " about to send"); } if (n == -1) _sendThreshold = 0; else { _sendThreshold = outgoing() - n; if (_sendThreshold < 0) _sendThreshold = 0; } waitUntil(_sentSettled); } public void recv(int n) throws TimeoutException { if (_driver == null) { throw new IllegalStateException("cannot recv while messenger is stopped"); } if (_logger.isLoggable(Level.FINE) && n != -1) { _logger.fine(this + " about to wait for up to " + n + " messages to be received"); } if (n == -1) { _credit_mode = LinkCreditMode.LINK_CREDIT_AUTO; } else { _credit_mode = LinkCreditMode.LINK_CREDIT_EXPLICIT; if (n > _distributed) _credit = n - _distributed; else // cancel unallocated _credit = 0; } distributeCredit(); waitUntil(_messageAvailable); } public void recv() throws TimeoutException { recv(-1); } public int receiving() { return _credit + _distributed; } public Message get() { StoreEntry entry = _incomingStore.get( null ); if (entry != null) { Message message = Proton.message(); message.decode( entry.getEncodedMsg(), 0, entry.getEncodedLength() ); _incomingTracker = new TrackerImpl(TrackerImpl.Type.INCOMING, _incomingStore.trackEntry(entry)); _incomingStore.freeEntry( entry ); return message; } return null; } private int pumpIn(String address, Receiver receiver) { Delivery delivery = receiver.current(); if (delivery.isReadable() && !delivery.isPartial()) { StoreEntry entry = _incomingStore.put( address ); entry.setDelivery( delivery ); _logger.log(Level.FINE, "Readable delivery found: " + delivery); int size = delivery.pending(); byte[] buffer = new byte[size]; int read = receiver.recv( buffer, 0, buffer.length ); if (read != size) { throw new IllegalStateException(); } entry.setEncodedMsg( buffer, size ); receiver.advance(); // account for the used credit, replenish if // low (< 20% maximum per-link batch) and // extra credit available assert(_distributed > 0); _distributed--; if (!receiver.getDrain() && _blocked.isEmpty() && _credit > 0) { final int max = perLinkCredit(); final int lo_thresh = (int)(max * 0.2 + 0.5); if (receiver.getRemoteCredit() < lo_thresh) { final int more = Math.min(_credit, max - receiver.getRemoteCredit()); _credit -= more; _distributed += more; receiver.flow(more); } } // check if blocked if (receiver.getRemoteCredit() == 0 && _credited.contains(receiver)) { _credited.remove(receiver); if (receiver.getDrain()) { receiver.setDrain(false); assert( _draining > 0 ); _draining--; } _blocked.add(receiver); } } return 0; } public void subscribe(String source) throws MessengerException { if (_driver == null) { throw new IllegalStateException("messenger is stopped"); } String routed = routeAddress(source); Address address = new Address(routed); String hostName = address.getHost(); if (hostName == null) throw new MessengerException("Invalid address (hostname cannot be null): " + routed); int port = Integer.valueOf(address.getImpliedPort()); if (address.isPassive()) { if(_logger.isLoggable(Level.FINE)) { _logger.fine(this + " about to subscribe to source " + source + " using address " + hostName + ":" + port); } ListenerContext ctx = new ListenerContext(address); _driver.createListener(hostName, port, ctx); } else { if(_logger.isLoggable(Level.FINE)) { _logger.fine(this + " about to subscribe to source " + source); } getLink(address, new ReceiverFinder(address.getName())); } } public int outgoing() { return _outgoingStore.size() + queued(true); } public int incoming() { return _incomingStore.size() + queued(false); } public int getIncomingWindow() { return _incomingStore.getWindow(); } public void setIncomingWindow(int window) { _incomingStore.setWindow(window); } public int getOutgoingWindow() { return _outgoingStore.getWindow(); } public void setOutgoingWindow(int window) { _outgoingStore.setWindow(window); } public Tracker incomingTracker() { return _incomingTracker; } public Tracker outgoingTracker() { return _outgoingTracker; } private Store getTrackerStore(Tracker tracker) { return ((TrackerImpl)tracker).isOutgoing() ? _outgoingStore : _incomingStore; } @Override public void reject(Tracker tracker, int flags) { int id = ((TrackerImpl)tracker).getSequence(); getTrackerStore(tracker).update(id, Status.REJECTED, flags, false, false); } @Override public void accept(Tracker tracker, int flags) { int id = ((TrackerImpl)tracker).getSequence(); getTrackerStore(tracker).update(id, Status.ACCEPTED, flags, false, false); } @Override public void settle(Tracker tracker, int flags) { int id = ((TrackerImpl)tracker).getSequence(); getTrackerStore(tracker).update(id, Status.UNKNOWN, flags, true, true); } public Status getStatus(Tracker tracker) { int id = ((TrackerImpl)tracker).getSequence(); StoreEntry e = getTrackerStore(tracker).getEntry(id); if (e != null) { return e.getStatus(); } return Status.UNKNOWN; } @Override public void route(String pattern, String address) { _routes.rule(pattern, address); } @Override public void rewrite(String pattern, String address) { _rewrites.rule(pattern, address); } private int queued(boolean outgoing) { int count = 0; if (_driver != null) { for (Connector c : _driver.connectors()) { Connection connection = c.getConnection(); for (Link link : new Links(connection, ACTIVE, ANY)) { if (outgoing) { if (link instanceof Sender) count += link.getQueued(); } else { if (link instanceof Receiver) count += link.getQueued(); } } } } return count; } private void bringDestruction() { for (Connector c : _awaitingDestruction) { c.destroy(); } _awaitingDestruction.clear(); } private void processAllConnectors() { distributeCredit(); for (Connector c : _driver.connectors()) { processEndpoints(c); try { if (c.process()) { _worked = true; } } catch (IOException e) { _logger.log(Level.SEVERE, "Error processing connection", e); } } bringDestruction(); distributeCredit(); } private void processActive() { //process active listeners for (Listener l = _driver.listener(); l != null; l = _driver.listener()) { _worked = true; Connector c = l.accept(); Connection connection = Proton.connection(); connection.setContainer(_name); ListenerContext ctx = (ListenerContext) l.getContext(); connection.setContext(new ConnectionContext(ctx.getAddress(), c)); c.setConnection(connection); Transport transport = c.getTransport(); //TODO: full SASL Sasl sasl = c.sasl(); if (sasl != null) { sasl.server(); sasl.setMechanisms(new String[]{"ANONYMOUS"}); sasl.done(Sasl.SaslOutcome.PN_SASL_OK); } transport.ssl(ctx.getDomain()); connection.open(); } // process connectors, reclaiming credit on closed connectors for (Connector c = _driver.connector(); c != null; c = _driver.connector()) { _worked = true; if (c.isClosed()) { _awaitingDestruction.add(c); reclaimCredit(c.getConnection()); } else { _logger.log(Level.FINE, "Processing active connector " + c); try { c.process(); processEndpoints(c); c.process(); } catch (IOException e) { _logger.log(Level.SEVERE, "Error processing connection", e); } } } bringDestruction(); distributeCredit(); } private void processEndpoints(Connector c) { Connection connection = c.getConnection(); if (connection.getLocalState() == EndpointState.UNINITIALIZED) { connection.open(); } Delivery delivery = connection.getWorkHead(); while (delivery != null) { Link link = delivery.getLink(); if (delivery.isUpdated()) { if (link instanceof Sender) { delivery.disposition(delivery.getRemoteState()); } StoreEntry e = (StoreEntry) delivery.getContext(); if (e != null) e.updated(); } if (delivery.isReadable()) { pumpIn( link.getSource().getAddress(), (Receiver)link ); } Delivery next = delivery.getWorkNext(); delivery.clear(); delivery = next; } for (Session session : new Sessions(connection, UNINIT, ANY)) { session.open(); _logger.log(Level.FINE, "Opened session " + session); } for (Link link : new Links(connection, UNINIT, ANY)) { //TODO: the following is not correct; should only copy those properties that we understand link.setSource(link.getRemoteSource()); link.setTarget(link.getRemoteTarget()); linkAdded(link); link.open(); _logger.log(Level.FINE, "Opened link " + link); } distributeCredit(); for (Link link : new Links(connection, ACTIVE, ACTIVE)) { if (link instanceof Sender) { pumpOut(link.getTarget().getAddress(), (Sender)link); } } for (Session session : new Sessions(connection, ACTIVE, CLOSED)) { session.close(); } for (Link link : new Links(connection, ANY, CLOSED)) { if (link.getLocalState() == EndpointState.ACTIVE) { link.close(); } else { reclaimLink(link); } } if (connection.getRemoteState() == EndpointState.CLOSED) { if (connection.getLocalState() == EndpointState.ACTIVE) { connection.close(); } } } private boolean waitUntil(Predicate condition) throws TimeoutException { if (_blocking) { boolean done = waitUntil(condition, _timeout); if (!done) { _logger.log(Level.SEVERE, String.format ("Timeout when waiting for condition %s after %s ms", condition, _timeout)); throw new TimeoutException(); } return done; } else { return waitUntil(condition, 0); } } private boolean waitUntil(Predicate condition, long timeout) { if (_driver == null) { throw new IllegalStateException("cannot wait while messenger is stopped"); } processAllConnectors(); // wait until timeout expires or until test is true long now = System.currentTimeMillis(); final long deadline = timeout < 0 ? Long.MAX_VALUE : now + timeout; boolean done = false; while (true) { done = condition.test(); if (done) break; long remaining; if (timeout < 0) remaining = -1; else { remaining = deadline - now; if (remaining < 0) break; } // Update the credit scheduler. If the scheduler detects // credit imbalance on the links, wake up in time to // service credit drain distributeCredit(); if (_next_drain != 0) { long wakeup = (_next_drain > now) ? _next_drain - now : 0; remaining = (remaining == -1) ? wakeup : Math.min(remaining, wakeup); } boolean woken; woken = _driver.doWait(remaining); processActive(); if (woken) { throw new InterruptException(); } now = System.currentTimeMillis(); } return done; } private Connection lookup(Address address) { for (Connector c : _driver.connectors()) { Connection connection = c.getConnection(); ConnectionContext ctx = (ConnectionContext) connection.getContext(); if (ctx.matches(address)) { return connection; } } return null; } private void reclaimCredit(Connection connection) { for (Link link : new Links(connection, ANY, ANY)) { reclaimLink(link); } } private void distributeCredit() { if (_receivers == 0) return; if (_credit_mode == LinkCreditMode.LINK_CREDIT_AUTO) { // replenish, but limit the max total messages buffered final int max = _receivers * _credit_batch; final int used = _distributed + incoming(); if (max > used) _credit = max - used; } // reclaim any credit left over after draining links has completed if (_draining > 0) { Iterator itr = _credited.iterator(); while (itr.hasNext()) { Receiver link = (Receiver) itr.next(); if (link.getDrain()) { if (!link.draining()) { // drain completed for this link int drained = link.drained(); assert(_distributed >= drained); _distributed -= drained; _credit += drained; link.setDrain(false); _draining--; itr.remove(); _blocked.add(link); } } } } // distribute available credit to blocked links final int batch = perLinkCredit(); while (_credit > 0 && !_blocked.isEmpty()) { Receiver link = _blocked.get(0); _blocked.remove(0); final int more = Math.min(_credit, batch); _distributed += more; _credit -= more; link.flow(more); _credited.add(link); // flow changed, must process it ConnectionContext ctx = (ConnectionContext) link.getSession().getConnection().getContext(); try { ctx.getConnector().process(); } catch (IOException e) { _logger.log(Level.SEVERE, "Error processing connection", e); } } if (_blocked.isEmpty()) { _next_drain = 0; } else { // not enough credit for all links - start draining granted credit if (_draining == 0) { // don't do it too often - pace ourselves (it's expensive) if (_next_drain == 0) { _next_drain = System.currentTimeMillis() + 250; } else if (_next_drain <= System.currentTimeMillis()) { // initiate drain, free up at most enough to satisfy blocked _next_drain = 0; int needed = _blocked.size() * batch; for (Receiver link : _credited) { if (!link.getDrain()) { link.setDrain(true); needed -= link.getRemoteCredit(); _draining++; // drain requested on link, must process it ConnectionContext ctx = (ConnectionContext) link.getSession().getConnection().getContext(); try { ctx.getConnector().process(); } catch (IOException e) { _logger.log(Level.SEVERE, "Error processing connection", e); } if (needed <= 0) break; } } } } } } private interface Predicate { boolean test(); } private class SentSettled implements Predicate { public boolean test() { //are all sent messages settled? int total = _outgoingStore.size(); for (Connector c : _driver.connectors()) { // TBD // check if transport is done generating output // pn_transport_t *transport = pn_connector_transport(ctor); // if (transport) { // if (!pn_transport_quiesced(transport)) { // pn_connector_process(ctor); // return false; // } // } Connection connection = c.getConnection(); for (Link link : new Links(connection, ACTIVE, ANY)) { if (link instanceof Sender) { total += link.getQueued(); } } // TBD: there is no per-link unsettled // deliveries iterator, so for now get the // deliveries by walking the outgoing trackers Iterator entries = _outgoingStore.trackedEntries(); while (entries.hasNext() && total <= _sendThreshold) { StoreEntry e = (StoreEntry) entries.next(); if (e != null ) { Delivery d = e.getDelivery(); if (d != null) { if (d.getRemoteState() == null && !d.remotelySettled()) { total++; } } } } } return total <= _sendThreshold; } } private class MessageAvailable implements Predicate { public boolean test() { //do we have at least one pending message? if (_incomingStore.size() > 0) return true; for (Connector c : _driver.connectors()) { Connection connection = c.getConnection(); Delivery delivery = connection.getWorkHead(); while (delivery != null) { if (delivery.isReadable() && !delivery.isPartial()) { return true; } else { delivery = delivery.getWorkNext(); } } } // if no connections, or not listening, exit as there won't ever be a message if (!_driver.listeners().iterator().hasNext() && !_driver.connectors().iterator().hasNext()) return true; return false; } } private class AllClosed implements Predicate { public boolean test() { if (_driver == null) { return true; } for (Connector c : _driver.connectors()) { if (!c.isClosed()) { return false; } } _driver.destroy(); _driver = null; return true; } } private boolean _worked = false; private class WorkPred implements Predicate { public boolean test() { return _worked; } } private final SentSettled _sentSettled = new SentSettled(); private final MessageAvailable _messageAvailable = new MessageAvailable(); private final AllClosed _allClosed = new AllClosed(); private final WorkPred _workPred = new WorkPred(); private interface LinkFinder { C test(Link link); C create(Session session); } private class SenderFinder implements LinkFinder { private final String _path; SenderFinder(String path) { _path = path == null ? "" : path; } public Sender test(Link link) { if (link instanceof Sender && matchTarget((Target) link.getTarget(), _path)) { return (Sender) link; } else { return null; } } public Sender create(Session session) { Sender sender = session.sender(_path); Target target = new Target(); target.setAddress(_path); sender.setTarget(target); // the C implemenation does this: Source source = new Source(); source.setAddress(_path); sender.setSource(source); if (getOutgoingWindow() > 0) { // use explicit settlement via dispositions (not pre-settled) sender.setSenderSettleMode(SenderSettleMode.UNSETTLED); sender.setReceiverSettleMode(ReceiverSettleMode.SECOND); // desired } return sender; } } private class ReceiverFinder implements LinkFinder { private final String _path; ReceiverFinder(String path) { _path = path == null ? "" : path; } public Receiver test(Link link) { if (link instanceof Receiver && matchSource((Source) link.getSource(), _path)) { return (Receiver) link; } else { return null; } } public Receiver create(Session session) { Receiver receiver = session.receiver(_path); Source source = new Source(); source.setAddress(_path); receiver.setSource(source); // the C implemenation does this: Target target = new Target(); target.setAddress(_path); receiver.setTarget(target); if (getIncomingWindow() > 0) { // use explicit settlement via dispositions (not pre-settled) receiver.setSenderSettleMode(SenderSettleMode.UNSETTLED); // desired receiver.setReceiverSettleMode(ReceiverSettleMode.SECOND); } return receiver; } } private C getLink(Address address, LinkFinder finder) { Connection connection = lookup(address); if (connection == null) { String host = address.getHost(); int port = Integer.valueOf(address.getImpliedPort()); Connector connector = _driver.createConnector(host, port, null); _logger.log(Level.FINE, "Connecting to " + host + ":" + port); connection = Proton.connection(); connection.setContainer(_name); connection.setHostname(host); connection.setContext(new ConnectionContext(address, connector)); connector.setConnection(connection); Sasl sasl = connector.sasl(); if (sasl != null) { sasl.client(); sasl.setMechanisms(new String[]{"ANONYMOUS"}); } if ("amqps".equalsIgnoreCase(address.getScheme())) { Transport transport = connector.getTransport(); SslDomain domain = makeDomain(address, SslDomain.Mode.CLIENT); if (_trustedDb != null) { domain.setPeerAuthentication(SslDomain.VerifyMode.VERIFY_PEER); //domain.setPeerAuthentication(SslDomain.VerifyMode.VERIFY_PEER_NAME); } else { domain.setPeerAuthentication(SslDomain.VerifyMode.ANONYMOUS_PEER); } Ssl ssl = transport.ssl(domain); //ssl.setPeerHostname(host); } connection.open(); } for (Link link : new Links(connection, ACTIVE, ANY)) { C result = finder.test(link); if (result != null) return result; } Session session = connection.session(); session.open(); C link = finder.create(session); linkAdded(link); link.open(); return link; } private static class Links implements Iterable { private final Connection _connection; private final EnumSet _local; private final EnumSet _remote; Links(Connection connection, EnumSet local, EnumSet remote) { _connection = connection; _local = local; _remote = remote; } public java.util.Iterator iterator() { return new LinkIterator(_connection, _local, _remote); } } private static class LinkIterator implements java.util.Iterator { private final EnumSet _local; private final EnumSet _remote; private Link _next; LinkIterator(Connection connection, EnumSet local, EnumSet remote) { _local = local; _remote = remote; _next = connection.linkHead(_local, _remote); } public boolean hasNext() { return _next != null; } public Link next() { try { return _next; } finally { _next = _next.next(_local, _remote); } } public void remove() { throw new UnsupportedOperationException(); } } private static class Sessions implements Iterable { private final Connection _connection; private final EnumSet _local; private final EnumSet _remote; Sessions(Connection connection, EnumSet local, EnumSet remote) { _connection = connection; _local = local; _remote = remote; } public java.util.Iterator iterator() { return new SessionIterator(_connection, _local, _remote); } } private static class SessionIterator implements java.util.Iterator { private final EnumSet _local; private final EnumSet _remote; private Session _next; SessionIterator(Connection connection, EnumSet local, EnumSet remote) { _local = local; _remote = remote; _next = connection.sessionHead(_local, _remote); } public boolean hasNext() { return _next != null; } public Session next() { try { return _next; } finally { _next = _next.next(_local, _remote); } } public void remove() { throw new UnsupportedOperationException(); } } private void adjustReplyTo(Message m) { String original = m.getReplyTo(); if (original != null) { if (original.startsWith("~/")) { m.setReplyTo("amqp://" + _name + "/" + original.substring(2)); } else if (original.equals("~")) { m.setReplyTo("amqp://" + _name); } } } private static boolean matchTarget(Target target, String path) { if (target == null) return path.isEmpty(); else return path.equals(target.getAddress()); } private static boolean matchSource(Source source, String path) { if (source == null) return path.isEmpty(); else return path.equals(source.getAddress()); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("MessengerImpl [_name=").append(_name).append("]"); return builder.toString(); } // compute the maximum amount of credit each receiving link is // entitled to. The actual credit given to the link depends on // what amount of credit is actually available. private int perLinkCredit() { if (_receivers == 0) return 0; int total = _credit + _distributed; return Math.max(total/_receivers, 1); } // a new link has been created, account for it. private void linkAdded(Link link) { if (link instanceof Receiver) { _receivers++; _blocked.add((Receiver)link); link.setContext(Boolean.TRUE); } } // a link is being removed, account for it. private void linkRemoved(Link _link) { if (_link instanceof Receiver && (Boolean) _link.getContext()) { _link.setContext(Boolean.FALSE); Receiver link = (Receiver)_link; assert _receivers > 0; _receivers--; if (link.getDrain()) { link.setDrain(false); assert _draining > 0; _draining--; } if (_blocked.contains(link)) _blocked.remove(link); else if (_credited.contains(link)) _credited.remove(link); else assert(false); } } private class ConnectionContext { private Address _address; private Connector _connector; public ConnectionContext(Address address, Connector connector) { _address = address; _connector = connector; } public Address getAddress() { return _address; } public boolean matches(Address address) { String host = address.getHost(); String port = address.getImpliedPort(); Connection conn = _connector.getConnection(); return host.equals(conn.getRemoteContainer()) || (_address.getHost().equals(host) && _address.getImpliedPort().equals(port)); } public Connector getConnector() { return _connector; } } private SslDomain makeDomain(Address address, SslDomain.Mode mode) { SslDomain domain = Proton.sslDomain(); domain.init(mode); if (_certificate != null) { domain.setCredentials(_certificate, _privateKey, _password); } if (_trustedDb != null) { domain.setTrustedCaDb(_trustedDb); } if ("amqps".equalsIgnoreCase(address.getScheme())) { domain.allowUnsecuredClient(false); } else { domain.allowUnsecuredClient(true); } return domain; } private class ListenerContext { private Address _address; private SslDomain _domain; public ListenerContext(Address address) { _address = address; _domain = makeDomain(address, SslDomain.Mode.SERVER); } public SslDomain getDomain() { return _domain; } public Address getAddress() { return _address; } } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/impl/Address.java0000664000000000000000000001125412562450203026453 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.messenger.impl; /** * Address * */ public class Address { private String _address; private boolean _passive; private String _scheme; private String _user; private String _pass; private String _host; private String _port; private String _name; public void clear() { _passive = false; _scheme = null; _user = null; _pass = null; _host = null; _port = null; _name = null; } public Address() { clear(); } public Address(String address) { clear(); int start = 0; int schemeEnd = address.indexOf("://", start); if (schemeEnd >= 0) { _scheme = address.substring(start, schemeEnd); start = schemeEnd + 3; } String uphp; int slash = address.indexOf("/", start); if (slash >= 0) { uphp = address.substring(start, slash); _name = address.substring(slash + 1); } else { uphp = address.substring(start); } String hp; int at = uphp.indexOf('@'); if (at >= 0) { String up = uphp.substring(0, at); hp = uphp.substring(at + 1); int colon = up.indexOf(':'); if (colon >= 0) { _user = up.substring(0, colon); _pass = up.substring(colon + 1); } else { _user = up; } } else { hp = uphp; } if (hp.startsWith("[")) { int close = hp.indexOf(']'); if (close >= 0) { _host = hp.substring(1, close); if (hp.substring(close + 1).startsWith(":")) { _port = hp.substring(close + 2); } } } if (_host == null) { int colon = hp.indexOf(':'); if (colon >= 0) { _host = hp.substring(0, colon); _port = hp.substring(colon + 1); } else { _host = hp; } } if (_host.startsWith("~")) { _host = _host.substring(1); _passive = true; } } public String toString() { String str = new String(); if (_scheme != null) str += _scheme + "://"; if (_user != null) str += _user; if (_pass != null) str += ":" + _pass; if (_user != null || _pass != null) str += "@"; if (_host != null) { if (_host.contains(":")) str += "[" + _host + "]"; else str += _host; } if (_port != null) str += ":" + _port; if (_name != null) str += "/" + _name; return str; } public boolean isPassive() { return _passive; } public String getScheme() { return _scheme; } public String getUser() { return _user; } public String getPass() { return _pass; } public String getHost() { return _host; } public String getPort() { return _port; } public String getImpliedPort() { if (_port == null) { return getDefaultPort(); } else { return getPort(); } } public String getDefaultPort() { if ("amqps".equals(_scheme)) return "5671"; else return "5672"; } public String getName() { return _name; } public void setScheme(String scheme) { _scheme= scheme; } public void setUser(String user) { _user= user; } public void setPass(String pass) { _pass= pass; } public void setHost(String host) { _host= host; } public void setPort(String port) { _port= port; } public void setName(String name) { _name= name; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/Tracker.java0000664000000000000000000000156612562450203025525 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.messenger; public interface Tracker { } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/Status.java0000664000000000000000000000173212562450203025410 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.messenger; public enum Status { UNKNOWN, PENDING, ACCEPTED, REJECTED, RELEASED, MODIFIED, ABORTED, SETTLED } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/MessengerException.java0000664000000000000000000000240312562450203027730 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.messenger; import org.apache.qpid.proton.ProtonException; public class MessengerException extends ProtonException { public MessengerException() { } public MessengerException(String message) { super(message); } public MessengerException(String message, Throwable cause) { super(message, cause); } public MessengerException(Throwable cause) { super(cause); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/messenger/Messenger.java0000664000000000000000000002151212562450203026053 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.messenger; import java.io.IOException; import org.apache.qpid.proton.TimeoutException; import org.apache.qpid.proton.message.Message; import org.apache.qpid.proton.messenger.impl.MessengerImpl; /** * * Messenger defines a high level interface for sending and receiving * messages. Every Messenger contains a single logical queue of * incoming messages and a single logical queue of outgoing * messages. These messages in these queues may be destined for, or * originate from, a variety of addresses. * *

Address Syntax

* * An address has the following form: * * [ amqp[s]:// ] [user[:password]@] domain [/[name]] * * Where domain can be one of: * * host | host:port | ip | ip:port | name * * The following are valid examples of addresses: * * - example.org * - example.org:1234 * - amqp://example.org * - amqps://example.org * - example.org/incoming * - amqps://example.org/outgoing * - amqps://fred:trustno1@example.org * - 127.0.0.1:1234 * - amqps://127.0.0.1:1234 * *

Sending & Receiving Messages

* * The Messenger interface works in conjuction with the Message * class. The Message class is a mutable holder of message content. * The put method will encode the content in a given Message object * into the outgoing message queue leaving that Message object free * to be modified or discarded without having any impact on the * content in the outgoing queue. * * Similarly, the get method will decode the content in the incoming * message queue into the supplied Message object. */ public interface Messenger { public static final class Factory { public static Messenger create() { return new MessengerImpl(); } public static Messenger create(String name) { return new MessengerImpl(name); } } /** * Flag for use with reject(), accept() and settle() methods. */ static final int CUMULATIVE = 0x01; /** * Places the content contained in the message onto the outgoing * queue of the Messenger. This method will never block. The * send call may be used to block until the messages are * sent. Either a send() or a recv() call is neceesary at present * to cause the messages to actually be sent out. */ void put(Message message) throws MessengerException; /** * Blocks until the outgoing queue is empty and, in the event that * an outgoing window has been set, until the messages in that * window have been received by the target to which they were * sent, or the operation times out. The timeout property * controls how long a Messenger will block before timing out. */ void send() throws TimeoutException; void send(int n) throws TimeoutException; /** * Subscribes the Messenger to messages originating from the * specified source. The source is an address as specified in the * Messenger introduction with the following addition. If the * domain portion of the address begins with the '~' character, * the Messenger will interpret the domain as host/port, bind * to it, and listen for incoming messages. For example * "~0.0.0.0", "amqp://~0.0.0.0" will bind to any local interface * and listen for incoming messages. */ void subscribe(String source) throws MessengerException; /** * Receives an arbitrary number of messages into the * incoming queue of the Messenger. This method will block until * at least one message is available or the operation times out. */ void recv() throws TimeoutException; /** * Receives up to the specified number of messages into the * incoming queue of the Messenger. This method will block until * at least one message is available or the operation times out. */ void recv(int count) throws TimeoutException; /** * Returns the capacity of the incoming message queue of * messenger. Note this count does not include those messages * already available on the incoming queue (see * incoming()). Rather it returns the number of incoming queue * entries available for receiving messages */ int receiving(); /** * Returns the message from the head of the incoming message * queue. */ Message get(); /** * Transitions the Messenger to an active state. A Messenger is * initially created in an inactive state. When inactive, a * Messenger will not send or receive messages from its internal * queues. A Messenger must be started before calling send() or * recv(). */ void start() throws IOException; /** * Transitions the Messenger to an inactive state. An inactive * Messenger will not send or receive messages from its internal * queues. A Messenger should be stopped before being discarded to * ensure a clean shutdown handshake occurs on any internally managed * connections. */ void stop(); boolean stopped(); /** Sends or receives any outstanding messages queued for a * messenger. If timeout is zero, no blocking is done. A timeout * of -1 blocks forever, otherwise timeout is the maximum time (in * millisecs) to block. Returns True if work was performed. */ boolean work(long timeout) throws TimeoutException; void interrupt(); void setTimeout(long timeInMillis); long getTimeout(); boolean isBlocking(); void setBlocking(boolean b); /** * Returns a count of the messages currently on the outgoing queue * (i.e. those that have been put() but not yet actually sent * out). */ int outgoing(); /** * Returns a count of the messages available on the incoming * queue. */ int incoming(); int getIncomingWindow(); void setIncomingWindow(int window); int getOutgoingWindow(); void setOutgoingWindow(int window); /** * Returns a token which can be used to accept or reject the * message returned in the previous get() call. */ Tracker incomingTracker(); /** * Returns a token which can be used to track the status of the * message of the previous put() call. */ Tracker outgoingTracker(); /** * Rejects messages retrieved from the incoming message queue. The * tracker object for a message is obtained through a call to * incomingTracker() following a get(). If the flags argument * contains CUMULATIVE, then all message up to the one identified * by the tracker will be rejected. */ void reject(Tracker tracker, int flags); /** * Accepts messages retrieved from the incoming message queue. The * tracker object for a message is obtained through a call to * incomingTracker() following a get(). If the flags argument * contains CUMULATIVE, then all message up to the one identified * by the tracker will be accepted. */ void accept(Tracker tracker, int flags); void settle(Tracker tracker, int flags); /** * Gets the last known remote state of the delivery associated * with the given tracker. */ Status getStatus(Tracker tracker); void route(String pattern, String address); void rewrite(String pattern, String address); /** * Set the path to the certificate file. */ void setCertificate(String certificate); /** * Get the path to the certificate file. */ String getCertificate(); /** * Set the path to private key file. */ void setPrivateKey(String privateKey); /** * Get the path to the private key file. */ String getPrivateKey(); /** * Set the password for private key file. */ void setPassword(String password); /** * Get the password for the priate key file. */ String getPassword(); /** * Set the path to the trusted certificate database. */ void setTrustedCertificates(String trusted); /** * Get the path to the trusted certificate database. */ String getTrustedCertificates(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/message/0000775000000000000000000000000012562450203022713 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/message/impl/0000775000000000000000000000000012562450203023654 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/message/impl/MessageImpl.java0000664000000000000000000005350012562450203026730 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.message.impl; import java.nio.ByteBuffer; import java.util.Date; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedByte; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.messaging.*; import org.apache.qpid.proton.amqp.messaging.Data; import org.apache.qpid.proton.codec.*; import org.apache.qpid.proton.message.*; public class MessageImpl implements ProtonJMessage { private final AMQPMessageFormat _parser = new AMQPMessageFormat(); private Header _header; private DeliveryAnnotations _deliveryAnnotations; private MessageAnnotations _messageAnnotations; private Properties _properties; private ApplicationProperties _applicationProperties; private Section _body; private Footer _footer; private MessageFormat _format = MessageFormat.DATA; private static class EncoderDecoderPair { DecoderImpl decoder = new DecoderImpl(); EncoderImpl encoder = new EncoderImpl(decoder); { AMQPDefinedTypes.registerAllTypes(decoder, encoder); } } private static final ThreadLocal tlsCodec = new ThreadLocal() { @Override protected EncoderDecoderPair initialValue() { return new EncoderDecoderPair(); } }; /** * @deprecated This constructor's visibility will be reduced to the default scope in a future release. * Client code outside this module should use a {@link MessageFactory} instead */ @Deprecated public MessageImpl() { } /** * @deprecated This constructor's visibility will be reduced to the default scope in a future release. * Client code outside this module should use a {@link MessageFactory} instead */ @Deprecated public MessageImpl(Header header, DeliveryAnnotations deliveryAnnotations, MessageAnnotations messageAnnotations, Properties properties, ApplicationProperties applicationProperties, Section body, Footer footer) { _header = header; _deliveryAnnotations = deliveryAnnotations; _messageAnnotations = messageAnnotations; _properties = properties; _applicationProperties = applicationProperties; _body = body; _footer = footer; } @Override public boolean isDurable() { return (_header == null || _header.getDurable() == null) ? false : _header.getDurable(); } @Override public long getDeliveryCount() { return (_header == null || _header.getDeliveryCount() == null) ? 0l : _header.getDeliveryCount().longValue(); } @Override public short getPriority() { return (_header == null || _header.getPriority() == null) ? DEFAULT_PRIORITY : _header.getPriority().shortValue(); } @Override public boolean isFirstAcquirer() { return (_header == null || _header.getFirstAcquirer() == null) ? false : _header.getFirstAcquirer(); } @Override public long getTtl() { return (_header == null || _header.getTtl() == null) ? 0l : _header.getTtl().longValue(); } @Override public void setDurable(boolean durable) { if (_header == null) { if (durable) { _header = new Header(); } else { return; } } _header.setDurable(durable); } @Override public void setTtl(long ttl) { if (_header == null) { if (ttl != 0l) { _header = new Header(); } else { return; } } _header.setTtl(UnsignedInteger.valueOf(ttl)); } @Override public void setDeliveryCount(long deliveryCount) { if (_header == null) { if (deliveryCount == 0l) { return; } _header = new Header(); } _header.setDeliveryCount(UnsignedInteger.valueOf(deliveryCount)); } @Override public void setFirstAcquirer(boolean firstAcquirer) { if (_header == null) { if (!firstAcquirer) { return; } _header = new Header(); } _header.setFirstAcquirer(firstAcquirer); } @Override public void setPriority(short priority) { if (_header == null) { if (priority == DEFAULT_PRIORITY) { return; } _header = new Header(); } _header.setPriority(UnsignedByte.valueOf((byte) priority)); } @Override public Object getMessageId() { return _properties == null ? null : _properties.getMessageId(); } @Override public long getGroupSequence() { return (_properties == null || _properties.getGroupSequence() == null) ? 0l : _properties.getGroupSequence().intValue(); } @Override public String getReplyToGroupId() { return _properties == null ? null : _properties.getReplyToGroupId(); } @Override public long getCreationTime() { return (_properties == null || _properties.getCreationTime() == null) ? 0l : _properties.getCreationTime().getTime(); } @Override public String getAddress() { return _properties == null ? null : _properties.getTo(); } @Override public byte[] getUserId() { if(_properties == null || _properties.getUserId() == null) { return null; } else { final Binary userId = _properties.getUserId(); byte[] id = new byte[userId.getLength()]; System.arraycopy(userId.getArray(),userId.getArrayOffset(),id,0,userId.getLength()); return id; } } @Override public String getReplyTo() { return _properties == null ? null : _properties.getReplyTo(); } @Override public String getGroupId() { return _properties == null ? null : _properties.getGroupId(); } @Override public String getContentType() { return (_properties == null || _properties.getContentType() == null) ? null : _properties.getContentType().toString(); } @Override public long getExpiryTime() { return (_properties == null || _properties.getAbsoluteExpiryTime() == null) ? 0l : _properties.getAbsoluteExpiryTime().getTime(); } @Override public Object getCorrelationId() { return (_properties == null) ? null : _properties.getCorrelationId(); } @Override public String getContentEncoding() { return (_properties == null || _properties.getContentEncoding() == null) ? null : _properties.getContentEncoding().toString(); } @Override public String getSubject() { return _properties == null ? null : _properties.getSubject(); } @Override public void setGroupSequence(long groupSequence) { if(_properties == null) { if(groupSequence == 0l) { return; } else { _properties = new Properties(); } } _properties.setGroupSequence(UnsignedInteger.valueOf((int) groupSequence)); } @Override public void setUserId(byte[] userId) { if(userId == null) { if(_properties != null) { _properties.setUserId(null); } } else { if(_properties == null) { _properties = new Properties(); } byte[] id = new byte[userId.length]; System.arraycopy(userId, 0, id,0, userId.length); _properties.setUserId(new Binary(id)); } } @Override public void setCreationTime(long creationTime) { if(_properties == null) { if(creationTime == 0l) { return; } _properties = new Properties(); } _properties.setCreationTime(new Date(creationTime)); } @Override public void setSubject(String subject) { if(_properties == null) { if(subject == null) { return; } _properties = new Properties(); } _properties.setSubject(subject); } @Override public void setGroupId(String groupId) { if(_properties == null) { if(groupId == null) { return; } _properties = new Properties(); } _properties.setGroupId(groupId); } @Override public void setAddress(String to) { if(_properties == null) { if(to == null) { return; } _properties = new Properties(); } _properties.setTo(to); } @Override public void setExpiryTime(long absoluteExpiryTime) { if(_properties == null) { if(absoluteExpiryTime == 0l) { return; } _properties = new Properties(); } _properties.setAbsoluteExpiryTime(new Date(absoluteExpiryTime)); } @Override public void setReplyToGroupId(String replyToGroupId) { if(_properties == null) { if(replyToGroupId == null) { return; } _properties = new Properties(); } _properties.setReplyToGroupId(replyToGroupId); } @Override public void setContentEncoding(String contentEncoding) { if(_properties == null) { if(contentEncoding == null) { return; } _properties = new Properties(); } _properties.setContentEncoding(Symbol.valueOf(contentEncoding)); } @Override public void setContentType(String contentType) { if(_properties == null) { if(contentType == null) { return; } _properties = new Properties(); } _properties.setContentType(Symbol.valueOf(contentType)); } @Override public void setReplyTo(String replyTo) { if(_properties == null) { if(replyTo == null) { return; } _properties = new Properties(); } _properties.setReplyTo(replyTo); } @Override public void setCorrelationId(Object correlationId) { if(_properties == null) { if(correlationId == null) { return; } _properties = new Properties(); } _properties.setCorrelationId(correlationId); } @Override public void setMessageId(Object messageId) { if(_properties == null) { if(messageId == null) { return; } _properties = new Properties(); } _properties.setMessageId(messageId); } @Override public Header getHeader() { return _header; } @Override public DeliveryAnnotations getDeliveryAnnotations() { return _deliveryAnnotations; } @Override public MessageAnnotations getMessageAnnotations() { return _messageAnnotations; } @Override public Properties getProperties() { return _properties; } @Override public ApplicationProperties getApplicationProperties() { return _applicationProperties; } @Override public Section getBody() { return _body; } @Override public Footer getFooter() { return _footer; } @Override public void setHeader(Header header) { _header = header; } @Override public void setDeliveryAnnotations(DeliveryAnnotations deliveryAnnotations) { _deliveryAnnotations = deliveryAnnotations; } @Override public void setMessageAnnotations(MessageAnnotations messageAnnotations) { _messageAnnotations = messageAnnotations; } @Override public void setProperties(Properties properties) { _properties = properties; } @Override public void setApplicationProperties(ApplicationProperties applicationProperties) { _applicationProperties = applicationProperties; } @Override public void setBody(Section body) { _body = body; } @Override public void setFooter(Footer footer) { _footer = footer; } @Override public int decode(byte[] data, int offset, int length) { final ByteBuffer buffer = ByteBuffer.wrap(data, offset, length); decode(buffer); return length-buffer.remaining(); } public void decode(ByteBuffer buffer) { DecoderImpl decoder = tlsCodec.get().decoder; decoder.setByteBuffer(buffer); _header = null; _deliveryAnnotations = null; _messageAnnotations = null; _properties = null; _applicationProperties = null; _body = null; _footer = null; Section section = null; if(buffer.hasRemaining()) { section = (Section) decoder.readObject(); } if(section instanceof Header) { _header = (Header) section; if(buffer.hasRemaining()) { section = (Section) decoder.readObject(); } else { section = null; } } if(section instanceof DeliveryAnnotations) { _deliveryAnnotations = (DeliveryAnnotations) section; if(buffer.hasRemaining()) { section = (Section) decoder.readObject(); } else { section = null; } } if(section instanceof MessageAnnotations) { _messageAnnotations = (MessageAnnotations) section; if(buffer.hasRemaining()) { section = (Section) decoder.readObject(); } else { section = null; } } if(section instanceof Properties) { _properties = (Properties) section; if(buffer.hasRemaining()) { section = (Section) decoder.readObject(); } else { section = null; } } if(section instanceof ApplicationProperties) { _applicationProperties = (ApplicationProperties) section; if(buffer.hasRemaining()) { section = (Section) decoder.readObject(); } else { section = null; } } if(section != null && !(section instanceof Footer)) { _body = section; if(buffer.hasRemaining()) { section = (Section) decoder.readObject(); } else { section = null; } } if(section instanceof Footer) { _footer = (Footer) section; } decoder.setByteBuffer(null); } @Override public int encode(byte[] data, int offset, int length) { ByteBuffer buffer = ByteBuffer.wrap(data, offset, length); return encode(new WritableBuffer.ByteBufferWrapper(buffer)); } @Override public int encode2(byte[] data, int offset, int length) { ByteBuffer buffer = ByteBuffer.wrap(data, offset, length); WritableBuffer.ByteBufferWrapper first = new WritableBuffer.ByteBufferWrapper(buffer); DroppingWritableBuffer second = new DroppingWritableBuffer(); CompositeWritableBuffer composite = new CompositeWritableBuffer(first, second); int start = composite.position(); encode(composite); return composite.position() - start; } @Override public int encode(WritableBuffer buffer) { int length = buffer.remaining(); EncoderImpl encoder = tlsCodec.get().encoder; encoder.setByteBuffer(buffer); if(getHeader() != null) { encoder.writeObject(getHeader()); } if(getDeliveryAnnotations() != null) { encoder.writeObject(getDeliveryAnnotations()); } if(getMessageAnnotations() != null) { encoder.writeObject(getMessageAnnotations()); } if(getProperties() != null) { encoder.writeObject(getProperties()); } if(getApplicationProperties() != null) { encoder.writeObject(getApplicationProperties()); } if(getBody() != null) { encoder.writeObject(getBody()); } if(getFooter() != null) { encoder.writeObject(getFooter()); } encoder.setByteBuffer((WritableBuffer)null); return length - buffer.remaining(); } /** * @deprecated This method will be removed in a future release. */ @Override public void load(Object data) { switch (_format) { case DATA: Binary binData; if(data instanceof byte[]) { binData = new Binary((byte[])data); } else if(data instanceof Binary) { binData = (Binary) data; } else if(data instanceof String) { final String strData = (String) data; byte[] bin = new byte[strData.length()]; for(int i = 0; i < bin.length; i++) { bin[i] = (byte) strData.charAt(i); } binData = new Binary(bin); } else { binData = null; } _body = new Data(binData); break; case TEXT: _body = new AmqpValue(data == null ? "" : data.toString()); break; default: // AMQP _body = new AmqpValue(parseAMQPFormat((String) data)); } } /** * @deprecated This method will be removed in a future release. */ @Override public Object save() { switch (_format) { case DATA: if(_body instanceof Data) { return ((Data)_body).getValue().getArray(); } else return null; case AMQP: if(_body instanceof AmqpValue) { return toAMQPFormat(((AmqpValue) _body).getValue()); } else { return null; } case TEXT: if(_body instanceof AmqpValue) { final Object value = ((AmqpValue) _body).getValue(); return value == null ? "" : value.toString(); } return null; default: return null; } } /** * @deprecated This method will be removed in a future release. */ @Override public String toAMQPFormat(Object value) { return _parser.encode(value); } /** * @deprecated This method will be removed in a future release. */ @Override public Object parseAMQPFormat(String value) { Object obj = _parser.format(value); return obj; } /** * @deprecated This method will be removed in a future release. */ @Override public void setMessageFormat(MessageFormat format) { _format = format; } /** * @deprecated This method will be removed in a future release. */ @Override public MessageFormat getMessageFormat() { return _format; } @Override public void clear() { _body = null; } @Override public MessageError getError() { return MessageError.OK; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Message{"); if (_header != null) { sb.append("header="); sb.append(_header); } if (_properties != null) { sb.append("properties="); sb.append(_properties); } if (_body != null) { sb.append("body="); sb.append(_body); } sb.append("}"); return sb.toString(); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/message/impl/AMQPMessageFormat.java0000664000000000000000000004356212562450203027745 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.message.impl; import java.math.BigDecimal; import java.nio.CharBuffer; import java.text.DecimalFormat; import java.util.*; import org.apache.qpid.proton.amqp.DescribedType; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.transport.Flow; import org.apache.qpid.proton.message.*; /** * @deprecated This class will be removed in a future release. */ class AMQPMessageFormat { private static final char START_LIST = '['; private static final char DESCRIPTOR_CHAR = '@'; private static final char SYMBOL_START = ':'; private static final char QUOTE_CHAR = '"'; private static final char START_MAP = '{'; private static final char END_LIST = ']'; private static final char END_MAP = '}'; private static final char[] HEX = "0123456789abcdef".toCharArray(); public String encode(Object o) { if(o instanceof Boolean) { return encodeBoolean((Boolean)o); } if(o instanceof byte[]) { return encodeBinary((byte[]) o); } if(o instanceof Number) { return encodeNumber((Number) o); } if(o instanceof String) { return encodeString((String) o); } if(o instanceof Symbol) { return encodeSymbol((Symbol) o); } if(o instanceof List) { return encodeList((List)o); } if(o instanceof Map) { return encodeMap((Map) o); } if(o instanceof DescribedType) { return encodeDescribedType((DescribedType)o); } if(o == null) { return "null"; } return null; } private String encodeBinary(byte[] o) { StringBuilder b = new StringBuilder(); b.append("b\""); for(byte x : o) { if(x >= 32 && x < 127 && x != '"' && x != '\\') { b.append((char)x); } else { b.append("\\x"); b.append(HEX[(x>>4) & 0x0f ]); b.append(HEX[(x) & 0x0f ]); } } b.append('"'); return b.toString(); } private String encodeNumber(Number o) { if(o instanceof Float || o instanceof Double || o instanceof BigDecimal) { DecimalFormat df = new DecimalFormat("############.#######"); return df.format(o); } else { Formatter f = new Formatter(); return f.format("%d", o.longValue()).toString(); } } private String encodeBoolean(boolean o) { return o ? "true" : "false"; } private String encodeDescribedType(DescribedType o) { StringBuilder b = new StringBuilder(); b.append(DESCRIPTOR_CHAR); b.append(encode(o.getDescriptor())); b.append(' '); b.append(encode(o.getDescribed())); return b.toString(); } private String encodeMap(Map o) { StringBuilder b = new StringBuilder(); b.append(START_MAP); boolean first = true; for(Map.Entry e : o.entrySet()) { if(first) { first = false; } else { b.append(','); b.append(' '); } b.append(encode(e.getKey())); b.append('='); b.append(encode(e.getValue())); } b.append(END_MAP); return b.toString(); } private String encodeList(List o) { StringBuilder b = new StringBuilder(); b.append(START_LIST); boolean first = true; for(Object e : o) { if(first) { first = false; } else { b.append(','); b.append(' '); } b.append(encode(e)); } b.append(END_LIST); return b.toString(); } private String encodeSymbol(Symbol o) { StringBuilder b = new StringBuilder(":"); String sym = o.toString(); if(needsQuoting(sym)) { b.append(encodeString(sym)); } else { b.append(sym); } return b.toString(); } private boolean needsQuoting(String sym) { for(char c : sym.toCharArray()) { if((c < '0' || c > '9') && (c <'a' || c>'z') && (c<'A' || c>'Z') && c != '_') { return true; } } return false; } private String encodeString(String o) { StringBuilder b = new StringBuilder(); b.append("\""); for(char c : ((String) o).toCharArray()) { if(c == '\\') { b.append("\\\\"); } else if( c == '\n') { b.append("\\n"); } else if( c == '\b') { b.append("\\b"); } else if( c == '\r') { b.append("\\r"); } else if( c == '\t') { b.append("\\t"); } else if( c == '\"') { b.append("\\\""); } else if(c < 32 || c > 127) { Formatter fmt = new Formatter(); b.append("\\u"); b.append(fmt.format("%04x",(int)c)); } else { b.append(c); } } b.append("\""); return b.toString(); } public static void main(String[] args) { Map m = new LinkedHashMap(); final Object x = Arrays.asList((Object) Symbol.valueOf("hel lo"), "hi", Symbol.valueOf("x")); m.put(Symbol.valueOf("ddd"), x); m.put("hello", "world"); final Flow flow = new Flow(); flow.setDrain(true); m.put(flow, "wibble"); final AMQPMessageFormat f = new AMQPMessageFormat(); System.err.println(f.encode(m)); byte[] data = {0, 23, 45, 98, (byte) 255, 32, 78, 12, 126, 127, (byte) 128, 66,67,68}; System.err.println(f.encodeBinary(data)); byte[] data2 = (byte[]) f.format(f.encode(data)); System.out.println(Arrays.equals(data,data2)); } public Object format(CharSequence s) { return readValue(CharBuffer.wrap(s)); } private void skipWhitespace(CharBuffer s) { while(s.hasRemaining()) { char c = s.get(); if(!Character.isWhitespace(c)) { s.position(s.position()-1); break; } } } private Object readValue(CharBuffer s) { skipWhitespace(s); if(!s.hasRemaining()) { throw new MessageFormatException("Expecting a value, but only whitespace found", s); } char c = s.get(s.position()); if(Character.isDigit(c) || c == '-' ) { return readNumber(s); } else if(c== SYMBOL_START) { return readSymbol(s); } else if(c== START_MAP) { return readMap(s); } else if(c== START_LIST) { return readList(s); } else if(c=='b') { return readBinary(s); } else if(c== DESCRIPTOR_CHAR) { return readDescribedType(s); } else if(c == 't') { expect(s, "true"); return Boolean.TRUE; } else if(c == 'f') { expect(s, "false"); return Boolean.FALSE; } else if(c == 'n') { expect(s, "null"); return null; } else if(c == '\"') { return readString(s); } throw new MessageFormatException("Cannot parse message string", s); } private Object readDescribedType(CharBuffer s) { expect(s, DESCRIPTOR_CHAR); final Object descriptor = readValue(s); final Object described = readValue(s); return new DescribedType() { public Object getDescriptor() { return descriptor; } public Object getDescribed() { return described; } @Override public int hashCode() { return super.hashCode(); } @Override public boolean equals(Object obj) { return obj instanceof DescribedType && descriptor == null ? ((DescribedType) obj).getDescriptor() == null : descriptor.equals(((DescribedType) obj).getDescriptor()) && described == null ? ((DescribedType) obj).getDescribed() == null : described.equals(((DescribedType) obj).getDescribed()); } @Override public String toString() { return ""+DESCRIPTOR_CHAR + descriptor + " " + described; } }; } private Object readBinary(CharBuffer s) { byte[] bytes = new byte[s.remaining()]; int length = 0; expect(s, "b\""); char c; while(s.hasRemaining()) { c = s.get(); if(c == '\\') { expect(s, 'x'); if(s.remaining()<2) { throw new MessageFormatException("binary string escaped numeric value not correctly formatted", s); } byte val; c = s.get(); if(c >= 'a' && c <= 'f') { val = (byte) (16 * (10 + (c - 'a'))); } else if(c >= 'A' && c <= 'F') { val = (byte) (16 * (10 + (c - 'A'))); } else if(c >= '0' && c <= '9') { val = (byte) (16 * (c - '0')); } else { throw new MessageFormatException("invalid value", s); } c = s.get(); if(c >= 'a' && c <= 'f') { val += (byte) (10 + (c - 'a')); } else if(c >= 'A' && c <= 'F') { val += (byte) (10 + (c - 'A')); } else if(c >= '0' && c <= '9') { val += (byte) (c - '0'); } else { throw new MessageFormatException("invalid value", s); } bytes[length++] = val; } else if(c == QUOTE_CHAR) { byte[] rval = new byte[length]; System.arraycopy(bytes,0,rval,0,length); return rval; } else if(c < 256) { bytes[length++] = (byte) c; } } throw new MessageFormatException("unterminated binary string", s); } private Object readList(CharBuffer s) { List list = new ArrayList(); expect(s, START_LIST); char c; while(s.hasRemaining()) { skipWhitespace(s); c = s.get(s.position()); if(c == END_LIST) { c = s.get(); return list; } if(!list.isEmpty()) { expect(s, ','); } list.add(readValue(s)); } throw new MessageFormatException("unterminated list", s); } private Object readMap(CharBuffer s) { Map map = new LinkedHashMap(); expect(s, START_MAP); char c; while(s.hasRemaining()) { skipWhitespace(s); c = s.get(s.position()); if(c == END_MAP) { c = s.get(); return map; } if(!map.isEmpty()) { expect(s, ','); } Object key = readValue(s); skipWhitespace(s); expect(s, '='); Object value = readValue(s); map.put(key,value); } throw new MessageFormatException("unterminated map", s); } private void expect(CharBuffer s, String t) { expect(s, t.toCharArray()); } private void expect(CharBuffer s, char... expect) { for(char e : expect) { char c = s.get(); if(c != e) { throw new IllegalArgumentException("expecting "+expect+" character" + s.toString()); } } } private Object readSymbol(CharBuffer s) { char c = s.get(); if(c != SYMBOL_START) { throw new IllegalArgumentException("expecting @ as first character" + s.toString()); } c = s.get(s.position()); if(c == QUOTE_CHAR) { return readQuotedSymbol(s); } else { return readUnquotedSymbol(s); } } private Object readUnquotedSymbol(CharBuffer s) { StringBuilder b = new StringBuilder(); while(s.hasRemaining()) { char c = s.get(s.position()); if(Character.isWhitespace(c) || c == '=' || c == ',') { break; } if(c > 255) { throw new MessageFormatException("Illegal character " + c, s); } s.get(); b.append(c); } return Symbol.valueOf(b.toString()); } private Object readQuotedSymbol(CharBuffer s) { String str = readString(s); return Symbol.valueOf(str); } private String readString(CharBuffer s) { expect(s, '\"'); StringBuilder b = new StringBuilder(); while(s.hasRemaining()) { char c = s.get(); if(c == QUOTE_CHAR) { return b.toString(); } else if(c == '\\') { if(!s.hasRemaining()) { throw new MessageFormatException("Unterminated escape",s); } c = s.get(); switch(c) { case 'b': b.append('\b'); break; case 'f': b.append('\f'); break; case 'n': b.append('\n'); break; case 'r': b.append('\r'); break; case 't': b.append('\t'); break; case '\\': b.append('\\'); break; case '\"': b.append('\"'); break; case 'u': if(s.remaining()<4) { throw new MessageFormatException("Incorrect format for unicode character",s); } char u; String num = new String(new char[] {s.get(),s.get(),s.get(),s.get()}); u = (char) Integer.parseInt(num, 16); b.append(u); break; default: b.append(c); } } else { b.append(c); } } throw new MessageFormatException("unterminated map", s); } private Object readNumber(CharBuffer s) { StringBuilder b = new StringBuilder(); while(s.hasRemaining()) { char c = s.get(s.position()); if(Character.isWhitespace(c) || c == END_LIST || c == END_MAP || c == ',' || c == '=' ) { break; } else { c = s.get(); } b.append(c); } Number num; String numberString = b.toString(); if(numberString.contains(".")) { num = Double.parseDouble(numberString); } else { num = Long.parseLong(numberString); if(num.longValue() >= Integer.MIN_VALUE && num.longValue() <= Integer.MAX_VALUE) { num = num.intValue(); } } return num; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/message/ProtonJMessage.java0000664000000000000000000000211312562450203026453 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.message; import org.apache.qpid.proton.codec.WritableBuffer; import org.apache.qpid.proton.message.Message; public interface ProtonJMessage extends Message { int encode2(byte[] data, int offset, int length); int encode(WritableBuffer buffer); }qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/message/MessageFormatException.java0000664000000000000000000000213012562450203030166 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.message; /** * @deprecated This class will be removed in a future release. */ public class MessageFormatException extends RuntimeException { public MessageFormatException(String message, CharSequence value) { super(message + ": "+ value); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/message/MessageFormat.java0000664000000000000000000000174112562450203026316 0ustar package org.apache.qpid.proton.message; /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /** * @deprecated This enum will be removed in a future release. */ public enum MessageFormat { DATA, TEXT, AMQP, JSON } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/message/MessageError.java0000664000000000000000000000157412562450203026163 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.message; public enum MessageError { OK } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/message/Message.java0000664000000000000000000001336412562450203025151 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.message; import org.apache.qpid.proton.amqp.messaging.ApplicationProperties; import org.apache.qpid.proton.amqp.messaging.DeliveryAnnotations; import org.apache.qpid.proton.amqp.messaging.Footer; import org.apache.qpid.proton.amqp.messaging.Header; import org.apache.qpid.proton.amqp.messaging.MessageAnnotations; import org.apache.qpid.proton.amqp.messaging.Properties; import org.apache.qpid.proton.amqp.messaging.Section; import org.apache.qpid.proton.message.impl.MessageImpl; /** * Represents a Message within Proton. * * Create instances of Message using a {@link MessageFactory} implementation. * */ public interface Message { public static final class Factory { public static Message create() { return new MessageImpl(); } public static Message create(Header header, DeliveryAnnotations deliveryAnnotations, MessageAnnotations messageAnnotations, Properties properties, ApplicationProperties applicationProperties, Section body, Footer footer) { return new MessageImpl(header, deliveryAnnotations, messageAnnotations, properties, applicationProperties, body, footer); } } short DEFAULT_PRIORITY = 4; boolean isDurable(); long getDeliveryCount(); short getPriority(); boolean isFirstAcquirer(); long getTtl(); void setDurable(boolean durable); void setTtl(long ttl); void setDeliveryCount(long deliveryCount); void setFirstAcquirer(boolean firstAcquirer); void setPriority(short priority); Object getMessageId(); long getGroupSequence(); String getReplyToGroupId(); long getCreationTime(); String getAddress(); byte[] getUserId(); String getReplyTo(); String getGroupId(); String getContentType(); long getExpiryTime(); Object getCorrelationId(); String getContentEncoding(); String getSubject(); void setGroupSequence(long groupSequence); void setUserId(byte[] userId); void setCreationTime(long creationTime); void setSubject(String subject); void setGroupId(String groupId); void setAddress(String to); void setExpiryTime(long absoluteExpiryTime); void setReplyToGroupId(String replyToGroupId); void setContentEncoding(String contentEncoding); void setContentType(String contentType); void setReplyTo(String replyTo); void setCorrelationId(Object correlationId); void setMessageId(Object messageId); Header getHeader(); DeliveryAnnotations getDeliveryAnnotations(); MessageAnnotations getMessageAnnotations(); Properties getProperties(); ApplicationProperties getApplicationProperties(); Section getBody(); Footer getFooter(); void setHeader(Header header); void setDeliveryAnnotations(DeliveryAnnotations deliveryAnnotations); void setMessageAnnotations(MessageAnnotations messageAnnotations); void setProperties(Properties properties); void setApplicationProperties(ApplicationProperties applicationProperties); void setBody(Section body); void setFooter(Footer footer); /** * TODO describe what happens if the data does not represent a complete message. * Currently this appears to leave the message in an unknown state. */ int decode(byte[] data, int offset, int length); /** * Encodes up to {@code length} bytes of the message into the provided byte array, * starting at position {@code offset}. * * TODO describe what happens if length is smaller than the encoded form, Currently * Proton-J throws an exception. What does Proton-C do? * * @return the number of bytes written to the byte array */ int encode(byte[] data, int offset, int length); /** * Loads message body from the {@code data}. * * @deprecated This method will be removed in a future release. * @see #setMessageFormat(MessageFormat) */ void load(Object data); /** * Return the message body in a format determined by {@link #getMessageFormat()}. * * @deprecated This method will be removed in a future release. */ Object save(); /** * @deprecated This method will be removed in a future release. */ String toAMQPFormat(Object value); /** * @deprecated This method will be removed in a future release. */ Object parseAMQPFormat(String value); /** * @deprecated This method will be removed in a future release. */ void setMessageFormat(MessageFormat format); /** * @deprecated This method will be removed in a future release. */ MessageFormat getMessageFormat(); void clear(); MessageError getError(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/logging/0000775000000000000000000000000012562450203022715 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/logging/ProtonLoggerFactory.java0000664000000000000000000000224712562450203027536 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.logging; import java.util.logging.Logger; /** * Thin convenience wrapper around {@link Logger} */ public class ProtonLoggerFactory { /** * Returns a logger named using the fully qualified name of the supplied class. */ public static Logger getLogger(Class clazz) { return Logger.getLogger(clazz.getName()); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/logging/LoggingProtocolTracer.java0000664000000000000000000000377012562450203030040 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.logging; import java.util.logging.Logger; import org.apache.qpid.proton.engine.impl.ProtocolTracer; import org.apache.qpid.proton.framing.TransportFrame; public class LoggingProtocolTracer implements ProtocolTracer { private static final String LOGGER_NAME_STEM = LoggingProtocolTracer.class.getName(); private static final Logger RECEIVED_LOGGER = Logger.getLogger(LOGGER_NAME_STEM + ".received"); private static final Logger SENT_LOGGER = Logger.getLogger(LOGGER_NAME_STEM + ".sent"); private String _logMessagePrefix; public LoggingProtocolTracer() { this("Transport"); } public LoggingProtocolTracer(String logMessagePrefix) { _logMessagePrefix = logMessagePrefix; } @Override public void receivedFrame(TransportFrame transportFrame) { RECEIVED_LOGGER.finer(_logMessagePrefix + " received frame: " + transportFrame); } @Override public void sentFrame(TransportFrame transportFrame) { SENT_LOGGER.finer(_logMessagePrefix + " writing frame: " + transportFrame); } public void setLogMessagePrefix(String logMessagePrefix) { _logMessagePrefix = logMessagePrefix; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/framing/0000775000000000000000000000000012562450203022712 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/framing/TransportFrame.java0000664000000000000000000000336712562450203026535 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.framing; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.transport.FrameBody; public class TransportFrame { private final int _channel; private final FrameBody _body; private final Binary _payload; public TransportFrame(final int channel, final FrameBody body, final Binary payload) { _payload = payload; _body = body; _channel = channel; } public int getChannel() { return _channel; } public FrameBody getBody() { return _body; } public Binary getPayload() { return _payload; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("TransportFrame{ _channel=").append(_channel).append(", _body=").append(_body).append("}"); return builder.toString(); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/0000775000000000000000000000000012562450203022534 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/0000775000000000000000000000000012562450203023475 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/0000775000000000000000000000000012562450203024276 5ustar ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslTransportWrapper.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslTransportWrapper.j0000664000000000000000000000202512562450203030467 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import org.apache.qpid.proton.engine.impl.TransportWrapper; public interface SslTransportWrapper extends TransportWrapper { String getCipherName(); String getProtocolName(); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslPeerDetailsImpl.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslPeerDetailsImpl.ja0000664000000000000000000000301712562450203030320 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine.impl.ssl; import org.apache.qpid.proton.engine.ProtonJSslPeerDetails; public class SslPeerDetailsImpl implements ProtonJSslPeerDetails { private final String _hostname; private final int _port; /** * @deprecated This constructor's visibility will be reduced to the default scope in a future release. * Client code outside this module should use a {@link EngineFactory} instead */ @Deprecated public SslPeerDetailsImpl(String hostname, int port) { _hostname = hostname; _port = port; } @Override public String getHostname() { return _hostname; } @Override public int getPort() { return _port; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslImpl.java0000664000000000000000000002011612562450203026524 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import java.nio.ByteBuffer; import org.apache.qpid.proton.ProtonUnsupportedOperationException; import org.apache.qpid.proton.engine.Ssl; import org.apache.qpid.proton.engine.SslDomain; import org.apache.qpid.proton.engine.SslPeerDetails; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; import org.apache.qpid.proton.engine.impl.PlainTransportWrapper; import org.apache.qpid.proton.engine.impl.TransportInput; import org.apache.qpid.proton.engine.impl.TransportOutput; import org.apache.qpid.proton.engine.impl.TransportWrapper; public class SslImpl implements Ssl { private SslTransportWrapper _unsecureClientAwareTransportWrapper; private final SslDomain _domain; private final ProtonSslEngineProvider _protonSslEngineProvider; private final SslPeerDetails _peerDetails; private TransportException _initException; /** * @param sslDomain must implement {@link ProtonSslEngineProvider}. This is not possible * enforce at the API level because {@link ProtonSslEngineProvider} is not part of the * public Proton API.

*/ public SslImpl(SslDomain domain, SslPeerDetails peerDetails) { _domain = domain; _protonSslEngineProvider = (ProtonSslEngineProvider)domain; _peerDetails = peerDetails; } public TransportWrapper wrap(TransportInput inputProcessor, TransportOutput outputProcessor) { if (_unsecureClientAwareTransportWrapper != null) { throw new IllegalStateException("Transport already wrapped"); } _unsecureClientAwareTransportWrapper = new UnsecureClientAwareTransportWrapper(inputProcessor, outputProcessor); return _unsecureClientAwareTransportWrapper; } @Override public String getCipherName() { if(_unsecureClientAwareTransportWrapper == null) { throw new IllegalStateException("Transport wrapper is uninitialised"); } return _unsecureClientAwareTransportWrapper.getCipherName(); } @Override public String getProtocolName() { if(_unsecureClientAwareTransportWrapper == null) { throw new IllegalStateException("Transport wrapper is uninitialised"); } return _unsecureClientAwareTransportWrapper.getProtocolName(); } private class UnsecureClientAwareTransportWrapper implements SslTransportWrapper { private final TransportInput _inputProcessor; private final TransportOutput _outputProcessor; private SslTransportWrapper _transportWrapper; private UnsecureClientAwareTransportWrapper(TransportInput inputProcessor, TransportOutput outputProcessor) { _inputProcessor = inputProcessor; _outputProcessor = outputProcessor; } @Override public int capacity() { initTransportWrapperOnFirstIO(); if (_initException == null) { return _transportWrapper.capacity(); } else { return Transport.END_OF_STREAM; } } @Override public int position() { initTransportWrapperOnFirstIO(); if (_initException == null) { return _transportWrapper.position(); } else { return Transport.END_OF_STREAM; } } @Override public ByteBuffer tail() { initTransportWrapperOnFirstIO(); if (_initException == null) { return _transportWrapper.tail(); } else { return null; } } @Override public void process() throws TransportException { initTransportWrapperOnFirstIO(); if (_initException == null) { _transportWrapper.process(); } else { throw new TransportException(_initException); } } @Override public void close_tail() { initTransportWrapperOnFirstIO(); if (_initException == null) { _transportWrapper.close_tail(); } } @Override public int pending() { initTransportWrapperOnFirstIO(); if (_initException == null) { return _transportWrapper.pending(); } else { throw new TransportException(_initException); } } @Override public ByteBuffer head() { initTransportWrapperOnFirstIO(); if (_initException == null) { return _transportWrapper.head(); } else { return null; } } @Override public void pop(int bytes) { initTransportWrapperOnFirstIO(); if (_initException == null) { _transportWrapper.pop(bytes); } } @Override public void close_head() { initTransportWrapperOnFirstIO(); if (_initException == null) { _transportWrapper.close_head(); } } @Override public String getCipherName() { if (_transportWrapper == null) { return null; } else { return _transportWrapper.getCipherName(); } } @Override public String getProtocolName() { if(_transportWrapper == null) { return null; } else { return _transportWrapper.getProtocolName(); } } private void initTransportWrapperOnFirstIO() { try { if (_initException == null && _transportWrapper == null) { SslTransportWrapper sslTransportWrapper = new SimpleSslTransportWrapper (_protonSslEngineProvider.createSslEngine(_peerDetails), _inputProcessor, _outputProcessor); if (_domain.allowUnsecuredClient() && _domain.getMode() == SslDomain.Mode.SERVER) { TransportWrapper plainTransportWrapper = new PlainTransportWrapper (_outputProcessor, _inputProcessor); _transportWrapper = new SslHandshakeSniffingTransportWrapper (sslTransportWrapper, plainTransportWrapper); } else { _transportWrapper = sslTransportWrapper; } } } catch (TransportException e) { _initException = e; } } } /** * {@inheritDoc} * @throws ProtonUnsupportedOperationException */ @Override public void setPeerHostname(String hostname) { throw new ProtonUnsupportedOperationException(); } /** * {@inheritDoc} * @throws ProtonUnsupportedOperationException */ @Override public String getPeerHostname() { throw new ProtonUnsupportedOperationException(); } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslHandshakeSniffingTransportWrapper.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslHandshakeSniffingT0000664000000000000000000001036212562450203030403 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import org.apache.qpid.proton.engine.impl.HandshakeSniffingTransportWrapper; import org.apache.qpid.proton.engine.impl.TransportWrapper; /** * SslHandshakeSniffingTransportWrapper * */ public class SslHandshakeSniffingTransportWrapper extends HandshakeSniffingTransportWrapper implements SslTransportWrapper { SslHandshakeSniffingTransportWrapper(SslTransportWrapper ssl, TransportWrapper plain) { super(ssl, plain); } @Override public String getCipherName() { if(isSecureWrapperSelected()) { return _wrapper1.getCipherName(); } else { return null; } } @Override public String getProtocolName() { if (isSecureWrapperSelected()) { return _wrapper1.getProtocolName(); } else { return null; } } private boolean isSecureWrapperSelected() { return _selectedTransportWrapper == _wrapper1; } protected int bufferSize() { // minimum length for determination return 5; } protected void makeDetermination(byte[] bytesInput) { boolean isSecure = checkForSslHandshake(bytesInput); if (isSecure) { _selectedTransportWrapper = _wrapper1; } else { _selectedTransportWrapper = _wrapper2; } } // TODO perhaps the sniffer should save up the bytes from each // input call until it has sufficient bytes to make the determination // and only then pass them to the secure or plain wrapped transport? private boolean checkForSslHandshake(byte[] buf) { if (buf.length >= bufferSize()) { /* * SSLv2 Client Hello format * http://www.mozilla.org/projects/security/pki/nss/ssl/draft02.html * * Bytes 0-1: RECORD-LENGTH Byte 2: MSG-CLIENT-HELLO (1) Byte 3: * CLIENT-VERSION-MSB Byte 4: CLIENT-VERSION-LSB * * Allowed versions: 2.0 - SSLv2 3.0 - SSLv3 3.1 - TLS 1.0 3.2 - TLS * 1.1 3.3 - TLS 1.2 * * The version sent in the Client-Hello is the latest version * supported by the client. NSS may send version 3.x in an SSLv2 * header for maximum compatibility. */ boolean isSSL2Handshake = buf[2] == 1 && // MSG-CLIENT-HELLO ((buf[3] == 3 && buf[4] <= 3) || // SSL 3.0 & TLS 1.0-1.2 // (v3.1-3.3) (buf[3] == 2 && buf[4] == 0)); // SSL 2 /* * SSLv3/TLS Client Hello format RFC 2246 * * Byte 0: ContentType (handshake - 22) Bytes 1-2: ProtocolVersion * {major, minor} * * Allowed versions: 3.0 - SSLv3 3.1 - TLS 1.0 3.2 - TLS 1.1 3.3 - * TLS 1.2 */ boolean isSSL3Handshake = buf[0] == 22 && // handshake (buf[1] == 3 && buf[2] <= 3); // SSL 3.0 & TLS 1.0-1.2 // (v3.1-3.3) return (isSSL2Handshake || isSSL3Handshake); } else { throw new IllegalArgumentException("Too few bytes (" + buf.length + ") to make SSL/plain determination."); } } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactory.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslEngineFacadeFactor0000664000000000000000000004760312562450203030345 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.security.KeyManagementException; import java.security.KeyPair; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Provider; import java.security.Security; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import org.apache.qpid.proton.engine.SslDomain; import org.apache.qpid.proton.engine.SslPeerDetails; import org.apache.qpid.proton.ProtonUnsupportedOperationException; import org.apache.qpid.proton.engine.TransportException; public class SslEngineFacadeFactory { private static final Logger _logger = Logger.getLogger(SslEngineFacadeFactory.class.getName()); /** * The protocol name used to create an {@link SSLContext}, taken from Java's list of * standard names at http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html * * TODO allow the protocol name to be overridden somehow */ private static final String TLS_PROTOCOL = "TLS"; private static final Class pemReaderClass = getClass("org.bouncycastle.openssl.PEMReader"); private static final Class passwordClass = getClass("org.bouncycastle.openssl.PasswordFinder"); private static final Class passwordProxy = makePasswordProxy(); private static final Constructor pemReaderCons = getConstructor(pemReaderClass, Reader.class, passwordClass); private static final Method readObjectMeth = getMethod(pemReaderClass, "readObject"); private static Class getClass(String klass) { try { return Class.forName(klass); } catch (ClassNotFoundException e) { _logger.warning("unable to load " + klass); } return null; } private static Constructor getConstructor(Class klass, Class ... params) { if (klass == null) { return null; } try { return klass.getConstructor(params); } catch (NoSuchMethodException e) { throw new TransportException(e); } } private static Method getMethod(Class klass, String name, Class ... params) { if (klass == null) { return null; } try { return klass.getMethod(name, params); } catch (NoSuchMethodException e) { throw new TransportException(e); } } private static Class makePasswordProxy() { if (passwordClass != null) { return Proxy.getProxyClass(passwordClass.getClassLoader(), new Class[] {passwordClass}); } else { return null; } } static { try { Class klass = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider"); Security.addProvider((Provider) klass.newInstance()); } catch (ClassNotFoundException e) { _logger.warning("unable to load bouncycastle provider"); } catch (InstantiationException e) { _logger.warning("unable to instantiate bouncycastle provider"); } catch (IllegalAccessException e) { _logger.warning("unable to access bouncycastle provider"); } } SslEngineFacadeFactory() { } /** * This is a list of all anonymous cipher suites supported by Java 6, excluding those that * use MD5. These are all supported by both Oracle's and IBM's Java 6 implementation. */ private static final List ANONYMOUS_CIPHER_SUITES = Arrays.asList( "TLS_DH_anon_WITH_AES_128_CBC_SHA", "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", "SSL_DH_anon_WITH_DES_CBC_SHA", "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"); /** lazily initialized */ private SSLContext _sslContext; /** * Returns a {@link ProtonSslEngine}. May cache the domain's settings so callers should invoke * {@link #resetCache()} if the domain changes. * * @param peerDetails may be used to return an engine that supports SSL resume. */ public ProtonSslEngine createProtonSslEngine(SslDomain domain, SslPeerDetails peerDetails) { SSLEngine engine = createAndInitialiseSslEngine(domain, peerDetails); if(_logger.isLoggable(Level.FINE)) { _logger.fine("Created SSL engine: " + engineToString(engine)); } return new DefaultSslEngineFacade(engine); } /** * Guarantees that no cached settings are used in subsequent calls to * {@link #createProtonSslEngine(SslDomain, SslPeerDetails)}. */ public void resetCache() { _sslContext = null; } private SSLEngine createAndInitialiseSslEngine(SslDomain domain, SslPeerDetails peerDetails) { SslDomain.Mode mode = domain.getMode(); SSLContext sslContext = getOrCreateSslContext(domain); SSLEngine sslEngine = createSslEngine(sslContext, peerDetails); if (domain.getPeerAuthentication() == SslDomain.VerifyMode.ANONYMOUS_PEER) { addAnonymousCipherSuites(sslEngine); } else { if (mode == SslDomain.Mode.SERVER) { sslEngine.setNeedClientAuth(true); } } if(_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, mode + " Enabled cipher suites " + Arrays.asList(sslEngine.getEnabledCipherSuites())); } boolean useClientMode = mode == SslDomain.Mode.CLIENT ? true : false; sslEngine.setUseClientMode(useClientMode); removeSSLv3Support(sslEngine); return sslEngine; } private static final String SSLV3_PROTOCOL = "SSLv3"; private static void removeSSLv3Support(final SSLEngine engine) { List enabledProtocols = Arrays.asList(engine.getEnabledProtocols()); if(enabledProtocols.contains(SSLV3_PROTOCOL)) { List allowedProtocols = new ArrayList(enabledProtocols); allowedProtocols.remove(SSLV3_PROTOCOL); engine.setEnabledProtocols(allowedProtocols.toArray(new String[allowedProtocols.size()])); } } /** * @param sslPeerDetails is allowed to be null. A non-null value is used to hint that SSL resumption * should be attempted */ private SSLEngine createSslEngine(SSLContext sslContext, SslPeerDetails sslPeerDetails) { final SSLEngine sslEngine; if(sslPeerDetails == null) { sslEngine = sslContext.createSSLEngine(); } else { sslEngine = sslContext.createSSLEngine(sslPeerDetails.getHostname(), sslPeerDetails.getPort()); } return sslEngine; } private SSLContext getOrCreateSslContext(SslDomain sslDomain) { if(_sslContext == null) { if(_logger.isLoggable(Level.FINE)) { _logger.fine("lazily creating new SSLContext using domain " + sslDomain); } final char[] dummyPassword = "unused-passphrase".toCharArray(); // Dummy password required by KeyStore and KeyManagerFactory, but never referred to again try { SSLContext sslContext = SSLContext.getInstance(TLS_PROTOCOL); KeyStore ksKeys = createKeyStoreFrom(sslDomain, dummyPassword); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(ksKeys, dummyPassword); final TrustManager[] trustManagers; if (sslDomain.getPeerAuthentication() == SslDomain.VerifyMode.ANONYMOUS_PEER) { trustManagers = new TrustManager[] { new AlwaysTrustingTrustManager() }; } else { TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ksKeys); trustManagers = tmf.getTrustManagers(); } sslContext.init(kmf.getKeyManagers(), trustManagers, null); _sslContext = sslContext; } catch (NoSuchAlgorithmException e) { throw new TransportException("Unexpected exception creating SSLContext", e); } catch (KeyStoreException e) { throw new TransportException("Unexpected exception creating SSLContext", e); } catch (UnrecoverableKeyException e) { throw new TransportException("Unexpected exception creating SSLContext", e); } catch (KeyManagementException e) { throw new TransportException("Unexpected exception creating SSLContext", e); } } return _sslContext; } private KeyStore createKeyStoreFrom(SslDomain sslDomain, char[] dummyPassword) { try { KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); keystore.load(null, null); if (sslDomain.getTrustedCaDb() != null) { String caCertAlias = "cacert"; if(_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, "_sslParams.getTrustedCaDb() : " + sslDomain.getTrustedCaDb()); } Certificate trustedCaCert = (Certificate) readPemObject(sslDomain.getTrustedCaDb(), null, Certificate.class); keystore.setCertificateEntry(caCertAlias, trustedCaCert); } if (sslDomain.getCertificateFile() != null && sslDomain.getPrivateKeyFile() != null) { String clientPrivateKeyAlias = "clientPrivateKey"; Certificate clientCertificate = (Certificate) readPemObject(sslDomain.getCertificateFile(), null, Certificate.class); Object keyOrKeyPair = readPemObject( sslDomain.getPrivateKeyFile(), sslDomain.getPrivateKeyPassword(), PrivateKey.class, KeyPair.class); final PrivateKey clientPrivateKey; if (keyOrKeyPair instanceof PrivateKey) { clientPrivateKey = (PrivateKey)keyOrKeyPair; } else if (keyOrKeyPair instanceof KeyPair) { clientPrivateKey = ((KeyPair)keyOrKeyPair).getPrivate(); } else { // Should not happen - readPemObject will have already verified key type throw new TransportException("Unexpected key type " + keyOrKeyPair); } keystore.setKeyEntry(clientPrivateKeyAlias, clientPrivateKey, dummyPassword, new Certificate[] { clientCertificate }); } return keystore; } catch (KeyStoreException e) { throw new TransportException("Unexpected exception creating keystore", e); } catch (NoSuchAlgorithmException e) { throw new TransportException("Unexpected exception creating keystore", e); } catch (CertificateException e) { throw new TransportException("Unexpected exception creating keystore", e); } catch (IOException e) { throw new TransportException("Unexpected exception creating keystore", e); } } private void addAnonymousCipherSuites(SSLEngine sslEngine) { List supportedSuites = Arrays.asList(sslEngine.getSupportedCipherSuites()); List currentEnabledSuites = Arrays.asList(sslEngine.getEnabledCipherSuites()); List enabledSuites = buildEnabledSuitesIncludingAnonymous(ANONYMOUS_CIPHER_SUITES, supportedSuites, currentEnabledSuites); sslEngine.setEnabledCipherSuites(enabledSuites.toArray(new String[0])); } private List buildEnabledSuitesIncludingAnonymous( List anonymousCipherSuites, List supportedSuites, List currentEnabled) { List newEnabled = new ArrayList(currentEnabled); int addedAnonymousCipherSuites = 0; for (String anonymousCipherSuiteName : anonymousCipherSuites) { if (supportedSuites.contains(anonymousCipherSuiteName)) { newEnabled.add(anonymousCipherSuiteName); addedAnonymousCipherSuites++; } } if (addedAnonymousCipherSuites == 0) { throw new TransportException ("None of " + anonymousCipherSuites + " anonymous cipher suites are within the supported list " + supportedSuites); } if(_logger.isLoggable(Level.FINE)) { _logger.fine("There are now " + newEnabled.size() + " cipher suites enabled (previously " + currentEnabled.size() + "), including " + addedAnonymousCipherSuites + " out of the " + anonymousCipherSuites.size() + " requested anonymous ones." ); } return newEnabled; } private String engineToString(SSLEngine engine) { return new StringBuilder("[ " ) .append(engine) .append(", needClientAuth=").append(engine.getNeedClientAuth()) .append(", useClientMode=").append(engine.getUseClientMode()) .append(", peerHost=").append(engine.getPeerHost()) .append(", peerPort=").append(engine.getPeerPort()) .append(" ]").toString(); } private Object readPemObject(String pemFile, String keyPassword, @SuppressWarnings("rawtypes") Class... expectedInterfaces) { final Object passwordFinder; if (keyPassword != null) { passwordFinder = getPasswordFinderFor(keyPassword); } else { passwordFinder = null; } Reader reader = null; Reader pemReader = null; if (pemReaderCons == null || readObjectMeth == null) { throw new ProtonUnsupportedOperationException(); } try { reader = new FileReader(pemFile); pemReader = (Reader) pemReaderCons.newInstance(new Object[] {reader, passwordFinder}); Object pemObject = readObjectMeth.invoke(pemReader); if (!checkPemObjectIsOfAllowedTypes(pemObject, expectedInterfaces)) { throw new TransportException ("File " + pemFile + " does not provide a object of the required type." + " Read an object of class " + pemObject.getClass().getName() + " whilst expecting an implementation of one of the following : " + Arrays.asList(expectedInterfaces)); } return pemObject; } catch(InstantiationException e) { _logger.log(Level.SEVERE, "Unable to read PEM object. Perhaps you need the unlimited strength libraries in /jre/lib/security/ ?", e); throw new TransportException("Unable to read PEM object from file " + pemFile, e); } catch(InvocationTargetException e) { _logger.log(Level.SEVERE, "Unable to read PEM object. Perhaps you need the unlimited strength libraries in /jre/lib/security/ ?", e); throw new TransportException("Unable to read PEM object from file " + pemFile, e); } catch (IllegalAccessException e) { throw new TransportException(e); } catch (IOException e) { throw new TransportException("Unable to read PEM object from file " + pemFile, e); } finally { if(pemReader != null) { try { pemReader.close(); } catch(IOException e) { _logger.log(Level.SEVERE, "Couldn't close PEM reader", e); } } if (reader != null) { try { reader.close(); } catch (IOException e) { _logger.log(Level.SEVERE, "Couldn't close PEM file reader", e); } } } } @SuppressWarnings("rawtypes") private boolean checkPemObjectIsOfAllowedTypes(Object pemObject, Class... expectedInterfaces) { if (expectedInterfaces.length == 0) { throw new IllegalArgumentException("Must be at least one expectedKeyTypes"); } for (Class keyInterface : expectedInterfaces) { if (keyInterface.isInstance(pemObject)) { return true; } } return false; } private Object getPasswordFinderFor(final String keyPassword) { if (passwordProxy == null) { throw new ProtonUnsupportedOperationException(); } try { Constructor con = passwordProxy.getConstructor(new Class[] {InvocationHandler.class}); Object finder = con.newInstance(new InvocationHandler() { public Object invoke(Object obj, Method meth, Object[] args) { return keyPassword.toCharArray(); } }); return finder; } catch (NoSuchMethodException e) { throw new TransportException(e); } catch (InstantiationException e) { throw new TransportException(e); } catch (IllegalAccessException e) { throw new TransportException(e); } catch (InvocationTargetException e) { throw new TransportException(e); } } private final class AlwaysTrustingTrustManager implements X509TrustManager { @Override public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { // Do not check certificate } @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { // Do not check certificate } } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SslDomainImpl.java0000664000000000000000000001033212562450203027653 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine.impl.ssl; import org.apache.qpid.proton.ProtonUnsupportedOperationException; import org.apache.qpid.proton.engine.ProtonJSslDomain; import org.apache.qpid.proton.engine.SslDomain; import org.apache.qpid.proton.engine.SslPeerDetails; public class SslDomainImpl implements SslDomain, ProtonSslEngineProvider, ProtonJSslDomain { private Mode _mode; private VerifyMode _verifyMode = VerifyMode.ANONYMOUS_PEER; private String _certificateFile; private String _privateKeyFile; private String _privateKeyPassword; private String _trustedCaDb; private boolean _allowUnsecuredClient; private final SslEngineFacadeFactory _sslEngineFacadeFactory = new SslEngineFacadeFactory(); /** * @deprecated This constructor's visibility will be reduced to the default scope in a future release. * Client code outside this module should use a {@link EngineFactory} instead */ @Deprecated public SslDomainImpl() { } @Override public void init(Mode mode) { _sslEngineFacadeFactory.resetCache(); _mode = mode; } @Override public Mode getMode() { return _mode; } @Override public void setCredentials(String certificateFile, String privateKeyFile, String privateKeyPassword) { _certificateFile = certificateFile; _privateKeyFile = privateKeyFile; _privateKeyPassword = privateKeyPassword; _sslEngineFacadeFactory.resetCache(); } @Override public void setTrustedCaDb(String certificateDb) { _trustedCaDb = certificateDb; _sslEngineFacadeFactory.resetCache(); } @Override public String getTrustedCaDb() { return _trustedCaDb; } @Override public void setPeerAuthentication(VerifyMode verifyMode) { if(verifyMode == VerifyMode.VERIFY_PEER_NAME) { throw new ProtonUnsupportedOperationException(); } _verifyMode = verifyMode; _sslEngineFacadeFactory.resetCache(); } @Override public VerifyMode getPeerAuthentication() { return _verifyMode; } @Override public String getPrivateKeyFile() { return _privateKeyFile; } @Override public String getPrivateKeyPassword() { return _privateKeyPassword; } @Override public String getCertificateFile() { return _certificateFile; } @Override public void allowUnsecuredClient(boolean allowUnsecured) { _allowUnsecuredClient = allowUnsecured; _sslEngineFacadeFactory.resetCache(); } @Override public boolean allowUnsecuredClient() { return _allowUnsecuredClient; } @Override public ProtonSslEngine createSslEngine(SslPeerDetails peerDetails) { return _sslEngineFacadeFactory.createProtonSslEngine(this, peerDetails); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("SslDomainImpl [_mode=").append(_mode) .append(", _verifyMode=").append(_verifyMode) .append(", _certificateFile=").append(_certificateFile) .append(", _privateKeyFile=").append(_privateKeyFile) .append(", _trustedCaDb=").append(_trustedCaDb) .append(", _allowUnsecuredClient=").append(_allowUnsecuredClient) .append("]"); return builder.toString(); } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapper.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWra0000664000000000000000000003317712562450203030536 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import static org.apache.qpid.proton.engine.impl.ByteBufferUtils.newWriteableBuffer; import java.nio.ByteBuffer; import java.util.logging.Level; import java.util.logging.Logger; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.Status; import javax.net.ssl.SSLException; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; import org.apache.qpid.proton.engine.impl.TransportInput; import org.apache.qpid.proton.engine.impl.TransportOutput; /** * TODO close the SSLEngine when told to, and modify {@link #wrapOutput()} and {@link #unwrapInput()} * to respond appropriately thereafter. */ public class SimpleSslTransportWrapper implements SslTransportWrapper { private static final Logger _logger = Logger.getLogger(SimpleSslTransportWrapper.class.getName()); private final ProtonSslEngine _sslEngine; private final TransportInput _underlyingInput; private final TransportOutput _underlyingOutput; private boolean _tail_closed = false; private ByteBuffer _inputBuffer; private boolean _head_closed = false; private ByteBuffer _outputBuffer; private ByteBuffer _head; /** * A buffer for the decoded bytes that will be passed to _underlyingInput. * This extra layer of buffering is necessary in case the underlying input's buffer * is too small for SSLEngine to ever unwrap into. */ private ByteBuffer _decodedInputBuffer; /** could change during the lifetime of the ssl connection owing to renegotiation. */ private String _cipherName; /** could change during the lifetime of the ssl connection owing to renegotiation. */ private String _protocolName; SimpleSslTransportWrapper(ProtonSslEngine sslEngine, TransportInput underlyingInput, TransportOutput underlyingOutput) { _underlyingInput = underlyingInput; _underlyingOutput = underlyingOutput; _sslEngine = sslEngine; int effectiveAppBufferMax = _sslEngine.getEffectiveApplicationBufferSize(); int packetSize = _sslEngine.getPacketBufferSize(); // Input and output buffers need to be large enough to contain one SSL packet, // as stated in SSLEngine JavaDoc. _inputBuffer = newWriteableBuffer(packetSize); _outputBuffer = newWriteableBuffer(packetSize); _head = _outputBuffer.asReadOnlyBuffer(); _head.limit(0); _decodedInputBuffer = newWriteableBuffer(effectiveAppBufferMax); if(_logger.isLoggable(Level.FINE)) { _logger.fine("Constructed " + this); } } /** * Unwraps the contents of {@link #_inputBuffer} and passes it to {@link #_underlyingInput}. * * Regarding the state of {@link #_inputBuffer}: * - On entry, it is assumed to be readable. * - On exit, it is still readable and its "remaining" bytes are those that we were unable * to unwrap (e.g. if they don't form a whole packet). */ private void unwrapInput() throws SSLException { while (true) { SSLEngineResult result = _sslEngine.unwrap(_inputBuffer, _decodedInputBuffer); logEngineClientModeAndResult(result, "input"); int read = result.bytesProduced(); Status status = result.getStatus(); HandshakeStatus hstatus = result.getHandshakeStatus(); int capacity = _underlyingInput.capacity(); if (capacity == Transport.END_OF_STREAM) { _tail_closed = true; if (_decodedInputBuffer.position() > 0) { throw new TransportException("bytes left unconsumed"); } } else { ByteBuffer tail = _underlyingInput.tail(); _decodedInputBuffer.flip(); int limit = _decodedInputBuffer.limit(); int overflow = _decodedInputBuffer.remaining() - capacity; if (overflow > 0) { _decodedInputBuffer.limit(limit - overflow); } tail.put(_decodedInputBuffer); _decodedInputBuffer.limit(limit); _decodedInputBuffer.compact(); _underlyingInput.process(); capacity = _underlyingInput.capacity(); if (capacity == Transport.END_OF_STREAM) { _tail_closed = true; } } switch (status) { case CLOSED: _tail_closed = true; break; case BUFFER_OVERFLOW: { ByteBuffer old = _decodedInputBuffer; _decodedInputBuffer = newWriteableBuffer(old.capacity()*2); old.flip(); _decodedInputBuffer.put(old); } continue; case BUFFER_UNDERFLOW: if (_tail_closed) { _head_closed = true; } // wait for more data break; case OK: break; } switch (hstatus) { case NEED_WRAP: // wait for write to kick in break; case NEED_TASK: runDelegatedTasks(result); continue; case FINISHED: updateCipherAndProtocolName(result); case NOT_HANDSHAKING: case NEED_UNWRAP: if (_inputBuffer.position() > 0 && status == Status.OK) { continue; } else { if (_inputBuffer.position() == 0 && hstatus == HandshakeStatus.NEED_UNWRAP && _tail_closed) { _head_closed = true; } break; } } break; } } /** * Wrap the underlying transport's output, passing it to the output buffer. * * {@link #_outputBuffer} is assumed to be writeable on entry and is guaranteed to * be still writeable on exit. */ private void wrapOutput() throws SSLException { while (true) { int pending = _underlyingOutput.pending(); if (pending < 0) { _head_closed = true; } ByteBuffer clearOutputBuffer = _underlyingOutput.head(); SSLEngineResult result = _sslEngine.wrap(clearOutputBuffer, _outputBuffer); logEngineClientModeAndResult(result, "output"); int written = result.bytesConsumed(); _underlyingOutput.pop(written); pending = _underlyingOutput.pending(); Status status = result.getStatus(); switch (status) { case CLOSED: _head_closed = true; break; case OK: break; case BUFFER_OVERFLOW: ByteBuffer old = _outputBuffer; _outputBuffer = newWriteableBuffer(_outputBuffer.capacity()*2); _head = _outputBuffer.asReadOnlyBuffer(); old.flip(); _outputBuffer.put(old); continue; case BUFFER_UNDERFLOW: throw new IllegalStateException("app buffer underflow"); } HandshakeStatus hstatus = result.getHandshakeStatus(); switch (hstatus) { case NEED_UNWRAP: // wait for input data if (_inputBuffer.position() == 0 && _tail_closed) { _head_closed = true; } break; case NEED_WRAP: // keep looping continue; case NEED_TASK: runDelegatedTasks(result); continue; case FINISHED: updateCipherAndProtocolName(result); // intentionally fall through case NOT_HANDSHAKING: if (pending > 0 && status == Status.OK) { continue; } else { break; } } break; } } private boolean hasSpaceForSslPacket(ByteBuffer byteBuffer) { return byteBuffer.remaining() >= _sslEngine.getPacketBufferSize(); } /** @return the cipher name, which is null until the SSL handshaking is completed */ @Override public String getCipherName() { return _cipherName; } /** @return the protocol name, which is null until the SSL handshaking is completed */ @Override public String getProtocolName() { return _protocolName; } private void updateCipherAndProtocolName(SSLEngineResult result) { if (result.getHandshakeStatus() == HandshakeStatus.FINISHED) { _cipherName = _sslEngine.getCipherSuite(); _protocolName = _sslEngine.getProtocol(); } } private void runDelegatedTasks(SSLEngineResult result) { if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable runnable; while ((runnable = _sslEngine.getDelegatedTask()) != null) { runnable.run(); } HandshakeStatus hsStatus = _sslEngine.getHandshakeStatus(); if (hsStatus == HandshakeStatus.NEED_TASK) { throw new RuntimeException("handshake shouldn't need additional tasks"); } } } private void logEngineClientModeAndResult(SSLEngineResult result, String direction) { if(_logger.isLoggable(Level.FINEST)) { _logger.log(Level.FINEST, "useClientMode = " + _sslEngine.getUseClientMode() + " direction = " + direction + " " + resultToString(result)); } } private String resultToString(SSLEngineResult result) { return new StringBuilder("[SSLEngineResult status = ").append(result.getStatus()) .append(" handshakeStatus = ").append(result.getHandshakeStatus()) .append(" bytesConsumed = ").append(result.bytesConsumed()) .append(" bytesProduced = ").append(result.bytesProduced()) .append("]").toString(); } @Override public int capacity() { if (_tail_closed) return Transport.END_OF_STREAM; return _inputBuffer.remaining(); } @Override public int position() { if (_tail_closed) return Transport.END_OF_STREAM; return _inputBuffer.position(); } @Override public ByteBuffer tail() { if (_tail_closed) throw new TransportException("tail closed"); return _inputBuffer; } @Override public void process() throws TransportException { if (_tail_closed) throw new TransportException("tail closed"); _inputBuffer.flip(); try { unwrapInput(); } catch (SSLException e) { _logger.log(Level.WARNING, e.getMessage()); _inputBuffer.position(_inputBuffer.limit()); _tail_closed = true; } finally { _inputBuffer.compact(); } } @Override public void close_tail() { try { _underlyingInput.close_tail(); } finally { _tail_closed = true; } } @Override public int pending() { try { wrapOutput(); } catch (SSLException e) { _logger.log(Level.WARNING, e.getMessage()); _head_closed = true; } _head.limit(_outputBuffer.position()); if (_head_closed && _outputBuffer.position() == 0) { return Transport.END_OF_STREAM; } return _outputBuffer.position(); } @Override public ByteBuffer head() { pending(); return _head; } @Override public void pop(int bytes) { _outputBuffer.flip(); _outputBuffer.position(bytes); _outputBuffer.compact(); _head.position(0); _head.limit(_outputBuffer.position()); } @Override public void close_head() { _underlyingOutput.close_head(); int p = pending(); if (p > 0) { pop(p); } } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("SimpleSslTransportWrapper [sslEngine=").append(_sslEngine) .append(", inputBuffer=").append(_inputBuffer) .append(", outputBuffer=").append(_outputBuffer) .append(", decodedInputBuffer=").append(_decodedInputBuffer) .append(", cipherName=").append(_cipherName) .append(", protocolName=").append(_protocolName) .append("]"); return builder.toString(); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/ProtonSslEngineProvider.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/ProtonSslEngineProvid0000664000000000000000000000226112562450203030477 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine.impl.ssl; import org.apache.qpid.proton.engine.SslPeerDetails; public interface ProtonSslEngineProvider { /** * Returns an SSL engine. * * @param sslPeerDetails the details of the remote peer. If non-null, may be used to assist SSL session resumption. */ public ProtonSslEngine createSslEngine(SslPeerDetails peerDetails); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/ProtonSslEngine.java0000664000000000000000000000462112562450203030235 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import java.nio.ByteBuffer; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.Status; import javax.net.ssl.SSLException; /** * Thin wrapper around an {@link SSLEngine}. */ public interface ProtonSslEngine { /** * @see SSLEngine#wrap(ByteBuffer, ByteBuffer) * * Note that wrap really does write one packet worth of data to the * dst byte buffer. If dst byte buffer is insufficiently large the * pointers within both src and dst are unchanged and the bytesConsumed and * bytesProduced on the returned result are zero. */ SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException; /** * @see SSLEngine#unwrap(ByteBuffer, ByteBuffer) * * Note that unwrap does read exactly one packet of encoded data from src * and write to dst. If src contains insufficient bytes to read a complete * packet {@link Status#BUFFER_UNDERFLOW} occurs. If underflow occurs the * pointers within both src and dst are unchanged and the bytesConsumed and * bytesProduced on the returned result are zero. */ SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException; Runnable getDelegatedTask(); HandshakeStatus getHandshakeStatus(); /** * Gets the application buffer size. */ int getEffectiveApplicationBufferSize(); int getPacketBufferSize(); String getCipherSuite(); String getProtocol(); boolean getUseClientMode(); } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/DefaultSslEngineFacade.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/DefaultSslEngineFacad0000664000000000000000000000631212562450203030336 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl.ssl; import java.nio.ByteBuffer; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.Status; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; class DefaultSslEngineFacade implements ProtonSslEngine { private final SSLEngine _sslEngine; /** * Our testing has shown that application buffers need to be a bit larger * than that provided by {@link SSLSession#getApplicationBufferSize()} otherwise * {@link Status#BUFFER_OVERFLOW} will result on {@link SSLEngine#unwrap()}. * Sun's own example uses 50, so we use the same. */ private static final int APPLICATION_BUFFER_EXTRA = 50; DefaultSslEngineFacade(SSLEngine sslEngine) { _sslEngine = sslEngine; } @Override public SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException { return _sslEngine.wrap(src, dst); } @Override public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException { return _sslEngine.unwrap(src, dst); } /** * @see #APPLICATION_BUFFER_EXTRA */ @Override public int getEffectiveApplicationBufferSize() { return getApplicationBufferSize() + APPLICATION_BUFFER_EXTRA; } private int getApplicationBufferSize() { return _sslEngine.getSession().getApplicationBufferSize(); } @Override public int getPacketBufferSize() { return _sslEngine.getSession().getPacketBufferSize(); } @Override public String getCipherSuite() { return _sslEngine.getSession().getCipherSuite(); } @Override public String getProtocol() { return _sslEngine.getSession().getProtocol(); } @Override public Runnable getDelegatedTask() { return _sslEngine.getDelegatedTask(); } @Override public HandshakeStatus getHandshakeStatus() { return _sslEngine.getHandshakeStatus(); } @Override public boolean getUseClientMode() { return _sslEngine.getUseClientMode(); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("DefaultSslEngineFacade [_sslEngine=").append(_sslEngine).append("]"); return builder.toString(); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportWrapper.java0000664000000000000000000000165212562450203027701 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; public interface TransportWrapper extends TransportInput, TransportOutput { } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportSession.java0000664000000000000000000003606212562450203027707 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.util.HashMap; import java.util.Map; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.transport.Disposition; import org.apache.qpid.proton.amqp.transport.Flow; import org.apache.qpid.proton.amqp.transport.Role; import org.apache.qpid.proton.amqp.transport.Transfer; import org.apache.qpid.proton.engine.Event; class TransportSession { private static final int HANDLE_MAX = 65535; private final TransportImpl _transport; private final SessionImpl _session; private int _localChannel = -1; private int _remoteChannel = -1; private boolean _openSent; private final UnsignedInteger _handleMax = UnsignedInteger.valueOf(HANDLE_MAX); //TODO: should this be configurable? // This is used for the delivery-id actually stamped in each transfer frame of a given message delivery. private UnsignedInteger _outgoingDeliveryId = UnsignedInteger.ZERO; // These are used for the session windows communicated via Begin/Flow frames // and the conceptual transfer-id relating to updating them. private UnsignedInteger _incomingWindowSize = UnsignedInteger.ZERO; private UnsignedInteger _outgoingWindowSize = UnsignedInteger.ZERO; private UnsignedInteger _nextOutgoingId = UnsignedInteger.ONE; private UnsignedInteger _nextIncomingId = null; private final Map> _remoteHandlesMap = new HashMap>(); private final Map> _localHandlesMap = new HashMap>(); private final Map _halfOpenLinks = new HashMap(); private UnsignedInteger _incomingDeliveryId = null; private UnsignedInteger _remoteIncomingWindow; private UnsignedInteger _remoteOutgoingWindow; private UnsignedInteger _remoteNextIncomingId = _nextOutgoingId; private UnsignedInteger _remoteNextOutgoingId; private final Map _unsettledIncomingDeliveriesById = new HashMap(); private final Map _unsettledOutgoingDeliveriesById = new HashMap(); private int _unsettledIncomingSize; private boolean _endReceived; private boolean _beginSent; TransportSession(TransportImpl transport, SessionImpl session) { _transport = transport; _session = session; _outgoingWindowSize = UnsignedInteger.valueOf(session.getOutgoingWindow()); } void unbind() { unsetLocalChannel(); unsetRemoteChannel(); } public SessionImpl getSession() { return _session; } public int getLocalChannel() { return _localChannel; } public void setLocalChannel(int localChannel) { if (!isLocalChannelSet()) { _session.incref(); } _localChannel = localChannel; } public int getRemoteChannel() { return _remoteChannel; } public void setRemoteChannel(int remoteChannel) { if (!isRemoteChannelSet()) { _session.incref(); } _remoteChannel = remoteChannel; } public boolean isOpenSent() { return _openSent; } public void setOpenSent(boolean openSent) { _openSent = openSent; } public boolean isRemoteChannelSet() { return _remoteChannel != -1; } public boolean isLocalChannelSet() { return _localChannel != -1; } public void unsetLocalChannel() { if (isLocalChannelSet()) { unsetLocalHandles(); _session.decref(); } _localChannel = -1; } private void unsetLocalHandles() { for (TransportLink tl : _localHandlesMap.values()) { tl.clearLocalHandle(); } _localHandlesMap.clear(); } public void unsetRemoteChannel() { if (isRemoteChannelSet()) { unsetRemoteHandles(); _session.decref(); } _remoteChannel = -1; } private void unsetRemoteHandles() { for (TransportLink tl : _remoteHandlesMap.values()) { tl.clearRemoteHandle(); } _remoteHandlesMap.clear(); } public UnsignedInteger getHandleMax() { return _handleMax; } public UnsignedInteger getIncomingWindowSize() { return _incomingWindowSize; } void updateIncomingWindow() { int size = _transport.getMaxFrameSize(); if (size <= 0) { _incomingWindowSize = UnsignedInteger.valueOf(2147483647); // biggest legal value } else { _incomingWindowSize = UnsignedInteger.valueOf((_session.getIncomingCapacity() - _session.getIncomingBytes())/size); } } public UnsignedInteger getOutgoingDeliveryId() { return _outgoingDeliveryId; } void incrementOutgoingDeliveryId() { _outgoingDeliveryId = _outgoingDeliveryId.add(UnsignedInteger.ONE); } public UnsignedInteger getOutgoingWindowSize() { return _outgoingWindowSize; } public UnsignedInteger getNextOutgoingId() { return _nextOutgoingId; } public TransportLink getLinkFromRemoteHandle(UnsignedInteger handle) { return _remoteHandlesMap.get(handle); } public UnsignedInteger allocateLocalHandle(TransportLink transportLink) { for(int i = 0; i <= HANDLE_MAX; i++) { UnsignedInteger handle = UnsignedInteger.valueOf(i); if(!_localHandlesMap.containsKey(handle)) { _localHandlesMap.put(handle, transportLink); transportLink.setLocalHandle(handle); return handle; } } throw new IllegalStateException("no local handle available for allocation"); } public void addLinkRemoteHandle(TransportLink link, UnsignedInteger remoteHandle) { _remoteHandlesMap.put(remoteHandle, link); } public void addLinkLocalHandle(TransportLink link, UnsignedInteger localhandle) { _localHandlesMap.put(localhandle, link); } public void freeLocalHandle(UnsignedInteger handle) { _localHandlesMap.remove(handle); } public void freeRemoteHandle(UnsignedInteger handle) { _remoteHandlesMap.remove(handle); } public TransportLink resolveHalfOpenLink(String name) { return _halfOpenLinks.remove(name); } public void addHalfOpenLink(TransportLink link) { _halfOpenLinks.put(link.getName(), link); } public void handleTransfer(Transfer transfer, Binary payload) { DeliveryImpl delivery; incrementNextIncomingId(); if(transfer.getDeliveryId() == null || transfer.getDeliveryId().equals(_incomingDeliveryId)) { TransportReceiver transportReceiver = (TransportReceiver) getLinkFromRemoteHandle(transfer.getHandle()); ReceiverImpl receiver = transportReceiver.getReceiver(); Binary deliveryTag = transfer.getDeliveryTag(); delivery = _unsettledIncomingDeliveriesById.get(_incomingDeliveryId); delivery.getTransportDelivery().incrementSessionSize(); } else { // TODO - check deliveryId has been incremented by one _incomingDeliveryId = transfer.getDeliveryId(); // TODO - check link handle valid and a receiver TransportReceiver transportReceiver = (TransportReceiver) getLinkFromRemoteHandle(transfer.getHandle()); ReceiverImpl receiver = transportReceiver.getReceiver(); Binary deliveryTag = transfer.getDeliveryTag(); delivery = receiver.delivery(deliveryTag.getArray(), deliveryTag.getArrayOffset(), deliveryTag.getLength()); TransportDelivery transportDelivery = new TransportDelivery(_incomingDeliveryId, delivery, transportReceiver); delivery.setTransportDelivery(transportDelivery); _unsettledIncomingDeliveriesById.put(_incomingDeliveryId, delivery); getSession().incrementIncomingDeliveries(1); } if( transfer.getState()!=null ) { delivery.setRemoteDeliveryState(transfer.getState()); } _unsettledIncomingSize++; // TODO - should this be a copy? if(payload != null) { if(delivery.getDataLength() == 0) { delivery.setData(payload.getArray()); delivery.setDataLength(payload.getLength()); delivery.setDataOffset(payload.getArrayOffset()); } else { byte[] data = new byte[delivery.getDataLength() + payload.getLength()]; System.arraycopy(delivery.getData(), delivery.getDataOffset(), data, 0, delivery.getDataLength()); System.arraycopy(payload.getArray(), payload.getArrayOffset(), data, delivery.getDataLength(), payload.getLength()); delivery.setData(data); delivery.setDataOffset(0); delivery.setDataLength(data.length); } getSession().incrementIncomingBytes(payload.getLength()); } delivery.updateWork(); if(!(transfer.getMore() || transfer.getAborted())) { delivery.setComplete(); delivery.getLink().getTransportLink().decrementLinkCredit(); delivery.getLink().getTransportLink().incrementDeliveryCount(); } if(Boolean.TRUE == transfer.getSettled()) { delivery.setRemoteSettled(true); } _incomingWindowSize = _incomingWindowSize.subtract(UnsignedInteger.ONE); // this will cause a flow to happen if (_incomingWindowSize.equals(UnsignedInteger.ZERO)) { delivery.getLink().modified(false); } getSession().getConnection().put(Event.Type.DELIVERY, delivery); } public void freeLocalChannel() { unsetLocalChannel(); } public void freeRemoteChannel() { unsetRemoteChannel(); } private void setRemoteIncomingWindow(UnsignedInteger incomingWindow) { _remoteIncomingWindow = incomingWindow; } void decrementRemoteIncomingWindow() { _remoteIncomingWindow = _remoteIncomingWindow.subtract(UnsignedInteger.ONE); } private void setRemoteOutgoingWindow(UnsignedInteger outgoingWindow) { _remoteOutgoingWindow = outgoingWindow; } void handleFlow(Flow flow) { UnsignedInteger inext = flow.getNextIncomingId(); UnsignedInteger iwin = flow.getIncomingWindow(); if(inext != null) { setRemoteNextIncomingId(inext); setRemoteIncomingWindow(inext.add(iwin).subtract(_nextOutgoingId)); } else { setRemoteIncomingWindow(iwin); } setRemoteNextOutgoingId(flow.getNextOutgoingId()); setRemoteOutgoingWindow(flow.getOutgoingWindow()); if(flow.getHandle() != null) { TransportLink transportLink = getLinkFromRemoteHandle(flow.getHandle()); transportLink.handleFlow(flow); } } private void setRemoteNextOutgoingId(UnsignedInteger nextOutgoingId) { _remoteNextOutgoingId = nextOutgoingId; } private void setRemoteNextIncomingId(UnsignedInteger remoteNextIncomingId) { _remoteNextIncomingId = remoteNextIncomingId; } void handleDisposition(Disposition disposition) { UnsignedInteger id = disposition.getFirst(); UnsignedInteger last = disposition.getLast() == null ? id : disposition.getLast(); final Map unsettledDeliveries = disposition.getRole() == Role.RECEIVER ? _unsettledOutgoingDeliveriesById : _unsettledIncomingDeliveriesById; while(id.compareTo(last)<=0) { DeliveryImpl delivery = unsettledDeliveries.get(id); if(delivery != null) { if(disposition.getState() != null) { delivery.setRemoteDeliveryState(disposition.getState()); } if(Boolean.TRUE.equals(disposition.getSettled())) { delivery.setRemoteSettled(true); unsettledDeliveries.remove(id); } delivery.updateWork(); getSession().getConnection().put(Event.Type.DELIVERY, delivery); } id = id.add(UnsignedInteger.ONE); } //TODO - Implement. } void addUnsettledOutgoing(UnsignedInteger deliveryId, DeliveryImpl delivery) { _unsettledOutgoingDeliveriesById.put(deliveryId, delivery); } public boolean hasOutgoingCredit() { return _remoteIncomingWindow == null ? false : _remoteIncomingWindow.compareTo(UnsignedInteger.ZERO)>0; } void incrementOutgoingId() { _nextOutgoingId = _nextOutgoingId.add(UnsignedInteger.ONE); } public void settled(TransportDelivery transportDelivery) { if(transportDelivery.getTransportLink().getLink() instanceof ReceiverImpl) { _unsettledIncomingDeliveriesById.remove(transportDelivery.getDeliveryId()); getSession().modified(false); } else { _unsettledOutgoingDeliveriesById.remove(transportDelivery.getDeliveryId()); getSession().modified(false); } } public UnsignedInteger getNextIncomingId() { return _nextIncomingId; } public void setNextIncomingId(UnsignedInteger nextIncomingId) { _nextIncomingId = nextIncomingId; } public void incrementNextIncomingId() { _nextIncomingId = _nextIncomingId.add(UnsignedInteger.ONE); } public boolean endReceived() { return _endReceived; } public void receivedEnd() { _endReceived = true; } public boolean beginSent() { return _beginSent; } public void sentBegin() { _beginSent = true; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportSender.java0000664000000000000000000000430012562450203027472 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.transport.Flow; class TransportSender extends TransportLink { private boolean _drain; private static final UnsignedInteger ORIGINAL_DELIVERY_COUNT = UnsignedInteger.ZERO; TransportSender(SenderImpl link) { super(link); setDeliveryCount(ORIGINAL_DELIVERY_COUNT); link.setTransportLink(this); } @Override void handleFlow(Flow flow) { super.handleFlow(flow); _drain = flow.getDrain(); getLink().setDrain(flow.getDrain()); int oldCredit = getLink().getCredit(); UnsignedInteger oldLimit = getLinkCredit().add(getDeliveryCount()); UnsignedInteger transferLimit = flow.getLinkCredit().add(flow.getDeliveryCount() == null ? ORIGINAL_DELIVERY_COUNT : flow.getDeliveryCount()); UnsignedInteger linkCredit = transferLimit.subtract(getDeliveryCount()); setLinkCredit(linkCredit); getLink().setCredit(transferLimit.subtract(oldLimit).intValue() + oldCredit); DeliveryImpl current = getLink().current(); getLink().getConnectionImpl().workUpdate(current); setLinkCredit(linkCredit); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportReceiver.java0000664000000000000000000000317212562450203030024 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.amqp.transport.Flow; class TransportReceiver extends TransportLink { TransportReceiver(ReceiverImpl link) { super(link); link.setTransportLink(this); } public ReceiverImpl getReceiver() { return getLink(); } @Override void handleFlow(Flow flow) { super.handleFlow(flow); int remote = getRemoteDeliveryCount().intValue(); int local = getDeliveryCount().intValue(); int delta = remote - local; if(delta > 0) { getLink().addCredit(-delta); setLinkCredit(getRemoteLinkCredit()); setDeliveryCount(getRemoteDeliveryCount()); getLink().setDrained(getLink().getDrained() + delta); } } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportOutputWriter.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportOutputWriter.jav0000664000000000000000000000227312562450203030615 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine.impl; import java.nio.ByteBuffer; import org.apache.qpid.proton.engine.TransportException; interface TransportOutputWriter { /** * Writes my pending output bytes into outputBuffer. Does not * subsequently flip it. Returns true on end of stream. */ boolean writeInto(ByteBuffer outputBuffer); void closed(TransportException error); } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportOutputAdaptor.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportOutputAdaptor.ja0000664000000000000000000000653712562450203030554 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine.impl; import static org.apache.qpid.proton.engine.impl.ByteBufferUtils.*; import java.nio.ByteBuffer; import org.apache.qpid.proton.engine.Transport; class TransportOutputAdaptor implements TransportOutput { private static final ByteBuffer _emptyHead = newReadableBuffer(0).asReadOnlyBuffer(); private final TransportOutputWriter _transportOutputWriter; private final int _maxFrameSize; private ByteBuffer _outputBuffer = null; private ByteBuffer _head = null; private boolean _output_done = false; private boolean _head_closed = false; TransportOutputAdaptor(TransportOutputWriter transportOutputWriter, int maxFrameSize) { _transportOutputWriter = transportOutputWriter; _maxFrameSize = maxFrameSize > 0 ? maxFrameSize : 4*1024; } @Override public int pending() { if (_head_closed) { return Transport.END_OF_STREAM; } if(_outputBuffer == null) { init_buffers(); } _output_done = _transportOutputWriter.writeInto(_outputBuffer); _head.limit(_outputBuffer.position()); if (_outputBuffer.position() == 0 && _outputBuffer.capacity() > TransportImpl.BUFFER_RELEASE_THRESHOLD) { release_buffers(); } if (_output_done && (_outputBuffer == null || _outputBuffer.position() == 0)) { return Transport.END_OF_STREAM; } else { return _outputBuffer == null ? 0 : _outputBuffer.position(); } } @Override public ByteBuffer head() { pending(); return _head != null ? _head : _emptyHead; } @Override public void pop(int bytes) { if (_outputBuffer != null) { _outputBuffer.flip(); _outputBuffer.position(bytes); _outputBuffer.compact(); _head.position(0); _head.limit(_outputBuffer.position()); if (_outputBuffer.position() == 0 && _outputBuffer.capacity() > TransportImpl.BUFFER_RELEASE_THRESHOLD) { release_buffers(); } } } @Override public void close_head() { _head_closed = true; _transportOutputWriter.closed(null); release_buffers(); } private void init_buffers() { _outputBuffer = newWriteableBuffer(_maxFrameSize); _head = _outputBuffer.asReadOnlyBuffer(); _head.limit(0); } private void release_buffers() { _head = null; _outputBuffer = null; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportOutput.java0000664000000000000000000000205512562450203027557 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.nio.ByteBuffer; import org.apache.qpid.proton.engine.Transport; public interface TransportOutput { int pending(); ByteBuffer head(); void pop(int bytes); void close_head(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportLink.java0000664000000000000000000001231612562450203027155 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.transport.Flow; import org.apache.qpid.proton.engine.Event; class TransportLink { private UnsignedInteger _localHandle; private String _name; private UnsignedInteger _remoteHandle; private UnsignedInteger _deliveryCount; private UnsignedInteger _linkCredit = UnsignedInteger.ZERO; private T _link; private UnsignedInteger _remoteDeliveryCount; private UnsignedInteger _remoteLinkCredit; private boolean _detachReceived; private boolean _attachSent; protected TransportLink(T link) { _link = link; _name = link.getName(); } static TransportLink createTransportLink(L link) { if (link instanceof ReceiverImpl) { ReceiverImpl r = (ReceiverImpl) link; TransportReceiver tr = new TransportReceiver(r); r.setTransportLink(tr); return (TransportLink) tr; } else { SenderImpl s = (SenderImpl) link; TransportSender ts = new TransportSender(s); s.setTransportLink(ts); return (TransportLink) ts; } } void unbind() { clearLocalHandle(); clearRemoteHandle(); } public UnsignedInteger getLocalHandle() { return _localHandle; } public void setLocalHandle(UnsignedInteger localHandle) { if (_localHandle == null) { _link.incref(); } _localHandle = localHandle; } public boolean isLocalHandleSet() { return _localHandle != null; } public String getName() { return _name; } public void setName(String name) { _name = name; } public void clearLocalHandle() { if (_localHandle != null) { _link.decref(); } _localHandle = null; } public UnsignedInteger getRemoteHandle() { return _remoteHandle; } public void setRemoteHandle(UnsignedInteger remoteHandle) { if (_remoteHandle == null) { _link.incref(); } _remoteHandle = remoteHandle; } public void clearRemoteHandle() { if (_remoteHandle != null) { _link.decref(); } _remoteHandle = null; } public UnsignedInteger getDeliveryCount() { return _deliveryCount; } public UnsignedInteger getLinkCredit() { return _linkCredit; } public void addCredit(int credits) { _linkCredit = UnsignedInteger.valueOf(_linkCredit.intValue() + credits); } public boolean hasCredit() { return getLinkCredit().compareTo(UnsignedInteger.ZERO) > 0; } public T getLink() { return _link; } void handleFlow(Flow flow) { _remoteDeliveryCount = flow.getDeliveryCount(); _remoteLinkCredit = flow.getLinkCredit(); _link.getConnectionImpl().put(Event.Type.LINK_FLOW, _link); } void setLinkCredit(UnsignedInteger linkCredit) { _linkCredit = linkCredit; } public void setDeliveryCount(UnsignedInteger deliveryCount) { _deliveryCount = deliveryCount; } public void settled(TransportDelivery transportDelivery) { getLink().getSession().getTransportSession().settled(transportDelivery); } UnsignedInteger getRemoteDeliveryCount() { return _remoteDeliveryCount; } UnsignedInteger getRemoteLinkCredit() { return _remoteLinkCredit; } public void setRemoteLinkCredit(UnsignedInteger remoteLinkCredit) { _remoteLinkCredit = remoteLinkCredit; } void decrementLinkCredit() { _linkCredit = _linkCredit.subtract(UnsignedInteger.ONE); } void incrementDeliveryCount() { _deliveryCount = _deliveryCount.add(UnsignedInteger.ONE); } public void receivedDetach() { _detachReceived = true; } public boolean detachReceived() { return _detachReceived; } public boolean attachSent() { return _attachSent; } public void sentAttach() { _attachSent = true; } public void setRemoteDeliveryCount(UnsignedInteger remoteDeliveryCount) { _remoteDeliveryCount = remoteDeliveryCount; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportInput.java0000664000000000000000000000217312562450203027357 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.nio.ByteBuffer; import org.apache.qpid.proton.engine.TransportException; public interface TransportInput { int capacity(); int position(); ByteBuffer tail() throws TransportException; void process() throws TransportException; void close_tail(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportImpl.java0000664000000000000000000015261012562450203027163 0ustar /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.qpid.proton.engine.impl; import static org.apache.qpid.proton.engine.impl.ByteBufferUtils.pourArrayToBuffer; import static org.apache.qpid.proton.engine.impl.ByteBufferUtils.pourBufferToArray; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedShort; import org.apache.qpid.proton.amqp.transport.Attach; import org.apache.qpid.proton.amqp.transport.Begin; import org.apache.qpid.proton.amqp.transport.Close; import org.apache.qpid.proton.amqp.transport.ConnectionError; import org.apache.qpid.proton.amqp.transport.DeliveryState; import org.apache.qpid.proton.amqp.transport.Detach; import org.apache.qpid.proton.amqp.transport.Disposition; import org.apache.qpid.proton.amqp.transport.End; import org.apache.qpid.proton.amqp.transport.ErrorCondition; import org.apache.qpid.proton.amqp.transport.Flow; import org.apache.qpid.proton.amqp.transport.FrameBody; import org.apache.qpid.proton.amqp.transport.Open; import org.apache.qpid.proton.amqp.transport.Role; import org.apache.qpid.proton.amqp.transport.Transfer; import org.apache.qpid.proton.codec.AMQPDefinedTypes; import org.apache.qpid.proton.codec.DecoderImpl; import org.apache.qpid.proton.codec.EncoderImpl; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Event; import org.apache.qpid.proton.engine.ProtonJTransport; import org.apache.qpid.proton.engine.Sasl; import org.apache.qpid.proton.engine.Ssl; import org.apache.qpid.proton.engine.SslDomain; import org.apache.qpid.proton.engine.SslPeerDetails; import org.apache.qpid.proton.engine.TransportException; import org.apache.qpid.proton.engine.TransportResult; import org.apache.qpid.proton.engine.TransportResultFactory; import org.apache.qpid.proton.engine.impl.ssl.SslImpl; import org.apache.qpid.proton.framing.TransportFrame; import org.apache.qpid.proton.reactor.Reactor; import org.apache.qpid.proton.reactor.Selectable; public class TransportImpl extends EndpointImpl implements ProtonJTransport, FrameBody.FrameBodyHandler, FrameHandler, TransportOutputWriter { static final int BUFFER_RELEASE_THRESHOLD = Integer.getInteger("proton.transport_buffer_release_threshold", 2 * 1024 * 1024); private static final int CHANNEL_MAX_LIMIT = 65535; private static final boolean getBooleanEnv(String name) { String value = System.getenv(name); return "true".equalsIgnoreCase(value) || "1".equals(value) || "yes".equalsIgnoreCase(value); } private static final boolean FRM_ENABLED = getBooleanEnv("PN_TRACE_FRM"); private static final int TRACE_FRAME_PAYLOAD_LENGTH = Integer.getInteger("proton.trace_frame_payload_length", 1024); // trace levels private int _levels = (FRM_ENABLED ? TRACE_FRM : 0); private FrameParser _frameParser; private ConnectionImpl _connectionEndpoint; private boolean _isOpenSent; private boolean _isCloseSent; private boolean _headerWritten; private Map _remoteSessions = new HashMap(); private Map _localSessions = new HashMap(); private TransportInput _inputProcessor; private TransportOutput _outputProcessor; private DecoderImpl _decoder = new DecoderImpl(); private EncoderImpl _encoder = new EncoderImpl(_decoder); private int _maxFrameSize = DEFAULT_MAX_FRAME_SIZE; private int _remoteMaxFrameSize = 512; private int _channelMax = CHANNEL_MAX_LIMIT; private int _remoteChannelMax = CHANNEL_MAX_LIMIT; private final FrameWriter _frameWriter; private boolean _closeReceived; private Open _open; private SaslImpl _sasl; private SslImpl _ssl; private final Ref _protocolTracer = new Ref(null); private TransportResult _lastTransportResult = TransportResultFactory.ok(); private boolean _init; private boolean _processingStarted; private FrameHandler _frameHandler = this; private boolean _head_closed = false; private ErrorCondition _condition = null; private boolean postedHeadClosed = false; private boolean postedTailClosed = false; private boolean postedTransportError = false; private int _localIdleTimeout = 0; private int _remoteIdleTimeout = 0; private long _bytesInput = 0; private long _bytesOutput = 0; private long _localIdleDeadline = 0; private long _lastBytesInput = 0; private long _lastBytesOutput = 0; private long _remoteIdleDeadline = 0; private Selectable _selectable; private Reactor _reactor; /** * @deprecated This constructor's visibility will be reduced to the default scope in a future release. * Client code outside this module should use a {@link EngineFactory} instead */ @Deprecated public TransportImpl() { this(DEFAULT_MAX_FRAME_SIZE); } /** * Creates a transport with the given maximum frame size. * Note that the maximumFrameSize also determines the size of the output buffer. */ TransportImpl(int maxFrameSize) { AMQPDefinedTypes.registerAllTypes(_decoder, _encoder); _maxFrameSize = maxFrameSize; _frameWriter = new FrameWriter(_encoder, _remoteMaxFrameSize, FrameWriter.AMQP_FRAME_TYPE, _protocolTracer, this); } private void init() { if(!_init) { _init = true; _frameParser = new FrameParser(_frameHandler , _decoder, _maxFrameSize); _inputProcessor = _frameParser; _outputProcessor = new TransportOutputAdaptor(this, _maxFrameSize); } } @Override public void trace(int levels) { _levels = levels; } @Override public int getMaxFrameSize() { return _maxFrameSize; } @Override public int getRemoteMaxFrameSize() { return _remoteMaxFrameSize; } @Override public void setMaxFrameSize(int maxFrameSize) { if(_init) { throw new IllegalStateException("Cannot set max frame size after transport has been initialised"); } _maxFrameSize = maxFrameSize; } @Override public int getChannelMax() { return _channelMax; } @Override public void setChannelMax(int n) { if(_isOpenSent) { throw new IllegalArgumentException("Cannot change channel max after open frame has been sent"); } if(n < CHANNEL_MAX_LIMIT) { _channelMax = n; } else { _channelMax = CHANNEL_MAX_LIMIT; } } @Override public int getRemoteChannelMax() { return _remoteChannelMax; } @Override public ErrorCondition getCondition() { return _condition; } @Override public void bind(Connection conn) { // TODO - check if already bound _connectionEndpoint = (ConnectionImpl) conn; put(Event.Type.CONNECTION_BOUND, conn); _connectionEndpoint.setTransport(this); _connectionEndpoint.incref(); if(getRemoteState() != EndpointState.UNINITIALIZED) { _connectionEndpoint.handleOpen(_open); if(getRemoteState() == EndpointState.CLOSED) { _connectionEndpoint.setRemoteState(EndpointState.CLOSED); } _frameParser.flush(); } } @Override public void unbind() { for (TransportSession ts: _localSessions.values()) { ts.unbind(); } for (TransportSession ts: _remoteSessions.values()) { ts.unbind(); } put(Event.Type.CONNECTION_UNBOUND, _connectionEndpoint); _connectionEndpoint.modifyEndpoints(); _connectionEndpoint.setTransport(null); _connectionEndpoint.decref(); } @Override public int input(byte[] bytes, int offset, int length) { oldApiCheckStateBeforeInput(length).checkIsOk(); ByteBuffer inputBuffer = getInputBuffer(); int numberOfBytesConsumed = pourArrayToBuffer(bytes, offset, length, inputBuffer); processInput().checkIsOk(); return numberOfBytesConsumed; } /** * This method is public as it is used by Python layer. * @see Transport#input(byte[], int, int) */ public TransportResult oldApiCheckStateBeforeInput(int inputLength) { _lastTransportResult.checkIsOk(); if(inputLength == 0) { if(_connectionEndpoint == null || _connectionEndpoint.getRemoteState() != EndpointState.CLOSED) { return TransportResultFactory.error(new TransportException("Unexpected EOS when remote connection not closed: connection aborted")); } } return TransportResultFactory.ok(); } //================================================================================================================== // Process model state to generate output @Override public int output(byte[] bytes, final int offset, final int size) { ByteBuffer outputBuffer = getOutputBuffer(); int numberOfBytesOutput = pourBufferToArray(outputBuffer, bytes, offset, size); outputConsumed(); return numberOfBytesOutput; } @Override public boolean writeInto(ByteBuffer outputBuffer) { processHeader(); processOpen(); processBegin(); processAttach(); processReceiverFlow(); // we process transport work twice intentionally, the first // pass may end up settling deliveries that the second pass // can clean up processTransportWork(); processTransportWork(); processSenderFlow(); processDetach(); processEnd(); processClose(); _frameWriter.readBytes(outputBuffer); return _isCloseSent || _head_closed; } @Override public Sasl sasl() { if(_sasl == null) { if(_processingStarted) { throw new IllegalStateException("Sasl can't be initiated after transport has started processing"); } init(); _sasl = new SaslImpl(this, _remoteMaxFrameSize); TransportWrapper transportWrapper = _sasl.wrap(_inputProcessor, _outputProcessor); _inputProcessor = transportWrapper; _outputProcessor = transportWrapper; } return _sasl; } /** * {@inheritDoc} * *

Note that sslDomain must implement {@link ProtonSslEngineProvider}. This is not possible * enforce at the API level because {@link ProtonSslEngineProvider} is not part of the * public Proton API.

*/ @Override public Ssl ssl(SslDomain sslDomain, SslPeerDetails sslPeerDetails) { if (_ssl == null) { init(); _ssl = new SslImpl(sslDomain, sslPeerDetails); TransportWrapper transportWrapper = _ssl.wrap(_inputProcessor, _outputProcessor); _inputProcessor = transportWrapper; _outputProcessor = transportWrapper; } return _ssl; } @Override public Ssl ssl(SslDomain sslDomain) { return ssl(sslDomain, null); } private void processDetach() { if(_connectionEndpoint != null) { EndpointImpl endpoint = _connectionEndpoint.getTransportHead(); while(endpoint != null) { if(endpoint instanceof LinkImpl) { LinkImpl link = (LinkImpl) endpoint; TransportLink transportLink = getTransportState(link); SessionImpl session = link.getSession(); TransportSession transportSession = getTransportState(session); if(((link.getLocalState() == EndpointState.CLOSED) || link.detached()) && transportLink.isLocalHandleSet() && transportSession.isLocalChannelSet() && !_isCloseSent) { if((link instanceof SenderImpl) && link.getQueued() > 0 && !transportLink.detachReceived() && !transportSession.endReceived() && !_closeReceived) { endpoint = endpoint.transportNext(); continue; } UnsignedInteger localHandle = transportLink.getLocalHandle(); transportLink.clearLocalHandle(); transportSession.freeLocalHandle(localHandle); Detach detach = new Detach(); detach.setHandle(localHandle); detach.setClosed(!link.detached()); ErrorCondition localError = link.getCondition(); if( localError.getCondition() !=null ) { detach.setError(localError); } writeFrame(transportSession.getLocalChannel(), detach, null, null); } endpoint.clearModified(); } endpoint = endpoint.transportNext(); } } } private void writeFlow(TransportSession ssn, TransportLink link) { Flow flow = new Flow(); flow.setNextIncomingId(ssn.getNextIncomingId()); flow.setNextOutgoingId(ssn.getNextOutgoingId()); ssn.updateIncomingWindow(); flow.setIncomingWindow(ssn.getIncomingWindowSize()); flow.setOutgoingWindow(ssn.getOutgoingWindowSize()); if (link != null) { flow.setHandle(link.getLocalHandle()); flow.setDeliveryCount(link.getDeliveryCount()); flow.setLinkCredit(link.getLinkCredit()); flow.setDrain(link.getLink().getDrain()); } writeFrame(ssn.getLocalChannel(), flow, null, null); } private void processSenderFlow() { if(_connectionEndpoint != null) { EndpointImpl endpoint = _connectionEndpoint.getTransportHead(); while(endpoint != null) { if(endpoint instanceof SenderImpl) { SenderImpl sender = (SenderImpl) endpoint; if(sender.getDrain() && sender.getDrained() > 0) { TransportSender transportLink = sender.getTransportLink(); TransportSession transportSession = sender.getSession().getTransportSession(); UnsignedInteger credits = transportLink.getLinkCredit(); transportLink.setLinkCredit(UnsignedInteger.valueOf(0)); transportLink.setDeliveryCount(transportLink.getDeliveryCount().add(credits)); transportLink.setLinkCredit(UnsignedInteger.ZERO); sender.setDrained(0); writeFlow(transportSession, transportLink); } } endpoint = endpoint.transportNext(); } } } private void processTransportWork() { if(_connectionEndpoint != null) { DeliveryImpl delivery = _connectionEndpoint.getTransportWorkHead(); while(delivery != null) { LinkImpl link = delivery.getLink(); if (link instanceof SenderImpl) { if (processTransportWorkSender(delivery, (SenderImpl) link)) { delivery = delivery.clearTransportWork(); } else { delivery = delivery.getTransportWorkNext(); } } else { if (processTransportWorkReceiver(delivery, (ReceiverImpl) link)) { delivery = delivery.clearTransportWork(); } else { delivery = delivery.getTransportWorkNext(); } } } } } private boolean processTransportWorkSender(DeliveryImpl delivery, SenderImpl snd) { TransportLink tpLink = snd.getTransportLink(); SessionImpl session = snd.getSession(); TransportSession tpSession = session.getTransportSession(); boolean wasDone = delivery.isDone(); if(!delivery.isDone() && (delivery.getDataLength() > 0 || delivery != snd.current()) && tpSession.hasOutgoingCredit() && tpLink.hasCredit() && tpSession.isLocalChannelSet() && tpLink.getLocalHandle() != null && !_frameWriter.isFull()) { UnsignedInteger deliveryId = tpSession.getOutgoingDeliveryId(); TransportDelivery tpDelivery = new TransportDelivery(deliveryId, delivery, tpLink); delivery.setTransportDelivery(tpDelivery); final Transfer transfer = new Transfer(); transfer.setDeliveryId(deliveryId); transfer.setDeliveryTag(new Binary(delivery.getTag())); transfer.setHandle(tpLink.getLocalHandle()); if(delivery.getLocalState() != null) { transfer.setState(delivery.getLocalState()); } if(delivery.isSettled()) { transfer.setSettled(Boolean.TRUE); } else { tpSession.addUnsettledOutgoing(deliveryId, delivery); } if(snd.current() == delivery) { transfer.setMore(true); } transfer.setMessageFormat(UnsignedInteger.ZERO); ByteBuffer payload = delivery.getData() == null ? null : ByteBuffer.wrap(delivery.getData(), delivery.getDataOffset(), delivery.getDataLength()); writeFrame(tpSession.getLocalChannel(), transfer, payload, new PartialTransfer(transfer)); tpSession.incrementOutgoingId(); tpSession.decrementRemoteIncomingWindow(); if(payload == null || !payload.hasRemaining()) { session.incrementOutgoingBytes(-delivery.pending()); delivery.setData(null); delivery.setDataLength(0); if (!transfer.getMore()) { delivery.setDone(); tpLink.setDeliveryCount(tpLink.getDeliveryCount().add(UnsignedInteger.ONE)); tpLink.setLinkCredit(tpLink.getLinkCredit().subtract(UnsignedInteger.ONE)); tpSession.incrementOutgoingDeliveryId(); session.incrementOutgoingDeliveries(-1); snd.decrementQueued(); } } else { int delta = delivery.getDataLength() - payload.remaining(); delivery.setDataOffset(delivery.getDataOffset() + delta); delivery.setDataLength(payload.remaining()); session.incrementOutgoingBytes(-delta); } if (snd.getLocalState() != EndpointState.CLOSED) { getConnectionImpl().put(Event.Type.LINK_FLOW, snd); } } if(wasDone && delivery.getLocalState() != null) { TransportDelivery tpDelivery = delivery.getTransportDelivery(); Disposition disposition = new Disposition(); disposition.setFirst(tpDelivery.getDeliveryId()); disposition.setLast(tpDelivery.getDeliveryId()); disposition.setRole(Role.SENDER); disposition.setSettled(delivery.isSettled()); if(delivery.isSettled()) { tpDelivery.settled(); } disposition.setState(delivery.getLocalState()); writeFrame(tpSession.getLocalChannel(), disposition, null, null); } return !delivery.isBuffered(); } private boolean processTransportWorkReceiver(DeliveryImpl delivery, ReceiverImpl rcv) { TransportDelivery tpDelivery = delivery.getTransportDelivery(); SessionImpl session = rcv.getSession(); TransportSession tpSession = session.getTransportSession(); if (tpSession.isLocalChannelSet()) { boolean settled = delivery.isSettled(); DeliveryState localState = delivery.getLocalState(); Disposition disposition = new Disposition(); disposition.setFirst(tpDelivery.getDeliveryId()); disposition.setLast(tpDelivery.getDeliveryId()); disposition.setRole(Role.RECEIVER); disposition.setSettled(settled); disposition.setState(localState); if(localState == null && settled) { disposition.setState(delivery.getDefaultDeliveryState()); } writeFrame(tpSession.getLocalChannel(), disposition, null, null); if (settled) { tpDelivery.settled(); } return true; } return false; } private void processReceiverFlow() { if(_connectionEndpoint != null) { EndpointImpl endpoint = _connectionEndpoint.getTransportHead(); while(endpoint != null) { if(endpoint instanceof ReceiverImpl) { ReceiverImpl receiver = (ReceiverImpl) endpoint; TransportLink transportLink = getTransportState(receiver); TransportSession transportSession = getTransportState(receiver.getSession()); if(receiver.getLocalState() == EndpointState.ACTIVE) { int credits = receiver.clearUnsentCredits(); if(credits != 0 || receiver.getDrain() || transportSession.getIncomingWindowSize().equals(UnsignedInteger.ZERO)) { transportLink.addCredit(credits); writeFlow(transportSession, transportLink); } } } endpoint = endpoint.transportNext(); } endpoint = _connectionEndpoint.getTransportHead(); while(endpoint != null) { if(endpoint instanceof SessionImpl) { SessionImpl session = (SessionImpl) endpoint; TransportSession transportSession = getTransportState(session); if(session.getLocalState() == EndpointState.ACTIVE) { if(transportSession.getIncomingWindowSize().equals(UnsignedInteger.ZERO)) { writeFlow(transportSession, null); } } } endpoint = endpoint.transportNext(); } } } private void processAttach() { if(_connectionEndpoint != null) { EndpointImpl endpoint = _connectionEndpoint.getTransportHead(); while(endpoint != null) { if(endpoint instanceof LinkImpl) { LinkImpl link = (LinkImpl) endpoint; TransportLink transportLink = getTransportState(link); if(link.getLocalState() != EndpointState.UNINITIALIZED && !transportLink.attachSent()) { if( (link.getRemoteState() == EndpointState.ACTIVE && !transportLink.isLocalHandleSet()) || link.getRemoteState() == EndpointState.UNINITIALIZED) { SessionImpl session = link.getSession(); TransportSession transportSession = getTransportState(session); UnsignedInteger localHandle = transportSession.allocateLocalHandle(transportLink); if(link.getRemoteState() == EndpointState.UNINITIALIZED) { transportSession.addHalfOpenLink(transportLink); } Attach attach = new Attach(); attach.setHandle(localHandle); attach.setName(transportLink.getName()); if(link.getSenderSettleMode() != null) { attach.setSndSettleMode(link.getSenderSettleMode()); } if(link.getReceiverSettleMode() != null) { attach.setRcvSettleMode(link.getReceiverSettleMode()); } if(link.getSource() != null) { attach.setSource(link.getSource()); } if(link.getTarget() != null) { attach.setTarget(link.getTarget()); } attach.setRole(endpoint instanceof ReceiverImpl ? Role.RECEIVER : Role.SENDER); if(link instanceof SenderImpl) { attach.setInitialDeliveryCount(UnsignedInteger.ZERO); } writeFrame(transportSession.getLocalChannel(), attach, null, null); transportLink.sentAttach(); } } } endpoint = endpoint.transportNext(); } } } private void processHeader() { if(!_headerWritten) { _frameWriter.writeHeader(AmqpHeader.HEADER); _headerWritten = true; } } private void processOpen() { if ((_condition != null || (_connectionEndpoint != null && _connectionEndpoint.getLocalState() != EndpointState.UNINITIALIZED)) && !_isOpenSent) { Open open = new Open(); if (_connectionEndpoint != null) { String cid = _connectionEndpoint.getLocalContainerId(); open.setContainerId(cid == null ? "" : cid); open.setHostname(_connectionEndpoint.getHostname()); open.setDesiredCapabilities(_connectionEndpoint.getDesiredCapabilities()); open.setOfferedCapabilities(_connectionEndpoint.getOfferedCapabilities()); open.setProperties(_connectionEndpoint.getProperties()); } else { open.setContainerId(""); } if (_maxFrameSize > 0) { open.setMaxFrameSize(UnsignedInteger.valueOf(_maxFrameSize)); } if (_channelMax > 0) { open.setChannelMax(UnsignedShort.valueOf((short) _channelMax)); } // as per the recommendation in the spec, advertise half our // actual timeout to the remote if (_localIdleTimeout > 0) { open.setIdleTimeOut(new UnsignedInteger(_localIdleTimeout / 2)); } _isOpenSent = true; writeFrame(0, open, null, null); } } private void processBegin() { if(_connectionEndpoint != null) { EndpointImpl endpoint = _connectionEndpoint.getTransportHead(); while(endpoint != null) { if(endpoint instanceof SessionImpl) { SessionImpl session = (SessionImpl) endpoint; TransportSession transportSession = getTransportState(session); if(session.getLocalState() != EndpointState.UNINITIALIZED && !transportSession.beginSent()) { int channelId = allocateLocalChannel(transportSession); Begin begin = new Begin(); if(session.getRemoteState() != EndpointState.UNINITIALIZED) { begin.setRemoteChannel(UnsignedShort.valueOf((short) transportSession.getRemoteChannel())); } transportSession.updateIncomingWindow(); begin.setHandleMax(transportSession.getHandleMax()); begin.setIncomingWindow(transportSession.getIncomingWindowSize()); begin.setOutgoingWindow(transportSession.getOutgoingWindowSize()); begin.setNextOutgoingId(transportSession.getNextOutgoingId()); writeFrame(channelId, begin, null, null); transportSession.sentBegin(); } } endpoint = endpoint.transportNext(); } } } private TransportSession getTransportState(SessionImpl session) { TransportSession transportSession = session.getTransportSession(); if(transportSession == null) { transportSession = new TransportSession(this, session); session.setTransportSession(transportSession); } return transportSession; } private TransportLink getTransportState(LinkImpl link) { TransportLink transportLink = link.getTransportLink(); if(transportLink == null) { transportLink = TransportLink.createTransportLink(link); } return transportLink; } private int allocateLocalChannel(TransportSession transportSession) { for (int i = 0; i < _connectionEndpoint.getMaxChannels(); i++) { if (!_localSessions.containsKey(i)) { _localSessions.put(i, transportSession); transportSession.setLocalChannel(i); return i; } } return -1; } private int freeLocalChannel(TransportSession transportSession) { final int channel = transportSession.getLocalChannel(); _localSessions.remove(channel); transportSession.freeLocalChannel(); return channel; } private void processEnd() { if(_connectionEndpoint != null) { EndpointImpl endpoint = _connectionEndpoint.getTransportHead(); while(endpoint != null) { SessionImpl session; TransportSession transportSession; if((endpoint instanceof SessionImpl)) { if ((session = (SessionImpl)endpoint).getLocalState() == EndpointState.CLOSED && (transportSession = session.getTransportSession()).isLocalChannelSet() && !_isCloseSent) { if (hasSendableMessages(session)) { endpoint = endpoint.transportNext(); continue; } int channel = freeLocalChannel(transportSession); End end = new End(); ErrorCondition localError = endpoint.getCondition(); if( localError.getCondition() !=null ) { end.setError(localError); } writeFrame(channel, end, null, null); } endpoint.clearModified(); } endpoint = endpoint.transportNext(); } } } private boolean hasSendableMessages(SessionImpl session) { if (_connectionEndpoint == null) { return false; } if(!_closeReceived && (session == null || !session.getTransportSession().endReceived())) { EndpointImpl endpoint = _connectionEndpoint.getTransportHead(); while(endpoint != null) { if(endpoint instanceof SenderImpl) { SenderImpl sender = (SenderImpl) endpoint; if((session == null || sender.getSession() == session) && sender.getQueued() != 0 && !getTransportState(sender).detachReceived()) { return true; } } endpoint = endpoint.transportNext(); } } return false; } private void processClose() { if ((_condition != null || (_connectionEndpoint != null && _connectionEndpoint.getLocalState() == EndpointState.CLOSED)) && !_isCloseSent) { if(!hasSendableMessages(null)) { Close close = new Close(); ErrorCondition localError; if (_connectionEndpoint == null) { localError = _condition; } else { localError = _connectionEndpoint.getCondition(); } if(localError.getCondition() != null) { close.setError(localError); } _isCloseSent = true; writeFrame(0, close, null, null); if (_connectionEndpoint != null) { _connectionEndpoint.clearModified(); } } } } protected void writeFrame(int channel, FrameBody frameBody, ByteBuffer payload, Runnable onPayloadTooLarge) { _frameWriter.writeFrame(channel, frameBody, payload, onPayloadTooLarge); } //================================================================================================================== @Override protected ConnectionImpl getConnectionImpl() { return _connectionEndpoint; } @Override void postFinal() {} @Override void doFree() { } //================================================================================================================== // handle incoming amqp data @Override public void handleOpen(Open open, Binary payload, Integer channel) { setRemoteState(EndpointState.ACTIVE); if(_connectionEndpoint != null) { _connectionEndpoint.handleOpen(open); } else { _open = open; } if(open.getMaxFrameSize().longValue() > 0) { _remoteMaxFrameSize = (int) open.getMaxFrameSize().longValue(); _frameWriter.setMaxFrameSize(_remoteMaxFrameSize); } if (open.getChannelMax().longValue() > 0) { _remoteChannelMax = (int) open.getChannelMax().longValue(); } if (open.getIdleTimeOut() != null && open.getIdleTimeOut().longValue() > 0) { _remoteIdleTimeout = open.getIdleTimeOut().intValue(); } } @Override public void handleBegin(Begin begin, Binary payload, Integer channel) { // TODO - check channel < max_channel TransportSession transportSession = _remoteSessions.get(channel); if(transportSession != null) { // TODO - fail due to begin on begun session } else { SessionImpl session; if(begin.getRemoteChannel() == null) { session = _connectionEndpoint.session(); transportSession = getTransportState(session); } else { // TODO check null transportSession = _localSessions.get(begin.getRemoteChannel().intValue()); if (transportSession == null) { throw new NullPointerException("uncorrelated channel: " + begin.getRemoteChannel()); } session = transportSession.getSession(); } transportSession.setRemoteChannel(channel); session.setRemoteState(EndpointState.ACTIVE); transportSession.setNextIncomingId(begin.getNextOutgoingId()); _remoteSessions.put(channel, transportSession); _connectionEndpoint.put(Event.Type.SESSION_REMOTE_OPEN, session); } } @Override public void handleAttach(Attach attach, Binary payload, Integer channel) { TransportSession transportSession = _remoteSessions.get(channel); if(transportSession == null) { // TODO - fail due to attach on non-begun session } else { SessionImpl session = transportSession.getSession(); final UnsignedInteger handle = attach.getHandle(); if (handle.compareTo(transportSession.getHandleMax()) > 0) { // The handle-max value is the highest handle value that can be used on the session. A peer MUST // NOT attempt to attach a link using a handle value outside the range that its partner can handle. // A peer that receives a handle outside the supported range MUST close the connection with the // framing-error error-code. ErrorCondition condition = new ErrorCondition(ConnectionError.FRAMING_ERROR, "handle-max exceeded"); _connectionEndpoint.setCondition(condition); _connectionEndpoint.setLocalState(EndpointState.CLOSED); if (!_isCloseSent) { Close close = new Close(); close.setError(condition); _isCloseSent = true; writeFrame(0, close, null, null); } close_tail(); return; } TransportLink transportLink = transportSession.getLinkFromRemoteHandle(handle); LinkImpl link = null; if(transportLink != null) { // TODO - fail - attempt attach on a handle which is in use } else { transportLink = transportSession.resolveHalfOpenLink(attach.getName()); if(transportLink == null) { link = (attach.getRole() == Role.RECEIVER) ? session.sender(attach.getName()) : session.receiver(attach.getName()); transportLink = getTransportState(link); } else { link = transportLink.getLink(); } if(attach.getRole() == Role.SENDER) { transportLink.setDeliveryCount(attach.getInitialDeliveryCount()); } link.setRemoteState(EndpointState.ACTIVE); link.setRemoteSource(attach.getSource()); link.setRemoteTarget(attach.getTarget()); link.setRemoteReceiverSettleMode(attach.getRcvSettleMode()); link.setRemoteSenderSettleMode(attach.getSndSettleMode()); transportLink.setName(attach.getName()); transportLink.setRemoteHandle(handle); transportSession.addLinkRemoteHandle(transportLink, handle); } _connectionEndpoint.put(Event.Type.LINK_REMOTE_OPEN, link); } } @Override public void handleFlow(Flow flow, Binary payload, Integer channel) { TransportSession transportSession = _remoteSessions.get(channel); if(transportSession == null) { // TODO - fail due to attach on non-begun session } else { transportSession.handleFlow(flow); } } @Override public void handleTransfer(Transfer transfer, Binary payload, Integer channel) { // TODO - check channel < max_channel TransportSession transportSession = _remoteSessions.get(channel); if(transportSession != null) { transportSession.handleTransfer(transfer, payload); } else { // TODO - fail due to begin on begun session } } @Override public void handleDisposition(Disposition disposition, Binary payload, Integer channel) { TransportSession transportSession = _remoteSessions.get(channel); if(transportSession == null) { // TODO - fail due to attach on non-begun session } else { transportSession.handleDisposition(disposition); } } @Override public void handleDetach(Detach detach, Binary payload, Integer channel) { TransportSession transportSession = _remoteSessions.get(channel); if(transportSession == null) { // TODO - fail due to attach on non-begun session } else { TransportLink transportLink = transportSession.getLinkFromRemoteHandle(detach.getHandle()); if(transportLink != null) { LinkImpl link = transportLink.getLink(); transportLink.receivedDetach(); transportSession.freeRemoteHandle(transportLink.getRemoteHandle()); if (detach.getClosed()) { _connectionEndpoint.put(Event.Type.LINK_REMOTE_CLOSE, link); } else { _connectionEndpoint.put(Event.Type.LINK_REMOTE_DETACH, link); } transportLink.clearRemoteHandle(); link.setRemoteState(EndpointState.CLOSED); if(detach.getError() != null) { link.getRemoteCondition().copyFrom(detach.getError()); } } else { // TODO - fail - attempt attach on a handle which is in use } } } @Override public void handleEnd(End end, Binary payload, Integer channel) { TransportSession transportSession = _remoteSessions.get(channel); if(transportSession == null) { // TODO - fail due to attach on non-begun session } else { _remoteSessions.remove(channel); transportSession.receivedEnd(); transportSession.unsetRemoteChannel(); SessionImpl session = transportSession.getSession(); session.setRemoteState(EndpointState.CLOSED); ErrorCondition errorCondition = end.getError(); if(errorCondition != null) { session.getRemoteCondition().copyFrom(errorCondition); } _connectionEndpoint.put(Event.Type.SESSION_REMOTE_CLOSE, session); } } @Override public void handleClose(Close close, Binary payload, Integer channel) { _closeReceived = true; _remoteIdleTimeout = 0; setRemoteState(EndpointState.CLOSED); if(_connectionEndpoint != null) { _connectionEndpoint.setRemoteState(EndpointState.CLOSED); if(close.getError() != null) { _connectionEndpoint.getRemoteCondition().copyFrom(close.getError()); } _connectionEndpoint.put(Event.Type.CONNECTION_REMOTE_CLOSE, _connectionEndpoint); } } @Override public boolean handleFrame(TransportFrame frame) { if (!isHandlingFrames()) { throw new IllegalStateException("Transport cannot accept frame: " + frame); } log(INCOMING, frame); ProtocolTracer tracer = _protocolTracer.get(); if( tracer != null ) { tracer.receivedFrame(frame); } frame.getBody().invoke(this,frame.getPayload(), frame.getChannel()); return _closeReceived; } void put(Event.Type type, Object context) { if (_connectionEndpoint != null) { _connectionEndpoint.put(type, context); } } private void maybePostClosed() { if (postedHeadClosed && postedTailClosed) { put(Event.Type.TRANSPORT_CLOSED, this); } } @Override public void closed(TransportException error) { if (!_closeReceived || error != null) { if (error == null) { _condition = new ErrorCondition(ConnectionError.FRAMING_ERROR, "connection aborted"); } else { _condition = new ErrorCondition(ConnectionError.FRAMING_ERROR, error.toString()); } _head_closed = true; } if (_condition != null && !postedTransportError) { put(Event.Type.TRANSPORT_ERROR, this); postedTransportError = true; } if (!postedTailClosed) { put(Event.Type.TRANSPORT_TAIL_CLOSED, this); postedTailClosed = true; maybePostClosed(); } } @Override public boolean isHandlingFrames() { return _connectionEndpoint != null || getRemoteState() == EndpointState.UNINITIALIZED; } @Override public ProtocolTracer getProtocolTracer() { return _protocolTracer.get(); } @Override public void setProtocolTracer(ProtocolTracer protocolTracer) { this._protocolTracer.set(protocolTracer); } @Override public ByteBuffer getInputBuffer() { return tail(); } @Override public TransportResult processInput() { try { process(); return TransportResultFactory.ok(); } catch (TransportException e) { return TransportResultFactory.error(e); } } @Override public ByteBuffer getOutputBuffer() { pending(); return head(); } @Override public void outputConsumed() { pop(_outputProcessor.head().position()); } @Override public int capacity() { init(); return _inputProcessor.capacity(); } @Override public ByteBuffer tail() { init(); return _inputProcessor.tail(); } @Override public void process() throws TransportException { _processingStarted = true; try { init(); int beforePosition = _inputProcessor.position(); _inputProcessor.process(); _bytesInput += beforePosition - _inputProcessor.position(); } catch (TransportException e) { _head_closed = true; throw e; } } @Override public void close_tail() { init(); _inputProcessor.close_tail(); } @Override public int pending() { init(); return _outputProcessor.pending(); } @Override public ByteBuffer head() { init(); return _outputProcessor.head(); } @Override public void pop(int bytes) { init(); _outputProcessor.pop(bytes); _bytesOutput += bytes; int p = pending(); if (p < 0 && !postedHeadClosed) { put(Event.Type.TRANSPORT_HEAD_CLOSED, this); postedHeadClosed = true; maybePostClosed(); } } @Override public void setIdleTimeout(int timeout) { _localIdleTimeout = timeout; } @Override public int getIdleTimeout() { return _localIdleTimeout; } @Override public int getRemoteIdleTimeout() { return _remoteIdleTimeout; } @Override public long tick(long now) { long timeout = 0; if (_localIdleTimeout > 0) { if (_localIdleDeadline == 0 || _lastBytesInput != _bytesInput) { _localIdleDeadline = now + _localIdleTimeout; _lastBytesInput = _bytesInput; } else if (_localIdleDeadline <= now) { _localIdleDeadline = now + _localIdleTimeout; if (_connectionEndpoint != null && _connectionEndpoint.getLocalState() != EndpointState.CLOSED) { ErrorCondition condition = new ErrorCondition(Symbol.getSymbol("amqp:resource-limit-exceeded"), "local-idle-timeout expired"); _connectionEndpoint.setCondition(condition); _connectionEndpoint.setLocalState(EndpointState.CLOSED); if (!_isOpenSent) { if ((_sasl != null) && (!_sasl.isDone())) { _sasl.fail(); } Open open = new Open(); _isOpenSent = true; writeFrame(0, open, null, null); } if (!_isCloseSent) { Close close = new Close(); close.setError(condition); _isCloseSent = true; writeFrame(0, close, null, null); } close_tail(); } } timeout = _localIdleDeadline; } if (_remoteIdleTimeout != 0 && !_isCloseSent) { if (_remoteIdleDeadline == 0 || _lastBytesOutput != _bytesOutput) { _remoteIdleDeadline = now + (_remoteIdleTimeout / 2); _lastBytesOutput = _bytesOutput; } else if (_remoteIdleDeadline <= now) { _remoteIdleDeadline = now + (_remoteIdleTimeout / 2); if (pending() == 0) { writeFrame(0, null, null, null); _lastBytesOutput += pending(); } } timeout = Math.min(timeout == 0 ? _remoteIdleDeadline : timeout, _remoteIdleDeadline); } return timeout; } @Override public long getFramesOutput() { return _frameWriter.getFramesOutput(); } @Override public long getFramesInput() { return _frameParser.getFramesInput(); } @Override public void close_head() { _outputProcessor.close_head(); } @Override public boolean isClosed() { int p = pending(); int c = capacity(); return p == END_OF_STREAM && c == END_OF_STREAM; } @Override public String toString() { return "TransportImpl [_connectionEndpoint=" + _connectionEndpoint + ", " + super.toString() + "]"; } private static class PartialTransfer implements Runnable { private final Transfer _transfer; public PartialTransfer(Transfer transfer) { _transfer = transfer; } @Override public void run() { _transfer.setMore(true); } } /** * Override the default frame handler. Must be called before the transport starts being used * (e.g. {@link #getInputBuffer()}, {@link #getOutputBuffer()}, {@link #ssl(SslDomain)} etc). */ public void setFrameHandler(FrameHandler frameHandler) { _frameHandler = frameHandler; } static String INCOMING = "<-"; static String OUTGOING = "->"; void log(String event, TransportFrame frame) { if (isTraceFramesEnabled()) { StringBuilder msg = new StringBuilder(); msg.append("[").append(System.identityHashCode(this)).append(":") .append(frame.getChannel()).append("]"); msg.append(" ").append(event).append(" ").append(frame.getBody()); Binary bin = frame.getPayload(); if (bin != null) { msg.append(" (").append(bin.getLength()).append(") "); msg.append(StringUtils.toQuotedString(bin, TRACE_FRAME_PAYLOAD_LENGTH, true)); } System.out.println(msg.toString()); } } boolean isTraceFramesEnabled() { return (_levels & TRACE_FRM) != 0; } @Override void localOpen() {} @Override void localClose() {} public void setSelectable(Selectable selectable) { _selectable = selectable; } public Selectable getSelectable() { return _selectable; } public void setReactor(Reactor reactor) { _reactor = reactor; } public Reactor getReactor() { return _reactor; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/TransportDelivery.java0000664000000000000000000000332012562450203030036 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.amqp.UnsignedInteger; public class TransportDelivery { private UnsignedInteger _deliveryId; private DeliveryImpl _delivery; private TransportLink _transportLink; private int _sessionSize = 1; TransportDelivery(UnsignedInteger currentDeliveryId, DeliveryImpl delivery, TransportLink transportLink) { _deliveryId = currentDeliveryId; _delivery = delivery; _transportLink = transportLink; } public UnsignedInteger getDeliveryId() { return _deliveryId; } public TransportLink getTransportLink() { return _transportLink; } void incrementSessionSize() { _sessionSize++; } int getSessionSize() { return _sessionSize; } void settled() { _transportLink.settled(this); _delivery.updateWork(); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/StringUtils.java0000664000000000000000000000527112562450203026634 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.amqp.Binary; public class StringUtils { /** * Converts the Binary to a quoted string. * * @param bin the Binary to convert * @param stringLength the maximum length of stringified content (excluding the quotes, and truncated indicator) * @param appendIfTruncated appends "...(truncated)" if not all of the payload is present in the string * @return the converted string */ public static String toQuotedString(final Binary bin,final int stringLength,final boolean appendIfTruncated) { if(bin == null) { return "\"\""; } final byte[] binData = bin.getArray(); final int binLength = bin.getLength(); final int offset = bin.getArrayOffset(); StringBuilder str = new StringBuilder(); str.append("\""); int size = 0; boolean truncated = false; for (int i = 0; i < binLength; i++) { byte c = binData[offset + i]; if (c > 31 && c < 127 && c != '\\') { if (size + 1 <= stringLength) { size += 1; str.append((char) c); } else { truncated = true; break; } } else { if (size + 4 <= stringLength) { size += 4; str.append(String.format("\\x%02x", c)); } else { truncated = true; break; } } } str.append("\""); if (truncated && appendIfTruncated) { str.append("...(truncated)"); } return str.toString(); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SessionImpl.java0000664000000000000000000001650312562450203026612 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.util.ArrayList; import java.util.EnumSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Event; import org.apache.qpid.proton.engine.ProtonJSession; import org.apache.qpid.proton.engine.Session; public class SessionImpl extends EndpointImpl implements ProtonJSession { private final ConnectionImpl _connection; private Map _senders = new LinkedHashMap(); private Map _receivers = new LinkedHashMap(); private List _oldLinksToFree = new ArrayList(); private TransportSession _transportSession; private int _incomingCapacity = 1024*1024; private int _incomingBytes = 0; private int _outgoingBytes = 0; private int _incomingDeliveries = 0; private int _outgoingDeliveries = 0; private long _outgoingWindow = Integer.MAX_VALUE; private LinkNode _node; SessionImpl(ConnectionImpl connection) { _connection = connection; _connection.incref(); _node = _connection.addSessionEndpoint(this); _connection.put(Event.Type.SESSION_INIT, this); } @Override public SenderImpl sender(String name) { SenderImpl sender = _senders.get(name); if(sender == null) { sender = new SenderImpl(this, name); _senders.put(name, sender); } else { if(sender.getLocalState() == EndpointState.CLOSED && sender.getRemoteState() == EndpointState.CLOSED) { _oldLinksToFree.add(sender); sender = new SenderImpl(this, name); _senders.put(name, sender); } } return sender; } @Override public ReceiverImpl receiver(String name) { ReceiverImpl receiver = _receivers.get(name); if(receiver == null) { receiver = new ReceiverImpl(this, name); _receivers.put(name, receiver); } else { if(receiver.getLocalState() == EndpointState.CLOSED && receiver.getRemoteState() == EndpointState.CLOSED) { _oldLinksToFree.add(receiver); receiver = new ReceiverImpl(this, name); _receivers.put(name, receiver); } } return receiver; } @Override public Session next(EnumSet local, EnumSet remote) { LinkNode.Query query = new EndpointImplQuery(local, remote); LinkNode sessionNode = _node.next(query); return sessionNode == null ? null : sessionNode.getValue(); } @Override protected ConnectionImpl getConnectionImpl() { return _connection; } @Override public ConnectionImpl getConnection() { return getConnectionImpl(); } @Override void postFinal() { _connection.put(Event.Type.SESSION_FINAL, this); _connection.decref(); } @Override void doFree() { _connection.freeSession(this); _connection.removeSessionEndpoint(_node); _node = null; List senders = new ArrayList(_senders.values()); for(SenderImpl sender : senders) { sender.free(); } _senders.clear(); List receivers = new ArrayList(_receivers.values()); for(ReceiverImpl receiver : receivers) { receiver.free(); } _receivers.clear(); List links = new ArrayList(_oldLinksToFree); for(LinkImpl link : links) { link.free(); } } void modifyEndpoints() { for (SenderImpl snd : _senders.values()) { snd.modifyEndpoints(); } for (ReceiverImpl rcv : _receivers.values()) { rcv.modifyEndpoints(); } modified(); } TransportSession getTransportSession() { return _transportSession; } void setTransportSession(TransportSession transportSession) { _transportSession = transportSession; } void setNode(LinkNode node) { _node = node; } void freeSender(SenderImpl sender) { String name = sender.getName(); SenderImpl existing = _senders.get(name); if (sender.equals(existing)) { _senders.remove(name); } else { _oldLinksToFree.remove(sender); } } void freeReceiver(ReceiverImpl receiver) { String name = receiver.getName(); ReceiverImpl existing = _receivers.get(name); if (receiver.equals(existing)) { _receivers.remove(name); } else { _oldLinksToFree.remove(receiver); } } @Override public int getIncomingCapacity() { return _incomingCapacity; } @Override public void setIncomingCapacity(int capacity) { _incomingCapacity = capacity; } @Override public int getIncomingBytes() { return _incomingBytes; } void incrementIncomingBytes(int delta) { _incomingBytes += delta; } @Override public int getOutgoingBytes() { return _outgoingBytes; } void incrementOutgoingBytes(int delta) { _outgoingBytes += delta; } void incrementIncomingDeliveries(int delta) { _incomingDeliveries += delta; } int getOutgoingDeliveries() { return _outgoingDeliveries; } void incrementOutgoingDeliveries(int delta) { _outgoingDeliveries += delta; } @Override void localOpen() { getConnectionImpl().put(Event.Type.SESSION_LOCAL_OPEN, this); } @Override void localClose() { getConnectionImpl().put(Event.Type.SESSION_LOCAL_CLOSE, this); } @Override public void setOutgoingWindow(long outgoingWindow) { if(outgoingWindow < 0 || outgoingWindow > 0xFFFFFFFFL) { throw new IllegalArgumentException("Value '" + outgoingWindow + "' must be in the" + " range [0 - 2^32-1]"); } _outgoingWindow = outgoingWindow; } @Override public long getOutgoingWindow() { return _outgoingWindow; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SenderImpl.java0000664000000000000000000000576512562450203026417 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.util.Iterator; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Sender; public class SenderImpl extends LinkImpl implements Sender { private int _offered; private TransportSender _transportLink; SenderImpl(SessionImpl session, String name) { super(session, name); } public void offer(final int credits) { _offered = credits; } public int send(final byte[] bytes, int offset, int length) { if( getLocalState() == EndpointState.CLOSED ) { throw new IllegalStateException("send not allowed after the sender is closed."); } DeliveryImpl current = current(); if(current == null || current.getLink() != this) { throw new IllegalArgumentException();//TODO. } int sent = current.send(bytes, offset, length); if (sent > 0) { getSession().incrementOutgoingBytes(sent); } return sent; } public void abort() { //TODO. } @Override void doFree() { getSession().freeSender(this); super.doFree(); } @Override public boolean advance() { DeliveryImpl delivery = current(); if (delivery != null) { delivery.setComplete(); } boolean advance = super.advance(); if(advance && _offered > 0) { _offered--; } if(advance) { decrementCredit(); delivery.addToTransportWorkList(); getSession().incrementOutgoingDeliveries(1); } return advance; } boolean hasOfferedCredits() { return _offered > 0; } @Override TransportSender getTransportLink() { return _transportLink; } void setTransportLink(TransportSender transportLink) { _transportLink = transportLink; } @Override public void setCredit(int credit) { super.setCredit(credit); /* while(getQueued()>0 && getCredit()>0) { advance(); }*/ } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslSniffer.java0000664000000000000000000000312412562450203026557 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; /** * SaslSniffer * */ class SaslSniffer extends HandshakeSniffingTransportWrapper { SaslSniffer(TransportWrapper sasl, TransportWrapper other) { super(sasl, other); } protected int bufferSize() { return AmqpHeader.SASL_HEADER.length; } protected void makeDetermination(byte[] bytes) { if (bytes.length < bufferSize()) { throw new IllegalArgumentException("insufficient bytes"); } for (int i = 0; i < AmqpHeader.SASL_HEADER.length; i++) { if (bytes[i] != AmqpHeader.SASL_HEADER[i]) { _selectedTransportWrapper = _wrapper2; return; } } _selectedTransportWrapper = _wrapper1; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslImpl.java0000664000000000000000000005041112562450203026065 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import static org.apache.qpid.proton.engine.impl.ByteBufferUtils.newWriteableBuffer; import static org.apache.qpid.proton.engine.impl.ByteBufferUtils.pourAll; import static org.apache.qpid.proton.engine.impl.ByteBufferUtils.pourBufferToArray; import java.nio.ByteBuffer; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.qpid.proton.ProtonUnsupportedOperationException; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.security.SaslChallenge; import org.apache.qpid.proton.amqp.security.SaslCode; import org.apache.qpid.proton.amqp.security.SaslFrameBody; import org.apache.qpid.proton.amqp.security.SaslInit; import org.apache.qpid.proton.amqp.security.SaslMechanisms; import org.apache.qpid.proton.amqp.security.SaslResponse; import org.apache.qpid.proton.codec.AMQPDefinedTypes; import org.apache.qpid.proton.codec.DecoderImpl; import org.apache.qpid.proton.codec.EncoderImpl; import org.apache.qpid.proton.engine.Sasl; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; public class SaslImpl implements Sasl, SaslFrameBody.SaslFrameBodyHandler, SaslFrameHandler { private static final Logger _logger = Logger.getLogger(SaslImpl.class.getName()); public static final byte SASL_FRAME_TYPE = (byte) 1; private final DecoderImpl _decoder = new DecoderImpl(); private final EncoderImpl _encoder = new EncoderImpl(_decoder); private final TransportImpl _transport; private boolean _tail_closed = false; private final ByteBuffer _inputBuffer; private boolean _head_closed = false; private final ByteBuffer _outputBuffer; private final FrameWriter _frameWriter; private ByteBuffer _pending; private boolean _headerWritten; private Binary _challengeResponse; private SaslFrameParser _frameParser; private boolean _initReceived; private boolean _mechanismsSent; private boolean _initSent; enum Role { CLIENT, SERVER }; private SaslOutcome _outcome = SaslOutcome.PN_SASL_NONE; private SaslState _state = SaslState.PN_SASL_IDLE; private String _hostname; private boolean _done; private Symbol[] _mechanisms; private Symbol _chosenMechanism; private Role _role; private boolean _allowSkip = true; /** * @param maxFrameSize the size of the input and output buffers * returned by {@link SaslTransportWrapper#getInputBuffer()} and * {@link SaslTransportWrapper#getOutputBuffer()}. */ SaslImpl(TransportImpl transport, int maxFrameSize) { _transport = transport; _inputBuffer = newWriteableBuffer(maxFrameSize); _outputBuffer = newWriteableBuffer(maxFrameSize); AMQPDefinedTypes.registerAllTypes(_decoder,_encoder); _frameParser = new SaslFrameParser(this, _decoder); _frameWriter = new FrameWriter(_encoder, maxFrameSize, FrameWriter.SASL_FRAME_TYPE, null, _transport); } void fail() { if (_role == null || _role == Role.CLIENT) { _role = Role.CLIENT; _initSent = true; } else { _initReceived = true; } _done = true; _outcome = SaslOutcome.PN_SASL_SYS; } @Override public boolean isDone() { return _done && (_role==Role.CLIENT || _initReceived); } private void writeSaslOutput() { process(); _frameWriter.readBytes(_outputBuffer); if(_logger.isLoggable(Level.FINER)) { _logger.log(Level.FINER, "Finished writing SASL output. Output Buffer : " + _outputBuffer); } } private void process() { processHeader(); if(_role == Role.SERVER) { if(!_mechanismsSent && _mechanisms != null) { SaslMechanisms mechanisms = new SaslMechanisms(); mechanisms.setSaslServerMechanisms(_mechanisms); writeFrame(mechanisms); _mechanismsSent = true; _state = SaslState.PN_SASL_STEP; } if(getState() == SaslState.PN_SASL_STEP && getChallengeResponse() != null) { SaslChallenge challenge = new SaslChallenge(); challenge.setChallenge(getChallengeResponse()); writeFrame(challenge); setChallengeResponse(null); } if(_done) { org.apache.qpid.proton.amqp.security.SaslOutcome outcome = new org.apache.qpid.proton.amqp.security.SaslOutcome(); outcome.setCode(SaslCode.values()[_outcome.getCode()]); writeFrame(outcome); } } else if(_role == Role.CLIENT) { if(getState() == SaslState.PN_SASL_IDLE && _chosenMechanism != null) { processInit(); _state = SaslState.PN_SASL_STEP; //HACK: if we received an outcome before //we sent our init, change the state now if(_outcome != SaslOutcome.PN_SASL_NONE) { _state = classifyStateFromOutcome(_outcome); } } if(getState() == SaslState.PN_SASL_STEP && getChallengeResponse() != null) { processResponse(); } } } private void writeFrame(SaslFrameBody frameBody) { _frameWriter.writeFrame(frameBody); } @Override final public int recv(byte[] bytes, int offset, int size) { if(_pending == null) { return -1; } final int written = pourBufferToArray(_pending, bytes, offset, size); if(!_pending.hasRemaining()) { _pending = null; } return written; } @Override final public int send(byte[] bytes, int offset, int size) { byte[] data = new byte[size]; System.arraycopy(bytes, offset, data, 0, size); setChallengeResponse(new Binary(data)); return size; } final int processHeader() { if(!_headerWritten) { _frameWriter.writeHeader(AmqpHeader.SASL_HEADER); _headerWritten = true; return AmqpHeader.SASL_HEADER.length; } else { return 0; } } @Override public int pending() { return _pending == null ? 0 : _pending.remaining(); } void setPending(ByteBuffer pending) { _pending = pending; } @Override public SaslState getState() { return _state; } final Binary getChallengeResponse() { return _challengeResponse; } final void setChallengeResponse(Binary challengeResponse) { _challengeResponse = challengeResponse; } @Override public void setMechanisms(String... mechanisms) { if(mechanisms != null) { _mechanisms = new Symbol[mechanisms.length]; for(int i = 0; i < mechanisms.length; i++) { _mechanisms[i] = Symbol.valueOf(mechanisms[i]); } } if(_role == Role.CLIENT) { assert mechanisms != null; assert mechanisms.length == 1; _chosenMechanism = Symbol.valueOf(mechanisms[0]); } } @Override public String[] getRemoteMechanisms() { if(_role == Role.SERVER) { return _chosenMechanism == null ? new String[0] : new String[] { _chosenMechanism.toString() }; } else if(_role == Role.CLIENT) { if(_mechanisms == null) { return new String[0]; } else { String[] remoteMechanisms = new String[_mechanisms.length]; for(int i = 0; i < _mechanisms.length; i++) { remoteMechanisms[i] = _mechanisms[i].toString(); } return remoteMechanisms; } } else { throw new IllegalStateException(); } } public void setMechanism(Symbol mechanism) { _chosenMechanism = mechanism; } public Symbol getChosenMechanism() { return _chosenMechanism; } public void setResponse(Binary initialResponse) { setPending(initialResponse.asByteBuffer()); } @Override public void handle(SaslFrameBody frameBody, Binary payload) { frameBody.invoke(this, payload, null); } @Override public void handleInit(SaslInit saslInit, Binary payload, Void context) { if(_role == null) { server(); } checkRole(Role.SERVER); _hostname = saslInit.getHostname(); _chosenMechanism = saslInit.getMechanism(); _initReceived = true; if(saslInit.getInitialResponse() != null) { setPending(saslInit.getInitialResponse().asByteBuffer()); } } @Override public void handleResponse(SaslResponse saslResponse, Binary payload, Void context) { checkRole(Role.SERVER); setPending(saslResponse.getResponse() == null ? null : saslResponse.getResponse().asByteBuffer()); } @Override public void done(SaslOutcome outcome) { checkRole(Role.SERVER); _outcome = outcome; _done = true; _state = classifyStateFromOutcome(outcome); _logger.fine("SASL negotiation done: " + this); } private void checkRole(Role role) { if(role != _role) { throw new IllegalStateException("Role is " + _role + " but should be " + role); } } @Override public void handleMechanisms(SaslMechanisms saslMechanisms, Binary payload, Void context) { if(_role == null) { client(); } checkRole(Role.CLIENT); _mechanisms = saslMechanisms.getSaslServerMechanisms(); } @Override public void handleChallenge(SaslChallenge saslChallenge, Binary payload, Void context) { checkRole(Role.CLIENT); setPending(saslChallenge.getChallenge() == null ? null : saslChallenge.getChallenge().asByteBuffer()); } @Override public void handleOutcome(org.apache.qpid.proton.amqp.security.SaslOutcome saslOutcome, Binary payload, Void context) { checkRole(Role.CLIENT); for(SaslOutcome outcome : SaslOutcome.values()) { if(outcome.getCode() == saslOutcome.getCode().ordinal()) { _outcome = outcome; if (_state != SaslState.PN_SASL_IDLE) { _state = classifyStateFromOutcome(outcome); } break; } } _done = true; if(_logger.isLoggable(Level.FINE)) { _logger.fine("Handled outcome: " + this); } } private SaslState classifyStateFromOutcome(SaslOutcome outcome) { return outcome == SaslOutcome.PN_SASL_OK ? SaslState.PN_SASL_PASS : SaslState.PN_SASL_FAIL; } private void processResponse() { SaslResponse response = new SaslResponse(); response.setResponse(getChallengeResponse()); setChallengeResponse(null); writeFrame(response); } private void processInit() { SaslInit init = new SaslInit(); init.setHostname(_hostname); init.setMechanism(_chosenMechanism); if(getChallengeResponse() != null) { init.setInitialResponse(getChallengeResponse()); setChallengeResponse(null); } _initSent = true; writeFrame(init); } @Override public void plain(String username, String password) { client(); _chosenMechanism = Symbol.valueOf("PLAIN"); byte[] usernameBytes = username.getBytes(); byte[] passwordBytes = password.getBytes(); byte[] data = new byte[usernameBytes.length+passwordBytes.length+2]; System.arraycopy(usernameBytes, 0, data, 1, usernameBytes.length); System.arraycopy(passwordBytes, 0, data, 2+usernameBytes.length, passwordBytes.length); setChallengeResponse(new Binary(data)); } @Override public SaslOutcome getOutcome() { return _outcome; } @Override public void client() { _role = Role.CLIENT; if(_mechanisms != null) { assert _mechanisms.length == 1; _chosenMechanism = _mechanisms[0]; } } @Override public void server() { _role = Role.SERVER; } @Override public void allowSkip(boolean allowSkip) { _allowSkip = allowSkip; } public TransportWrapper wrap(final TransportInput input, final TransportOutput output) { return new SaslSniffer(new SaslTransportWrapper(input, output), new PlainTransportWrapper(output, input)) { protected boolean isDeterminationMade() { if (_role == Role.SERVER && _allowSkip) { return super.isDeterminationMade(); } else { _selectedTransportWrapper = _wrapper1; return true; } } }; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder .append("SaslImpl [_outcome=").append(_outcome) .append(", state=").append(_state) .append(", done=").append(_done) .append(", role=").append(_role) .append("]"); return builder.toString(); } private class SaslTransportWrapper implements TransportWrapper { private final TransportInput _underlyingInput; private final TransportOutput _underlyingOutput; private boolean _outputComplete; private final ByteBuffer _head; private SaslTransportWrapper(TransportInput input, TransportOutput output) { _underlyingInput = input; _underlyingOutput = output; _head = _outputBuffer.asReadOnlyBuffer(); _head.limit(0); } private void fillOutputBuffer() { if(isOutputInSaslMode()) { SaslImpl.this.writeSaslOutput(); if(_done) { _outputComplete = true; } } } /** * TODO rationalise this method with respect to the other similar checks of _role/_initReceived etc * @see SaslImpl#isDone() */ private boolean isInputInSaslMode() { return _role == null || (_role == Role.CLIENT && !_done) ||(_role == Role.SERVER && (!_initReceived || !_done)); } private boolean isOutputInSaslMode() { return _role == null || (_role == Role.CLIENT && (!_done || !_initSent)) || (_role == Role.SERVER && !_outputComplete); } @Override public int capacity() { if (_tail_closed) return Transport.END_OF_STREAM; if (isInputInSaslMode()) { return _inputBuffer.remaining(); } else { return _underlyingInput.capacity(); } } @Override public int position() { if (_tail_closed) return Transport.END_OF_STREAM; if (isInputInSaslMode()) { return _inputBuffer.position(); } else { return _underlyingInput.position(); } } @Override public ByteBuffer tail() { if (!isInputInSaslMode()) { return _underlyingInput.tail(); } return _inputBuffer; } @Override public void process() throws TransportException { _inputBuffer.flip(); try { reallyProcessInput(); } finally { _inputBuffer.compact(); } } @Override public void close_tail() { _tail_closed = true; if (isInputInSaslMode()) { _head_closed = true; _underlyingInput.close_tail(); } else { _underlyingInput.close_tail(); } } private void reallyProcessInput() throws TransportException { if(isInputInSaslMode()) { if(_logger.isLoggable(Level.FINER)) { _logger.log(Level.FINER, SaslImpl.this + " about to call input."); } _frameParser.input(_inputBuffer); } if(!isInputInSaslMode()) { if(_logger.isLoggable(Level.FINER)) { _logger.log(Level.FINER, SaslImpl.this + " about to call plain input"); } if (_inputBuffer.hasRemaining()) { int bytes = pourAll(_inputBuffer, _underlyingInput); if (bytes == Transport.END_OF_STREAM) { _tail_closed = true; } _underlyingInput.process(); } else { _underlyingInput.process(); } } } @Override public int pending() { if (isOutputInSaslMode() || _outputBuffer.position() != 0) { fillOutputBuffer(); _head.limit(_outputBuffer.position()); if (_head_closed && _outputBuffer.position() == 0) { return Transport.END_OF_STREAM; } else { return _outputBuffer.position(); } } else { return _underlyingOutput.pending(); } } @Override public ByteBuffer head() { if (isOutputInSaslMode() || _outputBuffer.position() != 0) { pending(); return _head; } else { return _underlyingOutput.head(); } } @Override public void pop(int bytes) { if (isOutputInSaslMode() || _outputBuffer.position() != 0) { _outputBuffer.flip(); _outputBuffer.position(bytes); _outputBuffer.compact(); _head.position(0); _head.limit(_outputBuffer.position()); } else { _underlyingOutput.pop(bytes); } } @Override public void close_head() { _underlyingOutput.close_head(); } } @Override public String getHostname() { if(_role != null) { checkRole(Role.SERVER); } return _hostname; } @Override public void setRemoteHostname(String hostname) { if(_role != null) { checkRole(Role.CLIENT); } _hostname = hostname; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslFrameParser.java0000664000000000000000000002233512562450203027377 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.nio.ByteBuffer; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.security.SaslFrameBody; import org.apache.qpid.proton.codec.ByteBufferDecoder; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.engine.TransportException; class SaslFrameParser { private SaslFrameHandler _sasl; enum State { SIZE_0, SIZE_1, SIZE_2, SIZE_3, PRE_PARSE, BUFFERING, PARSING, ERROR } private State _state = State.SIZE_0; private int _size; private ByteBuffer _buffer; private int _ignore = 8; private final ByteBufferDecoder _decoder; SaslFrameParser(SaslFrameHandler sasl, ByteBufferDecoder decoder) { _sasl = sasl; _decoder = decoder; } /** * Parse the provided SASL input and call my SASL frame handler with the result */ public void input(ByteBuffer input) throws TransportException { TransportException frameParsingError = null; int size = _size; State state = _state; ByteBuffer oldIn = null; // Note that we simply skip over the header rather than parsing it. if(_ignore != 0) { int bytesToEat = Math.min(_ignore, input.remaining()); input.position(input.position() + bytesToEat); _ignore -= bytesToEat; } while(input.hasRemaining() && state != State.ERROR && !_sasl.isDone()) { switch(state) { case SIZE_0: if(input.remaining() >= 4) { size = input.getInt(); state = State.PRE_PARSE; break; } else { size = (input.get() << 24) & 0xFF000000; if(!input.hasRemaining()) { state = State.SIZE_1; break; } } case SIZE_1: size |= (input.get() << 16) & 0xFF0000; if(!input.hasRemaining()) { state = State.SIZE_2; break; } case SIZE_2: size |= (input.get() << 8) & 0xFF00; if(!input.hasRemaining()) { state = State.SIZE_3; break; } case SIZE_3: size |= input.get() & 0xFF; state = State.PRE_PARSE; case PRE_PARSE: if(size < 8) { frameParsingError = new TransportException("specified frame size %d smaller than minimum frame header " + "size %d", _size, 8); state = State.ERROR; break; } if(input.remaining() < size-4) { _buffer = ByteBuffer.allocate(size-4); _buffer.put(input); state = State.BUFFERING; break; } case BUFFERING: if(_buffer != null) { if(input.remaining() < _buffer.remaining()) { _buffer.put(input); break; } else { ByteBuffer dup = input.duplicate(); dup.limit(dup.position()+_buffer.remaining()); input.position(input.position()+_buffer.remaining()); _buffer.put(dup); oldIn = input; _buffer.flip(); input = _buffer; state = State.PARSING; } } case PARSING: int dataOffset = (input.get() << 2) & 0x3FF; if(dataOffset < 8) { frameParsingError = new TransportException("specified frame data offset %d smaller than minimum frame header size %d", dataOffset, 8); state = State.ERROR; break; } else if(dataOffset > size) { frameParsingError = new TransportException("specified frame data offset %d larger than the frame size %d", dataOffset, _size); state = State.ERROR; break; } // type int type = input.get() & 0xFF; // SASL frame has no type-specific content in the frame header, so we skip next two bytes input.get(); input.get(); if(type != SaslImpl.SASL_FRAME_TYPE) { frameParsingError = new TransportException("unknown frame type: %d", type); state = State.ERROR; break; } if(dataOffset!=8) { input.position(input.position()+dataOffset-8); } // oldIn null iff not working on duplicated buffer if(oldIn == null) { oldIn = input; input = input.duplicate(); final int endPos = input.position() + size - dataOffset; input.limit(endPos); oldIn.position(endPos); } try { _decoder.setByteBuffer(input); Object val = _decoder.readObject(); Binary payload; if(input.hasRemaining()) { byte[] payloadBytes = new byte[input.remaining()]; input.get(payloadBytes); payload = new Binary(payloadBytes); } else { payload = null; } if(val instanceof SaslFrameBody) { SaslFrameBody frameBody = (SaslFrameBody) val; _sasl.handle(frameBody, payload); reset(); input = oldIn; oldIn = null; _buffer = null; state = State.SIZE_0; } else { state = State.ERROR; frameParsingError = new TransportException("Unexpected frame type encountered." + " Found a %s which does not implement %s", val == null ? "null" : val.getClass(), SaslFrameBody.class); } } catch (DecodeException ex) { state = State.ERROR; frameParsingError = new TransportException(ex); } break; case ERROR: // do nothing } } _state = state; _size = size; if(_state == State.ERROR) { if(frameParsingError != null) { throw frameParsingError; } else { throw new TransportException("Unable to parse, probably because of a previous error"); } } } private void reset() { _size = 0; _state = State.SIZE_0; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/SaslFrameHandler.java0000664000000000000000000000216612562450203027520 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.security.SaslFrameBody; /** * Used by {@link SaslFrameParser} to handle the frames it parses */ interface SaslFrameHandler { void handle(SaslFrameBody frameBody, Binary payload); boolean isDone(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/Ref.java0000664000000000000000000000207712562450203025062 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; /** * Ref * */ class Ref { T value; public Ref(T initial) { value = initial; } public T get() { return value; } public void set(T value) { this.value = value; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/RecordImpl.java0000664000000000000000000000263112562450203026402 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.engine.Record; import java.util.HashMap; import java.util.Map; /** * RecordImpl * */ public class RecordImpl implements Record { private Map values = new HashMap(); public void set(Object key, Class klass, T value) { values.put(key, value); } public T get(Object key, Class klass) { return klass.cast(values.get(key)); } public void clear() { values.clear(); } void copy(RecordImpl src) { values.putAll(src.values); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ReceiverImpl.java0000664000000000000000000000707212562450203026734 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.util.Iterator; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.engine.Receiver; public class ReceiverImpl extends LinkImpl implements Receiver { private boolean _drainFlagMode = true; @Override public boolean advance() { DeliveryImpl current = current(); if(current != null) { current.setDone(); } final boolean advance = super.advance(); if(advance) { decrementQueued(); decrementCredit(); getSession().incrementIncomingBytes(-current.pending()); getSession().incrementIncomingDeliveries(-1); if (getSession().getTransportSession().getIncomingWindowSize().equals(UnsignedInteger.ZERO)) { modified(); } } return advance; } private TransportReceiver _transportReceiver; private int _unsentCredits; ReceiverImpl(SessionImpl session, String name) { super(session, name); } public void flow(final int credits) { addCredit(credits); _unsentCredits += credits; modified(); if (!_drainFlagMode) { setDrain(false); _drainFlagMode = false; } } int clearUnsentCredits() { int credits = _unsentCredits; _unsentCredits = 0; return credits; } public int recv(final byte[] bytes, int offset, int size) { if (_current == null) { throw new IllegalStateException("no current delivery"); } int consumed = _current.recv(bytes, offset, size); if (consumed > 0) { getSession().incrementIncomingBytes(-consumed); if (getSession().getTransportSession().getIncomingWindowSize().equals(UnsignedInteger.ZERO)) { modified(); } } return consumed; } @Override void doFree() { getSession().freeReceiver(this); super.doFree(); } boolean hasIncoming() { return false; //TODO - Implement } void setTransportLink(TransportReceiver transportReceiver) { _transportReceiver = transportReceiver; } @Override TransportReceiver getTransportLink() { return _transportReceiver; } public void drain(int credit) { setDrain(true); flow(credit); _drainFlagMode = false; } public boolean draining() { return getDrain() && (getCredit() > getQueued()); } @Override public void setDrain(boolean drain) { super.setDrain(drain); modified(); _drainFlagMode = true; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ProtocolTracer.java0000664000000000000000000000216512562450203027306 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.framing.TransportFrame; /** * @author Hiram Chirino */ public interface ProtocolTracer { public void receivedFrame(TransportFrame transportFrame); public void sentFrame(TransportFrame transportFrame); } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/PlainTransportWrapper.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/PlainTransportWrapper.jav0000664000000000000000000000422712562450203030525 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.nio.ByteBuffer; import org.apache.qpid.proton.engine.TransportException; public class PlainTransportWrapper implements TransportWrapper { private final TransportOutput _outputProcessor; private final TransportInput _inputProcessor; public PlainTransportWrapper(TransportOutput outputProcessor, TransportInput inputProcessor) { _outputProcessor = outputProcessor; _inputProcessor = inputProcessor; } @Override public int capacity() { return _inputProcessor.capacity(); } @Override public int position() { return _inputProcessor.position(); } @Override public ByteBuffer tail() { return _inputProcessor.tail(); } @Override public void process() throws TransportException { _inputProcessor.process(); } @Override public void close_tail() { _inputProcessor.close_tail(); } @Override public int pending() { return _outputProcessor.pending(); } @Override public ByteBuffer head() { return _outputProcessor.head(); } @Override public void pop(int bytes) { _outputProcessor.pop(bytes); } @Override public void close_head() { _outputProcessor.close_head(); } }qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/LinkNode.java0000664000000000000000000000430112562450203026041 0ustar package org.apache.qpid.proton.engine.impl; /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ class LinkNode { public interface Query { public boolean matches(LinkNode node); } private E _value; private LinkNode _prev; private LinkNode _next; private LinkNode(E value) { _value = value; } public E getValue() { return _value; } public LinkNode getPrev() { return _prev; } public LinkNode getNext() { return _next; } public LinkNode next(Query query) { LinkNode next = _next; while(next != null && !query.matches(next)) { next = next.getNext(); } return next; } public LinkNode remove() { LinkNode prev = _prev; LinkNode next = _next; if(prev != null) { prev._next = next; } if(next != null) { next._prev = prev; } _next = _prev = null; return next; } public LinkNode addAtTail(E value) { if(_next == null) { _next = new LinkNode(value); _next._prev = this; return _next; } else { return _next.addAtTail(value); } } public static LinkNode newList(T value) { return new LinkNode(value); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/LinkImpl.java0000664000000000000000000002217412562450203026065 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.util.EnumSet; import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode; import org.apache.qpid.proton.amqp.transport.SenderSettleMode; import org.apache.qpid.proton.amqp.transport.Source; import org.apache.qpid.proton.amqp.transport.Target; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Event; import org.apache.qpid.proton.engine.Link; public abstract class LinkImpl extends EndpointImpl implements Link { private final SessionImpl _session; DeliveryImpl _head; DeliveryImpl _tail; DeliveryImpl _current; private String _name; private Source _source; private Source _remoteSource; private Target _target; private Target _remoteTarget; private int _queued; private int _credit; private int _unsettled; private int _drained; private SenderSettleMode _senderSettleMode; private SenderSettleMode _remoteSenderSettleMode; private ReceiverSettleMode _receiverSettleMode; private ReceiverSettleMode _remoteReceiverSettleMode; private LinkNode _node; private boolean _drain; private boolean _detached; LinkImpl(SessionImpl session, String name) { _session = session; _session.incref(); _name = name; ConnectionImpl conn = session.getConnectionImpl(); _node = conn.addLinkEndpoint(this); conn.put(Event.Type.LINK_INIT, this); } @Override public String getName() { return _name; } @Override public DeliveryImpl delivery(byte[] tag) { return delivery(tag, 0, tag.length); } @Override public DeliveryImpl delivery(byte[] tag, int offset, int length) { if (offset != 0 || length != tag.length) { throw new IllegalArgumentException("At present delivery tag must be the whole byte array"); } incrementQueued(); try { DeliveryImpl delivery = new DeliveryImpl(tag, this, _tail); if (_tail == null) { _head = delivery; } _tail = delivery; if (_current == null) { _current = delivery; } getConnectionImpl().workUpdate(delivery); return delivery; } catch (RuntimeException e) { e.printStackTrace(); throw e; } } @Override void postFinal() { _session.getConnectionImpl().put(Event.Type.LINK_FINAL, this); _session.decref(); } @Override void doFree() { DeliveryImpl dlv = _head; while (dlv != null) { dlv.free(); dlv = dlv.next(); } _session.getConnectionImpl().removeLinkEndpoint(_node); _node = null; } void modifyEndpoints() { modified(); } public void remove(DeliveryImpl delivery) { if(_head == delivery) { _head = delivery.getLinkNext(); } if(_tail == delivery) { _tail = delivery.getLinkPrevious(); } if(_current == delivery) { // TODO - what??? } } @Override public DeliveryImpl current() { return _current; } @Override public boolean advance() { if(_current != null ) { DeliveryImpl oldCurrent = _current; _current = _current.getLinkNext(); getConnectionImpl().workUpdate(oldCurrent); if(_current != null) { getConnectionImpl().workUpdate(_current); } return true; } else { return false; } } @Override protected ConnectionImpl getConnectionImpl() { return _session.getConnectionImpl(); } @Override public SessionImpl getSession() { return _session; } @Override public Source getRemoteSource() { return _remoteSource; } void setRemoteSource(Source source) { _remoteSource = source; } @Override public Target getRemoteTarget() { return _remoteTarget; } void setRemoteTarget(Target target) { _remoteTarget = target; } @Override public Source getSource() { return _source; } @Override public void setSource(Source source) { // TODO - should be an error if local state is ACTIVE _source = source; } @Override public Target getTarget() { return _target; } @Override public void setTarget(Target target) { // TODO - should be an error if local state is ACTIVE _target = target; } @Override public Link next(EnumSet local, EnumSet remote) { LinkNode.Query query = new EndpointImplQuery(local, remote); LinkNode linkNode = _node.next(query); return linkNode == null ? null : linkNode.getValue(); } abstract TransportLink getTransportLink(); @Override public int getCredit() { return _credit; } public void addCredit(int credit) { _credit+=credit; } public void setCredit(int credit) { _credit = credit; } boolean hasCredit() { return _credit > 0; } void incrementCredit() { _credit++; } void decrementCredit() { _credit--; } @Override public int getQueued() { return _queued; } void incrementQueued() { _queued++; } void decrementQueued() { _queued--; } @Override public int getUnsettled() { return _unsettled; } void incrementUnsettled() { _unsettled++; } void decrementUnsettled() { _unsettled--; } void setDrain(boolean drain) { _drain = drain; } @Override public boolean getDrain() { return _drain; } @Override public SenderSettleMode getSenderSettleMode() { return _senderSettleMode; } @Override public void setSenderSettleMode(SenderSettleMode senderSettleMode) { _senderSettleMode = senderSettleMode; } @Override public SenderSettleMode getRemoteSenderSettleMode() { return _remoteSenderSettleMode; } @Override public void setRemoteSenderSettleMode(SenderSettleMode remoteSenderSettleMode) { _remoteSenderSettleMode = remoteSenderSettleMode; } @Override public ReceiverSettleMode getReceiverSettleMode() { return _receiverSettleMode; } @Override public void setReceiverSettleMode(ReceiverSettleMode receiverSettleMode) { _receiverSettleMode = receiverSettleMode; } @Override public ReceiverSettleMode getRemoteReceiverSettleMode() { return _remoteReceiverSettleMode; } void setRemoteReceiverSettleMode(ReceiverSettleMode remoteReceiverSettleMode) { _remoteReceiverSettleMode = remoteReceiverSettleMode; } @Override public int drained() { int drained = 0; if (this instanceof SenderImpl) { if(getDrain() && hasCredit()) { _drained = getCredit(); setCredit(0); modified(); drained = _drained; } } else { drained = _drained; _drained = 0; } return drained; } int getDrained() { return _drained; } void setDrained(int value) { _drained = value; } @Override public int getRemoteCredit() { return _credit - _queued; } @Override public DeliveryImpl head() { return _head; } @Override void localOpen() { getConnectionImpl().put(Event.Type.LINK_LOCAL_OPEN, this); } @Override void localClose() { getConnectionImpl().put(Event.Type.LINK_LOCAL_CLOSE, this); } @Override public void detach() { _detached = true; getConnectionImpl().put(Event.Type.LINK_LOCAL_DETACH, this); modified(); } public boolean detached() { return _detached; } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/HandshakeSniffingTransportWrapper.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/HandshakeSniffingTranspor0000664000000000000000000001145012562450203030524 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.nio.ByteBuffer; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; import org.apache.qpid.proton.engine.impl.TransportWrapper; public abstract class HandshakeSniffingTransportWrapper implements TransportWrapper { protected final T1 _wrapper1; protected final T2 _wrapper2; private boolean _tail_closed = false; private boolean _head_closed = false; protected TransportWrapper _selectedTransportWrapper; private final ByteBuffer _determinationBuffer; protected HandshakeSniffingTransportWrapper (T1 wrapper1, T2 wrapper2) { _wrapper1 = wrapper1; _wrapper2 = wrapper2; _determinationBuffer = ByteBuffer.allocate(bufferSize()); } @Override public int capacity() { if (isDeterminationMade()) { return _selectedTransportWrapper.capacity(); } else { if (_tail_closed) { return Transport.END_OF_STREAM; } return _determinationBuffer.remaining(); } } @Override public int position() { if (isDeterminationMade()) { return _selectedTransportWrapper.position(); } else { if (_tail_closed) { return Transport.END_OF_STREAM; } return _determinationBuffer.position(); } } @Override public ByteBuffer tail() { if (isDeterminationMade()) { return _selectedTransportWrapper.tail(); } else { return _determinationBuffer; } } protected abstract int bufferSize(); protected abstract void makeDetermination(byte[] bytes); @Override public void process() throws TransportException { if (isDeterminationMade()) { _selectedTransportWrapper.process(); } else if (_determinationBuffer.remaining() == 0) { _determinationBuffer.flip(); byte[] bytesInput = new byte[_determinationBuffer.remaining()]; _determinationBuffer.get(bytesInput); makeDetermination(bytesInput); _determinationBuffer.rewind(); // TODO what if the selected transport has insufficient capacity?? Maybe use pour, and then try to finish pouring next time round. _selectedTransportWrapper.tail().put(_determinationBuffer); _selectedTransportWrapper.process(); } else if (_tail_closed) { throw new TransportException("connection aborted"); } } @Override public void close_tail() { try { if (isDeterminationMade()) { _selectedTransportWrapper.close_tail(); } } finally { _tail_closed = true; } } @Override public int pending() { if (_head_closed) { return Transport.END_OF_STREAM; } if (isDeterminationMade()) { return _selectedTransportWrapper.pending(); } else { return 0; } } private static final ByteBuffer EMPTY = ByteBuffer.allocate(0); @Override public ByteBuffer head() { if (isDeterminationMade()) { return _selectedTransportWrapper.head(); } else { return EMPTY; } } @Override public void pop(int bytes) { if (isDeterminationMade()) { _selectedTransportWrapper.pop(bytes); } else if (bytes > 0) { throw new IllegalStateException("no bytes have been read"); } } @Override public void close_head() { if (isDeterminationMade()) { _selectedTransportWrapper.close_head(); } else { _head_closed = true; } } protected boolean isDeterminationMade() { return _selectedTransportWrapper != null; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/FrameWriter.java0000664000000000000000000001512312562450203026571 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.transport.EmptyFrame; import org.apache.qpid.proton.amqp.transport.FrameBody; import org.apache.qpid.proton.codec.EncoderImpl; import org.apache.qpid.proton.codec.WritableBuffer; import org.apache.qpid.proton.framing.TransportFrame; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; /** * FrameWriter * */ class FrameWriter { static final byte AMQP_FRAME_TYPE = 0; static final byte SASL_FRAME_TYPE = (byte) 1; private EncoderImpl _encoder; private ByteBuffer _bbuf; private WritableBuffer _buffer; private int _maxFrameSize; private byte _frameType; final private Ref _protocolTracer; private TransportImpl _transport; private int _frameStart = 0; private int _payloadStart; private int _performativeSize; private long _framesOutput = 0; FrameWriter(EncoderImpl encoder, int maxFrameSize, byte frameType, Ref protocolTracer, TransportImpl transport) { _encoder = encoder; _bbuf = ByteBuffer.allocate(1024); _buffer = new WritableBuffer.ByteBufferWrapper(_bbuf); _encoder.setByteBuffer(_buffer); _maxFrameSize = maxFrameSize; _frameType = frameType; _protocolTracer = protocolTracer; _transport = transport; } void setMaxFrameSize(int maxFrameSize) { _maxFrameSize = maxFrameSize; } private void grow() { ByteBuffer old = _bbuf; _bbuf = ByteBuffer.allocate(_bbuf.capacity() * 2); _buffer = new WritableBuffer.ByteBufferWrapper(_bbuf); old.flip(); _bbuf.put(old); _encoder.setByteBuffer(_buffer); } void writeHeader(byte[] header) { _buffer.put(header, 0, header.length); } private void startFrame() { _frameStart = _buffer.position(); } private void writePerformative(Object frameBody) { while (_buffer.remaining() < 8) { grow(); } while (true) { try { _buffer.position(_frameStart + 8); if (frameBody != null) _encoder.writeObject(frameBody); break; } catch (BufferOverflowException e) { grow(); } } _payloadStart = _buffer.position(); _performativeSize = _payloadStart - _frameStart; } private void endFrame(int channel) { int frameSize = _buffer.position() - _frameStart; int limit = _buffer.position(); _buffer.position(_frameStart); _buffer.putInt(frameSize); _buffer.put((byte) 2); _buffer.put(_frameType); _buffer.putShort((short) channel); _buffer.position(limit); } void writeFrame(int channel, Object frameBody, ByteBuffer payload, Runnable onPayloadTooLarge) { startFrame(); writePerformative(frameBody); if(_maxFrameSize > 0 && payload != null && (payload.remaining() + _performativeSize) > _maxFrameSize) { if(onPayloadTooLarge != null) { onPayloadTooLarge.run(); } writePerformative(frameBody); } int capacity; if (_maxFrameSize > 0) { capacity = _maxFrameSize - _performativeSize; } else { capacity = Integer.MAX_VALUE; } int payloadSize = Math.min(payload == null ? 0 : payload.remaining(), capacity); ProtocolTracer tracer = _protocolTracer == null ? null : _protocolTracer.get(); if( tracer != null || _transport.isTraceFramesEnabled()) { // XXX: this is a bit of a hack but it eliminates duplicate // code, further refactor will fix this if (_frameType == AMQP_FRAME_TYPE) { ByteBuffer originalPayload = null; if( payload!=null ) { originalPayload = payload.duplicate(); originalPayload.limit(payload.position() + payloadSize); } Binary payloadBin = Binary.create(originalPayload); FrameBody body = null; if (frameBody == null) { body = new EmptyFrame(); } else { body = (FrameBody) frameBody; } TransportFrame frame = new TransportFrame(channel, body, payloadBin); _transport.log(TransportImpl.OUTGOING, frame); if(tracer != null) { tracer.sentFrame(frame); } } } if(payloadSize > 0) { while (_buffer.remaining() < payloadSize) { grow(); } int oldLimit = payload.limit(); payload.limit(payload.position() + payloadSize); _buffer.put(payload); payload.limit(oldLimit); } endFrame(channel); _framesOutput += 1; } void writeFrame(Object frameBody) { writeFrame(0, frameBody, null, null); } boolean isFull() { // XXX: this should probably be tunable return _bbuf.position() > 64*1024; } int readBytes(ByteBuffer dst) { ByteBuffer src = _bbuf.duplicate(); src.flip(); int size = Math.min(src.remaining(), dst.remaining()); int limit = src.limit(); src.limit(size); dst.put(src); src.limit(limit); _bbuf.rewind(); _bbuf.put(src); return size; } long getFramesOutput() { return _framesOutput; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/FrameParser.java0000664000000000000000000004667712562450203026573 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import static org.apache.qpid.proton.engine.impl.AmqpHeader.HEADER; import static org.apache.qpid.proton.engine.impl.ByteBufferUtils.newWriteableBuffer; import java.nio.ByteBuffer; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.transport.EmptyFrame; import org.apache.qpid.proton.amqp.transport.FrameBody; import org.apache.qpid.proton.codec.ByteBufferDecoder; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; import org.apache.qpid.proton.framing.TransportFrame; class FrameParser implements TransportInput { private static final Logger TRACE_LOGGER = Logger.getLogger("proton.trace"); private static final ByteBuffer _emptyInputBuffer = newWriteableBuffer(0); private enum State { HEADER0, HEADER1, HEADER2, HEADER3, HEADER4, HEADER5, HEADER6, HEADER7, SIZE_0, SIZE_1, SIZE_2, SIZE_3, PRE_PARSE, BUFFERING, PARSING, ERROR } private final FrameHandler _frameHandler; private final ByteBufferDecoder _decoder; private final int _inputBufferSize; private final int _localMaxFrameSize; private ByteBuffer _inputBuffer = null; private boolean _tail_closed = false; private State _state = State.HEADER0; private long _framesInput = 0; /** the stated size of the current frame */ private int _size; /** holds the current frame that is being parsed */ private ByteBuffer _frameBuffer; private TransportFrame _heldFrame; private TransportException _parsingError; /** * We store the last result when processing input so that * we know not to process any more input if it was an error. */ FrameParser(FrameHandler frameHandler, ByteBufferDecoder decoder, int localMaxFrameSize) { _frameHandler = frameHandler; _decoder = decoder; _localMaxFrameSize = localMaxFrameSize; _inputBufferSize = _localMaxFrameSize > 0 ? _localMaxFrameSize : 4*1024; } private void input(ByteBuffer in) throws TransportException { flushHeldFrame(); if (_heldFrame != null) { return; } TransportException frameParsingError = null; int size = _size; State state = _state; ByteBuffer oldIn = null; boolean transportAccepting = true; while(in.hasRemaining() && state != State.ERROR && transportAccepting) { switch(state) { case HEADER0: if(in.hasRemaining()) { byte c = in.get(); if(c != HEADER[0]) { frameParsingError = new TransportException("AMQP header mismatch value %x, expecting %x. In state: %s", c, HEADER[0], state); state = State.ERROR; break; } state = State.HEADER1; } else { break; } case HEADER1: if(in.hasRemaining()) { byte c = in.get(); if(c != HEADER[1]) { frameParsingError = new TransportException("AMQP header mismatch value %x, expecting %x. In state: %s", c, HEADER[1], state); state = State.ERROR; break; } state = State.HEADER2; } else { break; } case HEADER2: if(in.hasRemaining()) { byte c = in.get(); if(c != HEADER[2]) { frameParsingError = new TransportException("AMQP header mismatch value %x, expecting %x. In state: %s", c, HEADER[2], state); state = State.ERROR; break; } state = State.HEADER3; } else { break; } case HEADER3: if(in.hasRemaining()) { byte c = in.get(); if(c != HEADER[3]) { frameParsingError = new TransportException("AMQP header mismatch value %x, expecting %x. In state: %s", c, HEADER[3], state); state = State.ERROR; break; } state = State.HEADER4; } else { break; } case HEADER4: if(in.hasRemaining()) { byte c = in.get(); if(c != HEADER[4]) { frameParsingError = new TransportException("AMQP header mismatch value %x, expecting %x. In state: %s", c, HEADER[4], state); state = State.ERROR; break; } state = State.HEADER5; } else { break; } case HEADER5: if(in.hasRemaining()) { byte c = in.get(); if(c != HEADER[5]) { frameParsingError = new TransportException("AMQP header mismatch value %x, expecting %x. In state: %s", c, HEADER[5], state); state = State.ERROR; break; } state = State.HEADER6; } else { break; } case HEADER6: if(in.hasRemaining()) { byte c = in.get(); if(c != HEADER[6]) { frameParsingError = new TransportException("AMQP header mismatch value %x, expecting %x. In state: %s", c, HEADER[6], state); state = State.ERROR; break; } state = State.HEADER7; } else { break; } case HEADER7: if(in.hasRemaining()) { byte c = in.get(); if(c != HEADER[7]) { frameParsingError = new TransportException("AMQP header mismatch value %x, expecting %x. In state: %s", c, HEADER[7], state); state = State.ERROR; break; } state = State.SIZE_0; } else { break; } case SIZE_0: if(!in.hasRemaining()) { break; } if(in.remaining() >= 4) { size = in.getInt(); state = State.PRE_PARSE; break; } else { size = (in.get() << 24) & 0xFF000000; if(!in.hasRemaining()) { state = State.SIZE_1; break; } } case SIZE_1: size |= (in.get() << 16) & 0xFF0000; if(!in.hasRemaining()) { state = State.SIZE_2; break; } case SIZE_2: size |= (in.get() << 8) & 0xFF00; if(!in.hasRemaining()) { state = State.SIZE_3; break; } case SIZE_3: size |= in.get() & 0xFF; state = State.PRE_PARSE; case PRE_PARSE: ; if(size < 8) { frameParsingError = new TransportException("specified frame size %d smaller than minimum frame header " + "size %d", size, 8); state = State.ERROR; break; } if (_localMaxFrameSize > 0 && size > _localMaxFrameSize) { frameParsingError = new TransportException("specified frame size %d greater than maximum valid frame size %d", size, _localMaxFrameSize); state = State.ERROR; break; } if(in.remaining() < size-4) { _frameBuffer = ByteBuffer.allocate(size-4); _frameBuffer.put(in); state = State.BUFFERING; break; } case BUFFERING: if(_frameBuffer != null) { if(in.remaining() < _frameBuffer.remaining()) { _frameBuffer.put(in); break; } else { ByteBuffer dup = in.duplicate(); dup.limit(dup.position()+_frameBuffer.remaining()); in.position(in.position()+_frameBuffer.remaining()); _frameBuffer.put(dup); oldIn = in; _frameBuffer.flip(); in = _frameBuffer; state = State.PARSING; } } case PARSING: int dataOffset = (in.get() << 2) & 0x3FF; if(dataOffset < 8) { frameParsingError = new TransportException("specified frame data offset %d smaller than minimum frame header size %d", dataOffset, 8); state = State.ERROR; break; } else if(dataOffset > size) { frameParsingError = new TransportException("specified frame data offset %d larger than the frame size %d", dataOffset, _size); state = State.ERROR; break; } // type int type = in.get() & 0xFF; int channel = in.getShort() & 0xFFFF; if(type != 0) { frameParsingError = new TransportException("unknown frame type: %d", type); state = State.ERROR; break; } // note that this skips over the extended header if it's present if(dataOffset!=8) { in.position(in.position()+dataOffset-8); } // oldIn null iff not working on duplicated buffer final int frameBodySize = size - dataOffset; if(oldIn == null) { oldIn = in; in = in.duplicate(); final int endPos = in.position() + frameBodySize; in.limit(endPos); oldIn.position(endPos); } try { _framesInput += 1; Binary payload = null; Object val = null; if (frameBodySize > 0) { _decoder.setByteBuffer(in); val = _decoder.readObject(); _decoder.setByteBuffer(null); if(in.hasRemaining()) { byte[] payloadBytes = new byte[in.remaining()]; in.get(payloadBytes); payload = new Binary(payloadBytes); } else { payload = null; } } else { val = new EmptyFrame(); } if(val instanceof FrameBody) { FrameBody frameBody = (FrameBody) val; if(TRACE_LOGGER.isLoggable(Level.FINE)) { TRACE_LOGGER.log(Level.FINE, "IN: CH["+channel+"] : " + frameBody + (payload == null ? "" : "[" + payload + "]")); } TransportFrame frame = new TransportFrame(channel, frameBody, payload); if(_frameHandler.isHandlingFrames()) { _tail_closed = _frameHandler.handleFrame(frame); } else { transportAccepting = false; _heldFrame = frame; } } else { throw new TransportException("Frameparser encountered a " + (val == null? "null" : val.getClass()) + " which is not a " + FrameBody.class); } reset(); in = oldIn; oldIn = null; _frameBuffer = null; state = State.SIZE_0; } catch (DecodeException ex) { state = State.ERROR; frameParsingError = new TransportException(ex); } break; case ERROR: // do nothing } } if (_tail_closed) { if (in.hasRemaining()) { state = State.ERROR; frameParsingError = new TransportException("framing error"); } else if (state != State.SIZE_0) { state = State.ERROR; frameParsingError = new TransportException("connection aborted"); } else { _frameHandler.closed(null); } } _state = state; _size = size; if(_state == State.ERROR) { _tail_closed = true; if(frameParsingError != null) { _parsingError = frameParsingError; _frameHandler.closed(frameParsingError); } else { throw new TransportException("Unable to parse, probably because of a previous error"); } } } @Override public int capacity() { if (_tail_closed) { return Transport.END_OF_STREAM; } else { if (_inputBuffer != null) { return _inputBuffer.remaining(); } else { return _inputBufferSize; } } } @Override public int position() { if (_tail_closed) { return Transport.END_OF_STREAM; } return (_inputBuffer == null) ? 0 : _inputBuffer.position(); } @Override public ByteBuffer tail() { if (_tail_closed) { throw new TransportException("tail closed"); } if (_inputBuffer == null) { _inputBuffer = newWriteableBuffer(_inputBufferSize); } return _inputBuffer; } @Override public void process() throws TransportException { if (_inputBuffer != null) { _inputBuffer.flip(); try { input(_inputBuffer); } finally { if (_inputBuffer.hasRemaining()) { _inputBuffer.compact(); } else if (_inputBuffer.capacity() > TransportImpl.BUFFER_RELEASE_THRESHOLD) { _inputBuffer = null; } else { _inputBuffer.clear(); } } } else { input(_emptyInputBuffer); } } @Override public void close_tail() { _tail_closed = true; process(); } /** * Attempt to flush any cached data to the frame transport. This function * is useful if the {@link FrameHandler} state has changed. */ public void flush() { flushHeldFrame(); if (_heldFrame == null) { process(); } } private void flushHeldFrame() { if(_heldFrame != null && _frameHandler.isHandlingFrames()) { _tail_closed = _frameHandler.handleFrame(_heldFrame); _heldFrame = null; } } private void reset() { _size = 0; _state = State.SIZE_0; } long getFramesInput() { return _framesInput; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/FrameHandler.java0000664000000000000000000000264512562450203026677 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.engine.TransportException; import org.apache.qpid.proton.framing.TransportFrame; public interface FrameHandler { /** * @throws IllegalStateException if I am not currently accepting input * @see #isHandlingFrames() * @returns false on end of stream */ boolean handleFrame(TransportFrame frame); void closed(TransportException error); /** * Returns whether I am currently able to handle frames. * MUST be checked before calling {@link #handleFrame(TransportFrame)}. */ boolean isHandlingFrames(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/EventImpl.java0000664000000000000000000002372512562450203026254 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.util.Iterator; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.engine.Event; import org.apache.qpid.proton.engine.Handler; import org.apache.qpid.proton.engine.HandlerException; import org.apache.qpid.proton.engine.Link; import org.apache.qpid.proton.engine.Record; import org.apache.qpid.proton.engine.Session; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.reactor.Reactor; import org.apache.qpid.proton.reactor.Selectable; import org.apache.qpid.proton.reactor.Task; /** * EventImpl * */ class EventImpl implements Event { Type type; Object context; EventImpl next; RecordImpl attachments = new RecordImpl(); EventImpl() { this.type = null; } void init(Event.Type type, Object context) { this.type = type; this.context = context; this.attachments.clear(); } void clear() { type = null; context = null; attachments.clear(); } @Override public Type getType() { return type; } @Override public Object getContext() { return context; } @Override public void dispatch(Handler handler) { try { switch (type) { case CONNECTION_INIT: handler.onConnectionInit(this); break; case CONNECTION_LOCAL_OPEN: handler.onConnectionLocalOpen(this); break; case CONNECTION_REMOTE_OPEN: handler.onConnectionRemoteOpen(this); break; case CONNECTION_LOCAL_CLOSE: handler.onConnectionLocalClose(this); break; case CONNECTION_REMOTE_CLOSE: handler.onConnectionRemoteClose(this); break; case CONNECTION_BOUND: handler.onConnectionBound(this); break; case CONNECTION_UNBOUND: handler.onConnectionUnbound(this); break; case CONNECTION_FINAL: handler.onConnectionFinal(this); break; case SESSION_INIT: handler.onSessionInit(this); break; case SESSION_LOCAL_OPEN: handler.onSessionLocalOpen(this); break; case SESSION_REMOTE_OPEN: handler.onSessionRemoteOpen(this); break; case SESSION_LOCAL_CLOSE: handler.onSessionLocalClose(this); break; case SESSION_REMOTE_CLOSE: handler.onSessionRemoteClose(this); break; case SESSION_FINAL: handler.onSessionFinal(this); break; case LINK_INIT: handler.onLinkInit(this); break; case LINK_LOCAL_OPEN: handler.onLinkLocalOpen(this); break; case LINK_REMOTE_OPEN: handler.onLinkRemoteOpen(this); break; case LINK_LOCAL_DETACH: handler.onLinkLocalDetach(this); break; case LINK_REMOTE_DETACH: handler.onLinkRemoteDetach(this); break; case LINK_LOCAL_CLOSE: handler.onLinkLocalClose(this); break; case LINK_REMOTE_CLOSE: handler.onLinkRemoteClose(this); break; case LINK_FLOW: handler.onLinkFlow(this); break; case LINK_FINAL: handler.onLinkFinal(this); break; case DELIVERY: handler.onDelivery(this); break; case TRANSPORT: handler.onTransport(this); break; case TRANSPORT_ERROR: handler.onTransportError(this); break; case TRANSPORT_HEAD_CLOSED: handler.onTransportHeadClosed(this); break; case TRANSPORT_TAIL_CLOSED: handler.onTransportTailClosed(this); break; case TRANSPORT_CLOSED: handler.onTransportClosed(this); break; case REACTOR_FINAL: handler.onReactorFinal(this); break; case REACTOR_QUIESCED: handler.onReactorQuiesced(this); break; case REACTOR_INIT: handler.onReactorInit(this); break; case SELECTABLE_ERROR: handler.onSelectableError(this); break; case SELECTABLE_EXPIRED: handler.onSelectableExpired(this); break; case SELECTABLE_FINAL: handler.onSelectableFinal(this); break; case SELECTABLE_INIT: handler.onSelectableInit(this); break; case SELECTABLE_READABLE: handler.onSelectableReadable(this); break; case SELECTABLE_UPDATED: handler.onSelectableWritable(this); break; case SELECTABLE_WRITABLE: handler.onSelectableWritable(this); break; case TIMER_TASK: handler.onTimerTask(this); break; default: handler.onUnhandled(this); break; } } catch(RuntimeException runtimeException) { throw new HandlerException(handler, runtimeException); } Iterator children = handler.children(); while(children.hasNext()) { dispatch(children.next()); } } @Override public Connection getConnection() { if (context instanceof Connection) { return (Connection) context; } else if (context instanceof Transport) { Transport transport = getTransport(); if (transport == null) { return null; } return ((TransportImpl) transport).getConnectionImpl(); } else { Session ssn = getSession(); if (ssn == null) { return null; } return ssn.getConnection(); } } @Override public Session getSession() { if (context instanceof Session) { return (Session) context; } else { Link link = getLink(); if (link == null) { return null; } return link.getSession(); } } @Override public Link getLink() { if (context instanceof Link) { return (Link) context; } else { Delivery dlv = getDelivery(); if (dlv == null) { return null; } return dlv.getLink(); } } @Override public Delivery getDelivery() { if (context instanceof Delivery) { return (Delivery) context; } else { return null; } } @Override public Transport getTransport() { if (context instanceof Transport) { return (Transport) context; } else { return null; } } @Override public Selectable getSelectable() { if (context instanceof Selectable) { return (Selectable) context; } else { return null; } } @Override public Reactor getReactor() { if (context instanceof Reactor) { return (Reactor) context; } else if (context instanceof Task) { return ((Task)context).getReactor(); } else if (context instanceof Transport) { return ((TransportImpl)context).getReactor(); } else if (context instanceof Delivery) { return ((Delivery)context).getLink().getSession().getConnection().getReactor(); } else if (context instanceof Link) { return ((Link)context).getSession().getConnection().getReactor(); } else if (context instanceof Session) { return ((Session)context).getConnection().getReactor(); } else if (context instanceof Connection) { return ((Connection)context).getReactor(); } else if (context instanceof Selectable) { return ((Selectable)context).getReactor(); } return null; } @Override public Task getTask() { if (context instanceof Task) { return (Task) context; } else { return null; } } @Override public Record attachments() { return attachments; } @Override public Event copy() { EventImpl newEvent = new EventImpl(); newEvent.init(type, context); newEvent.attachments.copy(attachments); return newEvent; } @Override public String toString() { return "EventImpl{" + "type=" + type + ", context=" + context + '}'; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/EndpointImplQuery.java0000664000000000000000000000273212562450203027774 0ustar package org.apache.qpid.proton.engine.impl; /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ import java.util.EnumSet; import org.apache.qpid.proton.engine.EndpointState; class EndpointImplQuery implements LinkNode.Query { private final EnumSet _local; private final EnumSet _remote; EndpointImplQuery(EnumSet local, EnumSet remote) { _local = local; _remote = remote; } public boolean matches(LinkNode node) { return (_local == null || _local.contains(node.getValue().getLocalState())) && (_remote == null || _remote.contains(node.getValue().getRemoteState())); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/EndpointImpl.java0000664000000000000000000001162112562450203026743 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.amqp.transport.ErrorCondition; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Event; import org.apache.qpid.proton.engine.ProtonJEndpoint; import org.apache.qpid.proton.engine.Record; public abstract class EndpointImpl implements ProtonJEndpoint { private EndpointState _localState = EndpointState.UNINITIALIZED; private EndpointState _remoteState = EndpointState.UNINITIALIZED; private ErrorCondition _localError = new ErrorCondition(); private ErrorCondition _remoteError = new ErrorCondition(); private boolean _modified; private EndpointImpl _transportNext; private EndpointImpl _transportPrev; private Object _context; private Record _attachments = new RecordImpl(); private int refcount = 1; boolean freed = false; void incref() { refcount++; } void decref() { refcount--; if (refcount == 0) { postFinal(); } else if (refcount < 0) { throw new IllegalStateException(); } } abstract void postFinal(); abstract void localOpen(); abstract void localClose(); public void open() { switch(_localState) { case ACTIVE: // TODO case CLOSED: // TODO case UNINITIALIZED: _localState = EndpointState.ACTIVE; localOpen(); } modified(); } public void close() { switch(_localState) { case UNINITIALIZED: // TODO case CLOSED: // TODO case ACTIVE: _localState = EndpointState.CLOSED; localClose(); } modified(); } public EndpointState getLocalState() { return _localState; } public EndpointState getRemoteState() { return _remoteState; } public ErrorCondition getCondition() { return _localError; } @Override public void setCondition(ErrorCondition condition) { if(condition != null) { _localError.copyFrom(condition); } else { _localError.clear(); } } public ErrorCondition getRemoteCondition() { return _remoteError; } void setLocalState(EndpointState localState) { _localState = localState; } void setRemoteState(EndpointState remoteState) { // TODO - check state change legal _remoteState = remoteState; } void modified() { modified(true); } void modified(boolean emit) { if(!_modified) { _modified = true; getConnectionImpl().addModified(this); } if (emit) { ConnectionImpl conn = getConnectionImpl(); TransportImpl trans = conn.getTransport(); if (trans != null) { conn.put(Event.Type.TRANSPORT, trans); } } } protected abstract ConnectionImpl getConnectionImpl(); void clearModified() { if(_modified) { _modified = false; getConnectionImpl().removeModified(this); } } boolean isModified() { return _modified; } EndpointImpl transportNext() { return _transportNext; } EndpointImpl transportPrev() { return _transportPrev; } abstract void doFree(); final public void free() { if (freed) return; freed = true; doFree(); decref(); } void setTransportNext(EndpointImpl transportNext) { _transportNext = transportNext; } void setTransportPrev(EndpointImpl transportPrevious) { _transportPrev = transportPrevious; } public Object getContext() { return _context; } public void setContext(Object context) { _context = context; } public Record attachments() { return _attachments; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/DeliveryImpl.java0000664000000000000000000002373012562450203026752 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.util.Arrays; import org.apache.qpid.proton.engine.Delivery; import org.apache.qpid.proton.engine.Record; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.amqp.transport.DeliveryState; public class DeliveryImpl implements Delivery { private DeliveryImpl _linkPrevious; private DeliveryImpl _linkNext; private DeliveryImpl _workNext; private DeliveryImpl _workPrev; boolean _work; private DeliveryImpl _transportWorkNext; private DeliveryImpl _transportWorkPrev; boolean _transportWork; private Record _attachments = new RecordImpl(); private Object _context; private final byte[] _tag; private final LinkImpl _link; private DeliveryState _deliveryState; private boolean _settled; private boolean _remoteSettled; private DeliveryState _remoteDeliveryState; private DeliveryState _defaultDeliveryState = null; /** * A bit-mask representing the outstanding work on this delivery received from the transport layer * that has not yet been processed by the application. */ private int _flags = (byte) 0; private TransportDelivery _transportDelivery; private byte[] _data; private int _dataSize; private boolean _complete; private boolean _updated; private boolean _done; private int _offset; DeliveryImpl(final byte[] tag, final LinkImpl link, DeliveryImpl previous) { _tag = tag; _link = link; _link.incrementUnsettled(); _linkPrevious = previous; if(previous != null) { previous._linkNext = this; } } public byte[] getTag() { return _tag; } public LinkImpl getLink() { return _link; } public DeliveryState getLocalState() { return _deliveryState; } public DeliveryState getRemoteState() { return _remoteDeliveryState; } public boolean remotelySettled() { return _remoteSettled; } public int getMessageFormat() { return 0; } public void disposition(final DeliveryState state) { _deliveryState = state; if(!_remoteSettled) { addToTransportWorkList(); } } public void settle() { if (_settled) { return; } _settled = true; _link.decrementUnsettled(); if(!_remoteSettled) { addToTransportWorkList(); } else { _transportDelivery.settled(); } if(_link.current() == this) { _link.advance(); } _link.remove(this); if(_linkPrevious != null) { _linkPrevious._linkNext = _linkNext; } if(_linkNext != null) { _linkNext._linkPrevious = _linkPrevious; } updateWork(); } DeliveryImpl getLinkNext() { return _linkNext; } public DeliveryImpl next() { return getLinkNext(); } public void free() { settle(); } DeliveryImpl getLinkPrevious() { return _linkPrevious; } public DeliveryImpl getWorkNext() { if (_workNext != null) return _workNext; // the following hack is brought to you by the C implementation! if (!_work) // not on the work list return _link.getConnectionImpl().getWorkHead(); return null; } DeliveryImpl getWorkPrev() { return _workPrev; } void setWorkNext(DeliveryImpl workNext) { _workNext = workNext; } void setWorkPrev(DeliveryImpl workPrev) { _workPrev = workPrev; } int recv(byte[] bytes, int offset, int size) { final int consumed; if(_data != null) { //TODO - should only be if no bytes left consumed = Math.min(size, _dataSize); System.arraycopy(_data, _offset, bytes, offset, consumed); _offset += consumed; _dataSize -= consumed; } else { _dataSize = consumed = 0; } return (_complete && consumed == 0) ? Transport.END_OF_STREAM : consumed; //TODO - Implement } void updateWork() { getLink().getConnectionImpl().workUpdate(this); } DeliveryImpl clearTransportWork() { DeliveryImpl next = _transportWorkNext; getLink().getConnectionImpl().removeTransportWork(this); return next; } void addToTransportWorkList() { getLink().getConnectionImpl().addTransportWork(this); } DeliveryImpl getTransportWorkNext() { return _transportWorkNext; } DeliveryImpl getTransportWorkPrev() { return _transportWorkPrev; } void setTransportWorkNext(DeliveryImpl transportWorkNext) { _transportWorkNext = transportWorkNext; } void setTransportWorkPrev(DeliveryImpl transportWorkPrev) { _transportWorkPrev = transportWorkPrev; } TransportDelivery getTransportDelivery() { return _transportDelivery; } void setTransportDelivery(TransportDelivery transportDelivery) { _transportDelivery = transportDelivery; } public boolean isSettled() { return _settled; } int send(byte[] bytes, int offset, int length) { if(_data == null) { _data = new byte[length]; } else if(_data.length - _dataSize < length) { byte[] oldData = _data; _data = new byte[oldData.length + _dataSize]; System.arraycopy(oldData,_offset,_data,0,_dataSize); _offset = 0; } System.arraycopy(bytes,offset,_data,_dataSize+_offset,length); _dataSize+=length; addToTransportWorkList(); return length; //TODO - Implement. } byte[] getData() { return _data; } int getDataOffset() { return _offset; } int getDataLength() { return _dataSize; //TODO - Implement. } void setData(byte[] data) { _data = data; } void setDataLength(int length) { _dataSize = length; } public void setDataOffset(int arrayOffset) { _offset = arrayOffset; } public boolean isWritable() { return getLink() instanceof SenderImpl && getLink().current() == this && ((SenderImpl) getLink()).hasCredit(); } public boolean isReadable() { return getLink() instanceof ReceiverImpl && getLink().current() == this; } void setComplete() { _complete = true; } public boolean isPartial() { return !_complete; } void setRemoteDeliveryState(DeliveryState remoteDeliveryState) { _remoteDeliveryState = remoteDeliveryState; _updated = true; } public boolean isUpdated() { return _updated; } public void clear() { _updated = false; getLink().getConnectionImpl().workUpdate(this); } void setDone() { _done = true; } boolean isDone() { return _done; } void setRemoteSettled(boolean remoteSettled) { _remoteSettled = remoteSettled; _updated = true; } public boolean isBuffered() { if (_remoteSettled) return false; if (getLink() instanceof SenderImpl) { if (isDone()) { return false; } else { return _complete || _dataSize > 0; } } else { return false; } } public Object getContext() { return _context; } public void setContext(Object context) { _context = context; } public Record attachments() { return _attachments; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("DeliveryImpl [_tag=").append(Arrays.toString(_tag)) .append(", _link=").append(_link) .append(", _deliveryState=").append(_deliveryState) .append(", _settled=").append(_settled) .append(", _remoteSettled=").append(_remoteSettled) .append(", _remoteDeliveryState=").append(_remoteDeliveryState) .append(", _flags=").append(_flags) .append(", _defaultDeliveryState=").append(_defaultDeliveryState) .append(", _transportDelivery=").append(_transportDelivery) .append(", _dataSize=").append(_dataSize) .append(", _complete=").append(_complete) .append(", _updated=").append(_updated) .append(", _done=").append(_done) .append(", _offset=").append(_offset).append("]"); return builder.toString(); } public int pending() { return _dataSize; } @Override public void setDefaultDeliveryState(DeliveryState state) { _defaultDeliveryState = state; } @Override public DeliveryState getDefaultDeliveryState() { return _defaultDeliveryState; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ConnectionImpl.java0000664000000000000000000003677612562450203027304 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.util.ArrayList; import java.util.EnumSet; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.transport.Open; import org.apache.qpid.proton.engine.Collector; import org.apache.qpid.proton.engine.EndpointState; import org.apache.qpid.proton.engine.Event; import org.apache.qpid.proton.engine.Link; import org.apache.qpid.proton.engine.ProtonJConnection; import org.apache.qpid.proton.engine.Session; import org.apache.qpid.proton.reactor.Reactor; public class ConnectionImpl extends EndpointImpl implements ProtonJConnection { public static final int MAX_CHANNELS = 65535; private List _sessions = new ArrayList(); private EndpointImpl _transportTail; private EndpointImpl _transportHead; private int _maxChannels = MAX_CHANNELS; private LinkNode _sessionHead; private LinkNode _sessionTail; private LinkNode _linkHead; private LinkNode _linkTail; private DeliveryImpl _workHead; private DeliveryImpl _workTail; private TransportImpl _transport; private DeliveryImpl _transportWorkHead; private DeliveryImpl _transportWorkTail; private int _transportWorkSize = 0; private String _localContainerId = ""; private String _localHostname = ""; private String _remoteContainer; private String _remoteHostname; private Symbol[] _offeredCapabilities; private Symbol[] _desiredCapabilities; private Symbol[] _remoteOfferedCapabilities; private Symbol[] _remoteDesiredCapabilities; private Map _properties; private Map _remoteProperties; private Object _context; private CollectorImpl _collector; private Reactor _reactor; private static final Symbol[] EMPTY_SYMBOL_ARRAY = new Symbol[0]; /** * @deprecated This constructor's visibility will be reduced to the default scope in a future release. * Client code outside this module should use a {@link EngineFactory} instead */ @Deprecated public ConnectionImpl() { } @Override public SessionImpl session() { SessionImpl session = new SessionImpl(this); _sessions.add(session); return session; } void freeSession(SessionImpl session) { _sessions.remove(session); } protected LinkNode addSessionEndpoint(SessionImpl endpoint) { LinkNode node; if(_sessionHead == null) { node = _sessionHead = _sessionTail = LinkNode.newList(endpoint); } else { node = _sessionTail = _sessionTail.addAtTail(endpoint); } return node; } void removeSessionEndpoint(LinkNode node) { LinkNode prev = node.getPrev(); LinkNode next = node.getNext(); if(_sessionHead == node) { _sessionHead = next; } if(_sessionTail == node) { _sessionTail = prev; } node.remove(); } protected LinkNode addLinkEndpoint(LinkImpl endpoint) { LinkNode node; if(_linkHead == null) { node = _linkHead = _linkTail = LinkNode.newList(endpoint); } else { node = _linkTail = _linkTail.addAtTail(endpoint); } return node; } void removeLinkEndpoint(LinkNode node) { LinkNode prev = node.getPrev(); LinkNode next = node.getNext(); if(_linkHead == node) { _linkHead = next; } if(_linkTail == node) { _linkTail = prev; } node.remove(); } @Override public Session sessionHead(final EnumSet local, final EnumSet remote) { if(_sessionHead == null) { return null; } else { LinkNode.Query query = new EndpointImplQuery(local, remote); LinkNode node = query.matches(_sessionHead) ? _sessionHead : _sessionHead.next(query); return node == null ? null : node.getValue(); } } @Override public Link linkHead(EnumSet local, EnumSet remote) { if(_linkHead == null) { return null; } else { LinkNode.Query query = new EndpointImplQuery(local, remote); LinkNode node = query.matches(_linkHead) ? _linkHead : _linkHead.next(query); return node == null ? null : node.getValue(); } } @Override protected ConnectionImpl getConnectionImpl() { return this; } @Override void postFinal() { put(Event.Type.CONNECTION_FINAL, this); } @Override void doFree() { List sessions = new ArrayList(_sessions); for(Session session : sessions) { session.free(); } _sessions = null; } void modifyEndpoints() { if (_sessions != null) { for (SessionImpl ssn: _sessions) { ssn.modifyEndpoints(); } } if (!freed) { modified(); } } void handleOpen(Open open) { // TODO - store state setRemoteState(EndpointState.ACTIVE); setRemoteHostname(open.getHostname()); setRemoteContainer(open.getContainerId()); setRemoteDesiredCapabilities(open.getDesiredCapabilities()); setRemoteOfferedCapabilities(open.getOfferedCapabilities()); setRemoteProperties(open.getProperties()); put(Event.Type.CONNECTION_REMOTE_OPEN, this); } EndpointImpl getTransportHead() { return _transportHead; } EndpointImpl getTransportTail() { return _transportTail; } void addModified(EndpointImpl endpoint) { if(_transportTail == null) { endpoint.setTransportNext(null); endpoint.setTransportPrev(null); _transportHead = _transportTail = endpoint; } else { _transportTail.setTransportNext(endpoint); endpoint.setTransportPrev(_transportTail); _transportTail = endpoint; _transportTail.setTransportNext(null); } } void removeModified(EndpointImpl endpoint) { if(_transportHead == endpoint) { _transportHead = endpoint.transportNext(); } else { endpoint.transportPrev().setTransportNext(endpoint.transportNext()); } if(_transportTail == endpoint) { _transportTail = endpoint.transportPrev(); } else { endpoint.transportNext().setTransportPrev(endpoint.transportPrev()); } } @Override public int getMaxChannels() { return _maxChannels; } public String getLocalContainerId() { return _localContainerId; } @Override public void setLocalContainerId(String localContainerId) { _localContainerId = localContainerId; } @Override public DeliveryImpl getWorkHead() { return _workHead; } @Override public void setContainer(String container) { _localContainerId = container; } @Override public String getContainer() { return _localContainerId; } @Override public void setHostname(String hostname) { _localHostname = hostname; } @Override public String getRemoteContainer() { return _remoteContainer; } @Override public String getRemoteHostname() { return _remoteHostname; } @Override public void setOfferedCapabilities(Symbol[] capabilities) { _offeredCapabilities = capabilities; } @Override public void setDesiredCapabilities(Symbol[] capabilities) { _desiredCapabilities = capabilities; } @Override public Symbol[] getRemoteOfferedCapabilities() { return _remoteOfferedCapabilities == null ? EMPTY_SYMBOL_ARRAY : _remoteOfferedCapabilities; } @Override public Symbol[] getRemoteDesiredCapabilities() { return _remoteDesiredCapabilities == null ? EMPTY_SYMBOL_ARRAY : _remoteDesiredCapabilities; } Symbol[] getOfferedCapabilities() { return _offeredCapabilities; } Symbol[] getDesiredCapabilities() { return _desiredCapabilities; } void setRemoteOfferedCapabilities(Symbol[] remoteOfferedCapabilities) { _remoteOfferedCapabilities = remoteOfferedCapabilities; } void setRemoteDesiredCapabilities(Symbol[] remoteDesiredCapabilities) { _remoteDesiredCapabilities = remoteDesiredCapabilities; } Map getProperties() { return _properties; } @Override public void setProperties(Map properties) { _properties = properties; } @Override public Map getRemoteProperties() { return _remoteProperties; } void setRemoteProperties(Map remoteProperties) { _remoteProperties = remoteProperties; } @Override public String getHostname() { return _localHostname; } void setRemoteContainer(String remoteContainerId) { _remoteContainer = remoteContainerId; } void setRemoteHostname(String remoteHostname) { _remoteHostname = remoteHostname; } DeliveryImpl getWorkTail() { return _workTail; } void removeWork(DeliveryImpl delivery) { if (!delivery._work) return; DeliveryImpl next = delivery.getWorkNext(); DeliveryImpl prev = delivery.getWorkPrev(); if (prev != null) { prev.setWorkNext(next); } if (next != null) { next.setWorkPrev(prev); } if(_workHead == delivery) { _workHead = next; } if(_workTail == delivery) { _workTail = prev; } delivery._work = false; } void addWork(DeliveryImpl delivery) { if (delivery._work) return; delivery.setWorkNext(null); delivery.setWorkPrev(_workTail); if (_workTail != null) { _workTail.setWorkNext(delivery); } _workTail = delivery; if (_workHead == null) { _workHead = delivery; } delivery._work = true; } public Iterator getWorkSequence() { return new WorkSequence(_workHead); } void setTransport(TransportImpl transport) { _transport = transport; } @Override public TransportImpl getTransport() { return _transport; } private class WorkSequence implements Iterator { private DeliveryImpl _next; public WorkSequence(DeliveryImpl workHead) { _next = workHead; } @Override public boolean hasNext() { return _next != null; } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public DeliveryImpl next() { DeliveryImpl next = _next; if(next != null) { _next = next.getWorkNext(); } return next; } } DeliveryImpl getTransportWorkHead() { return _transportWorkHead; } int getTransportWorkSize() { return _transportWorkSize; } public void removeTransportWork(DeliveryImpl delivery) { if (!delivery._transportWork) return; DeliveryImpl next = delivery.getTransportWorkNext(); DeliveryImpl prev = delivery.getTransportWorkPrev(); if (prev != null) { prev.setTransportWorkNext(next); } if (next != null) { next.setTransportWorkPrev(prev); } if(_transportWorkHead == delivery) { _transportWorkHead = next; } if(_transportWorkTail == delivery) { _transportWorkTail = prev; } delivery._transportWork = false; _transportWorkSize--; } void addTransportWork(DeliveryImpl delivery) { modified(); if (delivery._transportWork) return; delivery.setTransportWorkNext(null); delivery.setTransportWorkPrev(_transportWorkTail); if (_transportWorkTail != null) { _transportWorkTail.setTransportWorkNext(delivery); } _transportWorkTail = delivery; if (_transportWorkHead == null) { _transportWorkHead = delivery; } delivery._transportWork = true; _transportWorkSize++; } void workUpdate(DeliveryImpl delivery) { if(delivery != null) { if(!delivery.isSettled() && (delivery.isReadable() || delivery.isWritable() || delivery.isUpdated())) { addWork(delivery); } else { removeWork(delivery); } } } @Override public Object getContext() { return _context; } @Override public void setContext(Object context) { _context = context; } @Override public void collect(Collector collector) { _collector = (CollectorImpl) collector; put(Event.Type.CONNECTION_INIT, this); LinkNode ssn = _sessionHead; while (ssn != null) { put(Event.Type.SESSION_INIT, ssn.getValue()); ssn = ssn.getNext(); } LinkNode lnk = _linkHead; while (lnk != null) { put(Event.Type.LINK_INIT, lnk.getValue()); lnk = lnk.getNext(); } } EventImpl put(Event.Type type, Object context) { if (_collector != null) { return _collector.put(type, context); } else { return null; } } @Override void localOpen() { put(Event.Type.CONNECTION_LOCAL_OPEN, this); } @Override void localClose() { put(Event.Type.CONNECTION_LOCAL_CLOSE, this); } @Override public Reactor getReactor() { return _reactor; } public void setReactor(Reactor reactor) { _reactor = reactor; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/CollectorImpl.java0000664000000000000000000000422012562450203027106 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import org.apache.qpid.proton.engine.Collector; import org.apache.qpid.proton.engine.Event; /** * CollectorImpl * */ public class CollectorImpl implements Collector { private EventImpl head; private EventImpl tail; private EventImpl free; public CollectorImpl() {} @Override public Event peek() { return head; } @Override public void pop() { if (head != null) { EventImpl next = head.next; head.next = free; free = head; head.clear(); head = next; } } public EventImpl put(Event.Type type, Object context) { if (tail != null && tail.getType() == type && tail.getContext() == context) { return null; } EventImpl event; if (free == null) { event = new EventImpl(); } else { event = free; free = free.next; event.next = null; } event.init(type, context); if (head == null) { head = event; tail = event; } else { tail.next = event; tail = event; } return event; } @Override public boolean more() { return head != null && head.next != null; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ByteBufferUtils.java0000664000000000000000000000763512562450203027431 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; import java.nio.ByteBuffer; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; public class ByteBufferUtils { /** * @return number of bytes poured */ public static int pour(ByteBuffer source, ByteBuffer destination) { int numberOfBytesToPour = Math.min(source.remaining(), destination.remaining()); ByteBuffer sourceSubBuffer = source.duplicate(); sourceSubBuffer.limit(sourceSubBuffer.position() + numberOfBytesToPour); destination.put(sourceSubBuffer); source.position(source.position() + numberOfBytesToPour); return numberOfBytesToPour; } /** * Assumes {@code destination} is ready to be written. * * @returns number of bytes poured which may be fewer than {@code sizeRequested} if * {@code destination} has insufficient remaining */ public static int pourArrayToBuffer(byte[] source, int offset, int sizeRequested, ByteBuffer destination) { int numberToWrite = Math.min(destination.remaining(), sizeRequested); destination.put(source, offset, numberToWrite); return numberToWrite; } /** * Pours the contents of {@code source} into {@code destinationTransportInput}, calling * the TransportInput many times if necessary. If the TransportInput returns a {@link TransportResult} * other than ok, data may remain in source. */ public static int pourAll(ByteBuffer source, TransportInput destinationTransportInput) throws TransportException { int capacity = destinationTransportInput.capacity(); if (capacity == Transport.END_OF_STREAM) { if (source.hasRemaining()) { throw new IllegalStateException("Destination has reached end of stream: " + destinationTransportInput); } else { return Transport.END_OF_STREAM; } } int total = source.remaining(); while(source.hasRemaining() && destinationTransportInput.capacity() > 0) { pour(source, destinationTransportInput.tail()); destinationTransportInput.process(); } return total - source.remaining(); } /** * Assumes {@code source} is ready to be read. * * @returns number of bytes poured which may be fewer than {@code sizeRequested} if * {@code source} has insufficient remaining */ public static int pourBufferToArray(ByteBuffer source, byte[] destination, int offset, int sizeRequested) { int numberToRead = Math.min(source.remaining(), sizeRequested); source.get(destination, offset, numberToRead); return numberToRead; } public static ByteBuffer newWriteableBuffer(int capacity) { ByteBuffer newBuffer = ByteBuffer.allocate(capacity); return newBuffer; } public static ByteBuffer newReadableBuffer(int capacity) { ByteBuffer newBuffer = ByteBuffer.allocate(capacity); newBuffer.flip(); return newBuffer; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/AmqpHeader.java0000664000000000000000000000210112562450203026341 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine.impl; public interface AmqpHeader { public static final byte[] HEADER = new byte[] { 'A', 'M', 'Q', 'P', 0, 1, 0, 0 }; public static final byte[] SASL_HEADER = new byte[] { 'A', 'M', 'Q', 'P', 3, 1, 0, 0 }; } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/AmqpErrorException.java0000664000000000000000000000162112562450203030127 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine.impl; public class AmqpErrorException extends Exception { } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/TransportResultFactory.java0000664000000000000000000000714212562450203030126 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import static org.apache.qpid.proton.engine.TransportResult.Status.ERROR; import static org.apache.qpid.proton.engine.TransportResult.Status.OK; import java.util.IllegalFormatException; import java.util.logging.Level; import java.util.logging.Logger; /** * Creates TransportResults. * Only intended for use by internal Proton classes. * This class resides in the api module so it can be used by both proton-j-impl and proton-jni. */ public class TransportResultFactory { private static final Logger LOGGER = Logger.getLogger(TransportResultFactory.class.getName()); private static final TransportResult _okResult = new TransportResultImpl(OK, null, null); public static TransportResult ok() { return _okResult; } public static TransportResult error(String format, Object... args) { String errorDescription; try { errorDescription = String.format(format, args); } catch(IllegalFormatException e) { LOGGER.log(Level.SEVERE, "Formating error in string " + format, e); errorDescription = format; } return new TransportResultImpl(ERROR, errorDescription, null); } public static TransportResult error(final String errorDescription) { return new TransportResultImpl(ERROR, errorDescription, null); } public static TransportResult error(final Exception e) { return new TransportResultImpl(ERROR, e == null ? null : e.toString(), e); } private static final class TransportResultImpl implements TransportResult { private final String _errorDescription; private final Status _status; private final Exception _exception; private TransportResultImpl(Status status, String errorDescription, Exception exception) { _status = status; _errorDescription = errorDescription; _exception = exception; } @Override public boolean isOk() { return _status == OK; } @Override public Status getStatus() { return _status; } @Override public String getErrorDescription() { return _errorDescription; } @Override public Exception getException() { return _exception; } @Override public void checkIsOk() { if (!isOk()) { Exception e = getException(); if (e != null) { throw new TransportException(e); } else { throw new TransportException(getErrorDescription()); } } } } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/TransportResult.java0000664000000000000000000000221112562450203026566 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; public interface TransportResult { enum Status { OK, ERROR } Status getStatus(); String getErrorDescription(); Exception getException(); /** * @throws TransportException if the result's state is not ok. */ void checkIsOk(); boolean isOk(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/TransportException.java0000664000000000000000000000360012562450203027251 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import java.util.IllegalFormatException; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.qpid.proton.ProtonException; public class TransportException extends ProtonException { private static final Logger LOGGER = Logger.getLogger(TransportException.class.getName()); public TransportException() { } public TransportException(String message) { super(message); } public TransportException(String message, Throwable cause) { super(message, cause); } public TransportException(Throwable cause) { super(cause); } private static String format(String format, Object ... args) { try { return String.format(format, args); } catch(IllegalFormatException e) { LOGGER.log(Level.SEVERE, "Formating error in string " + format, e); return format; } } public TransportException(String format, Object ... args) { this(format(format, args)); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Transport.java0000664000000000000000000001741412562450203025402 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import java.nio.ByteBuffer; import org.apache.qpid.proton.amqp.transport.ErrorCondition; import org.apache.qpid.proton.engine.impl.TransportImpl; /** *

* Operates on the entities in the associated {@link Connection} * by accepting and producing binary AMQP output, potentially * layered within SASL and/or SSL. *

*

* After a connection is bound with {@link #bind(Connection)}, the methods for accepting and producing * output are typically repeatedly called. See the specific methods for details of their legal usage. *

*

* Processing the input data received from another AMQP container. *

    *
  1. {@link #getInputBuffer()}
  2. *
  3. Write data into input buffer
  4. *
  5. {@link #processInput()}
  6. *
  7. Check the result, e.g. by calling {@link TransportResult#checkIsOk()}
  8. *
*

*

* Getting the output data to send to another AMQP container: *

    *
  1. {@link #getOutputBuffer()}
  2. *
  3. Read output from output buffer
  4. *
  5. {@link #outputConsumed()}
  6. *
*

* *

The following methods on the byte buffers returned by {@link #getInputBuffer()} and {@link #getOutputBuffer()} * must not be called: *

    *
  1. {@link ByteBuffer#clear()}
  2. *
  3. {@link ByteBuffer#compact()}
  4. *
  5. {@link ByteBuffer#flip()}
  6. *
  7. {@link ByteBuffer#mark()}
  8. *
*

*/ public interface Transport extends Endpoint { public static final class Factory { public static Transport create() { return new TransportImpl(); } } public static final int TRACE_OFF = 0; public static final int TRACE_RAW = 1; public static final int TRACE_FRM = 2; public static final int TRACE_DRV = 4; public static final int DEFAULT_MAX_FRAME_SIZE = -1; /** the lower bound for the agreed maximum frame size (in bytes). */ public int MIN_MAX_FRAME_SIZE = 512; public int SESSION_WINDOW = 16*1024; public int END_OF_STREAM = -1; public void trace(int levels); public void bind(Connection connection); public void unbind(); public int capacity(); public ByteBuffer tail(); public void process() throws TransportException; public void close_tail(); public int pending(); public ByteBuffer head(); public void pop(int bytes); public void close_head(); public boolean isClosed(); /** * Processes the provided input. * * @param bytes input bytes for consumption * @param offset the offset within bytes where input begins * @param size the number of bytes available for input * * @return the number of bytes consumed * @throws TransportException if the input is invalid, if the transport is already in an error state, * or if the input is empty (unless the remote connection is already closed) * @deprecated use {@link #getInputBuffer()} and {@link #processInput()} instead. */ @Deprecated public int input(byte[] bytes, int offset, int size); /** * Get a buffer that can be used to write input data into the transport. * Once the client has finished putting into the input buffer, {@link #processInput()} * must be called. * * Successive calls to this method are not guaranteed to return the same object. * Once {@link #processInput()} is called the buffer must not be used. * * @throws TransportException if the transport is already in an invalid state */ ByteBuffer getInputBuffer(); /** * Tell the transport to process the data written to the input buffer. * * If the returned result indicates failure, the transport will not accept any more input. * Specifically, any subsequent {@link #processInput()} calls on this object will * throw an exception. * * @return the result of processing the data, which indicates success or failure. * @see #getInputBuffer() */ TransportResult processInput(); /** * Has the transport produce up to size bytes placing the result * into dest beginning at position offset. * * @param dest array for output bytes * @param offset the offset within bytes where output begins * @param size the maximum number of bytes to be output * * @return the number of bytes written * @deprecated use {@link #getOutputBuffer()} and {@link #outputConsumed()} instead */ @Deprecated public int output(byte[] dest, int offset, int size); /** * Get a read-only byte buffer containing the transport's pending output. * Once the client has finished getting from the output buffer, {@link #outputConsumed()} * must be called. * * Successive calls to this method are not guaranteed to return the same object. * Once {@link #outputConsumed()} is called the buffer must not be used. * * If the transport's state changes AFTER calling this method, this will not be * reflected in the output buffer. */ ByteBuffer getOutputBuffer(); /** * Informs the transport that the output buffer returned by {@link #getOutputBuffer()} * is finished with, allowing implementation-dependent steps to be performed such as * reclaiming buffer space. */ void outputConsumed(); /** * Signal the transport to expect SASL frames used to establish a SASL layer prior to * performing the AMQP protocol version negotiation. This must first be performed before * the transport is used for processing. Subsequent invocations will return the same * {@link Sasl} object. * * @throws IllegalStateException if transport processing has already begun prior to initial invocation */ Sasl sasl() throws IllegalStateException; /** * Wrap this transport's output and input to apply SSL encryption and decryption respectively. * * This method is expected to be called at most once. A subsequent invocation will return the same * {@link Ssl} object, regardless of the parameters supplied. * * @param sslDomain the SSL settings to use * @param sslPeerDetails may be null, in which case SSL session resume will not be attempted * @return an {@link Ssl} object representing the SSL session. */ Ssl ssl(SslDomain sslDomain, SslPeerDetails sslPeerDetails); /** * As per {@link #ssl(SslDomain, SslPeerDetails)} but no attempt is made to resume a previous SSL session. */ Ssl ssl(SslDomain sslDomain); /** * Get the maximum frame size for the transport * * @return the maximum frame size */ int getMaxFrameSize(); void setMaxFrameSize(int size); int getRemoteMaxFrameSize(); int getChannelMax(); void setChannelMax(int n); int getRemoteChannelMax(); ErrorCondition getCondition(); void setIdleTimeout(int timeout); int getIdleTimeout(); int getRemoteIdleTimeout(); long tick(long now); long getFramesInput(); long getFramesOutput(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/SslPeerDetails.java0000664000000000000000000000303612562450203026264 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.engine.impl.ssl.SslPeerDetailsImpl; /** * The details of the remote peer involved in an SSL session. * * Used when creating an SSL session to hint that the underlying SSL implementation * should attempt to resume a previous session if one exists for the same peer details, * e.g. using session identifiers (http://tools.ietf.org/html/rfc5246) or session tickets * (http://tools.ietf.org/html/rfc5077). */ public interface SslPeerDetails { public static final class Factory { public static SslPeerDetails create(String hostname, int port) { return new SslPeerDetailsImpl(hostname, port); } } String getHostname(); int getPort(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/SslDomain.java0000664000000000000000000001173412562450203025276 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.engine.impl.ssl.SslDomainImpl; /** * I store the details used to create SSL sessions. */ public interface SslDomain { public static final class Factory { public static SslDomain create() { return new SslDomainImpl(); } } /** * Determines whether the endpoint acts as a client or server. */ public enum Mode { /** Local connection endpoint is an SSL client */ CLIENT, /** Local connection endpoint is an SSL server */ SERVER } /** * Determines the level of peer validation. * * {@link #ANONYMOUS_PEER} is configured by default. */ public enum VerifyMode { /** * will only connect to those peers that provide a valid identifying certificate signed * by a trusted CA and are using an authenticated cipher */ VERIFY_PEER, VERIFY_PEER_NAME, /** * does not require a valid certificate, and permits use of ciphers that * do not provide authentication */ ANONYMOUS_PEER, } /** * Initialize the ssl domain object. * * An SSL object be either an SSL server or an SSL client. It cannot be both. Those * transports that will be used to accept incoming connection requests must be configured * as an SSL server. Those transports that will be used to initiate outbound connections * must be configured as an SSL client. * */ void init(Mode mode); Mode getMode(); /** * Set the certificate that identifies the local node to the remote. * * This certificate establishes the identity for the local node. It will be sent to the * remote if the remote needs to verify the identity of this node. This may be used for * both SSL servers and SSL clients (if client authentication is required by the server). * * @param certificateFile path to file/database containing the identifying * certificate. * @param privateKeyFile path to file/database containing the private key used to * sign the certificate * @param password the password used to sign the key, else null if key is not * protected. */ void setCredentials(String certificateFile, String privateKeyFile, String password); String getPrivateKeyFile(); String getPrivateKeyPassword(); String getCertificateFile(); /** * Configure the set of trusted CA certificates used by this node to verify peers. * * If the local SSL client/server needs to verify the identity of the remote, it must * validate the signature of the remote's certificate. This function sets the database of * trusted CAs that will be used to verify the signature of the remote's certificate. * * @param certificateDb database of trusted CAs, used to authenticate the peer. */ void setTrustedCaDb(String certificateDb); String getTrustedCaDb(); /** * Configure the level of verification used on the peer certificate. * * This method controls how the peer's certificate is validated, if at all. By default, * neither servers nor clients attempt to verify their peers ({@link VerifyMode#ANONYMOUS_PEER}). * Once certificates and trusted CAs are configured, peer verification can be enabled. * * In order to verify a peer, a trusted CA must be configured. See * {@link #setTrustedCaDb(String)}. * * @note Servers must provide their own certificate when verifying a peer. See * {@link #setCredentials(String, String, String)}). * * @param mode the level of validation to apply to the peer */ void setPeerAuthentication(VerifyMode mode); VerifyMode getPeerAuthentication(); /** * Permit a server to accept connection requests from non-SSL clients. * * This configures the server to "sniff" the incoming client data stream, and dynamically * determine whether SSL/TLS is being used. This option is disabled by default: only * clients using SSL/TLS are accepted. */ void allowUnsecuredClient(boolean allowUnsecured); boolean allowUnsecuredClient(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Ssl.java0000664000000000000000000000341612562450203024144 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; /** * I represent the details of a particular SSL session. */ public interface Ssl { /** * Get the name of the Cipher that is currently in use. * * Gets a text description of the cipher that is currently active, or returns null if SSL * is not active (no cipher). Note that the cipher in use may change over time due to * renegotiation or other changes to the SSL state. * * @return the name of the cipher in use, or null if none */ String getCipherName(); /** * Get the name of the SSL protocol that is currently in use. * * Gets a text description of the SSL protocol that is currently active, or null if SSL * is not active. Note that the protocol may change over time due to renegotiation. * * @return the name of the protocol in use, or null if none */ String getProtocolName(); void setPeerHostname(String hostname); String getPeerHostname(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Session.java0000664000000000000000000000331312562450203025022 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import java.util.EnumSet; /** * Session * * Note that session level flow control is handled internally by Proton. */ public interface Session extends Endpoint { /** * Returns a newly created sender endpoint */ public Sender sender(String name); /** * Returns a newly created receiver endpoint */ public Receiver receiver(String name); public Session next(EnumSet local, EnumSet remote); public Connection getConnection(); public int getIncomingCapacity(); public void setIncomingCapacity(int bytes); public int getIncomingBytes(); public int getOutgoingBytes(); public long getOutgoingWindow(); /** * Sets the outgoing window size. * * @param outgoingWindowSize the outgoing window size */ public void setOutgoingWindow(long outgoingWindowSize); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Sender.java0000664000000000000000000000434312562450203024623 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; /** * Sender * */ public interface Sender extends Link { /** * indicates pending deliveries * * @param credits the number of pending deliveries * @todo is this absolute or cumulative? */ public void offer(int credits); /** * Sends some data for the current delivery. The application may call this method multiple * times for the same delivery. * * @return the number of bytes accepted * * TODO Proton-j current copies all the bytes it has been given so the return value will always be * length. Should this be changed? How does Proton-c behave? What should the application do if * the number of bytes accepted is smaller than length. */ public int send(byte[] bytes, int offset, int length); /** * Abort the current delivery. * * Note "pn_link_abort" is commented out in the .h */ public void abort(); /** * {@inheritDoc} * * Informs the sender that all the bytes of the current {@link Delivery} have been written. * The application must call this method in order for the delivery to be considered complete. * * @see #send(byte[], int, int) * * TODO fully state the rules regarding when you have to call this method, what happens if you don't call it * before creating another delivery etc. */ @Override public boolean advance(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Sasl.java0000664000000000000000000001241112562450203024300 0ustar package org.apache.qpid.proton.engine; /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ public interface Sasl { public enum SaslState { /** Pending configuration by application */ PN_SASL_CONF, /** Pending SASL Init */ PN_SASL_IDLE, /** negotiation in progress */ PN_SASL_STEP, /** negotiation completed successfully */ PN_SASL_PASS, /** negotiation failed */ PN_SASL_FAIL } public enum SaslOutcome { /** negotiation not completed */ PN_SASL_NONE((byte)-1), /** authentication succeeded */ PN_SASL_OK((byte)0), /** failed due to bad credentials */ PN_SASL_AUTH((byte)1), /** failed due to a system error */ PN_SASL_SYS((byte)2), /** failed due to unrecoverable error */ PN_SASL_PERM((byte)3), PN_SASL_TEMP((byte)4), PN_SASL_SKIPPED((byte)5); private final byte _code; /** failed due to transient error */ SaslOutcome(byte code) { _code = code; } public byte getCode() { return _code; } } public static SaslOutcome PN_SASL_NONE = SaslOutcome.PN_SASL_NONE; public static SaslOutcome PN_SASL_OK = SaslOutcome.PN_SASL_OK; public static SaslOutcome PN_SASL_AUTH = SaslOutcome.PN_SASL_AUTH; public static SaslOutcome PN_SASL_SYS = SaslOutcome.PN_SASL_SYS; public static SaslOutcome PN_SASL_PERM = SaslOutcome.PN_SASL_PERM; public static SaslOutcome PN_SASL_TEMP = SaslOutcome.PN_SASL_TEMP; public static SaslOutcome PN_SASL_SKIPPED = SaslOutcome.PN_SASL_SKIPPED; /** * Access the current state of the layer. * * @return The state of the sasl layer. */ SaslState getState(); /** * Set the acceptable SASL mechanisms for the layer. * * @param mechanisms a list of acceptable SASL mechanisms */ void setMechanisms(String... mechanisms); /** * Retrieve the list of SASL mechanisms provided by the remote. * * @return the SASL mechanisms advertised by the remote */ String[] getRemoteMechanisms(); /** * Set the remote hostname to indicate the host being connected to when * sending a SaslInit to the server. */ void setRemoteHostname(String hostname); /** * Retrieve the hostname indicated by the client when sending its SaslInit. * * @return the hostname indicated by the remote client, or null if none specified. */ String getHostname(); /** * Determine the size of the bytes available via recv(). * * Returns the size in bytes available via recv(). * * @return The number of bytes available, zero if no available data. */ int pending(); /** * Read challenge/response data sent from the peer. * * Use pending to determine the size of the data. * * @param bytes written with up to size bytes of inbound data. * @param offset the offset in the array to begin writing at * @param size maximum number of bytes that bytes can accept. * @return The number of bytes written to bytes, or an error code if < 0. */ int recv(byte[] bytes, int offset, int size); /** * Send challenge or response data to the peer. * * @param bytes The challenge/response data. * @param offset the point within the array at which the data starts at * @param size The number of data octets in bytes. * @return The number of octets read from bytes, or an error code if < 0 */ int send(byte[] bytes, int offset, int size); /** * Set the outcome of SASL negotiation * * Used by the server to set the result of the negotiation process. * * @todo */ void done(SaslOutcome outcome); /** * Configure the SASL layer to use the "PLAIN" mechanism. * * A utility function to configure a simple client SASL layer using * PLAIN authentication. * * @param username credential for the PLAIN authentication * mechanism * @param password credential for the PLAIN authentication * mechanism */ void plain(String username, String password); /** * Retrieve the outcome of SASL negotiation. */ SaslOutcome getOutcome(); void client(); void server(); /** * Set whether servers may accept incoming connections * that skip the SASL layer negotiation. */ void allowSkip(boolean allowSkip); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Record.java0000664000000000000000000000177712562450203024631 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; /** * Record * */ public interface Record { T get(Object key, Class klass); void set(Object key, Class klass, T value); void clear(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Receiver.java0000664000000000000000000000513712562450203025151 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; /** * Receiver * */ public interface Receiver extends Link { /** * Adds the specified number of credits. * * The number of link credits initialises to zero. It is the application's responsibility to call * this method to allow the receiver to receive {@code credits} more deliveries. */ public void flow(int credits); /** * Receive message data for the current delivery. * * If the caller takes all the bytes the Receiver currently has for this delivery then it is removed from * the Connection's work list. * * Before considering a delivery to be complete, the caller should examine {@link Delivery#isPartial()}. If * the delivery is partial, the caller should call {@link #recv(byte[], int, int)} again to receive * the additional bytes once the Delivery appears again on the Connection work-list. * * TODO might the flags other than IO_WORK in DeliveryImpl also prevent the work list being pruned? * e.g. what if a slow JMS consumer receives a disposition frame containing state=RELEASED? This is not IO_WORK. * * @param bytes the destination array where the message data is written * @param offset index in the array to start writing data at * @param size the maximum number of bytes to write * * @return number of bytes written. -1 if there are no more bytes for the current delivery. * * @see #current() */ public int recv(byte[] bytes, int offset, int size); public void drain(int credit); /** * {@inheritDoc} * * TODO document what this method conceptually does and when you should use it. */ @Override public boolean advance(); public boolean draining(); public void setDrain(boolean drain); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/ProtonJTransport.java0000664000000000000000000000225412562450203026712 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.impl.ProtocolTracer; /** * Extends {@link Transport} with functionality that is specific to proton-j */ public interface ProtonJTransport extends Transport { void setProtocolTracer(ProtocolTracer protocolTracer); ProtocolTracer getProtocolTracer(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/ProtonJSslPeerDetails.java0000664000000000000000000000203312562450203027574 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.engine.SslPeerDetails; /** * Extends {@link SslPeerDetails} with functionality specific to proton-j */ public interface ProtonJSslPeerDetails extends SslPeerDetails { } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/ProtonJSslDomain.java0000664000000000000000000000201712562450203026604 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.engine.SslDomain; /** * Extends {@link SslDomain} with functionality that is specific to proton-j */ public interface ProtonJSslDomain extends SslDomain { } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/ProtonJSession.java0000664000000000000000000000214412562450203026337 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.engine.Sender; import org.apache.qpid.proton.engine.Session; /** * Extends {@link Session} with functionality that is specific to proton-j */ public interface ProtonJSession extends Session, ProtonJEndpoint { Sender sender(String name); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/ProtonJEndpoint.java0000664000000000000000000000167012562450203026477 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.engine.Endpoint; public interface ProtonJEndpoint extends Endpoint { }qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/ProtonJConnection.java0000664000000000000000000000224212562450203027012 0ustar /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.engine.Connection; /** * Extends {@link Connection} with functionality that is specific to proton-j */ public interface ProtonJConnection extends Connection, ProtonJEndpoint { void setLocalContainerId(String localContainerId); @Override ProtonJSession session(); int getMaxChannels(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Link.java0000664000000000000000000001363712562450203024306 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import java.util.EnumSet; import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode; import org.apache.qpid.proton.amqp.transport.SenderSettleMode; import org.apache.qpid.proton.amqp.transport.Source; import org.apache.qpid.proton.amqp.transport.Target; /** * Link * * The settlement mode defaults are: * * Sender settle mode - {@link SenderSettleMode#MIXED}. * Receiver settle mode - {@link ReceiverSettleMode#FIRST} * * TODO describe the application's responsibility to honour settlement. */ public interface Link extends Endpoint { /** * Returns the name of the link * * @return the link name */ String getName(); /** * Create a delivery object based on the specified tag and adds it to the * this link's delivery list and its connection work list. * * TODO to clarify - this adds the delivery to the connection list. It is not yet * clear why this is done or if it is useful for the application to be able to discover * newly created deliveries from the {@link Connection#getWorkHead()}. * * @param tag a tag for the delivery * @return a new Delivery object */ public Delivery delivery(byte[] tag); /** * Create a delivery object based on the specified tag. This form * of the method is intended to allow the tag to be formed from a * subsequence of the byte array passed in. This might allow more * optimisation options in future but at present is not * implemented. * * @param tag a tag for the delivery * @param offset (currently ignored and must be 0) * @param length (currently ignored and must be the length of the tag array * @return a Delivery object */ public Delivery delivery(byte[] tag, int offset, int length); /** * Returns the head delivery on the link. */ Delivery head(); /** * Returns the current delivery */ Delivery current(); /** * Attempts to advance the current delivery. Advances it to the next delivery if one exists, else null. * * The behaviour of this method is different for senders and receivers. * * @return true if it can advance, false if it cannot * * TODO document the meaning of the return value more fully. Currently Senderimpl only returns false if there is no current delivery */ boolean advance(); Source getSource(); Target getTarget(); /** * Sets the source for this link. * * The initiator of the link must always provide a Source. * * An application responding to the creation of the link should perform an application * specific lookup on the {@link #getRemoteSource()} to determine an actual Source. If it * failed to determine an actual source, it should set null, and then go on to {@link #close()} * the link. * * @see "AMQP Spec 1.0 section 2.6.3" */ void setSource(Source address); /** * Expected to be used in a similar manner to {@link #setSource(Source)} */ void setTarget(Target address); /** * @see #setSource(Source) */ Source getRemoteSource(); /** * @see #setTarget(Target) */ Target getRemoteTarget(); public Link next(EnumSet local, EnumSet remote); public int getCredit(); public int getQueued(); public int getUnsettled(); public Session getSession(); SenderSettleMode getSenderSettleMode(); /** * Sets the sender settle mode. * * Should only be called during link set-up, i.e. before calling {@link #open()}. * * If this endpoint is the initiator of the link, this method can be used to set a value other than * the default. * * If this endpoint is not the initiator, this method should be used to set a local value. According * to the AMQP spec, the application may choose to accept the sender's suggestion * (accessed by calling {@link #getRemoteSenderSettleMode()}) or choose another value. The value * has no effect on Proton, but may be useful to the application at a later point. * * In order to be AMQP compliant the application is responsible for honouring the settlement mode. See {@link Link}. */ void setSenderSettleMode(SenderSettleMode senderSettleMode); /** * @see #setSenderSettleMode(SenderSettleMode) */ SenderSettleMode getRemoteSenderSettleMode(); ReceiverSettleMode getReceiverSettleMode(); /** * Sets the receiver settle mode. * * Used in analogous way to {@link #setSenderSettleMode(SenderSettleMode)} */ void setReceiverSettleMode(ReceiverSettleMode receiverSettleMode); /** * @see #setReceiverSettleMode(ReceiverSettleMode) */ ReceiverSettleMode getRemoteReceiverSettleMode(); /** * TODO should this be part of the interface? */ @Deprecated void setRemoteSenderSettleMode(SenderSettleMode remoteSenderSettleMode); public int drained(); public int getRemoteCredit(); public boolean getDrain(); public void detach(); public boolean detached(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/HandlerException.java0000664000000000000000000000227512562450203026641 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; public class HandlerException extends RuntimeException { private static final long serialVersionUID = 5300211824119834005L; private final Handler handler; public HandlerException(Handler handler, Throwable cause) { super(cause); this.handler = handler; } public Handler getHandler() { return handler; } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Handler.java0000664000000000000000000000471312562450203024761 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import java.util.Iterator; /** * Handler * */ public interface Handler { void onConnectionInit(Event e); void onConnectionLocalOpen(Event e); void onConnectionRemoteOpen(Event e); void onConnectionLocalClose(Event e); void onConnectionRemoteClose(Event e); void onConnectionBound(Event e); void onConnectionUnbound(Event e); void onConnectionFinal(Event e); void onSessionInit(Event e); void onSessionLocalOpen(Event e); void onSessionRemoteOpen(Event e); void onSessionLocalClose(Event e); void onSessionRemoteClose(Event e); void onSessionFinal(Event e); void onLinkInit(Event e); void onLinkLocalOpen(Event e); void onLinkRemoteOpen(Event e); void onLinkLocalDetach(Event e); void onLinkRemoteDetach(Event e); void onLinkLocalClose(Event e); void onLinkRemoteClose(Event e); void onLinkFlow(Event e); void onLinkFinal(Event e); void onDelivery(Event e); void onTransport(Event e); void onTransportError(Event e); void onTransportHeadClosed(Event e); void onTransportTailClosed(Event e); void onTransportClosed(Event e); void onReactorInit(Event e); void onReactorQuiesced(Event e); void onReactorFinal(Event e); void onTimerTask(Event e); void onSelectableInit(Event e); void onSelectableUpdated(Event e); void onSelectableReadable(Event e); void onSelectableWritable(Event e); void onSelectableExpired(Event e); void onSelectableError(Event e); void onSelectableFinal(Event e); void onUnhandled(Event e); void add(Handler child); Iterator children(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Extendable.java0000664000000000000000000000165512562450203025461 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; /** * Extendable * */ public interface Extendable { Record attachments(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Event.java0000664000000000000000000000467512562450203024474 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.reactor.Reactor; import org.apache.qpid.proton.reactor.Selectable; import org.apache.qpid.proton.reactor.Task; /** * Event * */ public interface Event extends Extendable { public enum Type { REACTOR_INIT, REACTOR_QUIESCED, REACTOR_FINAL, TIMER_TASK, CONNECTION_INIT, CONNECTION_BOUND, CONNECTION_UNBOUND, CONNECTION_LOCAL_OPEN, CONNECTION_REMOTE_OPEN, CONNECTION_LOCAL_CLOSE, CONNECTION_REMOTE_CLOSE, CONNECTION_FINAL, SESSION_INIT, SESSION_LOCAL_OPEN, SESSION_REMOTE_OPEN, SESSION_LOCAL_CLOSE, SESSION_REMOTE_CLOSE, SESSION_FINAL, LINK_INIT, LINK_LOCAL_OPEN, LINK_REMOTE_OPEN, LINK_LOCAL_DETACH, LINK_REMOTE_DETACH, LINK_LOCAL_CLOSE, LINK_REMOTE_CLOSE, LINK_FLOW, LINK_FINAL, DELIVERY, TRANSPORT, TRANSPORT_ERROR, TRANSPORT_HEAD_CLOSED, TRANSPORT_TAIL_CLOSED, TRANSPORT_CLOSED, SELECTABLE_INIT, SELECTABLE_UPDATED, SELECTABLE_READABLE, SELECTABLE_WRITABLE, SELECTABLE_EXPIRED, SELECTABLE_ERROR, SELECTABLE_FINAL } Type getType(); Object getContext(); void dispatch(Handler handler) throws HandlerException; Connection getConnection(); Session getSession(); Link getLink(); Delivery getDelivery(); Transport getTransport(); Reactor getReactor(); Selectable getSelectable(); Task getTask(); Event copy(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Engine.java0000664000000000000000000000270612562450203024611 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; /** * Engine * */ public final class Engine { private Engine() { } public static Collector collector() { return Collector.Factory.create(); } public static Connection connection() { return Connection.Factory.create(); } public static Transport transport() { return Transport.Factory.create(); } public static SslDomain sslDomain() { return SslDomain.Factory.create(); } public static SslPeerDetails sslPeerDetails(String hostname, int port) { return SslPeerDetails.Factory.create(hostname, port); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/EndpointState.java0000664000000000000000000000173412562450203026165 0ustar package org.apache.qpid.proton.engine; /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /** * Represents the state of a communication endpoint. */ public enum EndpointState { UNINITIALIZED, ACTIVE, CLOSED; } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Endpoint.java0000664000000000000000000000403212562450203025156 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.amqp.transport.ErrorCondition; public interface Endpoint extends Extendable { /** * @return the local endpoint state */ public EndpointState getLocalState(); /** * @return the remote endpoint state (as last communicated) */ public EndpointState getRemoteState(); /** * @return the local endpoint error, or null if there is none */ public ErrorCondition getCondition(); /** * Set the local error condition * @param condition */ public void setCondition(ErrorCondition condition); /** * @return the remote endpoint error, or null if there is none */ public ErrorCondition getRemoteCondition(); /** * free the endpoint and any associated resources */ public void free(); /** * transition local state to ACTIVE */ void open(); /** * transition local state to CLOSED */ void close(); /** * Sets an arbitrary an application owned object on the end-point. This object * is not used by Proton. */ public void setContext(Object o); /** * @see #setContext(Object) */ public Object getContext(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Delivery.java0000664000000000000000000000645712562450203025176 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.amqp.transport.DeliveryState; /** * A delivery of a message on a particular link. * * Whilst a message is logically a long-lived object, a delivery is short-lived - it * is only intended to be used by the application until it is settled and all its data has been read. */ public interface Delivery extends Extendable { public byte[] getTag(); public Link getLink(); public DeliveryState getLocalState(); public DeliveryState getRemoteState(); /** TODO is this required?? */ public int getMessageFormat(); /** * updates the state of the delivery * * @param state the new delivery state */ public void disposition(DeliveryState state); /** * Settles this delivery. * * Causes the delivery to be removed from the connection's work list (see {@link Connection#getWorkHead()}). * If this delivery is its link's current delivery, the link's current delivery pointer is advanced. */ public void settle(); /** * Returns whether this delivery has been settled. * * TODO proton-j and proton-c return the local and remote statuses respectively. Resolve this ambiguity. * * @see #settle() */ public boolean isSettled(); public boolean remotelySettled(); /** * TODO When does an application call this method? Do we really need this? */ public void free(); /** * @see Connection#getWorkHead() */ public Delivery getWorkNext(); public Delivery next(); public boolean isWritable(); /** * Returns whether this delivery has data ready to be received. * * @see Receiver#recv(byte[], int, int) */ public boolean isReadable(); public void setContext(Object o); public Object getContext(); /** * Returns whether this delivery's state or settled flag has ever remotely changed. * * TODO what is the main intended use case for calling this method? */ public boolean isUpdated(); public void clear(); public boolean isPartial(); public int pending(); public boolean isBuffered(); /** * Configures a default DeliveryState to be used if a * received delivery is settled/freed without any disposition * state having been previously applied. * * @param state the default delivery state */ public void setDefaultDeliveryState(DeliveryState state); public DeliveryState getDefaultDeliveryState(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Connection.java0000664000000000000000000000734412562450203025506 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import java.util.EnumSet; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.engine.impl.ConnectionImpl; import org.apache.qpid.proton.reactor.Reactor; import org.apache.qpid.proton.reactor.ReactorChild; /** * Maintains lists of sessions, links and deliveries in a state * that is interesting to the application. * * These are exposed by returning the head of those lists via * {@link #sessionHead(EnumSet, EnumSet)}, {@link #linkHead(EnumSet, EnumSet)} * {@link #getWorkHead()} respectively. */ public interface Connection extends Endpoint, ReactorChild { public static final class Factory { public static Connection create() { return new ConnectionImpl(); } } /** * Returns a newly created session * * TODO does the Connection's channel-max property limit how many sessions can be created, * or opened, or neither? */ public Session session(); /** * Returns the head of the list of sessions in the specified states. * * Typically used to discover sessions whose remote state has acquired * particular values, e.g. sessions that have been remotely opened or closed. * * TODO what ordering guarantees on the returned "linked list" are provided? * * @see Session#next(EnumSet, EnumSet) */ public Session sessionHead(EnumSet local, EnumSet remote); /** * Returns the head of the list of links in the specified states. * * Typically used to discover links whose remote state has acquired * particular values, e.g. links that have been remotely opened or closed. * * @see Link#next(EnumSet, EnumSet) */ public Link linkHead(EnumSet local, EnumSet remote); /** * Returns the head of the delivery work list. The delivery work list consists of * unsettled deliveries whose state has been changed by the other container * and not yet locally processed. * * @see Receiver#recv(byte[], int, int) * @see Delivery#settle() * @see Delivery#getWorkNext() */ public Delivery getWorkHead(); public void setContainer(String container); public String getContainer(); public void setHostname(String hostname); public String getHostname(); public String getRemoteContainer(); public String getRemoteHostname(); void setOfferedCapabilities(Symbol[] capabilities); void setDesiredCapabilities(Symbol[] capabilities); Symbol[] getRemoteOfferedCapabilities(); Symbol[] getRemoteDesiredCapabilities(); Map getRemoteProperties(); void setProperties(Map properties); @Override Object getContext(); @Override void setContext(Object context); void collect(Collector collector); Transport getTransport(); Reactor getReactor(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/Collector.java0000664000000000000000000000222112562450203025322 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import org.apache.qpid.proton.engine.impl.CollectorImpl; /** * Collector * */ public interface Collector { public static final class Factory { public static Collector create() { return new CollectorImpl(); } } Event peek(); void pop(); boolean more(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/engine/BaseHandler.java0000664000000000000000000001115312562450203025550 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.engine; import java.util.HashSet; import java.util.Iterator; /** * BaseHandler * */ public class BaseHandler implements Handler { public static Handler getHandler(Record r) { return r.get(Handler.class, Handler.class); } public static void setHandler(Record r, Handler handler) { r.set(Handler.class, Handler.class, handler); } public static Handler getHandler(Extendable ext) { return ext.attachments().get(Handler.class, Handler.class); } public static void setHandler(Extendable ext, Handler handler) { ext.attachments().set(Handler.class, Handler.class, handler); } private HashSet children = new HashSet(); @Override public void onConnectionInit(Event e) { onUnhandled(e); } @Override public void onConnectionLocalOpen(Event e) { onUnhandled(e); } @Override public void onConnectionRemoteOpen(Event e) { onUnhandled(e); } @Override public void onConnectionLocalClose(Event e) { onUnhandled(e); } @Override public void onConnectionRemoteClose(Event e) { onUnhandled(e); } @Override public void onConnectionBound(Event e) { onUnhandled(e); } @Override public void onConnectionUnbound(Event e) { onUnhandled(e); } @Override public void onConnectionFinal(Event e) { onUnhandled(e); } @Override public void onSessionInit(Event e) { onUnhandled(e); } @Override public void onSessionLocalOpen(Event e) { onUnhandled(e); } @Override public void onSessionRemoteOpen(Event e) { onUnhandled(e); } @Override public void onSessionLocalClose(Event e) { onUnhandled(e); } @Override public void onSessionRemoteClose(Event e) { onUnhandled(e); } @Override public void onSessionFinal(Event e) { onUnhandled(e); } @Override public void onLinkInit(Event e) { onUnhandled(e); } @Override public void onLinkLocalOpen(Event e) { onUnhandled(e); } @Override public void onLinkRemoteOpen(Event e) { onUnhandled(e); } @Override public void onLinkLocalDetach(Event e) { onUnhandled(e); } @Override public void onLinkRemoteDetach(Event e) { onUnhandled(e); } @Override public void onLinkLocalClose(Event e) { onUnhandled(e); } @Override public void onLinkRemoteClose(Event e) { onUnhandled(e); } @Override public void onLinkFlow(Event e) { onUnhandled(e); } @Override public void onLinkFinal(Event e) { onUnhandled(e); } @Override public void onDelivery(Event e) { onUnhandled(e); } @Override public void onTransport(Event e) { onUnhandled(e); } @Override public void onTransportError(Event e) { onUnhandled(e); } @Override public void onTransportHeadClosed(Event e) { onUnhandled(e); } @Override public void onTransportTailClosed(Event e) { onUnhandled(e); } @Override public void onTransportClosed(Event e) { onUnhandled(e); } @Override public void onReactorInit(Event e) { onUnhandled(e); } @Override public void onReactorQuiesced(Event e) { onUnhandled(e); } @Override public void onReactorFinal(Event e) { onUnhandled(e); } @Override public void onTimerTask(Event e) { onUnhandled(e); } @Override public void onSelectableInit(Event e) { onUnhandled(e); } @Override public void onSelectableUpdated(Event e) { onUnhandled(e); } @Override public void onSelectableReadable(Event e) { onUnhandled(e); } @Override public void onSelectableWritable(Event e) { onUnhandled(e); } @Override public void onSelectableExpired(Event e) { onUnhandled(e); } @Override public void onSelectableError(Event e) { onUnhandled(e); } @Override public void onSelectableFinal(Event e) { onUnhandled(e); } @Override public void onUnhandled(Event event) {} @Override public void add(Handler child) { children.add(child); } @Override public Iterator children() { return children.iterator(); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/driver/0000775000000000000000000000000012562450203022562 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/driver/impl/0000775000000000000000000000000012562450203023523 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/driver/impl/ListenerImpl.java0000664000000000000000000000472712562450203027007 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.driver.impl; import java.io.IOException; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.qpid.proton.driver.Connector; import org.apache.qpid.proton.driver.Listener; class ListenerImpl implements Listener { private C _context; private final ServerSocketChannel _channel; private final DriverImpl _driver; private final Logger _logger = Logger.getLogger("proton.driver"); private boolean _selected = false; ListenerImpl(DriverImpl driver, ServerSocketChannel c, C context) { _driver = driver; _channel = c; _context = context; } void selected() { if (!_selected) { _selected = true; _driver.selectListener(this); } } void unselected() { _selected = false; } public Connector accept() { try { SocketChannel c = _channel.accept(); if(c != null) { c.configureBlocking(false); return _driver.createServerConnector(c, null, this); } } catch (IOException e) { _logger.log(Level.SEVERE, "Exception when accepting connection",e); } return null; //TODO - we should probably throw an exception instead of returning null? } public C getContext() { return _context; } public void setContext(C context) { _context = context; } public void close() throws IOException { _channel.socket().close(); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/driver/impl/DriverImpl.java0000664000000000000000000001653412562450203026454 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.driver.impl; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.ArrayDeque; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.Queue; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.qpid.proton.driver.Connector; import org.apache.qpid.proton.driver.Driver; import org.apache.qpid.proton.driver.Listener; public class DriverImpl implements Driver { private Selector _selector; private Collection _listeners = new LinkedList(); private Collection _connectors = new LinkedList(); private Logger _logger = Logger.getLogger("proton.driver"); private Object _wakeupLock = new Object(); private boolean _woken = false; private Queue _selectedConnectors = new ArrayDeque(); private Queue _selectedListeners = new ArrayDeque(); public DriverImpl() throws IOException { _selector = Selector.open(); } public void wakeup() { synchronized (_wakeupLock) { _woken = true; } _selector.wakeup(); } public boolean doWait(long timeout) { try { boolean woken; synchronized (_wakeupLock) { woken = _woken; } if (woken || timeout == 0) { _selector.selectNow(); } else if (timeout < 0) { _selector.select(); } else { _selector.select(timeout); } synchronized (_wakeupLock) { woken = woken || _woken; _woken = false; } for (SelectionKey key : _selector.selectedKeys()) { if (key.isAcceptable()) { ListenerImpl l = (ListenerImpl) key.attachment(); l.selected(); } else { ConnectorImpl c = (ConnectorImpl) key.attachment(); c.selected(); } } _selector.selectedKeys().clear(); return woken; } catch (IOException e) { _logger.log(Level.SEVERE, "Exception when waiting for IO Event",e); throw new RuntimeException(e); } } void selectListener(ListenerImpl l) { _selectedListeners.add(l); } public Listener listener() { ListenerImpl listener = _selectedListeners.poll(); if (listener != null) { listener.unselected(); } return listener; } void selectConnector(ConnectorImpl c) { _selectedConnectors.add(c); } public Connector connector() { ConnectorImpl connector = _selectedConnectors.poll(); if (connector != null) { connector.unselected(); } return connector; } public void destroy() { try { _selector.close(); } catch (IOException e) { _logger.log(Level.SEVERE, "Exception when closing selector",e); throw new RuntimeException(e); } _listeners.clear(); _connectors.clear(); } public Listener createListener(String host, int port, C context) { try { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); ServerSocket serverSocket = serverSocketChannel.socket(); serverSocket.bind(new InetSocketAddress(host, port)); serverSocketChannel.configureBlocking(false); Listener listener = createListener(serverSocketChannel, context); _logger.fine("Created listener on " + host + ":" + port + ": " + context); return listener; } catch (ClosedChannelException e) { e.printStackTrace(); // TODO - Implement } catch (IOException e) { e.printStackTrace(); // TODO - Implement } return null; } public Listener createListener(ServerSocketChannel c, C context) { Listener l = new ListenerImpl(this, c, context); SelectionKey key = registerInterest(c,SelectionKey.OP_ACCEPT); key.attach(l); _listeners.add(l); return l; } public Connector createConnector(String host, int port, C context) { try { SocketChannel channel = SocketChannel.open(); channel.configureBlocking(false); // Disable the Nagle algorithm on TCP connections. channel.socket().setTcpNoDelay(true); channel.connect(new InetSocketAddress(host, port)); return createConnector(channel, context); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); throw new RuntimeException(e); } } public Connector createConnector(SelectableChannel c, C context) { SelectionKey key = registerInterest(c, SelectionKey.OP_READ | SelectionKey.OP_WRITE); Connector co = new ConnectorImpl(this, null, (SocketChannel)c, context, key); key.attach(co); _connectors.add(co); return co; } public void removeConnector(Connector c) { _connectors.remove(c); } public Iterable listeners() { return _listeners; } public Iterable connectors() { return _connectors; } protected Connector createServerConnector(SelectableChannel c, C context, Listener l) { SelectionKey key = registerInterest(c, SelectionKey.OP_READ | SelectionKey.OP_WRITE); Connector co = new ConnectorImpl(this, l, (SocketChannel)c, context, key); key.attach(co); _connectors.add(co); return co; } private SelectionKey registerInterest(SelectableChannel c, int opKeys) { try { return c.register(_selector, opKeys); } catch (ClosedChannelException e) { e.printStackTrace(); // TODO - Implement throw new RuntimeException(e); } } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/driver/impl/ConnectorImpl.java0000664000000000000000000001633612562450203027153 0ustar /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.qpid.proton.driver.impl; import static org.apache.qpid.proton.driver.impl.ConnectorImpl.ConnectorState.UNINITIALIZED; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.qpid.proton.Proton; import org.apache.qpid.proton.driver.Connector; import org.apache.qpid.proton.driver.Listener; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.Sasl; import org.apache.qpid.proton.engine.Transport; import org.apache.qpid.proton.engine.TransportException; class ConnectorImpl implements Connector { private static int DEFAULT_BUFFER_SIZE = 64 * 1024; private static int readBufferSize = Integer.getInteger ("pn.receive_buffer_size", DEFAULT_BUFFER_SIZE); private static int writeBufferSize = Integer.getInteger ("pn.send_buffer_size", DEFAULT_BUFFER_SIZE); enum ConnectorState {UNINITIALIZED, OPENED, EOS, CLOSED}; private final DriverImpl _driver; private final Listener _listener; private final SocketChannel _channel; private final Logger _logger = Logger.getLogger("proton.driver"); private C _context; private Connection _connection; private Transport _transport = Proton.transport(); private SelectionKey _key; private ConnectorState _state = UNINITIALIZED; private boolean _inputDone = false; private boolean _outputDone = false; private boolean _closed = false; private boolean _selected = false; private boolean _readAllowed = false; ConnectorImpl(DriverImpl driver, Listener listener, SocketChannel c, C context, SelectionKey key) { _driver = driver; _listener = listener; _channel = c; _context = context; _key = key; } void selected() { if (!_selected) { _selected = true; _driver.selectConnector(this); _readAllowed = true; } } void unselected() { _selected = false; } public boolean process() throws IOException { if (isClosed() || !_channel.finishConnect()) return false; boolean processed = false; if (!_inputDone) { if (read()) { processed = true; } } if (!_outputDone) { if (write()) { processed = true; } } if (_outputDone && _inputDone) { close(); } return processed; } private boolean read() throws IOException { if (!_readAllowed) return false; _readAllowed = false; boolean processed = false; int interest = _key.interestOps(); int capacity = _transport.capacity(); if (capacity == Transport.END_OF_STREAM) { _inputDone = true; } else { ByteBuffer tail = _transport.tail(); int bytesRead = _channel.read(tail); if (bytesRead < 0) { _transport.close_tail(); _inputDone = true; } else if (bytesRead > 0) { try { _transport.process(); } catch (TransportException e) { _logger.log(Level.SEVERE, this + " error processing input", e); } processed = true; } } capacity = _transport.capacity(); if (capacity > 0) { interest |= SelectionKey.OP_READ; } else { interest &= ~SelectionKey.OP_READ; if (capacity < 0) { _inputDone = true; } } _key.interestOps(interest); return processed; } private boolean write() throws IOException { boolean processed = false; int interest = _key.interestOps(); boolean writeBlocked = false; try { while (_transport.pending() > 0 && !writeBlocked) { ByteBuffer head = _transport.head(); int wrote = _channel.write(head); if (wrote > 0) { processed = true; _transport.pop(wrote); } else { writeBlocked = true; } } int pending = _transport.pending(); if (pending > 0) { interest |= SelectionKey.OP_WRITE; } else { interest &= ~SelectionKey.OP_WRITE; if (pending < 0) { _outputDone = true; } } } catch (TransportException e) { _logger.log(Level.SEVERE, this + " error", e); interest &= ~SelectionKey.OP_WRITE; _inputDone = true; _outputDone = true; } _key.interestOps(interest); return processed; } public Listener listener() { return _listener; } public Sasl sasl() { if (_transport != null) { return _transport.sasl(); } else { return null; } } public Connection getConnection() { return _connection; } public void setConnection(Connection connection) { _connection = connection; _transport.bind(_connection); } public Transport getTransport() { return _transport; } public C getContext() { return _context; } public void setContext(C context) { _context = context; } public void close() { if (!isClosed()) { try { _channel.close(); } catch (IOException e) { _logger.log(Level.SEVERE, "Exception when closing connection",e); } finally { _closed = true; selected(); } } } public boolean isClosed() { return _closed; } public void destroy() { close(); // close if not closed already _driver.removeConnector(this); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("ConnectorImpl [_channel=").append(_channel).append("]"); return builder.toString(); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/driver/Listener.java0000664000000000000000000000351412562450203025215 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.driver; /** * Server API. * * @param application supplied context */ public interface Listener { /** * Accept a connection that is pending on the listener. * * @return a new connector for the remote, or NULL on error. */ Connector accept(); /** * Access the application context that is associated with the listener. * * @return the application context that was passed when creating this * listener. See {@link Driver#createListener(String, int, Object) * createListener(String, int, Object)} and * {@link Driver#createConnector(java.nio.channels.SelectableChannel, Object) * createConnector(java.nio.channels.SelectableChannel, Object)} */ C getContext(); /** * Set the application context that is associated with this listener. * */ void setContext(C ctx); /** * Close the socket used by the listener. * */ void close() throws java.io.IOException; } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/driver/Driver.java0000664000000000000000000001203512562450203024661 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.driver; import java.io.IOException; import java.nio.channels.SelectableChannel; import java.nio.channels.ServerSocketChannel; import org.apache.qpid.proton.driver.impl.DriverImpl; /** * A driver for the proton engine. * * Manages {@link Connector}'s and {@link Listener}'s, which act as intermediaries between * the proton engine and the network. * * Provides methods for the application to access the "top half" of the engine API when the state * of the engine may have changed due to I/O or timing events - see {@link #connector()}. * * Connectors incorporate the SASL engine in order to provide a complete network stack: * AMQP over SASL over TCP. * * Unless otherwise stated, methods on Driver implementations are not necessarily thread-safe. */ public interface Driver { public static final class Factory { public static Driver create() throws IOException { return new DriverImpl(); } } /** * Force {@link #doWait(long)} to return. * * If the driver is not currently waiting then the next invocation of {@link #doWait(long)} * will return immediately unless the {@link #connector()} method is invoked in the meantime. * * Thread-safe. */ void wakeup(); /** * Wait for an active connector or listener, or for {@link #wakeup()} to be called. * * Thread-safe. * * @param timeout maximum time in milliseconds to wait. -1 means wait indefinitely. * * @param returns true if woken up */ boolean doWait(long timeout); /** * Get the next listener with pending data in the driver. * * @return null if no active listener available */ @SuppressWarnings("rawtypes") Listener listener(); /** * Get the next active connector in the driver. * * Returns the next connector with pending inbound data, available capacity * for outbound data, or pending tick. * * Clears the wake-up status that is set by {@link #wakeup()}. * * @return null if no active connector available */ @SuppressWarnings("rawtypes") Connector connector(); /** * Destruct the driver and all associated listeners, connectors and other resources. */ void destroy(); /** * Construct a listener for the given address. * * @param host local host address to listen on * @param port local port to listen on * @param context application-supplied, can be accessed via * {@link Listener#getContext() getContext()} method on a listener. * @return a new listener on the given host:port, null if error */ Listener createListener(String host, int port, C context); /** * Create a listener using the existing channel. * * @param c existing SocketChannel for listener to listen on * @param context application-supplied, can be accessed via * {@link Listener#getContext() getContext()} method on a listener. * @return a new listener on the given channel, null if error */ Listener createListener(ServerSocketChannel c, C context); /** * Construct a connector to the given remote address. * * @param host remote host to connect to. * @param port remote port to connect to. * @param context application-supplied, can be accessed via * {@link Connector#getContext() getContext()} method on a listener. * * @return a new connector to the given remote, or null on error. */ Connector createConnector(String host, int port, C context); /** * Create a connector using the existing file descriptor. * * @param fd existing SocketChannel for listener to listen on * @param context application-supplied, can be accessed via * {@link Connector#getContext() getContext()} method on a listener. * * @return a new connector to the given host:port, null if error. */ Connector createConnector(SelectableChannel fd, C context); /** * Return an iterator over all listeners. */ Iterable listeners(); /** * Return an iterator over all connectors. */ Iterable connectors(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/driver/Connector.java0000664000000000000000000000732612562450203025367 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.driver; import java.io.IOException; import org.apache.qpid.proton.engine.Connection; import org.apache.qpid.proton.engine.Sasl; import org.apache.qpid.proton.engine.Transport; /** * Intermediates between a proton engine {@link Connection} and the I/O * layer. * * The top half of the engine can be access via {@link #getConnection()}. * The bottom half of the engine is used by {@link #process()}. * Stores application specific context using {@link #setContext(Object)}. * * Implementations are not necessarily thread-safe. * * @param application supplied context */ public interface Connector { /** * Handle any inbound data, outbound data, or timing events pending on * the connector. * Typically, applications repeatedly invoke this method * during the lifetime of a connection. */ boolean process() throws IOException; /** * Access the listener which opened this connector. * * @return the listener which created this connector, or null if the * connector has no listener (e.g. an outbound client * connection). */ @SuppressWarnings("rawtypes") Listener listener(); /** * Access the Authentication and Security context of the connector. * * @return the Authentication and Security context for the connector, * or null if none. */ Sasl sasl(); /** * Access the Transport associated with the connector. * */ Transport getTransport(); /** * Access the AMQP Connection associated with the connector. * * @return the connection context for the connector, or null if none. */ Connection getConnection(); /** * Assign the AMQP Connection associated with the connector. * * @param connection the connection to associate with the connector. */ void setConnection(Connection connection); /** * Access the application context that is associated with the connector. * * @return the application context that was passed when creating this * connector. See * {@link Driver#createConnector(String, int, Object) * createConnector(String, int, Object)} and * {@link Driver#createConnector(java.nio.channels.SelectableChannel, Object) * createConnector(java.nio.channels.SelectableChannel, Object)}. */ C getContext(); /** * Assign a new application context to the connector. * * @param context new application context to associate with the connector */ void setContext(C context); /** * Close the socket used by the connector. */ void close(); /** * Determine if the connector is closed. */ boolean isClosed(); /** * Destructor for the given connector. * * Assumes the connector's socket has been closed prior to call. */ void destroy(); } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/0000775000000000000000000000000012562450203022344 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/0000775000000000000000000000000012562450203024400 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/TransferType.java0000664000000000000000000001461712562450203027702 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transport; import java.util.AbstractList; import java.util.List; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedByte; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transport.DeliveryState; import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode; import org.apache.qpid.proton.amqp.transport.Transfer; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public final class TransferType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000014L), Symbol.valueOf("amqp:transfer:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000014L); private TransferType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Transfer val) { return new TransferWrapper(val); } public static class TransferWrapper extends AbstractList { private Transfer _transfer; public TransferWrapper(Transfer transfer) { _transfer = transfer; } public Object get(final int index) { switch(index) { case 0: return _transfer.getHandle(); case 1: return _transfer.getDeliveryId(); case 2: return _transfer.getDeliveryTag(); case 3: return _transfer.getMessageFormat(); case 4: return _transfer.getSettled(); case 5: return _transfer.getMore(); case 6: return _transfer.getRcvSettleMode() == null ? null : _transfer.getRcvSettleMode().getValue(); case 7: return _transfer.getState(); case 8: return _transfer.getResume(); case 9: return _transfer.getAborted(); case 10: return _transfer.getBatchable(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _transfer.getBatchable() ? 11 : _transfer.getAborted() ? 10 : _transfer.getResume() ? 9 : _transfer.getState() != null ? 8 : _transfer.getRcvSettleMode() != null ? 7 : _transfer.getMore() ? 6 : _transfer.getSettled() != null ? 5 : _transfer.getMessageFormat() != null ? 4 : _transfer.getDeliveryTag() != null ? 3 : _transfer.getDeliveryId() != null ? 2 : 1; } } public Transfer newInstance(Object described) { List l = (List) described; Transfer o = new Transfer(); if(l.isEmpty()) { throw new DecodeException("The handle field cannot be omitted"); } switch(11 - l.size()) { case 0: Boolean batchable = (Boolean) l.get(10); o.setBatchable(batchable == null ? false : batchable); case 1: Boolean aborted = (Boolean) l.get(9); o.setAborted(aborted == null ? false : aborted); case 2: Boolean resume = (Boolean) l.get(8); o.setResume(resume == null ? false : resume); case 3: o.setState( (DeliveryState) l.get( 7 ) ); case 4: UnsignedByte receiverSettleMode = (UnsignedByte) l.get(6); o.setRcvSettleMode(receiverSettleMode == null ? null : ReceiverSettleMode.values()[receiverSettleMode.intValue()]); case 5: Boolean more = (Boolean) l.get(5); o.setMore(more == null ? false : more ); case 6: o.setSettled( (Boolean) l.get( 4 ) ); case 7: o.setMessageFormat( (UnsignedInteger) l.get( 3 ) ); case 8: o.setDeliveryTag( (Binary) l.get( 2 ) ); case 9: o.setDeliveryId( (UnsignedInteger) l.get( 1 ) ); case 10: o.setHandle( (UnsignedInteger) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Transfer.class; } public static void register(Decoder decoder, EncoderImpl encoder) { TransferType type = new TransferType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/OpenType.java0000664000000000000000000001534412562450203027015 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transport; import java.util.AbstractList; import java.util.List; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.UnsignedShort; import org.apache.qpid.proton.amqp.transport.Open; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public final class OpenType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000010L), Symbol.valueOf("amqp:open:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000010L); private OpenType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Open val) { return new OpenWrapper(val); } public static class OpenWrapper extends AbstractList { private Open _open; public OpenWrapper(Open open) { _open = open; } public Object get(final int index) { switch(index) { case 0: return _open.getContainerId(); case 1: return _open.getHostname(); case 2: return _open.getMaxFrameSize(); case 3: return _open.getChannelMax(); case 4: return _open.getIdleTimeOut(); case 5: return _open.getOutgoingLocales(); case 6: return _open.getIncomingLocales(); case 7: return _open.getOfferedCapabilities(); case 8: return _open.getDesiredCapabilities(); case 9: return _open.getProperties(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _open.getProperties() != null ? 10 : _open.getDesiredCapabilities() != null ? 9 : _open.getOfferedCapabilities() != null ? 8 : _open.getIncomingLocales() != null ? 7 : _open.getOutgoingLocales() != null ? 6 : _open.getIdleTimeOut() != null ? 5 : (_open.getChannelMax() != null && !_open.getChannelMax().equals(UnsignedShort.MAX_VALUE)) ? 4 : (_open.getMaxFrameSize() != null && !_open.getMaxFrameSize().equals(UnsignedInteger.MAX_VALUE)) ? 3 : _open.getHostname() != null ? 2 : 1; } } public Open newInstance(Object described) { List l = (List) described; Open o = new Open(); if(l.isEmpty()) { throw new DecodeException("The container-id field cannot be omitted"); } switch(10 - l.size()) { case 0: o.setProperties( (Map) l.get( 9 ) ); case 1: Object val1 = l.get( 8 ); if( val1 == null || val1.getClass().isArray() ) { o.setDesiredCapabilities( (Symbol[]) val1 ); } else { o.setDesiredCapabilities( (Symbol) val1 ); } case 2: Object val2 = l.get( 7 ); if( val2 == null || val2.getClass().isArray() ) { o.setOfferedCapabilities( (Symbol[]) val2 ); } else { o.setOfferedCapabilities( (Symbol) val2 ); } case 3: Object val3 = l.get( 6 ); if( val3 == null || val3.getClass().isArray() ) { o.setIncomingLocales( (Symbol[]) val3 ); } else { o.setIncomingLocales( (Symbol) val3 ); } case 4: Object val4 = l.get( 5 ); if( val4 == null || val4.getClass().isArray() ) { o.setOutgoingLocales( (Symbol[]) val4 ); } else { o.setOutgoingLocales( (Symbol) val4 ); } case 5: o.setIdleTimeOut( (UnsignedInteger) l.get( 4 ) ); case 6: UnsignedShort channelMax = (UnsignedShort) l.get(3); o.setChannelMax(channelMax == null ? UnsignedShort.MAX_VALUE : channelMax); case 7: UnsignedInteger maxFrameSize = (UnsignedInteger) l.get(2); o.setMaxFrameSize(maxFrameSize == null ? UnsignedInteger.MAX_VALUE : maxFrameSize); case 8: o.setHostname( (String) l.get( 1 ) ); case 9: o.setContainerId( (String) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Open.class; } public static void register(Decoder decoder, EncoderImpl encoder) { OpenType type = new OpenType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/FlowType.java0000664000000000000000000001261112562450203027015 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transport; import java.util.AbstractList; import java.util.List; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transport.Flow; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public final class FlowType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000013L), Symbol.valueOf("amqp:flow:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000013L); private FlowType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Flow val) { return new FlowWrapper(val); } public static class FlowWrapper extends AbstractList { private Flow _flow; public FlowWrapper(Flow flow) { _flow = flow; } public Object get(final int index) { switch(index) { case 0: return _flow.getNextIncomingId(); case 1: return _flow.getIncomingWindow(); case 2: return _flow.getNextOutgoingId(); case 3: return _flow.getOutgoingWindow(); case 4: return _flow.getHandle(); case 5: return _flow.getDeliveryCount(); case 6: return _flow.getLinkCredit(); case 7: return _flow.getAvailable(); case 8: return _flow.getDrain(); case 9: return _flow.getEcho(); case 10: return _flow.getProperties(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _flow.getProperties() != null ? 11 : _flow.getEcho() ? 10 : _flow.getDrain() ? 9 : _flow.getAvailable() != null ? 8 : _flow.getLinkCredit() != null ? 7 : _flow.getDeliveryCount() != null ? 6 : _flow.getHandle() != null ? 5 : 4; } } public Flow newInstance(Object described) { List l = (List) described; Flow o = new Flow(); if(l.size() <= 3) { throw new DecodeException("The outgoing-window field cannot be omitted"); } switch(11 - l.size()) { case 0: o.setProperties( (Map) l.get( 10 ) ); case 1: Boolean echo = (Boolean) l.get(9); o.setEcho(echo == null ? false : echo); case 2: Boolean drain = (Boolean) l.get(8); o.setDrain(drain == null ? false : drain ); case 3: o.setAvailable( (UnsignedInteger) l.get( 7 ) ); case 4: o.setLinkCredit( (UnsignedInteger) l.get( 6 ) ); case 5: o.setDeliveryCount( (UnsignedInteger) l.get( 5 ) ); case 6: o.setHandle( (UnsignedInteger) l.get( 4 ) ); case 7: o.setOutgoingWindow( (UnsignedInteger) l.get( 3 ) ); case 8: o.setNextOutgoingId( (UnsignedInteger) l.get( 2 ) ); case 9: o.setIncomingWindow( (UnsignedInteger) l.get( 1 ) ); case 10: o.setNextIncomingId( (UnsignedInteger) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Flow.class; } public static void register(Decoder decoder, EncoderImpl encoder) { FlowType type = new FlowType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/ErrorConditionType.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/ErrorConditionType.ja0000664000000000000000000000753712562450203030532 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transport; import java.util.AbstractList; import java.util.List; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transport.ErrorCondition; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public final class ErrorConditionType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x000000000000001dL), Symbol.valueOf("amqp:error:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x000000000000001dL); private ErrorConditionType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(ErrorCondition val) { return new ErrorConditionWrapper(val); } public static class ErrorConditionWrapper extends AbstractList { private ErrorCondition _errorCondition; public ErrorConditionWrapper(ErrorCondition errorCondition) { _errorCondition = errorCondition; } public Object get(final int index) { switch(index) { case 0: return _errorCondition.getCondition(); case 1: return _errorCondition.getDescription(); case 2: return _errorCondition.getInfo(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _errorCondition.getInfo() != null ? 3 : _errorCondition.getDescription() != null ? 2 : 1; } } public ErrorCondition newInstance(Object described) { List l = (List) described; ErrorCondition o = new ErrorCondition(); if(l.isEmpty()) { throw new DecodeException("The condition field cannot be omitted"); } switch(3 - l.size()) { case 0: o.setInfo( (Map) l.get( 2 ) ); case 1: o.setDescription( (String) l.get( 1 ) ); case 2: o.setCondition( (Symbol) l.get( 0 ) ); } return o; } public Class getTypeClass() { return ErrorCondition.class; } public static void register(Decoder decoder, EncoderImpl encoder) { ErrorConditionType type = new ErrorConditionType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/EndType.java0000664000000000000000000000513212562450203026614 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transport; import java.util.Collections; import java.util.List; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transport.End; import org.apache.qpid.proton.amqp.transport.ErrorCondition; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public final class EndType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000017L), Symbol.valueOf("amqp:end:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000017L); private EndType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(End val) { ErrorCondition errorCondition = val.getError(); return errorCondition == null ? Collections.EMPTY_LIST : Collections.singletonList(errorCondition); } public End newInstance(Object described) { List l = (List) described; End o = new End(); if(!l.isEmpty()) { o.setError( (ErrorCondition) l.get( 0 ) ); } return o; } public Class getTypeClass() { return End.class; } public static void register(Decoder decoder, EncoderImpl encoder) { EndType type = new EndType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/DispositionType.java0000664000000000000000000001147612562450203030422 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transport; import java.util.AbstractList; import java.util.List; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transport.DeliveryState; import org.apache.qpid.proton.amqp.transport.Disposition; import org.apache.qpid.proton.amqp.transport.Role; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public final class DispositionType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000015L), Symbol.valueOf("amqp:disposition:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000015L); private DispositionType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Disposition val) { return new DispositionWrapper(val); } private static final class DispositionWrapper extends AbstractList { private Disposition _disposition; public DispositionWrapper(Disposition disposition) { _disposition = disposition; } public Object get(final int index) { switch(index) { case 0: return _disposition.getRole().getValue(); case 1: return _disposition.getFirst(); case 2: return _disposition.getLast(); case 3: return _disposition.getSettled(); case 4: return _disposition.getState(); case 5: return _disposition.getBatchable(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _disposition.getBatchable() ? 6 : _disposition.getState() != null ? 5 : _disposition.getSettled() ? 4 : _disposition.getLast() != null ? 3 : 2; } } public Disposition newInstance(Object described) { List l = (List) described; Disposition o = new Disposition(); if(l.isEmpty()) { throw new DecodeException("The first field cannot be omitted"); } switch(6 - l.size()) { case 0: Boolean batchable = (Boolean) l.get(5); o.setBatchable(batchable == null ? false : batchable); case 1: o.setState( (DeliveryState) l.get( 4 ) ); case 2: Boolean settled = (Boolean) l.get(3); o.setSettled(settled == null ? false : settled); case 3: o.setLast( (UnsignedInteger) l.get( 2 ) ); case 4: o.setFirst( (UnsignedInteger) l.get( 1 ) ); case 5: o.setRole( Boolean.TRUE.equals(l.get( 0 )) ? Role.RECEIVER : Role.SENDER ); } return o; } public Class getTypeClass() { return Disposition.class; } public static void register(Decoder decoder, EncoderImpl encoder) { DispositionType type = new DispositionType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/DetachType.java0000664000000000000000000000742712562450203027307 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transport; import java.util.AbstractList; import java.util.List; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transport.Detach; import org.apache.qpid.proton.amqp.transport.ErrorCondition; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public final class DetachType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000016L), Symbol.valueOf("amqp:detach:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000016L); private DetachType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Detach val) { return new DetachWrapper(val); } public static class DetachWrapper extends AbstractList { private Detach _detach; public DetachWrapper(Detach detach) { _detach = detach; } public Object get(final int index) { switch(index) { case 0: return _detach.getHandle(); case 1: return _detach.getClosed(); case 2: return _detach.getError(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _detach.getError() != null ? 3 : _detach.getClosed() ? 2 : 1; } } public Detach newInstance(Object described) { List l = (List) described; Detach o = new Detach(); if(l.isEmpty()) { throw new DecodeException("The handle field cannot be omitted"); } switch(3 - l.size()) { case 0: o.setError( (ErrorCondition) l.get( 2 ) ); case 1: Boolean closed = (Boolean) l.get(1); o.setClosed(closed == null ? false : closed); case 2: o.setHandle( (UnsignedInteger) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Detach.class; } public static void register(Decoder decoder, EncoderImpl encoder) { DetachType type = new DetachType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/CloseType.java0000664000000000000000000000513012562450203027151 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transport; import java.util.Collections; import java.util.List; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transport.Close; import org.apache.qpid.proton.amqp.transport.ErrorCondition; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public final class CloseType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000018L), Symbol.valueOf("amqp:close:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000018L); private CloseType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Close val) { ErrorCondition error = val.getError(); return error == null ? Collections.EMPTY_LIST : Collections.singletonList(error); } public Close newInstance(Object described) { List l = (List) described; Close o = new Close(); if(!l.isEmpty()) { o.setError( (ErrorCondition) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Close.class; } public static void register(Decoder decoder, EncoderImpl encoder) { CloseType type = new CloseType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/BeginType.java0000664000000000000000000001265112562450203027136 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transport; import java.util.AbstractList; import java.util.List; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.UnsignedShort; import org.apache.qpid.proton.amqp.transport.Begin; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public final class BeginType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000011L), Symbol.valueOf("amqp:begin:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000011L); private BeginType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Begin val) { return new BeginWrapper(val); } private static class BeginWrapper extends AbstractList { private Begin _begin; public BeginWrapper(Begin begin) { _begin = begin; } public Object get(final int index) { switch(index) { case 0: return _begin.getRemoteChannel(); case 1: return _begin.getNextOutgoingId(); case 2: return _begin.getIncomingWindow(); case 3: return _begin.getOutgoingWindow(); case 4: return _begin.getHandleMax(); case 5: return _begin.getOfferedCapabilities(); case 6: return _begin.getDesiredCapabilities(); case 7: return _begin.getProperties(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _begin.getProperties() != null ? 8 : _begin.getDesiredCapabilities() != null ? 7 : _begin.getOfferedCapabilities() != null ? 6 : (_begin.getHandleMax() != null && !_begin.getHandleMax().equals(UnsignedInteger.MAX_VALUE)) ? 5 : 4; } } public Begin newInstance(Object described) { List l = (List) described; Begin o = new Begin(); if(l.size() <= 3) { throw new DecodeException("The outgoing-window field cannot be omitted"); } switch(8 - l.size()) { case 0: o.setProperties( (Map) l.get( 7 ) ); case 1: Object val1 = l.get( 6 ); if( val1 == null || val1.getClass().isArray() ) { o.setDesiredCapabilities( (Symbol[]) val1 ); } else { o.setDesiredCapabilities( (Symbol) val1 ); } case 2: Object val2 = l.get( 5 ); if( val2 == null || val2.getClass().isArray() ) { o.setOfferedCapabilities( (Symbol[]) val2 ); } else { o.setOfferedCapabilities( (Symbol) val2 ); } case 3: UnsignedInteger handleMax = (UnsignedInteger) l.get(4); o.setHandleMax(handleMax == null ? UnsignedInteger.MAX_VALUE : handleMax); case 4: o.setOutgoingWindow( (UnsignedInteger) l.get( 3 ) ); case 5: o.setIncomingWindow( (UnsignedInteger) l.get( 2 ) ); case 6: o.setNextOutgoingId( (UnsignedInteger) l.get( 1 ) ); case 7: o.setRemoteChannel( (UnsignedShort) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Begin.class; } public static void register(Decoder decoder, EncoderImpl encoder) { BeginType type = new BeginType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transport/AttachType.java0000664000000000000000000001751612562450203027323 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transport; import java.util.AbstractList; import java.util.List; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedByte; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transport.Attach; import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode; import org.apache.qpid.proton.amqp.transport.Role; import org.apache.qpid.proton.amqp.transport.SenderSettleMode; import org.apache.qpid.proton.amqp.transport.Source; import org.apache.qpid.proton.amqp.transport.Target; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public final class AttachType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000012L), Symbol.valueOf("amqp:attach:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000012L); private AttachType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Attach val) { return new AttachWrapper(val); } public static class AttachWrapper extends AbstractList { private Attach _attach; public AttachWrapper(Attach attach) { _attach = attach; } public Object get(final int index) { switch(index) { case 0: return _attach.getName(); case 1: return _attach.getHandle(); case 2: return _attach.getRole().getValue(); case 3: return _attach.getSndSettleMode().getValue(); case 4: return _attach.getRcvSettleMode().getValue(); case 5: return _attach.getSource(); case 6: return _attach.getTarget(); case 7: return _attach.getUnsettled(); case 8: return _attach.getIncompleteUnsettled(); case 9: return _attach.getInitialDeliveryCount(); case 10: return _attach.getMaxMessageSize(); case 11: return _attach.getOfferedCapabilities(); case 12: return _attach.getDesiredCapabilities(); case 13: return _attach.getProperties(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _attach.getProperties() != null ? 14 : _attach.getDesiredCapabilities() != null ? 13 : _attach.getOfferedCapabilities() != null ? 12 : _attach.getMaxMessageSize() != null ? 11 : _attach.getInitialDeliveryCount() != null ? 10 : _attach.getIncompleteUnsettled() ? 9 : _attach.getUnsettled() != null ? 8 : _attach.getTarget() != null ? 7 : _attach.getSource() != null ? 6 : (_attach.getRcvSettleMode() != null && !_attach.getRcvSettleMode().equals(ReceiverSettleMode.FIRST)) ? 5 : (_attach.getSndSettleMode() != null && !_attach.getSndSettleMode().equals(SenderSettleMode.MIXED)) ? 4 : 3; } } public Attach newInstance(Object described) { List l = (List) described; Attach o = new Attach(); if(l.size() <= 2) { throw new DecodeException("The role field cannot be omitted"); } switch(14 - l.size()) { case 0: o.setProperties( (Map) l.get( 13 ) ); case 1: Object val1 = l.get( 12 ); if( val1 == null || val1.getClass().isArray() ) { o.setDesiredCapabilities( (Symbol[]) val1 ); } else { o.setDesiredCapabilities( (Symbol) val1 ); } case 2: Object val2 = l.get( 11 ); if( val2 == null || val2.getClass().isArray() ) { o.setOfferedCapabilities( (Symbol[]) val2 ); } else { o.setOfferedCapabilities( (Symbol) val2 ); } case 3: o.setMaxMessageSize( (UnsignedLong) l.get( 10 ) ); case 4: o.setInitialDeliveryCount( (UnsignedInteger) l.get( 9 ) ); case 5: Boolean incompleteUnsettled = (Boolean) l.get(8); o.setIncompleteUnsettled(incompleteUnsettled == null ? false : incompleteUnsettled); case 6: o.setUnsettled( (Map) l.get( 7 ) ); case 7: o.setTarget( (Target) l.get( 6 ) ); case 8: o.setSource( (Source) l.get( 5 ) ); case 9: UnsignedByte rcvSettleMode = (UnsignedByte) l.get(4); o.setRcvSettleMode(rcvSettleMode == null ? ReceiverSettleMode.FIRST : ReceiverSettleMode.values()[rcvSettleMode.intValue()]); case 10: UnsignedByte sndSettleMode = (UnsignedByte) l.get(3); o.setSndSettleMode(sndSettleMode == null ? SenderSettleMode.MIXED : SenderSettleMode.values()[sndSettleMode.intValue()]); case 11: o.setRole( Boolean.TRUE.equals( l.get( 2 ) ) ? Role.RECEIVER : Role.SENDER); case 12: o.setHandle( (UnsignedInteger) l.get( 1 ) ); case 13: o.setName( (String) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Attach.class; } public static void register(Decoder decoder, EncoderImpl encoder) { AttachType type = new AttachType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transaction/0000775000000000000000000000000012562450203024671 5ustar ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transaction/TransactionalStateType.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transaction/TransactionalStateT0000664000000000000000000000743612562450203030555 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transaction; import java.util.AbstractList; import java.util.List; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.messaging.Outcome; import org.apache.qpid.proton.amqp.transaction.TransactionalState; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class TransactionalStateType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000034L), Symbol.valueOf("amqp:transactional-state:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000034L); private TransactionalStateType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(TransactionalState val) { return new TransactionalStateWrapper(val); } public static class TransactionalStateWrapper extends AbstractList { private TransactionalState _transactionalState; public TransactionalStateWrapper(TransactionalState transactionalState) { _transactionalState = transactionalState; } public Object get(final int index) { switch(index) { case 0: return _transactionalState.getTxnId(); case 1: return _transactionalState.getOutcome(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _transactionalState.getOutcome() != null ? 2 : 1; } } public TransactionalState newInstance(Object described) { List l = (List) described; TransactionalState o = new TransactionalState(); if(l.isEmpty()) { throw new DecodeException("The txn-id field cannot be omitted"); } switch(2 - l.size()) { case 0: o.setOutcome( (Outcome) l.get( 1 ) ); case 1: o.setTxnId( (Binary) l.get( 0 ) ); } return o; } public Class getTypeClass() { return TransactionalState.class; } public static void register(Decoder decoder, EncoderImpl encoder) { TransactionalStateType type = new TransactionalStateType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transaction/DischargeType.java0000664000000000000000000000676512562450203030305 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transaction; import java.util.AbstractList; import java.util.List; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transaction.Discharge; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class DischargeType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000032L), Symbol.valueOf("amqp:discharge:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000032L); private DischargeType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Discharge val) { return new DischargeWrapper(val); } public static class DischargeWrapper extends AbstractList { private Discharge _discharge; public DischargeWrapper(Discharge discharge) { _discharge = discharge; } public Object get(final int index) { switch(index) { case 0: return _discharge.getTxnId(); case 1: return _discharge.getFail(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _discharge.getFail() != null ? 2 : 1; } } public Discharge newInstance(Object described) { List l = (List) described; Discharge o = new Discharge(); if(l.isEmpty()) { throw new DecodeException("The txn-id field cannot be omitted"); } switch(2 - l.size()) { case 0: o.setFail( (Boolean) l.get( 1 ) ); case 1: o.setTxnId( (Binary) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Discharge.class; } public static void register(Decoder decoder, EncoderImpl encoder) { DischargeType type = new DischargeType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transaction/DeclaredType.java0000664000000000000000000000523012562450203030101 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transaction; import java.util.Collections; import java.util.List; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transaction.Declared; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class DeclaredType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000033L), Symbol.valueOf("amqp:declared:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000033L); private DeclaredType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Declared val) { return Collections.singletonList(val.getTxnId()); } public Declared newInstance(Object described) { List l = (List) described; Declared o = new Declared(); if(l.isEmpty()) { throw new DecodeException("The txn-id field cannot be omitted"); } o.setTxnId( (Binary) l.get( 0 ) ); return o; } public Class getTypeClass() { return Declared.class; } public static void register(Decoder decoder, EncoderImpl encoder) { DeclaredType type = new DeclaredType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transaction/DeclareType.java0000664000000000000000000000517012562450203027740 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transaction; import java.util.Collections; import java.util.List; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transaction.Declare; import org.apache.qpid.proton.amqp.transaction.GlobalTxId; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class DeclareType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000031L), Symbol.valueOf("amqp:declare:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000031L); private DeclareType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Declare val) { GlobalTxId globalId = val.getGlobalId(); return globalId == null ? Collections.EMPTY_LIST : Collections.singletonList(globalId); } public Declare newInstance(Object described) { List l = (List) described; Declare o = new Declare(); if(!l.isEmpty()) { o.setGlobalId( (GlobalTxId) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Declare.class; } public static void register(Decoder decoder, EncoderImpl encoder) { DeclareType type = new DeclareType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transaction/CoordinatorType.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/transaction/CoordinatorType.jav0000664000000000000000000000573612562450203030533 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.transaction; import java.util.Collections; import java.util.List; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.transaction.Coordinator; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class CoordinatorType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000030L), Symbol.valueOf("amqp:coordinator:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000030L); private CoordinatorType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Coordinator val) { Symbol[] capabilities = val.getCapabilities(); return capabilities == null || capabilities.length == 0 ? Collections.EMPTY_LIST : Collections.singletonList(capabilities); } public Coordinator newInstance(Object described) { List l = (List) described; Coordinator o = new Coordinator(); switch(1 - l.size()) { case 0: Object val0 = l.get( 0 ); if( val0 == null || val0.getClass().isArray() ) { o.setCapabilities( (Symbol[]) val0 ); } else { o.setCapabilities( (Symbol) val0 ); } } return o; } public Class getTypeClass() { return Coordinator.class; } public static void register(Decoder decoder, EncoderImpl encoder) { CoordinatorType type = new CoordinatorType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/security/0000775000000000000000000000000012562450203024213 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/security/SaslResponseType.java0000664000000000000000000000543712562450203030352 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.security; import java.util.Collections; import java.util.List; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.security.SaslResponse; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class SaslResponseType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000043L), Symbol.valueOf("amqp:sasl-response:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000043L); private SaslResponseType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(SaslResponse val) { return Collections.singletonList(val.getResponse()); } public SaslResponse newInstance(Object described) { List l = (List) described; SaslResponse o = new SaslResponse(); if(l.isEmpty()) { throw new DecodeException("The response field cannot be omitted"); } switch(1 - l.size()) { case 0: o.setResponse( (Binary) l.get( 0 ) ); } return o; } public Class getTypeClass() { return SaslResponse.class; } public static void register(Decoder decoder, EncoderImpl encoder) { SaslResponseType type = new SaslResponseType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/security/SaslOutcomeType.java0000664000000000000000000000723312562450203030163 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.security; import java.util.AbstractList; import java.util.List; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedByte; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.security.SaslCode; import org.apache.qpid.proton.amqp.security.SaslOutcome; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class SaslOutcomeType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000044L), Symbol.valueOf("amqp:sasl-outcome:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000044L); private SaslOutcomeType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(SaslOutcome val) { return new SaslOutcomeWrapper(val); } public static final class SaslOutcomeWrapper extends AbstractList { private final SaslOutcome _impl; public SaslOutcomeWrapper(SaslOutcome impl) { _impl = impl; } public Object get(final int index) { switch(index) { case 0: return _impl.getCode().getValue(); case 1: return _impl.getAdditionalData(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _impl.getAdditionalData() != null ? 2 : 1; } } public SaslOutcome newInstance(Object described) { List l = (List) described; SaslOutcome o = new SaslOutcome(); if(l.isEmpty()) { throw new DecodeException("The code field cannot be omitted"); } switch(2 - l.size()) { case 0: o.setAdditionalData( (Binary) l.get( 1 ) ); case 1: o.setCode(SaslCode.valueOf((UnsignedByte) l.get(0))); } return o; } public Class getTypeClass() { return SaslOutcome.class; } public static void register(Decoder decoder, EncoderImpl encoder) { SaslOutcomeType type = new SaslOutcomeType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/security/SaslMechanismsType.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/security/SaslMechanismsType.jav0000664000000000000000000000565712562450203030506 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.security; import java.util.Collections; import java.util.List; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.security.SaslMechanisms; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class SaslMechanismsType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000040L), Symbol.valueOf("amqp:sasl-mechanisms:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000040L); private SaslMechanismsType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(SaslMechanisms val) { return Collections.singletonList(val.getSaslServerMechanisms()); } public SaslMechanisms newInstance(Object described) { List l = (List) described; SaslMechanisms o = new SaslMechanisms(); if(l.isEmpty()) { throw new DecodeException("The sasl-server-mechanisms field cannot be omitted"); } Object val0 = l.get( 0 ); if( val0 == null || val0.getClass().isArray() ) { o.setSaslServerMechanisms( (Symbol[]) val0 ); } else { o.setSaslServerMechanisms( (Symbol) val0 ); } return o; } public Class getTypeClass() { return SaslMechanisms.class; } public static void register(Decoder decoder, EncoderImpl encoder) { SaslMechanismsType type = new SaslMechanismsType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/security/SaslInitType.java0000664000000000000000000000735012562450203027453 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.security; import java.util.AbstractList; import java.util.List; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.security.SaslInit; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class SaslInitType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000041L), Symbol.valueOf("amqp:sasl-init:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000041L); private SaslInitType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(SaslInit val) { return new SaslInitWrapper(val); } public static class SaslInitWrapper extends AbstractList { private SaslInit _saslInit; public SaslInitWrapper(SaslInit saslInit) { _saslInit = saslInit; } public Object get(final int index) { switch(index) { case 0: return _saslInit.getMechanism(); case 1: return _saslInit.getInitialResponse(); case 2: return _saslInit.getHostname(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _saslInit.getHostname() != null ? 3 : _saslInit.getInitialResponse() != null ? 2 : 1; } } public SaslInit newInstance(Object described) { List l = (List) described; SaslInit o = new SaslInit(); if(l.size() <= 0) { throw new DecodeException("The mechanism field cannot be omitted"); } switch(3 - l.size()) { case 0: o.setHostname( (String) l.get( 2 ) ); case 1: o.setInitialResponse( (Binary) l.get( 1 ) ); case 2: o.setMechanism( (Symbol) l.get( 0 ) ); } return o; } public Class getTypeClass() { return SaslInit.class; } public static void register(Decoder decoder, EncoderImpl encoder) { SaslInitType type = new SaslInitType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/security/SaslChallengeType.java0000664000000000000000000000534612562450203030435 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.security; import java.util.Collections; import java.util.List; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.security.SaslChallenge; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.DecodeException; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class SaslChallengeType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000042L), Symbol.valueOf("amqp:sasl-challenge:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000042L); private SaslChallengeType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(SaslChallenge val) { return Collections.singletonList(val.getChallenge()); } public SaslChallenge newInstance(Object described) { List l = (List) described; SaslChallenge o = new SaslChallenge(); if(l.isEmpty()) { throw new DecodeException("The challenge field cannot be omitted"); } o.setChallenge( (Binary) l.get( 0 ) ); return o; } public Class getTypeClass() { return SaslChallenge.class; } public static void register(Decoder decoder, EncoderImpl encoder) { SaslChallengeType type = new SaslChallengeType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/0000775000000000000000000000000012562450203024321 5ustar qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/TargetType.java0000664000000000000000000001265312562450203027263 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.messaging; import java.util.AbstractList; import java.util.List; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.messaging.Target; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; import org.apache.qpid.proton.amqp.messaging.TerminusDurability; import org.apache.qpid.proton.amqp.messaging.TerminusExpiryPolicy; public class TargetType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000029L), Symbol.valueOf("amqp:target:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000029L); public TargetType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Target val) { return new TargetWrapper(val); } private static final class TargetWrapper extends AbstractList { private final Target _impl; public TargetWrapper(Target impl) { _impl = impl; } public Object get(final int index) { switch(index) { case 0: return _impl.getAddress(); case 1: return _impl.getDurable().getValue(); case 2: return _impl.getExpiryPolicy().getPolicy(); case 3: return _impl.getTimeout(); case 4: return _impl.getDynamic(); case 5: return _impl.getDynamicNodeProperties(); case 6: return _impl.getCapabilities(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _impl.getCapabilities() != null ? 7 : _impl.getDynamicNodeProperties() != null ? 6 : _impl.getDynamic() ? 5 : (_impl.getTimeout() != null && !_impl.getTimeout().equals(UnsignedInteger.ZERO)) ? 4 : !_impl.getExpiryPolicy().equals(TerminusExpiryPolicy.SESSION_END) ? 3 : !_impl.getDurable().equals(TerminusDurability.NONE) ? 2 : _impl.getAddress() != null ? 1 : 0; } } public Target newInstance(Object described) { List l = (List) described; Target o = new Target(); switch(7 - l.size()) { case 0: Object val0 = l.get( 6 ); if( val0 == null || val0.getClass().isArray() ) { o.setCapabilities( (Symbol[]) val0 ); } else { o.setCapabilities( (Symbol) val0 ); } case 1: o.setDynamicNodeProperties( (Map) l.get( 5 ) ); case 2: Boolean dynamic = (Boolean) l.get(4); o.setDynamic(dynamic == null ? false : dynamic); case 3: UnsignedInteger timeout = (UnsignedInteger) l.get(3); o.setTimeout(timeout == null ? UnsignedInteger.ZERO : timeout); case 4: Symbol expiryPolicy = (Symbol) l.get(2); o.setExpiryPolicy(expiryPolicy == null ? TerminusExpiryPolicy.SESSION_END : TerminusExpiryPolicy.valueOf(expiryPolicy)); case 5: UnsignedInteger durable = (UnsignedInteger) l.get(1); o.setDurable(durable == null ? TerminusDurability.NONE : TerminusDurability.get(durable)); case 6: o.setAddress( (String) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Target.class; } public static void register(Decoder decoder, EncoderImpl encoder) { TargetType type = new TargetType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/SourceType.java0000664000000000000000000001517212562450203027274 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.messaging; import java.util.AbstractList; import java.util.List; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.messaging.Outcome; import org.apache.qpid.proton.amqp.messaging.Source; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; import org.apache.qpid.proton.amqp.messaging.TerminusDurability; import org.apache.qpid.proton.amqp.messaging.TerminusExpiryPolicy; public class SourceType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000028L), Symbol.valueOf("amqp:source:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000028L); public SourceType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Source val) { return new SourceWrapper(val); } private static final class SourceWrapper extends AbstractList { private final Source _impl; public SourceWrapper(Source impl) { _impl = impl; } public Object get(final int index) { switch(index) { case 0: return _impl.getAddress(); case 1: return _impl.getDurable().getValue(); case 2: return _impl.getExpiryPolicy().getPolicy(); case 3: return _impl.getTimeout(); case 4: return _impl.getDynamic(); case 5: return _impl.getDynamicNodeProperties(); case 6: return _impl.getDistributionMode(); case 7: return _impl.getFilter(); case 8: return _impl.getDefaultOutcome(); case 9: return _impl.getOutcomes(); case 10: return _impl.getCapabilities(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _impl.getCapabilities() != null ? 11 : _impl.getOutcomes() != null ? 10 : _impl.getDefaultOutcome() != null ? 9 : _impl.getFilter() != null ? 8 : _impl.getDistributionMode() != null ? 7 : _impl.getDynamicNodeProperties() != null ? 6 : _impl.getDynamic() ? 5 : (_impl.getTimeout() != null && !_impl.getTimeout().equals(UnsignedInteger.ZERO)) ? 4 : _impl.getExpiryPolicy() != TerminusExpiryPolicy.SESSION_END ? 3 : _impl.getDurable() != TerminusDurability.NONE ? 2 : _impl.getAddress() != null ? 1 : 0; } } public Source newInstance(Object described) { List l = (List) described; Source o = new Source(); switch(11 - l.size()) { case 0: Object val0 = l.get( 10 ); if( val0 == null || val0.getClass().isArray() ) { o.setCapabilities( (Symbol[]) val0 ); } else { o.setCapabilities( (Symbol) val0 ); } case 1: Object val1 = l.get( 9 ); if( val1 == null || val1.getClass().isArray() ) { o.setOutcomes( (Symbol[]) val1 ); } else { o.setOutcomes( (Symbol) val1 ); } case 2: o.setDefaultOutcome( (Outcome) l.get( 8 ) ); case 3: o.setFilter( (Map) l.get( 7 ) ); case 4: o.setDistributionMode( (Symbol) l.get( 6 ) ); case 5: o.setDynamicNodeProperties( (Map) l.get( 5 ) ); case 6: Boolean dynamic = (Boolean) l.get(4); o.setDynamic(dynamic == null ? false : dynamic); case 7: UnsignedInteger timeout = (UnsignedInteger) l.get(3); o.setTimeout(timeout == null ? UnsignedInteger.ZERO : timeout); case 8: Symbol expiryPolicy = (Symbol) l.get(2); o.setExpiryPolicy(expiryPolicy == null ? TerminusExpiryPolicy.SESSION_END : TerminusExpiryPolicy.valueOf(expiryPolicy)); case 9: UnsignedInteger durable = (UnsignedInteger) l.get(1); o.setDurable(durable == null ? TerminusDurability.NONE : TerminusDurability.get(durable)); case 10: o.setAddress( (String) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Source.class; } public static void register(Decoder decoder, EncoderImpl encoder) { SourceType type = new SourceType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/ReleasedType.java0000664000000000000000000000450212562450203027553 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.messaging; import java.util.Collections; import java.util.List; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.messaging.Released; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class ReleasedType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000026L), Symbol.valueOf("amqp:released:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000026L); public ReleasedType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Released val) { return Collections.EMPTY_LIST; } public Released newInstance(Object described) { return Released.getInstance(); } public Class getTypeClass() { return Released.class; } public static void register(Decoder decoder, EncoderImpl encoder) { ReleasedType type = new ReleasedType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/RejectedType.java0000664000000000000000000000624712562450203027564 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.messaging; import java.util.AbstractList; import java.util.List; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.messaging.Rejected; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; import org.apache.qpid.proton.amqp.transport.ErrorCondition; public class RejectedType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000025L), Symbol.valueOf("amqp:rejected:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000025L); private RejectedType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Rejected val) { return new RejectedWrapper(val); } private static final class RejectedWrapper extends AbstractList { private final Rejected _impl; private RejectedWrapper(Rejected impl) { _impl = impl; } public Object get(final int index) { switch(index) { case 0: return _impl.getError(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _impl.getError() != null ? 1 : 0; } } public Rejected newInstance(Object described) { List l = (List) described; Rejected o = new Rejected(); switch(1 - l.size()) { case 0: o.setError( (ErrorCondition) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Rejected.class; } public static void register(Decoder decoder, EncoderImpl encoder) { RejectedType type = new RejectedType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/ReceivedType.java0000664000000000000000000000666312562450203027567 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.messaging; import java.util.AbstractList; import java.util.List; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.messaging.Received; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public final class ReceivedType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000023L), Symbol.valueOf("amqp:received:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000023L); private ReceivedType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Received val) { return new ReceivedWrapper(val); } private static final class ReceivedWrapper extends AbstractList { private final Received _impl; private ReceivedWrapper(Received impl) { _impl = impl; } public Object get(final int index) { switch(index) { case 0: return _impl.getSectionNumber(); case 1: return _impl.getSectionOffset(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _impl.getSectionOffset() != null ? 2 : _impl.getSectionOffset() != null ? 1 : 0; } } public Received newInstance(Object described) { List l = (List) described; Received o = new Received(); switch(2 - l.size()) { case 0: o.setSectionOffset( (UnsignedLong) l.get( 1 ) ); case 1: o.setSectionNumber( (UnsignedInteger) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Received.class; } public static void register(Decoder decoder, EncoderImpl encoder) { ReceivedType type = new ReceivedType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/PropertiesType.java0000664000000000000000000001424012562450203030163 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.messaging; import java.util.AbstractList; import java.util.Date; import java.util.List; import org.apache.qpid.proton.amqp.Binary; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.messaging.Properties; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class PropertiesType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000073L), Symbol.valueOf("amqp:properties:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000073L); private PropertiesType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Properties val) { return new PropertiesWrapper(val); } private static final class PropertiesWrapper extends AbstractList { private Properties _impl; public PropertiesWrapper(Properties propertiesType) { _impl = propertiesType; } public Object get(final int index) { switch(index) { case 0: return _impl.getMessageId(); case 1: return _impl.getUserId(); case 2: return _impl.getTo(); case 3: return _impl.getSubject(); case 4: return _impl.getReplyTo(); case 5: return _impl.getCorrelationId(); case 6: return _impl.getContentType(); case 7: return _impl.getContentEncoding(); case 8: return _impl.getAbsoluteExpiryTime(); case 9: return _impl.getCreationTime(); case 10: return _impl.getGroupId(); case 11: return _impl.getGroupSequence(); case 12: return _impl.getReplyToGroupId(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _impl.getReplyToGroupId() != null ? 13 : _impl.getGroupSequence() != null ? 12 : _impl.getGroupId() != null ? 11 : _impl.getCreationTime() != null ? 10 : _impl.getAbsoluteExpiryTime() != null ? 9 : _impl.getContentEncoding() != null ? 8 : _impl.getContentType() != null ? 7 : _impl.getCorrelationId() != null ? 6 : _impl.getReplyTo() != null ? 5 : _impl.getSubject() != null ? 4 : _impl.getTo() != null ? 3 : _impl.getUserId() != null ? 2 : _impl.getMessageId() != null ? 1 : 0; } } public Properties newInstance(Object described) { List l = (List) described; Properties o = new Properties(); switch(13 - l.size()) { case 0: o.setReplyToGroupId( (String) l.get( 12 ) ); case 1: o.setGroupSequence( (UnsignedInteger) l.get( 11 ) ); case 2: o.setGroupId( (String) l.get( 10 ) ); case 3: o.setCreationTime( (Date) l.get( 9 ) ); case 4: o.setAbsoluteExpiryTime( (Date) l.get( 8 ) ); case 5: o.setContentEncoding( (Symbol) l.get( 7 ) ); case 6: o.setContentType( (Symbol) l.get( 6 ) ); case 7: o.setCorrelationId( (Object) l.get( 5 ) ); case 8: o.setReplyTo( (String) l.get( 4 ) ); case 9: o.setSubject( (String) l.get( 3 ) ); case 10: o.setTo( (String) l.get( 2 ) ); case 11: o.setUserId( (Binary) l.get( 1 ) ); case 12: o.setMessageId( (Object) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Properties.class; } public static void register(Decoder decoder, EncoderImpl encoder) { PropertiesType type = new PropertiesType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/ModifiedType.java0000664000000000000000000000720612562450203027553 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.messaging; import java.util.AbstractList; import java.util.List; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.messaging.Modified; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class ModifiedType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000027L), Symbol.valueOf("amqp:modified:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000027L); private ModifiedType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Modified val) { return new ModifiedWrapper(val); } public final class ModifiedWrapper extends AbstractList { private final Modified _impl; public ModifiedWrapper(Modified impl) { _impl = impl; } public Object get(final int index) { switch(index) { case 0: return _impl.getDeliveryFailed(); case 1: return _impl.getUndeliverableHere(); case 2: return _impl.getMessageAnnotations(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _impl.getMessageAnnotations() != null ? 3 : _impl.getUndeliverableHere() != null ? 2 : _impl.getDeliveryFailed() != null ? 1 : 0; } } public Modified newInstance(Object described) { List l = (List) described; Modified o = new Modified(); switch(3 - l.size()) { case 0: o.setMessageAnnotations( (Map) l.get( 2 ) ); case 1: o.setUndeliverableHere( (Boolean) l.get( 1 ) ); case 2: o.setDeliveryFailed( (Boolean) l.get( 0 ) ); } return o; } public Class getTypeClass() { return Modified.class; } public static void register(Decoder decoder, EncoderImpl encoder) { ModifiedType type = new ModifiedType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/MessageAnnotationsType.javaqpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/MessageAnnotationsTyp0000664000000000000000000000467512562450203030557 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.messaging; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.messaging.MessageAnnotations; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class MessageAnnotationsType extends AbstractDescribedType implements DescribedTypeConstructor { private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000072L), Symbol.valueOf("amqp:message-annotations:map"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000072L); public MessageAnnotationsType(EncoderImpl encoder) { super(encoder); } public UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected Map wrap(MessageAnnotations val) { return val.getValue(); } public MessageAnnotations newInstance(Object described) { return new MessageAnnotations( (Map) described ); } public Class getTypeClass() { return MessageAnnotations.class; } public static void register(Decoder decoder, EncoderImpl encoder) { MessageAnnotationsType constructor = new MessageAnnotationsType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, constructor); } encoder.register(constructor); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/HeaderType.java0000664000000000000000000001034312562450203027217 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.messaging; import java.util.AbstractList; import java.util.List; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedByte; import org.apache.qpid.proton.amqp.UnsignedInteger; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.messaging.Header; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class HeaderType extends AbstractDescribedType implements DescribedTypeConstructor
{ private static final Object[] DESCRIPTORS = { UnsignedLong.valueOf(0x0000000000000070L), Symbol.valueOf("amqp:header:list"), }; private static final UnsignedLong DESCRIPTOR = UnsignedLong.valueOf(0x0000000000000070L); public HeaderType(EncoderImpl encoder) { super(encoder); } @Override protected UnsignedLong getDescriptor() { return DESCRIPTOR; } @Override protected List wrap(Header val) { return new HeaderWrapper(val); } public final class HeaderWrapper extends AbstractList { private final Header _impl; public HeaderWrapper(Header impl) { _impl = impl; } @Override public Object get(final int index) { switch(index) { case 0: return _impl.getDurable(); case 1: return _impl.getPriority(); case 2: return _impl.getTtl(); case 3: return _impl.getFirstAcquirer(); case 4: return _impl.getDeliveryCount(); } throw new IllegalStateException("Unknown index " + index); } public int size() { return _impl.getDeliveryCount() != null ? 5 : _impl.getFirstAcquirer() != null ? 4 : _impl.getTtl() != null ? 3 : _impl.getPriority() != null ? 2 : _impl.getDurable() != null ? 1 : 0; } } public Header newInstance(Object described) { List l = (List) described; Header o = new Header(); switch(5 - l.size()) { case 0: o.setDeliveryCount( (UnsignedInteger) l.get( 4 ) ); case 1: o.setFirstAcquirer( (Boolean) l.get( 3 ) ); case 2: o.setTtl( (UnsignedInteger) l.get( 2 ) ); case 3: o.setPriority( (UnsignedByte) l.get( 1 ) ); case 4: o.setDurable( (Boolean) l.get( 0 ) ); } return o; } public Class
getTypeClass() { return Header.class; } public static void register(Decoder decoder, EncoderImpl encoder) { HeaderType type = new HeaderType(encoder); for(Object descriptor : DESCRIPTORS) { decoder.register(descriptor, type); } encoder.register(type); } } qpid-proton-0.10/proton-j/src/main/java/org/apache/qpid/proton/codec/messaging/FooterType.java0000664000000000000000000000441512562450203027270 0ustar /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.qpid.proton.codec.messaging; import java.util.Map; import org.apache.qpid.proton.amqp.Symbol; import org.apache.qpid.proton.amqp.UnsignedLong; import org.apache.qpid.proton.amqp.messaging.Footer; import org.apache.qpid.proton.codec.AbstractDescribedType; import org.apache.qpid.proton.codec.Decoder; import org.apache.qpid.proton.codec.DescribedTypeConstructor; import org.apache.qpid.proton.codec.EncoderImpl; public class FooterType extends AbstractDescribedType implements DescribedTypeConstructor