Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions
+15
View File
@@ -0,0 +1,15 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Wasabi
LOCAL_C_INCLUDES := $(ROOT_REPLICANT)
LOCAL_SRC_FILES := api.cpp ServiceManager.cpp SysCallbacks.cpp
LOCAL_STATIC_LIBRARIES := nu foundation
LOCAL_SHARED_LIBRARIES := nx
include $(BUILD_STATIC_LIBRARY)
+42
View File
@@ -0,0 +1,42 @@
MODULE_NAME := Wasabi
CPPSOURCES := api.cpp ServiceManager.cpp SysCallbacks.cpp
LIBRARY_FILENAME := lib$(MODULE_NAME).a
OUTPUT_PATH := ../build/$(MODULE_NAME)
ARCHIVE_PATH := ../build/lib
LIBRARY_FILEPATH := ../build/lib/$(LIBRARY_FILENAME)
CPPOBJS := $(patsubst %.cpp,$(OUTPUT_PATH)/%.o,$(CPPSOURCES))
CPPDEPS := $(patsubst %.o,$(OUTPUT_PATH)/%.d,$(CPPOBJS))
COBJS := $(patsubst %.c,$(OUTPUT_PATH)/%.o,$(CSOURCES))
CDEPS := $(patsubst %.o,$(OUTPUT_PATH)/%.d,$(COBJS))
OBJS := $(CPPOBJS) $(COBJS)
DEPS := $(CPPDEPS) $(CDEPS)
CFLAGS=-I..
CPPFLAGS := ${CFLAGS}
build: build-dir $(LIBRARY_FILEPATH)
build-dir:
@mkdir -p $(OUTPUT_PATH) > /dev/null 2> /dev/null
@mkdir -p $(ARCHIVE_PATH) > /dev/null 2> /dev/null
dep:
@rm ${DEPS}
$(OUTPUT_PATH)/%.o: %.cpp
#@echo Compiling $*.cpp
@$(CXX) $(CPPFLAGS) -MMD -MF $(OUTPUT_PATH)/$*.d -MT $(OUTPUT_PATH)/$*.o -c $*.cpp -o $(OUTPUT_PATH)/$*.o
$(LIBRARY_FILEPATH): ${OBJS}
$(AR) rcs $@ ${OBJS}
clean:
-rm -f ${OBJS} $(LIBRARY_FILENAME) ${DEPS}
-include $(DEPS)
+201
View File
@@ -0,0 +1,201 @@
#include "ServiceManager.h"
#include "api__wasabi-replicant.h"
#include "service/ifc_servicefactory.h"
#include "service/svccb.h"
using namespace nu;
ServiceManager::ServiceManager()
{
#ifdef _WIN32
component_wait = CreateSemaphoreW(NULL, 0, LONG_MAX, NULL);
#else
sem_init(&component_wait, 0, 0);
#endif
}
ServiceManager::~ServiceManager()
{
#ifdef _WIN32
if (component_wait)
CloseHandle(component_wait);
#else
sem_destroy(&component_wait);
#endif
}
int ServiceManager::Dispatchable_QueryInterface(GUID interface_guid, void **object)
{
if (interface_guid == ifc_component_sync::GetInterfaceGUID())
{
*object = (ifc_component_sync *)this;
}
return NErr_Unknown;
}
//-------------------------------------------
int ServiceManager::GetServiceIndex(GUID key)
{
for(int idx = 0; idx < services_indexer.size(); idx++)
{
if (memcmp(&key, &services_indexer[idx], sizeof(GUID)) == 0)
{
return idx;
}
}
return -1;
}
int ServiceManager::Service_Register(ifc_serviceFactory *svc)
{
AutoLock lock(serviceGuard LOCKNAME("ServiceManager::service_register"));
GUID service_type = svc->GetServiceType();
GUID service_id = svc->GetGUID();
// add the service to the master list
ifc_serviceFactory* new_factory = services[service_id];
if (new_factory) // if someone already has this GUID, we need to replace
{
// replace factory in services_by_type map
ServiceList* type_list = services_by_type[service_type];
if (type_list)
{
for (ServiceList::iterator itr=type_list->begin();itr!=type_list->end();itr++)
{
ifc_serviceFactory *f = *itr;
if (f->GetGUID() == service_id)
{
*itr = svc;
}
}
}
// tell the old factory we're kicking its ass to the curb.
new_factory->ServiceNotify(ifc_serviceFactory::ONUNREGISTERED);
// HAKAN:
// Should we delete old factory?
// new_factory = svc;
}
else // not used yet, just assign
{
//new_factory = svc;
services_indexer.push_back(service_id);
// add it to the by-type lookup
ServiceList *&type_list = services_by_type[service_type];
if (!type_list)
type_list = new ServiceList;
type_list->push_back(svc);
}
services[service_id]=svc;
// send notifications
svc->ServiceNotify(ifc_serviceFactory::ONREGISTERED);
WASABI2_API_SYSCB->IssueCallback(Service::event_type,
Service::on_register,
(intptr_t)&service_type, reinterpret_cast<intptr_t>(svc));
return NErr_Success;
}
int ServiceManager::Service_Unregister(ifc_serviceFactory *svc)
{
AutoLock lock(serviceGuard LOCKNAME("ServiceManager::Service_Unregister"));
GUID service_type = svc->GetServiceType();
GUID service_id = svc->GetGUID();
// remove it from the master list
ServiceMap::iterator itr = services.find(service_id);
if (itr != services.end())
services.erase(itr);
// and from the type lookup map
ServiceList *type_list = services_by_type[service_type];
if (type_list)
{
//type_list->eraseObject(svc);
for (auto it = type_list->begin(); it != type_list->end(); it++)
{
if (*it == svc)
{
it = type_list->erase(it);
break;
}
}
}
WASABI2_API_SYSCB->IssueCallback(Service::event_type, Service::on_deregister, (intptr_t)&service_type, reinterpret_cast<intptr_t>(svc));
svc->ServiceNotify(ifc_serviceFactory::ONUNREGISTERED);
return NErr_Success;
}
size_t ServiceManager::Service_GetServiceCount(GUID svc_type)
{
AutoLock lock(serviceGuard LOCKNAME("ServiceManager::Service_GetServiceCount"));
ServiceList *type_list = services_by_type[svc_type];
if (type_list)
return type_list->size();
else
return 0;
}
ifc_serviceFactory *ServiceManager::Service_EnumService(GUID svc_type, size_t n)
{
AutoLock lock(serviceGuard LOCKNAME("ServiceManager::Service_EnumService"));
ServiceList *type_list = services_by_type[svc_type];
if (type_list && (size_t)n < type_list->size())
return type_list->at(n);
else
return 0;
}
ifc_serviceFactory *ServiceManager::Service_EnumService(size_t n)
{
AutoLock lock(serviceGuard LOCKNAME("ServiceManager::Service_EnumService"));
if ((size_t)n < services.size())
{
//return services.at(n).second;
if (n < services_indexer.size())
{
GUID g = services_indexer[n];
return services[g];
}
}
return 0;
}
ifc_serviceFactory *ServiceManager::Service_GetServiceByGUID(GUID guid)
{
AutoLock lock(serviceGuard LOCKNAME("ServiceManager::service_getServiceByGuid"));
ServiceMap::iterator itr = services.find(guid);
if (itr != services.end())
return itr->second;
else
return 0;
}
void ServiceManager::Service_ComponentDone()
{
#ifdef _WIN32
ReleaseSemaphore(component_wait, 1, NULL);
#else
sem_post(&component_wait);
#endif
}
int ServiceManager::ComponentSync_Wait(size_t count)
{
while (count--)
{
#ifdef _WIN32
WaitForSingleObject(component_wait, INFINITE);
#else
sem_wait(&component_wait);
#endif
}
return NErr_Success;
}
+52
View File
@@ -0,0 +1,52 @@
#pragma once
#include "foundation/guid.h"
#include "service/api_service.h"
#include "nu/AutoLock.h"
#include "foundation/guid.h"
#include <vector>
#include <map>
#include "service/ifc_servicefactory.h"
#include "component/ifc_component_sync.h"
#ifdef _WIN32
#include <Windows.h>
#else
#include <semaphore.h>
#endif
class ServiceManager : public api_service, public ifc_component_sync
{
public:
ServiceManager();
~ServiceManager();
int WASABICALL Dispatchable_QueryInterface(GUID interface_guid, void **object);
int WASABICALL Service_Register(ifc_serviceFactory *svc);
int WASABICALL Service_Unregister(ifc_serviceFactory *svc);
size_t WASABICALL Service_GetServiceCount(GUID svc_type);
ifc_serviceFactory *WASABICALL Service_EnumService(GUID svc_type, size_t n);
ifc_serviceFactory *WASABICALL Service_EnumService(size_t n);
ifc_serviceFactory *WASABICALL Service_GetServiceByGUID(GUID guid);
void WASABICALL Service_ComponentDone();
private:
int WASABICALL ComponentSync_Wait(size_t count);
int GetServiceIndex(GUID key);
private:
nu::LockGuard serviceGuard;
typedef std::map<GUID, ifc_serviceFactory*> ServiceMap;
ServiceMap services;
std::vector<GUID> services_indexer;
typedef std::vector<ifc_serviceFactory*> ServiceList;
std::map<GUID, ServiceList*> services_by_type;
#ifdef _WIN32
HANDLE component_wait;
#else
sem_t component_wait;
#endif
};
extern ServiceManager service_manager;
+98
View File
@@ -0,0 +1,98 @@
#include "SysCallbacks.h"
#include "syscb/ifc_syscallback.h"
using namespace nu;
SysCallbacks::SysCallbacks()
{
reentry=0;
inCallback=false;
}
//note: it's OK to add in the middle of an issueCallback
//because new callbacks go at the end of the list
//and the lockguard prevents list corruption
int SysCallbacks::SysCallbacks_RegisterCallback(ifc_sysCallback *cb)
{
AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_registerCallback"));
callbacks.push_back(cb);
return 0;
}
int SysCallbacks::SysCallbacks_UnregisterCallback(ifc_sysCallback *cb)
{
AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_deregisterCallback"));
if (inCallback)
deleteMeAfterCallbacks.push_back(cb);
else
{
//callbacks.eraseAll(cb);
auto it = callbacks.begin();
while (it != callbacks.end())
{
if (*it != cb)
{
it++;
continue;
}
it = callbacks.erase(it);
}
}
return 0;
}
int SysCallbacks::SysCallbacks_IssueCallback( GUID eventtype, int msg, intptr_t param1, intptr_t param2 )
{
AutoLock lock( callbackGuard LOCKNAME( "SysCallbacks::syscb_issueCallback" ) );
reentry++;
inCallback = true;
for ( ifc_sysCallback *l_call_back : callbacks )
{
//if (!deleteMeAfterCallbacks.contains(callbacks[i]) && callbacks[i]->GetEventType() == eventtype)
if ( deleteMeAfterCallbacks.end() == std::find( deleteMeAfterCallbacks.begin(), deleteMeAfterCallbacks.end(), l_call_back ) && l_call_back->GetEventType() == eventtype )
l_call_back->Notify( msg, param1, param2 );
}
inCallback = false;
reentry--;
if ( reentry == 0 )
{
for ( ifc_sysCallback *l_delete_me_after_call_back : deleteMeAfterCallbacks )
{
//callbacks.eraseAll(deleteMeAfterCallbacks[i]);
auto it = callbacks.begin();
while ( it != callbacks.end() )
{
if ( *it != l_delete_me_after_call_back )
{
it++;
continue;
}
it = callbacks.erase( it );
}
}
deleteMeAfterCallbacks.clear();
}
return 0;
}
ifc_sysCallback *SysCallbacks::SysCallbacks_Enum( GUID eventtype, size_t n )
{
AutoLock lock( callbackGuard LOCKNAME( "SysCallbacks::syscb_enum" ) );
// TODO: maybe check !deleteMeAfterCallbacks.contains(callbacks[i])
for ( ifc_sysCallback *callback : callbacks )
{
if ( callback->GetEventType() == eventtype )
{
if ( n-- == 0 )
{
// benski> don't be fooled. most objects don't actually support reference counting
callback->Retain();
return callback;
}
}
}
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include "syscb/api_syscb.h"
#include <vector>
#include "nu/AutoLock.h"
#include "service/types.h"
#include "nx/nxstring.h"
#include "nswasabi/ServiceName.h"
class SysCallbacks : public api_syscb
{
public:
WASABI_SERVICE_NAME("System Callbacks API");
public:
SysCallbacks();
int WASABICALL SysCallbacks_RegisterCallback(ifc_sysCallback *cb);
int WASABICALL SysCallbacks_UnregisterCallback(ifc_sysCallback *cb);
int WASABICALL SysCallbacks_IssueCallback(GUID eventtype, int msg, intptr_t param1 = 0, intptr_t param2 = 0);
ifc_sysCallback *WASABICALL SysCallbacks_Enum(GUID eventtype, size_t n);
private:
nu::LockGuard callbackGuard;
std::vector<ifc_sysCallback*> callbacks;
std::vector<ifc_sysCallback*> deleteMeAfterCallbacks;
bool inCallback;
volatile int reentry;
};
extern SysCallbacks system_callbacks;
+1
View File
@@ -0,0 +1 @@
1.2
+31
View File
@@ -0,0 +1,31 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29609.76
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Wasabi-replicant", "Wasabi-replicant.vcxproj", "{4F34CA12-9F74-4A96-A917-8DEEA4961B31}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|Win32 = Debug|Win32
Release|x64 = Release|x64
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4F34CA12-9F74-4A96-A917-8DEEA4961B31}.Debug|x64.ActiveCfg = Debug|x64
{4F34CA12-9F74-4A96-A917-8DEEA4961B31}.Debug|x64.Build.0 = Debug|x64
{4F34CA12-9F74-4A96-A917-8DEEA4961B31}.Debug|Win32.ActiveCfg = Debug|Win32
{4F34CA12-9F74-4A96-A917-8DEEA4961B31}.Debug|Win32.Build.0 = Debug|Win32
{4F34CA12-9F74-4A96-A917-8DEEA4961B31}.Release|x64.ActiveCfg = Release|x64
{4F34CA12-9F74-4A96-A917-8DEEA4961B31}.Release|x64.Build.0 = Release|x64
{4F34CA12-9F74-4A96-A917-8DEEA4961B31}.Release|Win32.ActiveCfg = Release|Win32
{4F34CA12-9F74-4A96-A917-8DEEA4961B31}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E4791259-2DCD-4881-9B00-FB79EE40D483}
EndGlobalSection
EndGlobal
@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4F34CA12-9F74-4A96-A917-8DEEA4961B31}</ProjectGuid>
<RootNamespace>Wasabi</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;NDEBUG;_LIB;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="api.cpp" />
<ClCompile Include="ServiceManager.cpp" />
<ClCompile Include="SysCallbacks.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="api__wasabi-replicant.h" />
<ClInclude Include="precomp.h" />
<ClInclude Include="ServiceManager.h" />
<ClInclude Include="SysCallbacks.h" />
<ClInclude Include="Wasabi.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="api.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ServiceManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SysCallbacks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="api__wasabi-replicant.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="precomp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ServiceManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SysCallbacks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Wasabi.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{95e2a764-deca-4145-a564-704813803543}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{7214e4d1-7da7-46b4-961e-a698574d8f9c}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{966f3869-2bed-42a3-885b-6104297b3673}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
int Wasabi_Init();
#ifdef __cplusplus
}
#endif
+143
View File
@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="api.cpp" />
<ClCompile Include="ServiceManager.cpp" />
<ClCompile Include="SysCallbacks.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="api.h" />
<ClInclude Include="ServiceManager.h" />
<ClInclude Include="SysCallbacks.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{ABB5A3D1-9932-46B1-9488-F147C8B97868}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Wasabi</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,457 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXAggregateTarget section */
00B733F3151BAC6B00A8251C /* Wasabi-prepare */ = {
isa = PBXAggregateTarget;
buildConfigurationList = 00B733F4151BAC6B00A8251C /* Build configuration list for PBXAggregateTarget "Wasabi-prepare" */;
buildPhases = (
00B733FA151BACD800A8251C /* Generate Version Info */,
);
dependencies = (
0039B365152A1EF600D96D3E /* PBXTargetDependency */,
);
name = "Wasabi-prepare";
productName = "Wasabi-version";
};
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
008840BF1506528900625F51 /* Wasabi.h in Headers */ = {isa = PBXBuildFile; fileRef = B195370314F5F8390056BB8C /* Wasabi.h */; settings = {ATTRIBUTES = (Public, ); }; };
00B733A0151B6E2200A8251C /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B7339F151B6E2200A8251C /* version.h */; settings = {ATTRIBUTES = (Public, ); }; };
00C27EA515375730008D95CD /* precomp.h in Headers */ = {isa = PBXBuildFile; fileRef = 00C27EA41537572F008D95CD /* precomp.h */; };
B152EBB114F53F24005076BA /* api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B152EBAB14F53F24005076BA /* api.cpp */; };
B152EBB214F53F24005076BA /* api.h in Headers */ = {isa = PBXBuildFile; fileRef = B152EBAC14F53F24005076BA /* api.h */; settings = {ATTRIBUTES = (Public, ); }; };
B152EBB314F53F24005076BA /* ServiceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B152EBAD14F53F24005076BA /* ServiceManager.cpp */; };
B152EBB414F53F24005076BA /* ServiceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B152EBAE14F53F24005076BA /* ServiceManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
B152EBB514F53F24005076BA /* SysCallbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B152EBAF14F53F24005076BA /* SysCallbacks.cpp */; };
B152EBB614F53F24005076BA /* SysCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = B152EBB014F53F24005076BA /* SysCallbacks.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
0039B364152A1EF600D96D3E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B152EB9B14F53EFD005076BA /* Project object */;
proxyType = 1;
remoteGlobalIDString = 00B733AD151B76EB00A8251C;
remoteInfo = "Wasabi-cleanup";
};
00B733B1151B775400A8251C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B152EB9B14F53EFD005076BA /* Project object */;
proxyType = 1;
remoteGlobalIDString = 00B733AD151B76EB00A8251C;
remoteInfo = "Wasabi-cleanup";
};
00B733F7151BAC8600A8251C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = B152EB9B14F53EFD005076BA /* Project object */;
proxyType = 1;
remoteGlobalIDString = 00B733F3151BAC6B00A8251C;
remoteInfo = "Wasabi-version";
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
00B7339E151B6D9000A8251C /* VERSION */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = VERSION; sourceTree = "<group>"; };
00B7339F151B6E2200A8251C /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = $PROJECT_DERIVED_FILE_DIR/version.h; sourceTree = "<absolute>"; };
00C27EA41537572F008D95CD /* precomp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = precomp.h; sourceTree = "<group>"; };
B152EBA414F53EFD005076BA /* libWasabi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libWasabi.a; sourceTree = BUILT_PRODUCTS_DIR; };
B152EBAB14F53F24005076BA /* api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = api.cpp; sourceTree = "<group>"; };
B152EBAC14F53F24005076BA /* api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = api.h; sourceTree = "<group>"; };
B152EBAD14F53F24005076BA /* ServiceManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServiceManager.cpp; sourceTree = "<group>"; };
B152EBAE14F53F24005076BA /* ServiceManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceManager.h; sourceTree = "<group>"; };
B152EBAF14F53F24005076BA /* SysCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SysCallbacks.cpp; sourceTree = "<group>"; };
B152EBB014F53F24005076BA /* SysCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SysCallbacks.h; sourceTree = "<group>"; };
B195370314F5F8390056BB8C /* Wasabi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Wasabi.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
B152EBA114F53EFD005076BA /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
00B7339D151B6D7E00A8251C /* Version */ = {
isa = PBXGroup;
children = (
00B7339E151B6D9000A8251C /* VERSION */,
00B7339F151B6E2200A8251C /* version.h */,
);
name = Version;
sourceTree = "<group>";
};
B152EB9914F53EFD005076BA = {
isa = PBXGroup;
children = (
00C27EA41537572F008D95CD /* precomp.h */,
B195370314F5F8390056BB8C /* Wasabi.h */,
B152EBAB14F53F24005076BA /* api.cpp */,
B152EBAC14F53F24005076BA /* api.h */,
B152EBAD14F53F24005076BA /* ServiceManager.cpp */,
B152EBAE14F53F24005076BA /* ServiceManager.h */,
B152EBAF14F53F24005076BA /* SysCallbacks.cpp */,
B152EBB014F53F24005076BA /* SysCallbacks.h */,
00B7339D151B6D7E00A8251C /* Version */,
B152EBA514F53EFD005076BA /* Products */,
);
sourceTree = "<group>";
};
B152EBA514F53EFD005076BA /* Products */ = {
isa = PBXGroup;
children = (
B152EBA414F53EFD005076BA /* libWasabi.a */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
B152EBA214F53EFD005076BA /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
B152EBB214F53F24005076BA /* api.h in Headers */,
B152EBB414F53F24005076BA /* ServiceManager.h in Headers */,
B152EBB614F53F24005076BA /* SysCallbacks.h in Headers */,
008840BF1506528900625F51 /* Wasabi.h in Headers */,
00B733A0151B6E2200A8251C /* version.h in Headers */,
00C27EA515375730008D95CD /* precomp.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXLegacyTarget section */
00B733AD151B76EB00A8251C /* Wasabi-cleanup */ = {
isa = PBXLegacyTarget;
buildArgumentsString = "$(NSBUILD_TOOLS_BIN_DIR)/cleanbuild --xcode-mode --libraries \"$(LIBRARY_PATH)\" \"$(PUBLIC_HEADERS_DIR)\" \"$(DWARF_DSYM_PATH)\" \"$(PROJECT_DERIVED_FILE_DIR)/version.*\"";
buildConfigurationList = 00B733AE151B76EB00A8251C /* Build configuration list for PBXLegacyTarget "Wasabi-cleanup" */;
buildPhases = (
);
buildToolPath = /bin/sh;
buildWorkingDirectory = "";
dependencies = (
);
name = "Wasabi-cleanup";
passBuildSettingsInEnvironment = 1;
productName = "Wasabi-cleanup";
};
/* End PBXLegacyTarget section */
/* Begin PBXNativeTarget section */
B152EBA314F53EFD005076BA /* Wasabi */ = {
isa = PBXNativeTarget;
buildConfigurationList = B152EBA814F53EFD005076BA /* Build configuration list for PBXNativeTarget "Wasabi" */;
buildPhases = (
B152EBA014F53EFD005076BA /* Sources */,
B152EBA114F53EFD005076BA /* Frameworks */,
B152EBA214F53EFD005076BA /* Headers */,
00B733AB151B768500A8251C /* Install Public Headers */,
);
buildRules = (
);
dependencies = (
00B733B2151B775400A8251C /* PBXTargetDependency */,
00B733F8151BAC8600A8251C /* PBXTargetDependency */,
);
name = Wasabi;
productName = Wasabi;
productReference = B152EBA414F53EFD005076BA /* libWasabi.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
B152EB9B14F53EFD005076BA /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = "Nullsoft, Inc.";
};
buildConfigurationList = B152EB9E14F53EFD005076BA /* Build configuration list for PBXProject "Wasabi" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = B152EB9914F53EFD005076BA;
productRefGroup = B152EBA514F53EFD005076BA /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
B152EBA314F53EFD005076BA /* Wasabi */,
00B733AD151B76EB00A8251C /* Wasabi-cleanup */,
00B733F3151BAC6B00A8251C /* Wasabi-prepare */,
);
};
/* End PBXProject section */
/* Begin PBXShellScriptBuildPhase section */
00B733AB151B768500A8251C /* Install Public Headers */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
"$(BUILT_PRODUCTS_DIR)$(PUBLIC_HEADERS_FOLDER_PATH)",
);
name = "Install Public Headers";
outputPaths = (
"$(DSTROOT)$(PUBLIC_HEADERS_FOLDER_PATH)",
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = /bin/sh;
shellScript = "INSTALLTOOL=\"$NSBUILD_TOOLS_BIN_DIR/installtool\"\n$INSTALLTOOL --headers-only \\\n \"$SCRIPT_INPUT_FILE_0/\" \\\n \"$SCRIPT_OUTPUT_FILE_0\"\n";
showEnvVarsInLog = 0;
};
00B733FA151BACD800A8251C /* Generate Version Info */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 12;
files = (
);
inputPaths = (
"$(SRCROOT)/VERSION",
"$(NSBUILD_TOOLS_SHARE_DIR)/nvgtool/lib-version.template.h",
);
name = "Generate Version Info";
outputPaths = (
"$(PROJECT_DERIVED_FILE_DIR)/version.h",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "PRODUCT_VERSION=$(cat \"$SCRIPT_INPUT_FILE_0\")\n\nif [ ! -d \"$PROJECT_DERIVED_FILE_DIR\" ]; then\n mkdir -p \"$PROJECT_DERIVED_FILE_DIR\"\nfi\n\nNVGTOOL=\"$NSBUILD_TOOLS_BIN_DIR/nvgtool\"\n$NVGTOOL --product-name \"$PRODUCT_NAME\" \\\n --product-version \"$PRODUCT_VERSION\" \\\n --input-file \"$SCRIPT_INPUT_FILE_1\" \\\n --output-file \"$SCRIPT_OUTPUT_FILE_0\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
B152EBA014F53EFD005076BA /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B152EBB114F53F24005076BA /* api.cpp in Sources */,
B152EBB314F53F24005076BA /* ServiceManager.cpp in Sources */,
B152EBB514F53F24005076BA /* SysCallbacks.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
0039B365152A1EF600D96D3E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 00B733AD151B76EB00A8251C /* Wasabi-cleanup */;
targetProxy = 0039B364152A1EF600D96D3E /* PBXContainerItemProxy */;
};
00B733B2151B775400A8251C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 00B733AD151B76EB00A8251C /* Wasabi-cleanup */;
targetProxy = 00B733B1151B775400A8251C /* PBXContainerItemProxy */;
};
00B733F8151BAC8600A8251C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 00B733F3151BAC6B00A8251C /* Wasabi-prepare */;
targetProxy = 00B733F7151BAC8600A8251C /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
00B733AF151B76EB00A8251C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
DWARF_DSYM_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME).dSYM";
LIBRARY_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME)";
PUBLIC_HEADERS_DIR = "$(BUILT_PRODUCTS_DIR)$(PUBLIC_HEADERS_FOLDER_PATH)";
};
name = Debug;
};
00B733B0151B76EB00A8251C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
DWARF_DSYM_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME).dSYM";
LIBRARY_PATH = "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_NAME)";
PUBLIC_HEADERS_DIR = "$(BUILT_PRODUCTS_DIR)$(PUBLIC_HEADERS_FOLDER_PATH)";
};
name = Release;
};
00B733F5151BAC6B00A8251C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
};
name = Debug;
};
00B733F6151BAC6B00A8251C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
};
name = Release;
};
B152EBA614F53EFD005076BA /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DYLIB_COMPATIBILITY_VERSION = "$(CURRENT_PROJECT_VERSION)";
DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)";
EXECUTABLE_EXTENSION = a;
EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME).$(EXECUTABLE_EXTENSION)";
EXECUTABLE_PREFIX = lib;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = precomp.h;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/lib";
INSTALL_PATH_PREFIX = /usr/local;
MACOSX_DEPLOYMENT_TARGET = 10.6;
NSBUILD_TOOLS_BIN_DIR = "$(NSBUILD_TOOLS_DIR)/bin";
NSBUILD_TOOLS_DIR = "$(SRCROOT)/../../build-tools";
NSBUILD_TOOLS_SHARE_DIR = "$(NSBUILD_TOOLS_DIR)/share";
ONLY_ACTIVE_ARCH = YES;
PRIVATE_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)";
PRODUCT_NAME = "$(PROJECT_NAME)";
PUBLIC_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)";
SDKROOT = macosx;
USER_HEADER_SEARCH_PATHS = ".. $(BUILT_PRODUCTS_DIR)$(INSTALL_PATH_PREFIX)/include";
};
name = Debug;
};
B152EBA714F53EFD005076BA /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = "$(CURRENT_PROJECT_VERSION)";
DYLIB_CURRENT_VERSION = "$(CURRENT_PROJECT_VERSION)";
EXECUTABLE_EXTENSION = a;
EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME).$(EXECUTABLE_EXTENSION)";
EXECUTABLE_PREFIX = lib;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = precomp.h;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/lib";
INSTALL_PATH_PREFIX = /usr/local;
MACOSX_DEPLOYMENT_TARGET = 10.6;
NSBUILD_TOOLS_BIN_DIR = "$(NSBUILD_TOOLS_DIR)/bin";
NSBUILD_TOOLS_DIR = "$(SRCROOT)/../../build-tools";
NSBUILD_TOOLS_SHARE_DIR = "$(NSBUILD_TOOLS_DIR)/share";
PRIVATE_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)";
PRODUCT_NAME = "$(PROJECT_NAME)";
PUBLIC_HEADERS_FOLDER_PATH = "$(INSTALL_PATH_PREFIX)/include/$(PRODUCT_NAME)";
SDKROOT = macosx;
USER_HEADER_SEARCH_PATHS = ".. $(BUILT_PRODUCTS_DIR)$(INSTALL_PATH_PREFIX)/include";
};
name = Release;
};
B152EBA914F53EFD005076BA /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
};
name = Debug;
};
B152EBAA14F53EFD005076BA /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
00B733AE151B76EB00A8251C /* Build configuration list for PBXLegacyTarget "Wasabi-cleanup" */ = {
isa = XCConfigurationList;
buildConfigurations = (
00B733AF151B76EB00A8251C /* Debug */,
00B733B0151B76EB00A8251C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
00B733F4151BAC6B00A8251C /* Build configuration list for PBXAggregateTarget "Wasabi-prepare" */ = {
isa = XCConfigurationList;
buildConfigurations = (
00B733F5151BAC6B00A8251C /* Debug */,
00B733F6151BAC6B00A8251C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B152EB9E14F53EFD005076BA /* Build configuration list for PBXProject "Wasabi" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B152EBA614F53EFD005076BA /* Debug */,
B152EBA714F53EFD005076BA /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B152EBA814F53EFD005076BA /* Build configuration list for PBXNativeTarget "Wasabi" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B152EBA914F53EFD005076BA /* Debug */,
B152EBAA14F53EFD005076BA /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = B152EB9B14F53EFD005076BA /* Project object */;
}
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0500"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B152EBA314F53EFD005076BA"
BuildableName = "libWasabi.a"
BlueprintName = "Wasabi"
ReferencedContainer = "container:Wasabi.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
+15
View File
@@ -0,0 +1,15 @@
#include "Wasabi.h"
#include "api__wasabi-replicant.h"
#include "nswasabi/singleton.h"
#include "foundation/error.h"
SysCallbacks system_callbacks;
ServiceManager service_manager;
static SingletonServiceFactory<SysCallbacks, api_syscb> syscb_factory;
int Wasabi_Init()
{
syscb_factory.Register(WASABI2_API_SVC, WASABI2_API_SYSCB);
return NErr_Success;
}
@@ -0,0 +1,7 @@
#pragma once
#include "ServiceManager.h"
#define WASABI2_API_SVC (&service_manager)
#include "SysCallbacks.h"
#define WASABI2_API_SYSCB (&system_callbacks)
+11
View File
@@ -0,0 +1,11 @@
//
// precomp.h
// Wasabi
//
#include "foundation/error.h"
#include "foundation/types.h"
#ifdef __cplusplus
#include "api__wasabi-replicant.h"
#endif
@@ -0,0 +1,62 @@
#pragma once
#include "../replicant/foundation/dispatch.h"
#include "../replicant/foundation/error.h"
#include "../replicant/service/types.h"
#include "../replicant/nx/nxuri.h"
// {23B96771-09D7-46d3-9AE2-20DCEA6C86EA}
static const GUID applicationApiServiceGuid =
{
0x23b96771, 0x9d7, 0x46d3, { 0x9a, 0xe2, 0x20, 0xdc, 0xea, 0x6c, 0x86, 0xea }
};
// ----------------------------------------------------------------------------
class api_application: public Wasabi2::Dispatchable
{
protected:
api_application() : Dispatchable(DISPATCHABLE_VERSION) {}
~api_application() {}
public:
static GUID GetServiceType() { return SVC_TYPE_UNIQUE; }
static GUID GetServiceGUID() { return applicationApiServiceGuid; }
const char *GetUserAgent() { return Application_GetUserAgent(); }
/* returns a path where you can store data files, if you need to */
int GetDataPath(nx_uri_t *path) { return Application_GetDataPath(path); }
/* checks whether or not a particular feature has permissions to operate.
returns NErr_True or NErr_False. see features.h for known GUIDs */
int GetPermission(GUID feature) { return Application_GetPermission(feature); }
/* checks whether or not a particular feature is available.
This only includes some features that might be absent based on OS version, hardware support, or third party dependencies
It's meant for code that is otherwise unable to easily check directly or via other methods (e.g. WASABI2_API_SVC->GetService)
returns NErr_True or NErr_False. see features.h for known GUIDs */
int GetFeature(GUID feature) { return Application_GetFeature(feature); }
/* used by a component to set features that are available. See notes above for GetFeature
for thread-safety, you should only call this during your RegisterServices() function
(or during application init if you are hosting Wasabi) */
void SetFeature(GUID feature) { Application_SetFeature(feature); }
unsigned int GetBuildNumber() { return Application_GetBuildNumber(); }
int GetVersionString(nx_string_t *version) { return Application_GetVersionString(version); }
int GetProductShortName(nx_string_t *name) { return Application_GetProductShortName(name); }
int GetDeviceID(nx_string_t *value) { return Application_GetDeviceID(value); }
enum
{
DISPATCHABLE_VERSION,
};
protected:
virtual const char * Application_GetUserAgent()=0;
virtual int Application_GetDataPath(nx_uri_t *path)=0;
virtual int Application_GetPermission(GUID feature)=0;
virtual int Application_GetFeature(GUID feature)=0;
virtual void Application_SetFeature(GUID feature)=0;
virtual unsigned int Application_GetBuildNumber() { return 0; }
virtual int Application_GetVersionString(nx_string_t *version)=0;
virtual int Application_GetProductShortName(nx_string_t *name)=0;
virtual int Application_GetDeviceID(nx_string_t *value)=0;
};
+92
View File
@@ -0,0 +1,92 @@
#pragma once
#include "foundation/types.h"
#include "foundation/mkncc.h"
#ifdef __cplusplus
#include "syscb/ifc_syscallback.h"
#endif
/*
This is a listing of features that can be added to Application::SetPermission and api_application::SetFeature
or queried with api_application::GetPermission or api_application::GetFeature
if you are linking from a C file, prepend application_feature_ before each of these guids
if you are linking from a C++ file, these are in the Features namespace
*/
#ifdef __cplusplus
extern "C" {
#define FEATURE(x) x
#define PERMISSION(x) x
namespace Features {
#else
#define FEATURE(x) application_feature_ ## x
#define PERMISSION(x) x application_feature_ ## x
#endif
/* these gets sent via api_sysb when permissions change */
// {33C86C8A-281E-4CA7-88B0-9AF9A06C486D}
static const GUID FEATURE(event_type) =
{ 0x33c86c8a, 0x281e, 0x4ca7, { 0x88, 0xb0, 0x9a, 0xf9, 0xa0, 0x6c, 0x48, 0x6d } };
static const int FEATURE(permissions_changed) = 0;
static const int FEATURE(features_changed) = 1;
#ifdef __cplusplus
class SystemCallback : public ifc_sysCallback
{
protected:
GUID WASABICALL SysCallback_GetEventType() { return event_type; }
int WASABICALL SysCallback_Notify(int msg, intptr_t param1, intptr_t param2)
{
switch(msg)
{
case permissions_changed:
return FeaturesSystemCallback_OnPermissionsChanged();
case features_changed:
return FeaturesSystemCallback_OnFeaturesChanged();
default:
return NErr_Success;
}
}
virtual int WASABICALL FeaturesSystemCallback_OnPermissionsChanged() { return NErr_Success; }
virtual int WASABICALL FeaturesSystemCallback_OnFeaturesChanged() { return NErr_Success; }
};
#endif
#if 0
// {2E9CE2F8-E26D-4629-A3FF-5DF619136B2C}
static const GUID PERMISSION(crossfade) =
{ 0x2e9ce2f8, 0xe26d, 0x4629, { 0xa3, 0xff, 0x5d, 0xf6, 0x19, 0x13, 0x6b, 0x2c } };
// {F7CCB4E1-CD8B-4D0A-973A-0C1F15FDDAE2}
static const GUID PERMISSION(replaygain) =
{ 0xf7ccb4e1, 0xcd8b, 0x4d0a, { 0x97, 0x3a, 0xc, 0x1f, 0x15, 0xfd, 0xda, 0xe2 } };
// {9A52404E-764D-416D-9EC9-33AA84FBA13F}
static const GUID PERMISSION(equalizer) =
{ 0x9a52404e, 0x764d, 0x416d, { 0x9e, 0xc9, 0x33, 0xaa, 0x84, 0xfb, 0xa1, 0x3f } };
#endif
// {69663D62-5EC5-4B25-B91C-65E388C85E09}
static const GUID FEATURE(aac_playback) =
{ 0x69663d62, 0x5ec5, 0x4b25, { 0xb9, 0x1c, 0x65, 0xe3, 0x88, 0xc8, 0x5e, 0x9 } };
// {281E7D5B-3A46-4F60-9026-D3FCBFCDD2BB}
static const GUID PERMISSION(gapless) =
{ 0x281e7d5b, 0x3a46, 0x4f60, { 0x90, 0x26, 0xd3, 0xfc, 0xbf, 0xcd, 0xd2, 0xbb } };
// {4D6A0C67-D2FF-4F81-BA4F-369AF90BE680}
static const GUID PERMISSION(flac_playback) =
{ 0x4d6a0c67, 0xd2ff, 0x4f81, { 0xba, 0x4f, 0x36, 0x9a, 0xf9, 0xb, 0xe6, 0x80 } };
// {5599E564-400B-40EC-8393-A58D4A6BEBD9}
static const GUID PERMISSION(gracenote_autotag) =
{ 0x5599e564, 0x400b, 0x40ec, { 0x83, 0x93, 0xa5, 0x8d, 0x4a, 0x6b, 0xeb, 0xd9 } };
// {1A9106D7-C226-4B72-9A30-E4977A519234}
static const GUID PERMISSION(alac_playback) =
{ 0x1a9106d7, 0xc226, 0x4b72, { 0x9a, 0x30, 0xe4, 0x97, 0x7a, 0x51, 0x92, 0x34 } };
#ifdef __cplusplus
}
}
#endif
@@ -0,0 +1,57 @@
#pragma once
#include "foundation/dispatch.h"
#include "nx/nxuri.h"
#include "metadata/ifc_metadata.h"
/* this is the class you actually use */
class ifc_audio_decoder_callback : public Wasabi2::Dispatchable
{
protected:
ifc_audio_decoder_callback() : Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_audio_decoder_callback() {}
public:
/* you must implement this class to use the decoder */
class callback : public Wasabi2::Dispatchable
{
protected:
callback() : Dispatchable(DISPATCHABLE_VERSION) {}
~callback() {}
public:
/* frames is defined as all channels, e.g. 16bit stereo is 4 bytes per frame (2 bytes per sample)
return NErr_Success to continue receiving callbacks
*/
int OnAudio(const void *buffer, size_t buffer_frames) { return AudioDecoderCallback_OnAudio(buffer, buffer_frames); }
enum
{
DISPATCHABLE_VERSION=0,
};
private:
virtual int WASABICALL AudioDecoderCallback_OnAudio(const void *buffer, size_t buffer_frames)=0;
};
/* if possible, returns an upper bound on the number of frames used internally. this would be the maximum buffer_frames value you receive in a callback */
int GetFrameSize(size_t *frame_size) { return AudioDecoderCallback_GetFrameSize(frame_size); }
int GetMetadata(ifc_metadata **metadata) { return AudioDecoderCallback_GetMetadata(metadata); }
/* returns
* NErr_Success on a successfully completed decode
* NErr_Interrupted if the callback function aborted decoding
* anything else indicates a decoding error
*/
int Decode(ifc_audio_decoder_callback::callback *callback) { return AudioDecoderCallback_Decode(callback); }
/* Like decode, but only processes one frame.
returns NErr_EndOfFile on the last frame */
int DecodeStep(ifc_audio_decoder_callback::callback *callback) { return AudioDecoderCallback_DecodeStep(callback); }
enum
{
DISPATCHABLE_VERSION=0,
};
private:
virtual int WASABICALL AudioDecoderCallback_Decode(ifc_audio_decoder_callback::callback *callback)=0;
virtual int WASABICALL AudioDecoderCallback_DecodeStep(ifc_audio_decoder_callback::callback *callback)=0;
virtual int WASABICALL AudioDecoderCallback_GetFrameSize(size_t *frame_size)=0;
virtual int WASABICALL AudioDecoderCallback_GetMetadata(ifc_metadata **metadata)=0;
};
@@ -0,0 +1,23 @@
#pragma once
#include "foundation/dispatch.h"
#include "nx/nxuri.h"
#include "metadata/ifc_metadata.h"
class ifc_audio_decoder_packet : public Wasabi2::Dispatchable
{
protected:
ifc_audio_decoder_packet() : Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_audio_decoder_packet() {}
public:
int GetMetadata(ifc_metadata **metadata) { return AudioDecoderPacket_GetMetadata(metadata); }
int Decode(void **out_packet, size_t *frames_available) { return AudioDecoderPacket_Decode(out_packet, frames_available); }
enum
{
DISPATCHABLE_VERSION=0,
};
private:
virtual int WASABICALL AudioDecoderPacket_GetMetadata(ifc_metadata **metadata)=0;
virtual int WASABICALL AudioDecoderPacket_Decode(void **out_packet, size_t *frames_available)=0;
};
@@ -0,0 +1,34 @@
#pragma once
#include "foundation/dispatch.h"
#include "nx/nxuri.h"
#include "metadata/ifc_metadata.h"
class ifc_audio_decoder_pull : public Wasabi2::Dispatchable
{
protected:
ifc_audio_decoder_pull() : Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_audio_decoder_pull() {}
public:
/* if possible, returns an upper bound on the number of frames used internally. pull decoders are most optimal if you use this to malloc your buffer */
int GetFrameSize(size_t *frame_size) { return AudioDecoderPull_GetFrameSize(frame_size); }
int GetMetadata(ifc_metadata **metadata) { return AudioDecoderPull_GetMetadata(metadata); }
/* returns
* NErr_EndOfFile when decode is done (frames_written will be valid, but probably 0)
* NErr_Success on successful decode, but not end-of-file (frames_written will be valid)
* anything else indicates a decode error */
int Decode(void *buffer, size_t buffer_frames, size_t *frames_written) { return AudioDecoderPull_Decode(buffer, buffer_frames, frames_written); }
/* You need to call Close() when you are done (even if you Release) because some implementations might have ifc_metadata being the same object */
void Close() { AudioDecoderPull_Close(); }
enum
{
DISPATCHABLE_VERSION=0,
};
private:
virtual int WASABICALL AudioDecoderPull_GetFrameSize(size_t *frame_size)=0;
virtual int WASABICALL AudioDecoderPull_GetMetadata(ifc_metadata **metadata)=0;
virtual int WASABICALL AudioDecoderPull_Decode(void *buffer, size_t buffer_frames, size_t *frames_written)=0;
virtual void WASABICALL AudioDecoderPull_Close()=0;
};
+76
View File
@@ -0,0 +1,76 @@
#pragma once
#include "foundation/dispatch.h"
#include "foundation/error.h"
#include "audio/parameters.h"
class NOVTABLE ifc_audioout : public Wasabi2::Dispatchable
{
protected:
ifc_audioout() : Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_audioout() {}
public:
enum
{
CHANNEL_LAYOUT_MICROSOFT = 0x0, // microsoft channel order - http://www.microsoft.com/whdc/device/audio/multichaud.mspx#E4C
CHANNEL_LAYOUT_MPEG = 0x1,
};
enum
{
EXTENDED_FLAG_APPLY_GAIN=0x1, /* apply the gain value specified in Parameters::gain */
EXTENDED_FLAG_REPLAYGAIN=0x2, /* pass if you tried to figure out ReplayGain on your own. otherwise the Audio Output object will apply the default gain */
EXTENDED_FLAG_GAIN_MASK=EXTENDED_FLAG_APPLY_GAIN|EXTENDED_FLAG_REPLAYGAIN, /* a mask to check whether or not the gain value is valid */
/* so that you can check if a flag was set that you don't understand */
EXTENDED_FLAG_VALID_MASK=EXTENDED_FLAG_APPLY_GAIN|EXTENDED_FLAG_REPLAYGAIN,
};
struct Parameters
{
size_t sizeof_parameters;
nsaudio::Parameters audio;
/* anything after this needs sizeof_parameters to be large enough
AND a flag set in extended_fields_flags
if there's no flag for the field, it's because a default value of 0 can be assumed */
unsigned int extended_fields_flags; // set these if you use any of the following fields. see comment above
double gain; // additional gain specified by client. usually used for replaygain (so it can be combined with EQ pre-amp or float/pcm conversion)
size_t frames_trim_start; // number of frames to trim from the start
size_t frames_trim_end; // number of frames to trim from the start
};
int Output(const void *data, size_t data_size) { return AudioOutput_Output(data, data_size); }
// returns number of bytes that you can write
size_t CanWrite() { return AudioOutput_CanWrite(); }
void Flush(double seconds) { AudioOutput_Flush(seconds); }
void Pause(int state) { AudioOutput_Pause(state); }
/* called by the input plugin when no more output will be sent */
void Done() { AudioOutput_Done(); }
/* called by the input plugin when playback was forcefully stopped */
void Stop() { AudioOutput_Stop(); }
/* returns the latency in seconds (how many seconds until samples you're about to write show up at the audio output */
double Latency() { return AudioOutput_Latency(); }
/* only valid after a call to Done(). Returns NErr_True if there is still data in the buffer, NErr_False otherwise */
int Playing() { return AudioOutput_Playing(); }
protected:
virtual int WASABICALL AudioOutput_Output(const void *data, size_t data_size)=0;
virtual size_t WASABICALL AudioOutput_CanWrite()=0; // returns number of bytes that you can write
virtual void WASABICALL AudioOutput_Flush(double seconds)=0;
virtual void WASABICALL AudioOutput_Pause(int state)=0;
/* called by the input plugin when no more output will be sent */
virtual void WASABICALL AudioOutput_Done()=0;
/* called by the input plugin when playback was forcefully stopped */
virtual void WASABICALL AudioOutput_Stop()=0;
virtual double WASABICALL AudioOutput_Latency()=0;
virtual int WASABICALL AudioOutput_Playing()=0;
enum
{
DISPATCHABLE_VERSION,
};
};
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include "foundation/dispatch.h"
class ifc_equalizer : public Wasabi2::Dispatchable
{
protected:
ifc_equalizer() : Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_equalizer() {}
public:
int SetPreamp(double dB) { return Equalizer_SetPreamp(dB); }
int SetBand(unsigned int band, double dB) { return Equalizer_SetBand(band, dB); }
int Enable() { return Equalizer_Enable(); }
int Disable() { return Equalizer_Disable(); }
private:
virtual int WASABICALL Equalizer_SetPreamp(double dB)=0;
virtual int WASABICALL Equalizer_SetBand(unsigned int band, double dB)=0;
virtual int WASABICALL Equalizer_Enable()=0;
virtual int WASABICALL Equalizer_Disable()=0;
enum
{
DISPATCHABLE_VERSION,
};
};
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include "foundation/types.h"
#include "foundation/guid.h"
namespace nsaudio
{
enum
{
/* when this is set, the const void * passed to AudioOutput_Output is assumed to be an array of channels,
e.g. (format_type == nsaudio_type_float && (format_flags & FORMAT_FLAG_NONINTERLEAVED) && number_of_channels == 2)
means that you pass a float *[2] to AudioOutput_Output
*/
FORMAT_FLAG_INTERLEAVED=0x1,
FORMAT_FLAG_NONINTERLEAVED=0x2,
FORMAT_FLAG_NATIVE_ENDIAN=0x4,
FORMAT_FLAG_LITTLE_ENDIAN=0x8, /* audio is SPECIFICALLY little endian (as opposed to native endian on little-endian machines) */
FORMAT_FLAG_BIG_ENDIAN=0x10, /* audio is SPECIFICALLY big endian (as opposed to native endian on big-endian machines) */
FORMAT_FLAG_SIGNED=0x20, /* e.g. 8 bit PCM is typically unsigned (0-255) */
FORMAT_FLAG_UNSIGNED=0x40, /* e.g. 8 bit PCM is typically unsigned (0-255) */
/* so that you can check if a flag was set that you don't understand */
FORMAT_FLAG_VALID_INTERLEAVE = FORMAT_FLAG_INTERLEAVED|FORMAT_FLAG_NONINTERLEAVED,
FORMAT_FLAG_VALID_ENDIAN = FORMAT_FLAG_NATIVE_ENDIAN|FORMAT_FLAG_LITTLE_ENDIAN|FORMAT_FLAG_BIG_ENDIAN,
FORMAT_FLAG_VALID_SIGNED=FORMAT_FLAG_SIGNED|FORMAT_FLAG_UNSIGNED,
FORMAT_FLAG_VALID_MASK=FORMAT_FLAG_VALID_INTERLEAVE|FORMAT_FLAG_VALID_ENDIAN|FORMAT_FLAG_VALID_SIGNED,
};
// {4B80932C-E55F-4969-91EA-772584ABEDC2}
static const GUID format_type_pcm =
{ 0x4b80932c, 0xe55f, 0x4969, { 0x91, 0xea, 0x77, 0x25, 0x84, 0xab, 0xed, 0xc2 } };
// {6D47717F-A383-4CF8-BB1E-72254BE3F9DC}
static const GUID format_type_float =
{ 0x6d47717f, 0xa383, 0x4cf8, { 0xbb, 0x1e, 0x72, 0x25, 0x4b, 0xe3, 0xf9, 0xdc } };
struct Parameters
{
double sample_rate;
GUID format_type; // PCM, floating point, SPDIF pass-thru, etc.
unsigned int format_flags; // endian, interleaved, signed
unsigned int bytes_per_sample; // e.g. 4 for 20bit in a 32bit container
unsigned int bits_per_sample; // number of valid bits within the sample
unsigned int number_of_channels;
unsigned int channel_layout;
};
};
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include "foundation/types.h"
enum Agave_PositionType
{
AGAVE_PLAYPOSITION_100NANOECONDS = 0,
AGAVE_PLAYPOSITION_MILLISECONDS = 1,
AGAVE_PLAYPOSITION_SECONDS = 2,
AGAVE_PLAYPOSITION_HMSF= 3,
AGAVE_PLAYPOSITION_SAMPLE_FRAMES = 4,
AGAVE_PLAYPOSITION_BYTES = 5,
AGAVE_PLAYPOSITION_PACKETS = 6,
};
struct Agave_HMSF
{
uint8_t hours;
uint8_t minutes;
uint8_t seconds;
uint8_t frames;
};
union Agave_Position
{
uint64_t nanoseconds100; // in increments of 100 nanoseconds (microsoft style)
uint64_t milliseconds;
double seconds;
Agave_HMSF hmsf;
uint64_t sample_frames;
uint64_t bytes;
uint64_t packets;
};
struct Agave_Seek
{
Agave_PositionType position_type;
Agave_Position position;
};
static void Agave_Seek_SetBytes(Agave_Seek *seek, uint64_t bytes)
{
seek->position_type=AGAVE_PLAYPOSITION_BYTES;
seek->position.bytes = bytes;
}
@@ -0,0 +1,224 @@
#include "ComponentManagerBase.h"
#include "foundation/error.h"
#include "nx/nxuri.h"
ComponentManagerBase::ComponentManagerBase()
{
phase=PHASE_INITIALIZE;
service_api=0;
component_sync=0;
framework_guid = INVALID_GUID;
application_guid = INVALID_GUID;
}
int ComponentManagerBase::LateLoad(ifc_component *component)
{
int ret;
if (phase >= PHASE_REGISTERED)
{
ret = component->RegisterServices(service_api);
if (ret != NErr_Success)
{
int ret2 = component->Quit(service_api);
if (ret2 == NErr_TryAgain)
{
component_sync->Wait(1);
}
return ret;
}
}
if (phase >= PHASE_LOADING)
{
ret = component->OnLoading(service_api);
if (ret != NErr_Success)
{
int ret2 = component->Quit(service_api);
if (ret2 == NErr_TryAgain)
{
component_sync->Wait(1);
}
return ret;
}
}
if (phase >= PHASE_LOADED)
{
ret = component->OnLoaded(service_api);
if (ret != NErr_Success)
{
int ret2 = component->Quit(service_api);
if (ret2 == NErr_TryAgain)
{
component_sync->Wait(1);
}
return ret;
}
}
return NErr_Success;
}
void ComponentManagerBase::SetServiceAPI(api_service *_service_api)
{
this->service_api = _service_api;
service_api->QueryInterface(&component_sync);
}
int ComponentManagerBase::Load()
{
if (phase != PHASE_INITIALIZE)
return NErr_Error;
int ret;
/* RegisterServices phase */
for (ComponentList::iterator itr=components.begin();itr!=components.end();)
{
ifc_component *component = *itr;
//ComponentList::iterator next=itr;
//next++;
ret = component->RegisterServices(service_api);
if (ret != NErr_Success)
{
int ret2 = component->Quit(service_api);
if (ret2 == NErr_TryAgain)
{
component_sync->Wait(1);
}
NXURIRelease(component->component_info.filename);
CloseComponent(component);
itr = components.erase(itr);
}
else
{
itr++; // = next;
}
}
phase = PHASE_REGISTERED;
/* OnLoading phase */
for (ComponentList::iterator itr=components.begin();itr!=components.end();)
{
ifc_component *component = *itr;
//ComponentList::iterator next=itr;
//next++;
ret = component->OnLoading(service_api);
if (ret != NErr_Success)
{
int ret2 = component->Quit(service_api);
if (ret2 == NErr_TryAgain)
{
component_sync->Wait(1);
}
NXURIRelease(component->component_info.filename);
CloseComponent(component);
itr = components.erase(itr);
}
else
{
itr++; // = next;
}
}
phase = PHASE_LOADING;
/* OnLoaded phase */
for (ComponentList::iterator itr = components.begin(); itr != components.end();)
{
ifc_component* component = *itr;
//ComponentList::iterator next = itr;
//next++;
ret = component->OnLoaded(service_api);
if (ret != NErr_Success)
{
int ret2 = component->Quit(service_api);
if (ret2 == NErr_TryAgain)
{
component_sync->Wait(1);
}
NXURIRelease(component->component_info.filename);
CloseComponent(component);
itr = components.erase(itr);
}
else
{
itr++; // = next;
}
}
phase = PHASE_LOADED;
return NErr_Success;
}
int ComponentManagerBase::AddComponent(ifc_component *component)
{
int err;
if (NULL == component)
return NErr_BadParameter;
if (phase > PHASE_LOADED)
return NErr_Error;
if (component->component_info.wasabi_version != wasabi2_component_version
|| component->component_info.nx_api_version != nx_api_version
|| component->component_info.nx_platform_guid != nx_platform_guid)
{
return NErr_IncompatibleVersion;
}
if (component->component_info.framework_guid != INVALID_GUID
&& framework_guid != component->component_info.framework_guid)
{
return NErr_IncompatibleVersion;
}
if (component->component_info.application_guid != INVALID_GUID
&& application_guid != component->component_info.application_guid)
{
return NErr_IncompatibleVersion;
}
for (ComponentList::iterator itr = components.begin(); itr != components.end(); itr++)
{
ifc_component *registered_component = *itr;
if (registered_component->component_info.component_guid == component->component_info.component_guid)
return NErr_Error;
}
err = component->Initialize(service_api);
if (NErr_Success != err)
return err;
/* if the component was added late, we'll need to run some extra stages */
err = LateLoad(component);
if (NErr_Success != err)
return err;
components.push_back(component);
return NErr_Success;
}
void ComponentManagerBase::SetFrameworkGUID(GUID guid)
{
framework_guid = guid;
}
GUID ComponentManagerBase::GetFrameworkGUID()
{
return framework_guid;
}
void ComponentManagerBase::SetApplicationGUID(GUID guid)
{
application_guid = guid;
}
GUID ComponentManagerBase::GetApplicationGUID()
{
return application_guid;
}
@@ -0,0 +1,43 @@
#pragma once
#include "nx/nxuri.h"
#include "service/api_service.h"
#include "component/ifc_component.h"
#include <deque>
#include "component/ifc_component_sync.h"
class ComponentManagerBase
{
public:
void SetServiceAPI(api_service *service_api);
int Load();
void SetFrameworkGUID(GUID guid);
GUID GetFrameworkGUID();
void SetApplicationGUID(GUID guid);
GUID GetApplicationGUID();
virtual int AddComponent(ifc_component *component);
protected:
ComponentManagerBase();
int LateLoad(ifc_component *mod);
enum Phase
{
PHASE_INITIALIZE=0, /* components are still being added */
PHASE_REGISTERED=1, /* RegisterServices() has been called on all components */
PHASE_LOADING=2, /* OnLoading() has been called on all components */
PHASE_LOADED=3, /* OnLoaded() has been called on all components */
};
Phase phase;
typedef std::deque<ifc_component*> ComponentList;
ComponentList components;
api_service *service_api;
ifc_component_sync *component_sync;
GUID framework_guid;
GUID application_guid;
private:
/* your implementation needs to override this. You should call FreeLibrary(component->component_info.hModule); or dlclose(component->component_info.dl_handle); or similar */
virtual void CloseComponent(ifc_component *component)=0;
};
+95
View File
@@ -0,0 +1,95 @@
#pragma once
#include "foundation/dispatch.h"
#include "service/api_service.h"
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
#ifdef __APPLE__
#include <CoreFoundation/CoreFoundation.h> /* for CFBundleRef */
#endif
#include "nx/nxapi.h"
#include "nx/nxuri.h"
/* see http://wiki.office.aol.com/wiki/Replicant/Component */
/* in very rare cases, this will get incremented */
const int wasabi2_component_version = 0;
struct WasabiComponentInfo
{
/* these will be filled in by the host application loading your component */
#if defined(_WIN32)
HMODULE hModule;
#elif defined(__APPLE__)
/* depending on whether your component is a bundle or a dylib, one of these will be filled */
CFBundleRef bundle;
void *dl_handle; // pointer returned from dlopen
#else
void *dl_handle; // pointer returned from dlopen
#endif
nx_uri_t filename;
/* these are filled in during ifc_component's constructor. You don't need to change these */
int wasabi_version; /* major breaking changes to Wasabi (ABI changes, Dispatchable definition, etc) will change this. This is used to filter out components that are expecting something completely different than what the host API provides */
int nx_api_version; /* major breaking changes to the NX API will change this. */
GUID nx_platform_guid; /* platform that this is meant to link against. right now this mainly helps avoid loading android components on 'vanilla' linux, and vice-versa */
/* these are defaulted to INVALID_GUID. You can optionally override these in your Component's constructor */
GUID component_guid; /* a unique identifier for your Component */
GUID framework_guid; /* optionally set to the framework that your component is meant to work in. Can optionally be used as a filter by the Component Manager. This avoids loading, e.g., a replicant component on some completely different Wasabi-based framework */
GUID application_guid; /* if your component is meant to work with a specific application, you can define it here. Can optionally be used as a filter by the Component Manager. */
};
class NOVTABLE ifc_component : public Wasabi2::Dispatchable
//public wa::lists::node_ptr /* this is for internal use by the Component Manager! */
{
protected:
ifc_component(GUID component_guid) : Wasabi2::Dispatchable(DISPATCHABLE_VERSION)
{
memset(&component_info, 0, sizeof(component_info)); /* memsetting the whole thing avoids a bunch of ifdef code */
component_info.wasabi_version = wasabi2_component_version;
component_info.nx_api_version = nx_api_version;
component_info.nx_platform_guid = nx_platform_guid;
component_info.component_guid = component_guid;
}
~ifc_component() {}
public:
WasabiComponentInfo component_info; /* it's unusual for an interface to have data members, but this makes thing convienent */
int Initialize(api_service *_service_manager) { return Component_Initialize(_service_manager); }
int RegisterServices(api_service *_service_manager) { return Component_RegisterServices(_service_manager); }
int OnLoading(api_service *_service_manager) { return Component_OnLoading(_service_manager); }
int OnLoaded(api_service *_service_manager) {return Component_OnLoaded(_service_manager); }
int OnClosing(api_service *_service_manager) { return Component_OnClosing(_service_manager); }
void DeregisterServices(api_service *_service_manager) { Component_DeregisterServices(_service_manager); }
int OnClosed(api_service *_service_manager) { return Component_OnClosed(_service_manager); }
int Quit(api_service *_service_manager) { return Component_Quit(_service_manager); }
enum
{
DISPATCHABLE_VERSION,
};
private:
/* these 4 will get called in sequence during component load, see http://wiki.office.aol.com/wiki/Replicant/Component for details */
// TODO: get rid of default implementations, eventually
virtual int WASABICALL Component_Initialize(api_service *_service_manager) { return NErr_Success; }
virtual int WASABICALL Component_RegisterServices(api_service *_service_manager)=0;
virtual int WASABICALL Component_OnLoading(api_service *_service_manager) { return NErr_Success; }
virtual int WASABICALL Component_OnLoaded(api_service *_service_manager) { return NErr_Success; }
virtual int WASABICALL Component_OnClosing(api_service *_service_manager) { return NErr_Success; }
virtual void WASABICALL Component_DeregisterServices(api_service *_service_manager)=0;
virtual int WASABICALL Component_OnClosed(api_service *_service_manager) { return NErr_Success; }
virtual int WASABICALL Component_Quit(api_service *_service_manager) { return NErr_Success; }
};
extern "C" typedef ifc_component *(*GETCOMPONENT_FUNC)();
@@ -0,0 +1,22 @@
#pragma once
#include "foundation/dispatch.h"
// {667F8818-AECD-4017-80EE-C43E096E68C1}
static const GUID ifc_component_sync_interface_guid =
{ 0x667f8818, 0xaecd, 0x4017, { 0x80, 0xee, 0xc4, 0x3e, 0x9, 0x6e, 0x68, 0xc1 } };
class ifc_component_sync : public Wasabi2::Dispatchable
{
protected:
ifc_component_sync() : Wasabi2::Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_component_sync() {}
public:
static GUID GetInterfaceGUID() { return ifc_component_sync_interface_guid; }
int Wait(size_t count) { return ComponentSync_Wait(count); }
enum
{
DISPATCHABLE_VERSION=0,
};
private:
virtual int WASABICALL ComponentSync_Wait(size_t count)=0;
};
@@ -0,0 +1,88 @@
#include "ComponentManager.h"
#include "foundation/error.h"
#include "nx/nxuri.h"
int ComponentManager::AddComponent(nx_uri_t filename)
{
if (phase > PHASE_LOADED)
return NErr_Error;
HMODULE hLib = LoadLibraryW(filename->string);
if (hLib)
{
GETCOMPONENT_FUNC pr = (GETCOMPONENT_FUNC)GetProcAddress(hLib, "GetWasabi2Component");
if (pr)
{
ifc_component *component = pr();
if (component)
{
if (component->component_info.wasabi_version != wasabi2_component_version
|| component->component_info.nx_api_version != nx_api_version
|| component->component_info.nx_platform_guid != nx_platform_guid)
{
FreeLibrary(hLib);
return NErr_IncompatibleVersion;
}
component->component_info.hModule = hLib;
component->component_info.filename = NXURIRetain(filename);
int ret = component->Initialize(service_api);
if (ret != NErr_Success)
{
NXURIRelease(component->component_info.filename);
FreeLibrary(hLib);
return ret;
}
/* if the component was added late, we'll need to run some extra stages */
ret = LateLoad(component);
if (ret != NErr_Success)
{
NXURIRelease(component->component_info.filename);
FreeLibrary(hLib);
return ret;
}
components.push_back(component);
return NErr_Success;
}
}
return NErr_Error;
}
else
{
return NErr_FileNotFound;
}
}
int ComponentManager::AddDirectory(nx_uri_t directory)
{
WIN32_FIND_DATAW find_data = {0};
nx_uri_t directory_mask;
int ret = NXURICreateFromPath(&directory_mask, L"*.w6c", directory);
if (ret != NErr_Success)
return ret;
HANDLE find_handle = FindFirstFileW(directory_mask->string, &find_data);
if (find_handle != INVALID_HANDLE_VALUE)
{
do
{
nx_uri_t w6c_filename;
if (NXURICreateFromPath(&w6c_filename, find_data.cFileName, directory) == NErr_Success)
{
AddComponent(w6c_filename);
NXURIRelease(w6c_filename);
}
}
while (FindNextFileW(find_handle,&find_data));
FindClose(find_handle);
}
return NErr_Success;
}
void ComponentManager::CloseComponent(ifc_component *component)
{
FreeLibrary(component->component_info.hModule);
}
@@ -0,0 +1,12 @@
#pragma once
#include "../ComponentManagerBase.h"
class ComponentManager : public ComponentManagerBase
{
public:
int AddComponent(nx_uri_t filename);
int AddDirectory(nx_uri_t directory);
private:
void CloseComponent(ifc_component *component);
};
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include "foundation/dispatch.h"
#include "audio/ifc_audio_decoder_callback.h"
#include "audio/parameters.h"
#include "service/types.h"
#include "nx/nxuri.h"
// {AA4404BC-69E7-4898-9296-420F774C3331}
static const GUID decode_api_service_guid =
{ 0xaa4404bc, 0x69e7, 0x4898, { 0x92, 0x96, 0x42, 0xf, 0x77, 0x4c, 0x33, 0x31 } };
/* benski> some of this is TODO as of 25-Jan-2012
We want to have several ways to create a decoder
1) Simple method. Create a decoder of the desired style (callback, pull, packet). api_decode will convert between styles if necessary
2) Constraint method: Non-zero values for nsaudio::Parameters members are treated as requirements and api_decode will convert. Flags might indicate that sample rate or channels is a "maximum" rather than a strict requirement
3) Multiple nsaudio::Parameters values. Used if you are a little more flexible in the data format, e.g. if you can handle 16bit audio or floating point
*/
class api_decode : public Wasabi2::Dispatchable
{
protected:
api_decode() : Wasabi2::Dispatchable(DISPATCHABLE_VERSION) {}
~api_decode() {}
public:
static GUID GetServiceType() { return SVC_TYPE_UNIQUE; }
static GUID GetServiceGUID() { return decode_api_service_guid; }
int CreateAudioDecoder_Callback(ifc_audio_decoder_callback **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags) { return DecodeAPI_CreateAudioDecoder_Callback(decoder, filename, parameters, flags); }
enum
{
DISPATCHABLE_VERSION=0,
};
private:
virtual int WASABICALL DecodeAPI_CreateAudioDecoder_Callback(ifc_audio_decoder_callback **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags)=0;
};
@@ -0,0 +1,20 @@
#pragma once
#include "foundation/dispatch.h"
class ifc_raw_media_reader : public Wasabi2::Dispatchable
{
protected:
ifc_raw_media_reader() : Wasabi2::Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_raw_media_reader() {}
public:
int Read(void *buffer, size_t buffer_size, size_t *bytes_read) { return RawMediaReader_Read(buffer, buffer_size, bytes_read); }
/* TODO: we'll probably need stuff in here like EndOfFile, determining a good buffer size, etc */
enum
{
DISPATCHABLE_VERSION=0,
};
protected:
virtual int WASABICALL RawMediaReader_Read(void *buffer, size_t buffer_size, size_t *bytes_read)=0;
};
+80
View File
@@ -0,0 +1,80 @@
#pragma once
#include "foundation/dispatch.h"
#include "audio/parameters.h"
#include "audio/ifc_audio_decoder_callback.h"
#include "audio/ifc_audio_decoder_pull.h"
#include "nx/nxuri.h"
/* if you return NErr_TryAgain, you will be called again with pass=1 after all other services get a chance at the file */
// DA3BB978-4A85-409F-B67C-10E3E1CF73CB
static const GUID decode_service_type_guid =
{ 0xDA3BB978, 0x4A85, 0x409F, { 0xB6, 0x7C, 0x10, 0xE3, 0xE1, 0xCF, 0x73, 0xCB } };
class svc_decode : public Wasabi2::Dispatchable
{
protected:
svc_decode() : Dispatchable(DISPATCHABLE_VERSION) {}
~svc_decode() {}
public:
static GUID GetServiceType() { return decode_service_type_guid; }
/*
* return values for the CreateAudioDecoder family of functions
* * NErr_Success: Decoder successfully created
* * NErr_False: File type not supported by this decoder
* * NErr_UnsupportedInterface: File type is supported by this decoder, but not the particular style (callback, pull, packet).
* * Any other code is interpreted as an error and enumeration will stop!
*/
/* Flags are defined in ifc_audio_decoder_callback */
int CreateAudioDecoder_Callback(ifc_audio_decoder_callback **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags) { return DecodeService_CreateAudioDecoder_Callback(decoder, filename, parameters, flags); }
int CreateAudioDecoder_Pull(ifc_audio_decoder_pull **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags) { return DecodeService_CreateAudioDecoder_Pull(decoder, filename, parameters, flags); }
int CreateAudioDecoder_Callback(unsigned int pass, ifc_audio_decoder_callback **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags)
{
if (dispatchable_version == 0)
{
if (pass == 0)
return DecodeService_CreateAudioDecoder_Callback(decoder, filename, parameters, flags);
else
return NErr_False;
}
else
return DecodeService_CreateAudioDecoder_Callback(pass, decoder, filename, parameters, flags);
}
int CreateAudioDecoder_Pull(unsigned int pass, ifc_audio_decoder_pull **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags)
{
if (dispatchable_version == 0)
{
if (pass == 0)
return DecodeService_CreateAudioDecoder_Pull(decoder, filename, parameters, flags);
else
return NErr_False;
}
else
return DecodeService_CreateAudioDecoder_Pull(pass, decoder, filename, parameters, flags);
}
enum
{
/* Additional flags are defined in the specific decoder interface (e.g. ifc_audio_decoder_pull.h)
They should start at 0x80000001 to ensure uniqueness */
FLAG_NO_METADATA= (1 << 0), // tells the decoder that it doesn't need to parse metadata
FLAG_VALIDATION = (1 << 1), // turns on codec/file-format specific extra validation checks. for most implementations this means turning on CRC checking
};
enum
{
DISPATCHABLE_VERSION=1,
};
private:
/* these two no longer have to be implemented */
virtual int WASABICALL DecodeService_CreateAudioDecoder_Callback(ifc_audio_decoder_callback **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags) { return DecodeService_CreateAudioDecoder_Callback(0, decoder, filename, parameters, flags); }
virtual int WASABICALL DecodeService_CreateAudioDecoder_Pull(ifc_audio_decoder_pull **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags) { return DecodeService_CreateAudioDecoder_Pull(0, decoder, filename, parameters, flags); }
virtual int WASABICALL DecodeService_CreateAudioDecoder_Callback(unsigned int pass, ifc_audio_decoder_callback **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags) { return NErr_NotImplemented; }
virtual int WASABICALL DecodeService_CreateAudioDecoder_Pull(unsigned int pass, ifc_audio_decoder_pull **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags) { return NErr_NotImplemented; }
};
@@ -0,0 +1,27 @@
#pragma once
#include "foundation/dispatch.h"
#include "ifc_raw_media_reader.h"
#include "nx/nxuri.h"
// {BE616DD5-5F42-4E42-88CF-CB7DCB47A3CD}
static const GUID svc_raw_media_reader_guid =
{ 0xbe616dd5, 0x5f42, 0x4e42, { 0x88, 0xcf, 0xcb, 0x7d, 0xcb, 0x47, 0xa3, 0xcd } };
class svc_raw_media_reader : public Wasabi2::Dispatchable
{
protected:
svc_raw_media_reader() : Wasabi2::Dispatchable(DISPATCHABLE_VERSION) {}
~svc_raw_media_reader() {}
public:
static GUID GetServiceType() { return svc_raw_media_reader_guid; }
int CreateRawMediaReader(ifc_raw_media_reader **reader, nx_uri_t filename, unsigned int pass) { return RawMediaReaderService_CreateRawMediaReader(reader, filename, pass); }
enum
{
DISPATCHABLE_VERSION = 0,
};
protected:
virtual int WASABICALL RawMediaReaderService_CreateRawMediaReader(ifc_raw_media_reader **reader, nx_uri_t filename, unsigned int pass)=0;
};
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include "decode/svc_decode.h"
#include "nswasabi/ServiceName.h"
// {F07160ED-2820-4DA5-9CE9-857A4CD9DFA0}
static const GUID file_decoder_guid =
{ 0xf07160ed, 0x2820, 0x4da5, { 0x9c, 0xe9, 0x85, 0x7a, 0x4c, 0xd9, 0xdf, 0xa0 } };
class FileDecoderService : public svc_decode
{
public:
WASABI_SERVICE_NAME("File Decoder");
WASABI_SERVICE_GUID(file_decoder_guid);
private:
int WASABICALL DecodeService_CreateAudioDecoder_Callback(unsigned int pass, ifc_audio_decoder_callback **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags);
int WASABICALL DecodeService_CreateAudioDecoder_Pull(unsigned int pass, ifc_audio_decoder_pull **decoder, nx_uri_t filename, nsaudio::Parameters *parameters, int flags);
};
+112
View File
@@ -0,0 +1,112 @@
#pragma once
#include "metadata/svc_metadata.h"
#include "metadata/ifc_metadata.h"
#include "nswasabi/ServiceName.h"
#include "nx/nxuri.h"
#include "nx/nxfile.h"
#include "nsid3v2/nsid3v2.h"
#include "nsid3v1/nsid3v1.h"
#include "nsapev2/nsapev2.h"
#include "nswasabi/ID3v2Metadata.h"
#include "nswasabi/APEv2Metadata.h"
#include "nswasabi/ID3v1Metadata.h"
#include "ifc_filemetadata_editor.h"
// {6FCF1A5A-79D0-4FB8-9911-222638CA32A1}
static const GUID file_metadata_guid =
{ 0x6fcf1a5a, 0x79d0, 0x4fb8, { 0x99, 0x11, 0x22, 0x26, 0x38, 0xca, 0x32, 0xa1 } };
class FileMetadataService : public svc_metadata
{
public:
WASABI_SERVICE_NAME("File Metadata");
WASABI_SERVICE_GUID(file_metadata_guid);
private:
int WASABICALL MetadataService_EnumerateExtensions(unsigned int index, nx_string_t *extension);
int WASABICALL MetadataService_CreateMetadata(unsigned int pass, nx_uri_t filename, ifc_metadata **metadata);
int WASABICALL MetadataService_CreateMetadataEditor(unsigned int pass, nx_uri_t filename, ifc_metadata_editor **metadata);
};
class FileMetadata
{
public:
ns_error_t SetFileInformation(nx_uri_t filename, nx_file_stat_t file_stat);
ns_error_t FindMetadata(nx_file_t file);
bool HasMetadata() const; // returns whether or not there was any metadata found
protected:
FileMetadata();
~FileMetadata();
ns_error_t OwnID3v2(nsid3v2_tag_t id3v2, uint64_t position, uint64_t length);
ns_error_t OwnID3v1(nsid3v1_tag_t id3v1, uint64_t position, uint64_t length);
ns_error_t OwnAPEv2(nsapev2_tag_t apev2, uint64_t position, uint64_t length);
ns_error_t OwnLyrics3(void *lyrics, uint64_t position, uint64_t length);
nx_uri_t filename;
nx_file_stat_s file_stat;
template <class tag_t>
class MetaTag
{
public:
MetaTag() : tag(0), position(0), length(0) {}
tag_t tag;
uint64_t position;
uint64_t length;
};
/* ID3v2 */
MetaTag<nsid3v2_tag_t> id3v2;
ID3v2Metadata id3v2_metadata;
/* ID3v1 */
MetaTag<nsid3v1_tag_t> id3v1;
ID3v1Metadata id3v1_metadata;
/* APEv2 */
MetaTag<nsapev2_tag_t> apev2;
APEv2Metadata apev2_metadata;
MetaTag<void *> lyrics3;
uint64_t start_position;
uint64_t content_length;
uint64_t end_position;
};
class FileMetadataRead : public FileMetadata, public ifc_metadata
{
private:
int WASABICALL Metadata_GetField(int field, unsigned int index, nx_string_t *value);
int WASABICALL Metadata_GetInteger(int field, unsigned int index, int64_t *value);
int WASABICALL Metadata_GetReal(int field, unsigned int index, double *value);
int WASABICALL Metadata_GetArtwork(int field, unsigned int index, artwork_t *artwork, data_flags_t flags);
int WASABICALL Metadata_GetBinary(int field, unsigned int index, nx_data_t *data);
int WASABICALL Metadata_GetMetadata(int field, unsigned int index, ifc_metadata **metadata);
int WASABICALL Metadata_Serialize(nx_data_t *data);
};
class FileMetadataWrite : public FileMetadata, public ifc_metadata_editor
{
public:
FileMetadataWrite();
~FileMetadataWrite();
int Initialize(ifc_filemetadata_editor *editor);
private:
/* ifc_metadata_editor implementation */
int WASABICALL MetadataEditor_Save();
int WASABICALL MetadataEditor_SaveAs(nx_uri_t destination);
int WASABICALL MetadataEditor_SetField(int field, unsigned int index, nx_string_t value);
int WASABICALL MetadataEditor_SetInteger(int field, unsigned int index, int64_t value);
int WASABICALL MetadataEditor_SetReal(int field, unsigned int index, double value);
int WASABICALL MetadataEditor_SetArtwork(int field, unsigned int index, artwork_t *artwork, data_flags_t flags);
int MakeID3v2();
ifc_filemetadata_editor *editor;
};
+54
View File
@@ -0,0 +1,54 @@
#pragma once
#include "player/svc_playback.h"
#include "nx/nxstring.h"
#include "nx/nxfile.h"
#include "nswasabi/ServiceName.h"
#include "nswasabi/PlaybackBase.h"
#include "ifc_fileplayback.h"
#include "replaygain/ifc_replaygain_settings.h"
#include "FileMetadata.h"
// {60DB6A52-1A82-4C0D-A947-203549260758}
static const GUID file_playback_guid =
{ 0x60db6a52, 0x1a82, 0x4c0d, { 0xa9, 0x47, 0x20, 0x35, 0x49, 0x26, 0x7, 0x58 } };
class FilePlaybackService : public svc_playback
{
public:
WASABI_SERVICE_NAME("File Playback");
static GUID GetServiceGUID() { return file_playback_guid; }
FilePlaybackService();
int WASABICALL PlaybackService_CreatePlayback(unsigned int pass, nx_uri_t filename, ifc_player *player, ifc_playback **out_playback_object);
};
class FilePlayback : public PlaybackBase, public ifc_fileplayback_parent
{
public:
FilePlayback();
~FilePlayback();
ns_error_t Initialize(nx_uri_t filename, ifc_player *player);
private:
ns_error_t WASABICALL FilePlaybackParent_OpenOutput(const ifc_audioout::Parameters *parameters);
ns_error_t WASABICALL FilePlaybackParent_Output(const void *audio_data, size_t audio_data_length, size_t *frames_consumed, double begin_position_seconds);
ns_error_t WASABICALL FilePlaybackParent_OutputNonInterleaved(const void *audio_data, size_t audio_data_length, size_t *frames_consumed, double begin_position_seconds);
ns_error_t WASABICALL FilePlaybackParent_OnMetadata(ifc_metadata *new_metadata);
ifc_fileplayback *implementation;
nx_file_t file;
ifc_audioout *out;
bool paused;
double last_position;
ns_error_t exact_length, exact_bitrate;
ifc_audioout::Parameters parameters;
const uint8_t **output_pointers;
ifc_metadata *implementation_metadata;
FileMetadataRead *metadata;
ns_error_t Internal_Interrupt();
ns_error_t OutputWait();
ns_error_t WaitForClose();
/* Thread function */
static nx_thread_return_t NXTHREADCALL FilePlayerThreadFunction(nx_thread_parameter_t param);
nx_thread_return_t NXTHREADCALL DecodeLoop();
};
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include "decode/svc_raw_media_reader.h"
#include "decode/ifc_raw_media_reader.h"
#include "nswasabi/ServiceName.h"
#include "svc_filerawreader.h"
// {3877B6CF-937B-4E83-9A88-02E16B3A9654}
static const GUID file_raw_reader_guid =
{ 0x3877b6cf, 0x937b, 0x4e83, { 0x9a, 0x88, 0x2, 0xe1, 0x6b, 0x3a, 0x96, 0x54 } };
class FileRawReaderService : public svc_raw_media_reader
{
public:
WASABI_SERVICE_NAME("File Raw Reader");
WASABI_SERVICE_GUID(file_raw_reader_guid);
int WASABICALL RawMediaReaderService_CreateRawMediaReader(ifc_raw_media_reader **reader, nx_uri_t filename, unsigned int pass);
};
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include "service/api_service.h"
#include "application/api_application.h"
#include "syscb/api_syscb.h"
#include "metadata/api_metadata.h"
#include "filelock/api_filelock.h"
DECLARE_EXTERNAL_SERVICE(api_service, WASABI2_API_SVC);
DECLARE_EXTERNAL_SERVICE(api_application, WASABI2_API_APP);
DECLARE_EXTERNAL_SERVICE(api_syscb, WASABI2_API_SYSCB);
DECLARE_EXTERNAL_SERVICE(api_metadata, REPLICANT_API_METADATA);
DECLARE_EXTERNAL_SERVICE(api_filelock, REPLICANT_API_FILELOCK);
@@ -0,0 +1,43 @@
#pragma once
#include "foundation/dispatch.h"
#include "foundation/error.h"
#include "metadata/ifc_metadata_editor.h"
class ifc_filemetadata_editor : public Wasabi2::Dispatchable
{
protected:
ifc_filemetadata_editor() : Wasabi2::Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_filemetadata_editor() {}
public:
ns_error_t GetMetdataObject(ifc_metadata_editor **metadata) { return FileMetadata_GetMetdataObject(metadata); }
ns_error_t Save(nx_file_t file) { return FileMetadata_Save(file); }
ns_error_t RequireTempFile() { return FileMetadata_RequireTempFile(); }
ns_error_t SaveAs(nx_file_t destination, nx_file_t source) { return FileMetadata_SaveAs(destination, source); }
void Close() { FileMetadata_Close(); }
ns_error_t WantID3v2(int *position) { return FileMetadata_WantID3v2(position); }
ns_error_t WantID3v1() { return FileMetadata_WantID3v1(); }
ns_error_t WantAPEv2(int *position) { return FileMetadata_WantAPEv2(position); }
ns_error_t WantLyrics3() { return FileMetadata_WantLyrics3(); }
enum
{
DISPATCHABLE_VERSION=0,
TAG_POSITION_INDIFFERENT=0,
TAG_POSITION_PREPENDED=1,
TAG_POSITION_APPENDED=2,
};
protected:
virtual ns_error_t WASABICALL FileMetadata_GetMetdataObject(ifc_metadata_editor **metadata)=0;
virtual ns_error_t WASABICALL FileMetadata_Save(nx_file_t file) { return NErr_NotImplemented; }
virtual ns_error_t WASABICALL FileMetadata_RequireTempFile()=0;
virtual ns_error_t WASABICALL FileMetadata_SaveAs(nx_file_t destination, nx_file_t source) { return NErr_NotImplemented; }
virtual void WASABICALL FileMetadata_Close() {}
virtual ns_error_t WASABICALL FileMetadata_WantID3v2(int *position) { return NErr_False; }
virtual ns_error_t WASABICALL FileMetadata_WantID3v1() { return NErr_False; }
virtual ns_error_t WASABICALL FileMetadata_WantAPEv2(int *position) { return NErr_False; }
virtual ns_error_t WASABICALL FileMetadata_WantLyrics3() { return NErr_False; }
};
+77
View File
@@ -0,0 +1,77 @@
#pragma once
#include "audio/ifc_audioout.h"
#include "foundation/error.h"
#include "foundation/dispatch.h"
#include "metadata/ifc_metadata.h"
#include "player/types.h"
#include "nx/nxfile.h"
class ifc_fileplayback_parent : public Wasabi2::Dispatchable
{
protected:
ifc_fileplayback_parent() : Wasabi2::Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_fileplayback_parent() {}
public:
// only call these functions during DecodeStep!
// if any of these return an error, return it from DecodeStep().
// these return NErr_Aborted if there's a seek pending, and NErr_Interrupted if there is an interrupt pending
ns_error_t OpenOutput(const ifc_audioout::Parameters *parameters) { return FilePlaybackParent_OpenOutput(parameters); }
ns_error_t Output(const void *audio_data, size_t audio_data_length, size_t *frames_consumed, double begin_position_seconds) { return FilePlaybackParent_Output(audio_data, audio_data_length, frames_consumed, begin_position_seconds); }
ns_error_t OutputNonInterleaved(const void *audio_data, size_t audio_data_length, size_t *frames_consumed, double begin_position_seconds) { return FilePlaybackParent_OutputNonInterleaved(audio_data, audio_data_length, frames_consumed, begin_position_seconds); }
// call this if you have mid-stream metadata updates.
ns_error_t OnMetadata(ifc_metadata *new_metadata) { return FilePlaybackParent_OnMetadata(new_metadata); }
enum
{
DISPATCHABLE_VERSION=0,
};
protected:
virtual ns_error_t WASABICALL FilePlaybackParent_OpenOutput(const ifc_audioout::Parameters *parameters)=0;
virtual ns_error_t WASABICALL FilePlaybackParent_Output(const void *audio_data, size_t audio_data_length, size_t *frames_consumed, double begin_position_seconds)=0;
virtual ns_error_t WASABICALL FilePlaybackParent_OutputNonInterleaved(const void *audio_data, size_t audio_data_length, size_t *frames_consumed, double begin_position_seconds)=0;
virtual ns_error_t WASABICALL FilePlaybackParent_OnMetadata(ifc_metadata *new_metadata)=0;
};
class ifc_fileplayback : public Wasabi2::Dispatchable
{
protected:
ifc_fileplayback() : Wasabi2::Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_fileplayback() {}
public:
void Close() { FilePlayback_Close(); }
ns_error_t Seekable() { return FilePlayback_Seekable(); }
ns_error_t GetMetadata(ifc_metadata **metadata) { return FilePlayback_GetMetadata(metadata); }
ns_error_t GetLength(double *length, ns_error_t *exact) { return FilePlayback_GetLength(length, exact); }
ns_error_t GetBitrate(double *bitrate, ns_error_t *exact) { return FilePlayback_GetBitrate(bitrate, exact); }
ns_error_t Seek(const Agave_Seek *seek, ns_error_t *seek_error, double *new_position) { return FilePlayback_Seek(seek, seek_error, new_position); }
ns_error_t DecodeStep() { return FilePlayback_DecodeStep(); }
ns_error_t Interrupt(Agave_Seek *resume_information) { return FilePlayback_Interrupt(resume_information); }
ns_error_t Resume(Agave_Seek *resume_information, nx_file_t file, ifc_metadata *parent_metadata) { return FilePlayback_Resume(resume_information, file, parent_metadata); }
enum
{
DISPATCHABLE_VERSION=0,
};
protected:
/* you need to handle the possibility that Close gets called more than one time */
virtual void WASABICALL FilePlayback_Close()=0;
virtual ns_error_t WASABICALL FilePlayback_Seekable()=0;
/* implementation note: add a reference (Retain) before assigning the value */
virtual ns_error_t WASABICALL FilePlayback_GetMetadata(ifc_metadata **metadata)=0;
/* if you set *exact=NErr_False, GetLength will get called after the next DecodeStep */
virtual ns_error_t WASABICALL FilePlayback_GetLength(double *length, ns_error_t *exact)=0;
virtual ns_error_t WASABICALL FilePlayback_GetBitrate(double *bitrate, ns_error_t *exact)=0;
/* only return an error if you're in a state you can't recover from.
if you can't seek, then just don't seek and return NErr_Success */
virtual ns_error_t WASABICALL FilePlayback_Seek(const Agave_Seek *seek, ns_error_t *seek_error, double *new_position)=0;
/* return NErr_Success to continue
NErr_EndOfFile to indicate a natural end of file
otherwise return an error
do _not_ return NErr_Stopped, NErr_Aborted, or NErr_Interrupted, unless they were returned from an ifc_fileplayback_parent function, as these have special meaning */
virtual ns_error_t WASABICALL FilePlayback_DecodeStep()=0;
/* Save information and close the OS file handle.
fill resume_information with whatever information you'll need to resume */
virtual ns_error_t WASABICALL FilePlayback_Interrupt(Agave_Seek *resume_information)=0;
/* During resume, be sure to call player->SetMetadata again */
virtual ns_error_t WASABICALL FilePlayback_Resume(Agave_Seek *resume_information, nx_file_t file, ifc_metadata *parent_metadata)=0;
};
+2
View File
@@ -0,0 +1,2 @@
#pragma once
#include "nx/nxstring.h"
+32
View File
@@ -0,0 +1,32 @@
//
// precomp.h
// mp3
//
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#ifdef __cplusplus
#include "new"
#endif
#include "foundation/error.h"
#include "foundation/types.h"
#include "nu/ByteReader.h"
#include "nu/ByteWriter.h"
#include "nu/strsafe.h"
#include "nx/nx.h"
#ifdef __cplusplus
#include "nu/PtrDeque.h"
#include "nswasabi/ReferenceCounted.h"
#include "nswasabi/ServiceName.h"
#include "service/ifc_servicefactory.h"
#endif
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include "foundation/dispatch.h"
#include "audio/parameters.h"
#include "audio/ifc_audio_decoder_callback.h"
#include "audio/ifc_audio_decoder_pull.h"
#include "nx/nxuri.h"
#include "nx/nxfile.h"
#include "foundation/error.h"
#include "decode/svc_decode.h"
// {5F8FD642-9346-4400-803F-A20F342916FD}
static const GUID filedecode_service_type_guid =
{ 0x5f8fd642, 0x9346, 0x4400, { 0x80, 0x3f, 0xa2, 0xf, 0x34, 0x29, 0x16, 0xfd } };
class NOVTABLE svc_filedecode : public Wasabi2::Dispatchable
{
protected:
svc_filedecode() : Dispatchable(DISPATCHABLE_VERSION) {}
~svc_filedecode() {}
public:
static GUID GetServiceType() { return filedecode_service_type_guid; }
ns_error_t CreateAudioDecoder_Callback(ifc_audio_decoder_callback **decoder, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata, nsaudio::Parameters *parameters, int flags) { return FileDecodeService_CreateAudioDecoder_Callback(decoder, filename, file, parent_metadata, parameters, flags); }
enum
{
DISPATCHABLE_VERSION=0,
};
protected:
virtual ns_error_t WASABICALL FileDecodeService_CreateAudioDecoder_Callback(ifc_audio_decoder_callback **decoder, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata, nsaudio::Parameters *parameters, int flags)=0;
};
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include "foundation/foundation.h"
#include "nx/nxstring.h"
#include "ifc_filemetadata_editor.h"
// {92269164-30E1-469A-96C3-96879EF6C39E}
static const GUID file_metadata_service_type_guid =
{ 0x92269164, 0x30e1, 0x469a, { 0x96, 0xc3, 0x96, 0x87, 0x9e, 0xf6, 0xc3, 0x9e } };
class svc_filemetadata : public Wasabi2::Dispatchable
{
protected:
svc_filemetadata() : Dispatchable(DISPATCHABLE_VERSION) {}
~svc_filemetadata() {}
public:
static GUID GetServiceType() { return file_metadata_service_type_guid; }
// to make the implementation more flexible, you need to NXStringRelease on the extension you get (i.e. this function follows Apple's "Create" rule)
int EnumerateExtensions(unsigned int index, nx_string_t *extension) { return FileMetadataService_EnumerateExtensions(index, extension); }
int CreateFileMetadata(ifc_metadata **file_metadata, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata) { return FileMetadataService_CreateFileMetadata(file_metadata, filename, file, parent_metadata); }
int CreateFileMetadataEditor(ifc_filemetadata_editor **file_metadata, nx_uri_t filename, nx_file_t file, ifc_metadata_editor *parent_metadata) { return FileMetadataService_CreateFileMetadataEditor(file_metadata, filename, file, parent_metadata); }
enum
{
DISPATCHABLE_VERSION=0,
};
private:
// implementation note: to make the implementation more flexible, you need to NXStringRetain on the extension you pass back (i.e. follow Apple's "Create" rule)
virtual int WASABICALL FileMetadataService_EnumerateExtensions(unsigned int index, nx_string_t *extension)=0;
virtual int WASABICALL FileMetadataService_CreateFileMetadata(ifc_metadata **file_metadata, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata)=0;
virtual int WASABICALL FileMetadataService_CreateFileMetadataEditor(ifc_filemetadata_editor **file_metadata, nx_uri_t filename, nx_file_t file, ifc_metadata_editor *parent_metadata) { return NErr_NotImplemented; }
};
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include "foundation/dispatch.h"
#include "nx/nxuri.h"
#include "nx/nxfile.h"
#include "foundation/error.h"
#include "ifc_fileplayback.h"
#include "metadata/ifc_metadata.h"
// {AAB6F26D-FF99-4CE8-BC7F-81BEA9F35CA9}
static const GUID svc_fileplayback_type_guid =
{ 0xaab6f26d, 0xff99, 0x4ce8, { 0xbc, 0x7f, 0x81, 0xbe, 0xa9, 0xf3, 0x5c, 0xa9 } };
class NOVTABLE svc_fileplayback : public Wasabi2::Dispatchable
{
protected:
svc_fileplayback() : Dispatchable(DISPATCHABLE_VERSION) {}
~svc_fileplayback() {}
public:
static GUID GetServiceType() { return svc_fileplayback_type_guid; }
ns_error_t CreatePlayback(ifc_fileplayback **out_playback_object, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata, ifc_fileplayback_parent *parent) { return FilePlaybackService_CreatePlayback(out_playback_object, filename, file, parent_metadata, parent); }
enum
{
DISPATCHABLE_VERSION=0,
};
protected:
/* do _not_ retain/release the ifc_fileplayback_parent object! */
virtual ns_error_t WASABICALL FilePlaybackService_CreatePlayback(ifc_fileplayback **out_playback_object, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata, ifc_fileplayback_parent *parent)=0;
};
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include "foundation/dispatch.h"
#include "nx/nxuri.h"
#include "nx/nxfile.h"
#include "foundation/error.h"
#include "decode/ifc_raw_media_reader.h"
#include "metadata/ifc_metadata.h"
// {FF84B47B-5ED4-45E8-B822-0F8FE20F80A8}
static const GUID filerawreader_service_type_guid =
{ 0xff84b47b, 0x5ed4, 0x45e8, { 0xb8, 0x22, 0xf, 0x8f, 0xe2, 0xf, 0x80, 0xa8 } };
class NOVTABLE svc_filerawreader : public Wasabi2::Dispatchable
{
protected:
svc_filerawreader() : Dispatchable(DISPATCHABLE_VERSION) {}
~svc_filerawreader() {}
public:
static GUID GetServiceType() { return filerawreader_service_type_guid; }
int CreateRawMediaReader(ifc_raw_media_reader **reader, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata) { return FileRawReaderService_CreateRawMediaReader(reader, filename, file, parent_metadata); }
enum
{
DISPATCHABLE_VERSION=0,
};
protected:
virtual ns_error_t WASABICALL FileRawReaderService_CreateRawMediaReader(ifc_raw_media_reader **reader, nx_uri_t filename, nx_file_t file, ifc_metadata *parent_metadata)=0;
};
+49
View File
@@ -0,0 +1,49 @@
#pragma once
#include "foundation/foundation.h"
#include "nx/nxuri.h"
#include "service/types.h"
class cb_filelock : public Wasabi2::Dispatchable
{
protected:
cb_filelock() : Wasabi2::Dispatchable(DISPATCHABLE_VERSION) {}
~cb_filelock() {}
public:
int Interrupt() { return FileLockCallback_Interrupt(); }
enum
{
DISPATCHABLE_VERSION=0,
};
private:
virtual int WASABICALL FileLockCallback_Interrupt()=0;
};
// {AC2E21C6-7C66-47F6-8C99-267D6CAA1942}
static const GUID file_lock_service_guid =
{ 0xac2e21c6, 0x7c66, 0x47f6, { 0x8c, 0x99, 0x26, 0x7d, 0x6c, 0xaa, 0x19, 0x42 } };
class api_filelock : public Wasabi2::Dispatchable
{
protected:
api_filelock() : Wasabi2::Dispatchable(DISPATCHABLE_VERSION) {}
~api_filelock() {}
public:
static GUID GetServiceType() { return SVC_TYPE_UNIQUE; }
static GUID GetServiceGUID() { return file_lock_service_guid; }
int WaitForRead(nx_uri_t filename) { return FileLock_WaitForRead(filename); }
int WaitForReadInterruptable(nx_uri_t filename, cb_filelock *callback) { return FileLock_WaitForReadInterruptable(filename, callback); }
int WaitForWrite(nx_uri_t filename) { return FileLock_WaitForWrite(filename); }
int WaitForWriteInterruptable(nx_uri_t filename, cb_filelock *callback) { return FileLock_WaitForWriteInterruptable(filename, callback); }
int UnlockFile(nx_uri_t filename) { return FileLock_UnlockFile(filename); }
enum
{
DISPATCHABLE_VERSION=0,
};
private:
virtual int WASABICALL FileLock_WaitForRead(nx_uri_t filename)=0;
virtual int WASABICALL FileLock_WaitForReadInterruptable(nx_uri_t filename, cb_filelock *callback)=0;
virtual int WASABICALL FileLock_WaitForWrite(nx_uri_t filename)=0;
virtual int WASABICALL FileLock_WaitForWriteInterruptable(nx_uri_t filename, cb_filelock *callback)=0;
virtual int WASABICALL FileLock_UnlockFile(nx_uri_t filename)=0;
};
+9
View File
@@ -0,0 +1,9 @@
#pragma once
# if defined(__GNUC__)
#include <stdlib.h> // for posix_memalign
#define NALIGN(x) __attribute__((aligned(x)))
#elif defined(_MSC_VER)
#include <malloc.h> // for _aligned_malloc
#define NALIGN(x) __declspec (align(x))
#endif
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#if defined(_WIN64) && defined(_M_X64)
#include "win-amd64/atomics.h"
#elif defined(_WIN32) && defined(_M_IX86)
#include "win-x86/atomics.h"
#elif defined(__APPLE__) && defined(__amd64__)
#include "osx-amd64/atomics.h"
#elif defined(__APPLE__) && defined(__i386__)
#include "osx-x86/atomics.h"
#elif defined(__ANDROID__) && defined(__ARM_ARCH_7A__)
#include "android-armv7/atomics.h"
#elif defined(__ANDROID__) && (defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5TE__))
#include "android-arm/atomics.h"
#elif defined(__ANDROID__) && defined(__i386__)
#include "android-x86/atomics.h"
#elif defined(__linux__) && defined(__x86_64)
#include "linux-amd64/atomics.h"
#else
#error Port Me!
#endif
+74
View File
@@ -0,0 +1,74 @@
#pragma once
#include "guid.h"
#ifdef WIN32
#ifndef NOVTABLE
#define NOVTABLE __declspec(novtable)
#endif
#else
#define NOVTABLE
#endif
#if defined(__GNUC__) && (defined(__x86_32__) || defined(__i386__))
#define WASABICALL __attribute__((stdcall))
#elif defined (_WIN32)
#define WASABICALL __stdcall
#else
#define WASABICALL
#endif
namespace Wasabi2
{
class NOVTABLE Dispatchable
{
protected:
Dispatchable(size_t _dispatchable_version) : dispatchable_version(_dispatchable_version) {}
~Dispatchable() {}
public:
#define dispatch_call(code, default_return, func) (DispatchValid(code))?(default_return):func
#define dispatch_voidcall(code, func) if (DispatchValid(code)) func
bool DispatchValid(size_t code) const
{
return code < dispatchable_version;
}
size_t Retain()
{
return Dispatchable_Retain();
}
size_t Release()
{
return Dispatchable_Release();
}
int QueryInterface(GUID interface_guid, void **object)
{
return Dispatchable_QueryInterface(interface_guid, object);
}
template <class ifc_t>
int QueryInterface(ifc_t **object)
{
return Dispatchable_QueryInterface(ifc_t::GetInterfaceGUID(), (void **)object);
}
protected:
virtual size_t WASABICALL Dispatchable_Retain() { return 0; }
virtual size_t WASABICALL Dispatchable_Release() { return 0; }
virtual int WASABICALL Dispatchable_QueryInterface(GUID interface_guid, void **object) { return 1; }
size_t dispatchable_version;
};
}
#ifndef DECLARE_EXTERNAL_SERVICE
#define DECLARE_EXTERNAL_SERVICE(_type, _name) extern _type *_name
#endif
#ifndef DEFINE_EXTERNAL_SERVICE
#define DEFINE_EXTERNAL_SERVICE(_type, _name) _type *_name=0
#endif
+88
View File
@@ -0,0 +1,88 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
enum
{
NErr_Success = 0,
NErr_True = 0,
NErr_Error = 1, // generic error
NErr_OutOfMemory = 2,
NErr_FileNotFound = 3,
NErr_NullPointer = 4,
NErr_NotImplemented = 5,// I'm a lazy programmer
NErr_EndOfFile = 6, // also used for "end of enumeration"
NErr_NeedMoreData = 7, // input buffer was too small to provide useful output. Use this instead of NErr_ReadTruncated when it is expected that the caller can call the function again with more data
NErr_False = 8, // returned from a bool-like function to indicate "false" as opposed to "i had an error while figuring it out"
NErr_FailedCreate = 9, // Object could not be created
NErr_Closed = 10,
NErr_TryAgain = 11, // often used in round-robin "isMine()" loops to indicate that you'll take it if no one else wants it first. can also be used for device I/O when the device is busy
NErr_NoDevice = 12,
NErr_UnsupportedFormat = 13,
NErr_Unknown = 14, // NOT meant to be "some unknown error". Usually returned when some passed in enumeration or keyword was an unknown, unexpected or unsupported value
NErr_Insufficient = 15, // output buffer was too small
NErr_Empty = 16,
NErr_LostSynchronization = 17,
NErr_TimedOut = 19,
NErr_BadParameter = 20,
NErr_NoAction = 21, // Returned when no action performed, for example when initializing but something has already been initialized
// Test case related values
NErr_TestFailed = 18, // Result on a test failure, typically used by unit tests and other test cases.
NErr_TestPassed = 0, // Result on a test success, typically used by unit tests and other test cases.
NErr_TestError = 1, // Result on a test error, typically used by unit tests and other test cases.
NErr_TestNotComplete = 22, // Result on a premature stop, typically used by unit tests and other test cases. This is to protect against a scenerio where a test case is in a 'PASSED' state up to a certain point but cannot finish execution due to data missing, environmental issues, etc.
NErr_Malformed = 23, // some peice of data was malformed or had unexpected value (typically returned by parsers)
NErr_WrongFormat = 24, // data was understood but is indicating a different format than expected. e.g. an layer 2 header being encountered by a layer 3 parser
NErr_Reserved = 25, // typically returned when a parser encounters data with a reserved flag set to true
NErr_Changed = 26, // something changed. e.g. samplerate changed mid-stream
NErr_Interrupted = 27,
NErr_ConnectionFailed = 28, // generic "can't connect" error
NErr_DNS = 29, // no DNS entry for the host
/* the follow map NError codes to HTTP error codes. but they can be used for other purposes, too */
NErr_BadRequest = 30, // aka HTTP 400
NErr_Unauthorized = 31, // aka HTTP 401
NErr_Forbidden = 32, // aka HTTP 403
NErr_NotFound = 33, // aka HTTP 404, differentiated from NErr_FileNotFound
NErr_BadMethod = 34, // aka HTTP 405
NErr_NotAcceptable = 35, // aka HTTP 406
NErr_ProxyAuthenticationRequired = 36, // aka HTTP 407
NErr_RequestTimeout = 37, // aka HTTP 408
NErr_Conflict = 38, // aka HTTP 409
NErr_Gone = 39, // aka HTTP 410
NErr_InternalServerError = 40, // aka HTTP 500
NErr_ServiceUnavailable = 41, // aka HTTP 503
NErr_Exception = 42, // Underlying library returns an error or exception that wasn't understood
NErr_Underrun = 43, // Asynchronous thread not supplying data fast enough, buffer has insufficient data
NErr_NoMatchingImplementation = 44, // Returned when a function that delegates functionality to a matching component is unable to find one e.g. api_playlistmanager::Load
NErr_IntegerOverflow = 45,
NErr_IncompatibleVersion = 46, // returned e.g. when a "size" field in a passed struct was larger than expected, or when a flag was set that's not understood
NErr_Disabled = 47,
NErr_ParameterOutOfRange = 48, // Used to signify that a paramater was passed in that is out of bounds for valid values.
NErr_OSNotSupported = 49, // something is not supported on this OS (e.g. WASAPI audio on Windows XP)
NErr_UnsupportedInterface = 50, // used for some APIs (notably svc_decode). It means that you can provide the requested functionality for the provided data (e.g. filename) but don't support the requested interface
NErr_DirectPointer = 51,
NErr_ReadOnly = 52,
NErr_EndOfEnumeration = NErr_EndOfFile, // we'll eventually make this its own number
NErr_ReadTruncated = 54, // somewhat similar to NErr_NeedMoreData. Meant to be used e.g. when a file or input buffer is shorter than expected. Use this instead of NErr_NeedMoreData when the caller cannot provide more data.
NErr_Aborted = 55,
NErr_BadReturnValue = 56, // e.g. a callback function returns an unexpected value
NErr_MaximumDepth = 57,
NErr_Stopped = 58,
NErr_LengthRequired = 59, // aka HTTP 411
NErr_PreconditionFailed = 60, // aka HTTP 411
NErr_TooLarge = 61, // aka HTTP 413
};
typedef int NError;
typedef int ns_error_t; // TODO: eventually make this the name of the enum
#ifdef __cplusplus
}
#endif
// be careful. only use this if your stack variables self-destruct
#define NSERROR_RETURN_ON_FAILURE(x) { int local_ret = x; if (local_ret != NErr_Success) return local_ret; }
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#ifdef _MSC_VER
#define DLLEXPORT __declspec(dllexport)
#elif defined(__GNUC__)
#define DLLEXPORT __attribute__ ((visibility("default")))
#else
#error port me!
#endif
#ifdef _MSC_VER
#define DLLIMPORT __declspec(dllimport)
#elif defined(__GNUC__)
#define DLLIMPORT
#else
#error port me!
#endif
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include "dispatch.h"
#include "atomics.h"
#include "error.h"
#include "guid.h"
#include "mkncc.h"
#include "types.h"
+35
View File
@@ -0,0 +1,35 @@
#ifndef WASABI2_FOUNDATION_GUID_H
#define WASABI2_FOUNDATION_GUID_H
#pragma once
#include "types.h"
#if !defined(_WIN32)
#ifdef __cplusplus
#if !defined(GUID_EQUALS_DEFINED) || !defined(_SYS_GUID_OPERATOR_EQ_)
#define GUID_EQUALS_DEFINED
#include <memory.h>
#include <string.h>
static __inline int operator ==(const GUID &a, const GUID &b) {
return !memcmp(&a, &b, sizeof(GUID));
}
static __inline int operator !=(const GUID &a, const GUID &b) {
return !!memcmp(&a, &b, sizeof(GUID));
}
#endif //GUID_EQUALS_DEFINED
#endif //__cplusplus
#else
#include <guiddef.h>
#endif
#ifdef __cplusplus
static __inline int operator <(const GUID &a, const GUID &b) {
return memcmp(&a, &b, sizeof(GUID)) < 0;
}
#endif
static const GUID INVALID_GUID = { 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} };
static const GUID GENERIC_GUID = { 0xFFFFFFFF, 0xFFFF, 0xFFFF, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} };
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef WASABI2_FOUNDATION_MKNCC_H
#define WASABI2_FOUNDATION_MKNCC_H
#pragma once
// note: this is endian-incompatible with win32's MAKEFOURCC
// otoh, it shows up nicely in a debug register ;)
#define MK4CC(a, b, c, d) ( (((unsigned long)a)<<24)|(((unsigned long)b)<<16)|(((unsigned long)c)<<8)|((unsigned long)d) )
#define MK3CC(b, c, d) ( (((unsigned long)b)<<16)|(((unsigned long)c)<<8)|((unsigned long)d) )
#define MK2CC(c, d) ( (((unsigned long)c)<<8)|((unsigned long)d) )
#endif
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#if defined(_WIN64) && defined(_M_X64)
#include "win-amd64/types.h"
#elif defined(_WIN32) && defined(_M_IX86)
#include "win-x86/types.h"
#elif defined(__APPLE__) && defined(__LP64__)
#include "osx-amd64/types.h"
#elif defined(__APPLE__) // TODO: && defined(__LP32__)
#include "osx-x86/types.h"
#elif defined(__ANDROID__)
#include "android-arm/types.h"
#elif defined(__linux__) && defined(__x86_64)
#include "linux-amd64/types.h"
#else
#error port me!
#endif
@@ -0,0 +1,104 @@
/*
Win64 (amd64) implementation
*/
#pragma once
#include "../../foundation/types.h"
#include <Windows.h>
#include <intrin.h>
#ifdef __cplusplus
#define NX_ATOMIC_INLINE inline
#else
#define NX_ATOMIC_INLINE
#endif
NX_ATOMIC_INLINE static size_t nx_atomic_inc(volatile size_t *addr)
{
return (size_t)_InterlockedIncrement64((volatile LONGLONG *)addr);
}
NX_ATOMIC_INLINE static size_t nx_atomic_dec(volatile size_t *addr)
{
return (size_t)_InterlockedDecrement64((volatile LONGLONG *)addr);
}
NX_ATOMIC_INLINE static size_t nx_atomic_dec_release(volatile size_t *addr)
{
return (size_t)_InterlockedDecrement64((volatile LONGLONG *)addr);
}
NX_ATOMIC_INLINE static void nx_atomic_write(size_t value, volatile size_t *addr)
{
InterlockedExchange64((volatile LONG64 *)addr, value);
}
NX_ATOMIC_INLINE static void nx_atomic_write_pointer(void *value, void* volatile *addr)
{
InterlockedExchangePointer(addr, value);
}
NX_ATOMIC_INLINE static size_t nx_atomic_add(size_t value, volatile size_t* addr)
{
return (size_t)InterlockedExchangeAdd64 ((volatile LONGLONG *)addr, (LONGLONG)value);
}
NX_ATOMIC_INLINE static size_t nx_atomic_sub(size_t value, volatile size_t* addr)
{
return (size_t)InterlockedExchangeAdd64((volatile LONGLONG *)addr, -(LONGLONG)value);
}
NX_ATOMIC_INLINE static void *nx_atomic_swap_pointer(void *value, void* volatile *addr)
{
return InterlockedExchangePointer(addr, value);
}
NX_ATOMIC_INLINE static int nx_atomic_cmpxchg_pointer(void *oldvalue, void *newvalue, void* volatile *addr)
{
return InterlockedCompareExchangePointer(addr, newvalue, oldvalue) == oldvalue;
}
/*
NX_ATOMIC_INLINE static int nx_atomic_cmpxchg2(size_t *oldvalue, size_t *newvalue, volatile size_t *addr)
{
return InterlockedCompare64Exchange128((LONG64 volatile *)addr, (LONG64)newvalue[1], (LONG64)newvalue[0], (LONG64)oldvalue[0]) == oldvalue[0];
}
*/
#if 0
NX_ATOMIC_INLINE static size_t atomic_increment(volatile size_t *val)
{
return (size_t)InterlockedIncrement((volatile LONG *)val);
}
NX_ATOMIC_INLINE static size_t atomic_decrement(volatile size_t *val)
{
return (size_t)InterlockedDecrement((volatile LONG *)val);
}
NX_ATOMIC_INLINE static void atomic_add(volatile size_t *val, size_t add)
{
InterlockedExchangeAdd64((volatile LONGLONG *)val, (LONGLONG)add);
}
NX_ATOMIC_INLINE static void atomic_sub(volatile size_t *val, size_t sub)
{
InterlockedExchangeAdd64((volatile LONGLONG *)val, -((LONGLONG)sub));
}
NX_ATOMIC_INLINE static void *atomic_exchange_pointer(void* volatile *target, void *value)
{
return InterlockedExchangePointer(target, value);
}
NX_ATOMIC_INLINE static bool atomic_compare_exchange_pointer(void* volatile *destination, void *exchange, void *compare)
{
return InterlockedCompareExchangePointer(destination, exchange, compare) == compare;
}
NX_ATOMIC_INLINE static void atomic_write(volatile size_t *dest, size_t src)
{
InterlockedExchange64((volatile LONG64 *)dest, src);
}
#endif
@@ -0,0 +1,92 @@
#pragma once
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <wchar.h>
// first, some standard int types
typedef unsigned int UINT;
typedef signed int SINT;
typedef unsigned char UCHAR;
typedef signed char SCHAR;
typedef unsigned long ARGB32;
typedef unsigned long RGB32;
typedef unsigned long ARGB24;
typedef unsigned long RGB24;
typedef unsigned short ARGB16;
typedef unsigned short RGB16;
typedef unsigned long FOURCC;
typedef wchar_t nsxml_char_t;
typedef wchar_t ns_char_t;
typedef wchar_t nsfilename_char_t;
typedef int socklen_t;
#if defined(_WIN64) && !defined(__GNUC__)
#include <stddef.h>
#include <stdint.h>
// since windows doesn't have stdint.h
typedef unsigned __int64 uint64_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int8 uint8_t;
typedef __int64 int64_t;
typedef __int32 int32_t;
typedef __int16 int16_t;
#ifdef _M_IX86
typedef int64_t intptr2_t;
#elif defined(_M_IX64)
typedef unsigned __int128 uint128_t;
typedef __int128 int128_t;
typedef int128_t intptr2_t
#endif
#else
#include <stdint.h>
#include <stddef.h>
#include <inttypes.h>
#endif
#ifndef GUID_DEFINED
#define GUID_DEFINED
typedef struct _GUID
{
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint8_t Data4[8];
} GUID;
/*
#ifndef _REFCLSID_DEFINED
#define REFGUID const GUID &
#define _REFCLSID_DEFINED
#endif
*/
#endif
// this is for GUID == and !=
#include <objbase.h>
#ifndef GUID_EQUALS_DEFINED
#define GUID_EQUALS_DEFINED
#endif
typedef SSIZE_T ssize_t;
#ifdef NULL
#undef NULL
#endif
#ifndef NULL
#define NULL 0
#endif
#ifdef _WIN32_WCE
typedef int intptr_t;
#endif
@@ -0,0 +1,61 @@
#pragma once
#include "../../foundation/types.h"
#include <Windows.h>
#include <intrin.h>
#ifdef __cplusplus
#define NX_ATOMIC_INLINE inline
#else
#define NX_ATOMIC_INLINE
#endif
NX_ATOMIC_INLINE static size_t nx_atomic_inc(volatile size_t *addr)
{
return (size_t)_InterlockedIncrement((volatile LONG *)addr);
}
NX_ATOMIC_INLINE static size_t nx_atomic_dec(volatile size_t *addr)
{
return (size_t)_InterlockedDecrement((volatile LONG *)addr);
}
NX_ATOMIC_INLINE static size_t nx_atomic_dec_release(volatile size_t *addr)
{
return (size_t)_InterlockedDecrement((volatile LONG *)addr);
}
NX_ATOMIC_INLINE static void nx_atomic_write(size_t value, volatile size_t *addr)
{
InterlockedExchange((LONG *)addr, value);
}
NX_ATOMIC_INLINE static void nx_atomic_write_pointer(void *value, void* volatile *addr)
{
InterlockedExchangePointer(addr, value);
}
NX_ATOMIC_INLINE static size_t nx_atomic_add(size_t value, volatile size_t* addr)
{
return (size_t)InterlockedExchangeAdd((volatile LONG *)addr, (LONG)value);
}
NX_ATOMIC_INLINE static size_t nx_atomic_sub(size_t value, volatile size_t* addr)
{
return (size_t)InterlockedExchangeAdd((volatile LONG *)addr, -(LONG)value);
}
NX_ATOMIC_INLINE static void *nx_atomic_swap_pointer(const void *value, void* volatile *addr)
{
return InterlockedExchangePointer(addr, (PVOID)value);
}
NX_ATOMIC_INLINE static int nx_atomic_cmpxchg_pointer(void *oldvalue, void *newvalue, void* volatile *addr)
{
return InterlockedCompareExchangePointer(addr, newvalue, oldvalue) == oldvalue;
}
#pragma intrinsic(_InterlockedCompareExchange64)
NX_ATOMIC_INLINE static int nx_atomic_cmpxchg2(int64_t oldvalue, int64_t newvalue, volatile int64_t *addr)
{
return _InterlockedCompareExchange64(addr, newvalue, oldvalue) == oldvalue;
}
+98
View File
@@ -0,0 +1,98 @@
#pragma once
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <wchar.h>
// first, some standard int types
typedef unsigned int UINT;
typedef signed int SINT;
typedef unsigned char UCHAR;
typedef signed char SCHAR;
typedef unsigned long ARGB32;
typedef unsigned long RGB32;
typedef unsigned long ARGB24;
typedef unsigned long RGB24;
typedef unsigned short ARGB16;
typedef unsigned short RGB16;
typedef unsigned long FOURCC;
typedef wchar_t nsxml_char_t;
typedef wchar_t ns_char_t;
typedef wchar_t nsfilename_char_t;
typedef int socklen_t;
#if defined(_WIN32) && !defined(__GNUC__)
#include <stddef.h>
#if _MSC_VER >= 1600
#include <stdint.h>
#else
// since windows doesn't have stdint.h
typedef unsigned __int64 uint64_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int8 uint8_t;
typedef signed __int64 int64_t;
typedef signed __int32 int32_t;
typedef signed __int16 int16_t;
typedef signed __int8 int8_t;
#ifdef _M_IX86
typedef int64_t intptr2_t;
#else if defined(_M_IX64)
typedef unsigned __int128 uint128_t;
typedef __int128 int128_t;
typedef int128_t intptr2_t
#endif
#endif
#else
#include <stdint.h>
#include <stddef.h>
#include <inttypes.h>
#endif
#ifndef GUID_DEFINED
#define GUID_DEFINED
typedef struct _GUID
{
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint8_t Data4[8];
} GUID;
/*
#ifndef _REFCLSID_DEFINED
#define REFGUID const GUID &
#define _REFCLSID_DEFINED
#endif
*/
#endif
// this is for GUID == and !=
#include <objbase.h>
#ifndef GUID_EQUALS_DEFINED
#define GUID_EQUALS_DEFINED
#endif
#if defined(_MSC_VER)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
#ifdef NULL
#undef NULL
#endif
#ifndef NULL
#define NULL 0
#endif
#ifdef _WIN32_WCE
typedef int intptr_t;
#endif
+325
View File
@@ -0,0 +1,325 @@
#include "http/api.h"
#include "HTTPPlayback.h"
#include "http/svc_http_demuxer.h"
#include "service/ifc_servicefactory.h"
#include <time.h>
#ifdef _WIN32
#include "nu/AutoChar.h"
#endif
#include "nu/strsafe.h"
#include "nx/nxsleep.h"
#ifdef __ANDROID__
#include <android/log.h> // TODO: replace with generic logging API
#else
#define ANDROID_LOG_INFO 0
#define ANDROID_LOG_ERROR 1
void __android_log_print(int, const char *, const char *, ...)
{
}
#endif
#include <time.h>
HTTPPlayback::HTTPPlayback()
{
http=0;
demuxer=0;
}
int HTTPPlayback::Initialize(nx_uri_t url, ifc_player *player)
{
int ret = PlaybackBase::Initialize(url, player);
if (ret != NErr_Success)
return ret;
http=0;
demuxer=0;
ifc_playback::Retain(); /* the thread needs to hold a reference to this object so that it doesn't disappear out from under us */
NXThreadCreate(&playback_thread, HTTPPlayerThreadFunction, this);
return NErr_Success;
}
HTTPPlayback::~HTTPPlayback()
{
if (demuxer)
demuxer->Release();
if (http)
jnl_http_release(http);
}
nx_thread_return_t HTTPPlayback::HTTPPlayerThreadFunction(nx_thread_parameter_t param)
{
HTTPPlayback *playback = (HTTPPlayback *)param;
NXThreadCurrentSetPriority(NX_THREAD_PRIORITY_PLAYBACK);
nx_thread_return_t ret = playback->DecodeLoop();
playback->ifc_playback::Release();
return ret;
}
int HTTPPlayback::Init()
{
http = jnl_http_create(2*1024*1024, 0);
if (!http)
return NErr_OutOfMemory;
return NErr_Success;
}
static void SetupHTTP(jnl_http_t http)
{
char accept[1024], user_agent[256];
accept[0]=0;
user_agent[0]=0;
size_t accept_length=sizeof(accept)/sizeof(*accept);
size_t user_agent_length=sizeof(user_agent)/sizeof(*user_agent);
char *p_accept = accept, *p_user_agent=user_agent;
const char *application_user_agent = WASABI2_API_APP->GetUserAgent();
StringCchCopyExA(p_user_agent, user_agent_length, application_user_agent, &p_user_agent, &user_agent_length, 0);
GUID http_demuxer_guid = svc_http_demuxer::GetServiceType();
ifc_serviceFactory *sf;
size_t n = 0;
while (sf = WASABI2_API_SVC->EnumService(http_demuxer_guid, n++))
{
svc_http_demuxer *l = (svc_http_demuxer*)sf->GetInterface();
if (l)
{
const char *this_accept;
size_t i=0;
while (this_accept=l->EnumerateAcceptedTypes(i++))
{
if (accept == p_accept) // first one added
StringCchCopyExA(p_accept, accept_length, this_accept, &p_accept, &accept_length, 0);
else
StringCchPrintfExA(p_accept, accept_length, &p_accept, &accept_length, 0, ", %s", this_accept);
}
const char *this_user_agent = l->GetUserAgent();
if (this_user_agent)
{
StringCchPrintfExA(p_user_agent, user_agent_length, &p_user_agent, &user_agent_length, 0, " %s", this_user_agent);
}
l->CustomizeHTTP(http);
l->Release();
}
}
if (accept != p_accept)
jnl_http_addheadervalue(http, "Accept", accept);
jnl_http_addheadervalue(http, "User-Agent", user_agent);
jnl_http_addheadervalue(http, "Connection", "close");
}
static NError FindDemuxer(nx_uri_t uri, jnl_http_t http, ifc_http_demuxer **demuxer)
{
GUID http_demuxer_guid = svc_http_demuxer::GetServiceType();
ifc_serviceFactory *sf;
bool again;
int pass=0;
do
{
size_t n = 0;
again=false;
while (sf = WASABI2_API_SVC->EnumService(http_demuxer_guid, n++))
{
svc_http_demuxer *l = (svc_http_demuxer*)sf->GetInterface();
if (l)
{
NError err = l->CreateDemuxer(uri, http, demuxer, pass);
if (err == NErr_Success)
return NErr_Success;
if (err == NErr_TryAgain)
again=true;
}
}
pass++;
} while (again);
return NErr_NoMatchingImplementation;
}
int HTTPPlayback::Internal_Connect(uint64_t byte_position)
{
int http_ver = byte_position?1:0;
if (byte_position != 0)
{
char str[512];
StringCchPrintfA(str, 512, "Range: bytes=%llu-", byte_position);
jnl_http_addheader(http, str);
}
//jnl_http_allow_accept_all_reply_codes(http);
#ifdef _WIN32
jnl_http_connect(http, AutoChar(filename->string), http_ver, "GET");
#else
jnl_http_connect(http, filename->string, http_ver, "GET");
#endif
/* wait for connection */
time_t start_time = time(0);
int http_status;
do
{
int ret = PlaybackBase::Sleep(10, PlaybackBase::WAKE_STOP);
if (ret == PlaybackBase::WAKE_STOP)
return NErr_Interrupted;
ret = jnl_http_run(http);
if (ret == HTTPGET_RUN_ERROR)
return NErr_ConnectionFailed;
if (start_time + 15 < time(0))
return NErr_TimedOut;
http_status = jnl_http_get_status(http);
} while (http_status == HTTPGET_STATUS_CONNECTING || http_status == HTTPGET_STATUS_READING_HEADERS);
if (http_status == HTTPGET_STATUS_ERROR)
{
switch(jnl_http_getreplycode(http))
{
case 400:
return NErr_BadRequest;
case 401:
// TODO: deal with this specially
return NErr_Unauthorized;
case 403:
// TODO: deal with this specially?
return NErr_Forbidden;
case 404:
return NErr_NotFound;
case 405:
return NErr_BadMethod;
case 406:
return NErr_NotAcceptable;
case 407:
// TODO: deal with this specially
return NErr_ProxyAuthenticationRequired;
case 408:
return NErr_RequestTimeout;
case 409:
return NErr_Conflict;
case 410:
return NErr_Gone;
case 500:
return NErr_InternalServerError;
case 503:
return NErr_ServiceUnavailable;
default:
return NErr_ConnectionFailed;
}
}
return NErr_Success;
}
nx_thread_return_t HTTPPlayback::DecodeLoop()
{
player->OnLoaded(filename);
int ret = Init();
if (ret != NErr_Success)
{
player->OnError(ret);
return 0;
}
SetupHTTP(http);
/* connect, then find an ifc_http_demuxer */
ret = Internal_Connect(0);
if (ret == NErr_Success && FindDemuxer(filename, http, &demuxer) == NErr_Success && demuxer)
{
/* turn control over to the demuxer */
ret = demuxer->Run(this, player, secondary_parameters);
if (ret == NErr_EndOfFile)
{
/* TODO: re-implement the individual demuxers so they keep calling set position for a while */
player->OnClosed();
return 0;
}
}
else if (ret == NErr_Interrupted)
{
player->OnStopped();
return 0;
}
else if (ret == NErr_TimedOut)
{
player->OnError(ret);
return 0;
}
else if (ret == NErr_Success)
{
player->OnError(NErr_NoMatchingImplementation);
return 0;
}
else
{
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[http] error: %d, reply code: %d", ret, jnl_http_getreplycode(http));
player->OnError(ret);
return 0;
}
return 0;
}
int HTTPPlayback::HTTP_Wake(int mask)
{
return PlaybackBase::Wake(mask);
}
int HTTPPlayback::HTTP_Check(int mask)
{
return PlaybackBase::Check(mask);
}
int HTTPPlayback::HTTP_Wait(unsigned int milliseconds, int mask)
{
return PlaybackBase::Wait(milliseconds, mask);
}
int HTTPPlayback::HTTP_Sleep(int milliseconds, int mask)
{
return PlaybackBase::Sleep(milliseconds, mask);
}
Agave_Seek *HTTPPlayback::HTTP_GetSeek()
{
return PlaybackBase::GetSeek();
}
void HTTPPlayback::HTTP_FreeSeek(Agave_Seek *seek)
{
PlaybackBase::FreeSeek(seek);
}
int HTTPPlayback::HTTP_Seek(uint64_t byte_position)
{
jnl_http_reset_headers(http);
SetupHTTP(http);
return Internal_Connect(byte_position);
}
#if defined(_WIN32) && !defined(strcasecmp)
#define strcasecmp _stricmp
#endif
int HTTPPlayback::HTTP_Seekable()
{
const char *accept_ranges = jnl_http_getheader(http, "accept-ranges");
if (accept_ranges && !strcasecmp(accept_ranges, "none"))
return NErr_False; /* server says it doesn't accept ranges */
/* note that not having an accept-ranges header doesn't necessary mean it's not seekable. see RFC2616 14.5 */
return NErr_True;
}
int HTTPPlayback::HTTP_AudioOpen(const ifc_audioout::Parameters *format, ifc_audioout **out_output)
{
__android_log_print(ANDROID_LOG_INFO, "libreplicant", "[http] output_service=%x", output_service);
return output_service->AudioOpen(format, player, secondary_parameters, out_output);
}
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include "nx/nxonce.h"
#include "jnetlib/jnetlib.h"
#include "http/ifc_http_demuxer.h"
#include "http/ifc_http.h"
#include "nswasabi/PlaybackBase.h"
class HTTPPlayback : public PlaybackBase, public ifc_http
{
public:
HTTPPlayback();
~HTTPPlayback();
int Initialize(nx_uri_t url, ifc_player *player);
/* ifc_http implementation */
int WASABICALL HTTP_Wake(int mask);
int WASABICALL HTTP_Check(int mask);
int WASABICALL HTTP_Wait(unsigned int milliseconds, int mask);
int WASABICALL HTTP_Sleep(int milliseconds, int mask);
Agave_Seek *WASABICALL HTTP_GetSeek();
void WASABICALL HTTP_FreeSeek(Agave_Seek *seek);
int WASABICALL HTTP_Seek(uint64_t byte_position);
int WASABICALL HTTP_Seekable();
int WASABICALL HTTP_AudioOpen(const ifc_audioout::Parameters *format, ifc_audioout **out_output);
private:
int Internal_Connect(uint64_t byte_position);
ifc_http_demuxer *demuxer;
volatile int paused;
volatile int stopped;
jnl_http_t http;
int Init();
nx_thread_return_t NXTHREADCALL DecodeLoop();
static nx_thread_return_t NXTHREADCALL HTTPPlayerThreadFunction(nx_thread_parameter_t param);
};
@@ -0,0 +1,28 @@
#include "HTTPPlaybackService.h"
#include "player/ifc_player.h"
#include "player/ifc_playback.h"
#include "HTTPPlayback.h"
#include "nx/nxpath.h"
#include "nswasabi/ReferenceCounted.h"
int HTTPPlaybackService::PlaybackService_CreatePlayback(unsigned int pass, nx_uri_t filename, ifc_player *player, ifc_playback **out_playback_object)
{
if (NXPathProtocol(filename, "http") == NErr_Success)
{
HTTPPlayback *http_playback = new ReferenceCounted<HTTPPlayback>;
if (!http_playback)
return NErr_OutOfMemory;
int ret = http_playback->Initialize(filename, player);
if (ret != NErr_Success)
{
http_playback->ifc_playback::Release();
return ret;
}
*out_playback_object = http_playback;
return NErr_Success;
}
return NErr_False;
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "player/svc_playback.h"
#include "nx/nxstring.h"
#include "nswasabi/ServiceName.h"
// {672AF800-F239-40e5-8C87-3B4D305B72B2}
static const GUID http_playback_guid =
{ 0x672af800, 0xf239, 0x40e5, { 0x8c, 0x87, 0x3b, 0x4d, 0x30, 0x5b, 0x72, 0xb2 } };
class HTTPPlaybackService : public svc_playback
{
public:
WASABI_SERVICE_NAME("HTTP Playback Service");
static GUID GetServiceGUID() { return http_playback_guid; }
int WASABICALL PlaybackService_CreatePlayback(unsigned int pass, nx_uri_t filename, ifc_player *player, ifc_playback **out_playback_object);
};
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include "service/api_service.h"
extern api_service *serviceApi;
#define WASABI2_API_SVC serviceApi
#include "application/api_application.h"
extern api_application *applicationApi;
#define WASABI2_API_APP applicationApi
+156
View File
@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B6B8BAE5-BC2C-4A78-97C3-D0A5053F11F2}</ProjectGuid>
<RootNamespace>http</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>x86_Debug\</OutDir>
<IntDir>x86_Debug\</IntDir>
<TargetExt>.w5c</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>x64_Debug\</OutDir>
<IntDir>x64_Debug\</IntDir>
<TargetExt>.w5c</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>x86_Release\</OutDir>
<IntDir>x86_Release\</IntDir>
<TargetExt>.w5c</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>x64_Release\</OutDir>
<IntDir>x64_Release\</IntDir>
<TargetExt>.w5c</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;HTTP_EXPORTS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<CustomBuildStep>
<Command>copy "$(TargetPath)" "$(ProgramFiles)\Replicant\$(TargetName)$(TargetExt)"</Command>
<Outputs>$(ProgramFiles)\Replicant\$(TargetName)$(TargetExt)</Outputs>
<Inputs>$(TargetPath);%(Inputs)</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;HTTP_EXPORTS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<CustomBuildStep>
<Command>copy "$(TargetPath)" "$(ProgramFiles)\Replicant\$(TargetName)$(TargetExt)"</Command>
<Outputs>$(ProgramFiles)\Replicant\$(TargetName)$(TargetExt)</Outputs>
<Inputs>$(TargetPath);%(Inputs)</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="HTTPPlayback.cpp" />
<ClCompile Include="HTTPPlaybackService.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="api.h" />
<ClInclude Include="HTTPPlayback.h" />
<ClInclude Include="HTTPPlaybackService.h" />
<ClInclude Include="ifc_http.h" />
<ClInclude Include="ifc_http_demuxer.h" />
<ClInclude Include="svc_http_demuxer.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\jnetlib\jnetlib.vcxproj">
<Project>{e105a0a2-7391-47c5-86ac-718003524c3d}</Project>
</ProjectReference>
<ProjectReference Include="..\nswasabi\nswasabi.vcxproj">
<Project>{480502a0-71da-4bf0-bf99-2720d69a526b}</Project>
</ProjectReference>
<ProjectReference Include="..\nu\nu.vcxproj">
<Project>{f1f5cd60-0d5b-4cea-9eeb-2f87ff9aa915}</Project>
</ProjectReference>
<ProjectReference Include="..\nx\nx.vcxproj">
<Project>{2851cf33-337d-44d9-ba6d-30547b1cdef0}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+68
View File
@@ -0,0 +1,68 @@
#pragma once
#include "foundation/dispatch.h"
#include "player/ifc_playback.h"
#include "foundation/types.h"
// TODO: benski> not sure that this is the best name for it, but it works for now
class ifc_http : public Wasabi2::Dispatchable
{
protected:
ifc_http() : Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_http() {}
public:
enum
{
WAKE_KILL=(1<<0),
WAKE_PLAY=(1<<1),
WAKE_PAUSE=(1<<2),
WAKE_STOP=(1<<3),
WAKE_INTERRUPT=(1<<4),
WAKE_UNPAUSE=(1<<5), // this is actually unused in wake_flags, just used as a return value from Wake/WakeReason
WAKE_RESUME=(1<<6), // this is actually unused in wake_flags, just used as a return value from Wake/WakeReason
WAKE_START_MASK = WAKE_PLAY|WAKE_STOP,
WAKE_KILL_MASK = WAKE_KILL|WAKE_STOP,
WAKE_ALL_MASK = WAKE_KILL|WAKE_PLAY|WAKE_PAUSE|WAKE_STOP|WAKE_INTERRUPT,
};
// these aren't the best names, either
// if playback flag isn't ready, sleeps until a flag changes and returns changed flag
int Wake(int mask) { return HTTP_Wake(mask); }
// checks for pending flags and updates them
int Check(int mask) { return HTTP_Check(mask); }
// like wake, but only wait a specified amount of time. will return 0 if flags didn't change
int Wait(unsigned int milliseconds, int mask) { return HTTP_Wait(milliseconds, mask); }
int Sleep(unsigned int milliseconds, int mask) { return HTTP_Sleep(milliseconds, mask); }
Agave_Seek *GetSeek() { return HTTP_GetSeek(); }
void FreeSeek(Agave_Seek *seek) { HTTP_FreeSeek(seek); }
int Seek(uint64_t byte_position) { return HTTP_Seek(byte_position); }
/* returns NErr_True / NErr_False, returns whether or not it's seekable by Range headers.
NErr_True doesn't mean 100% certainity that the stream is seekable.
Note that some protocols (e.g. RTSP) might still be seekable by other means than Range headers. */
int Seekable() { return HTTP_Seekable(); }
int AudioOpen(const ifc_audioout::Parameters *format, ifc_audioout **out_output) { return HTTP_AudioOpen(format, out_output); }
enum
{
DISPATCHABLE_VERSION,
};
protected:
virtual int WASABICALL HTTP_Wake(int mask)=0;
virtual int WASABICALL HTTP_Check(int mask)=0;
virtual int WASABICALL HTTP_Wait(unsigned int milliseconds, int mask)=0;
virtual int WASABICALL HTTP_Sleep(int milliseconds, int mask)=0;
virtual Agave_Seek *WASABICALL HTTP_GetSeek()=0;
virtual void WASABICALL HTTP_FreeSeek(Agave_Seek *seek)=0;
virtual int WASABICALL HTTP_Seek(uint64_t byte_position)=0;
virtual int WASABICALL HTTP_Seekable()=0;
virtual int WASABICALL HTTP_AudioOpen(const ifc_audioout::Parameters *format, ifc_audioout **out_output)=0;
};
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include "jnetlib/jnetlib_defines.h"
#include "foundation/dispatch.h"
#include "foundation/error.h"
#include "player/svc_output.h"
#include "player/ifc_player.h"
#include "http/ifc_http.h"
#include "player/ifc_playback_parameters.h"
class ifc_http_demuxer: public Wasabi2::Dispatchable
{
protected:
ifc_http_demuxer() : Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_http_demuxer() {}
public:
enum
{
DISPATCHABLE_VERSION,
};
int Run(ifc_http *http_parent, ifc_player *player, ifc_playback_parameters *secondary_parameters) { return HTTPDemuxer_Run(http_parent, player, secondary_parameters); }
protected:
virtual int WASABICALL HTTPDemuxer_Run(ifc_http *http_parent, ifc_player *player, ifc_playback_parameters *secondary_parameters)=0;
};
+68
View File
@@ -0,0 +1,68 @@
#include "api.h"
#include "jnetlib/jnetlib.h"
#include "component/ifc_component.h"
#include "service/ifc_servicefactory.h"
#include "foundation/export.h"
#include "nswasabi/singleton.h"
#include "HTTPPlaybackService.h"
static SingletonService<HTTPPlaybackService, svc_playback> playback_factory;
// {446BFBF6-8CE9-4697-844E-8386B5037685}
static const GUID http_component_guid =
{ 0x446bfbf6, 0x8ce9, 0x4697, { 0x84, 0x4e, 0x83, 0x86, 0xb5, 0x3, 0x76, 0x85 } };
class HTTPComponent : public ifc_component
{
public:
HTTPComponent() : ifc_component(http_component_guid) {}
int WASABICALL Component_Initialize(api_service *service);
int WASABICALL Component_RegisterServices(api_service *service);
void WASABICALL Component_DeregisterServices(api_service *service);
int WASABICALL Component_Quit(api_service *_service_manager);
};
static HTTPComponent http_component;
api_service *WASABI2_API_SVC=0;
api_application *WASABI2_API_APP=0;
int HTTPComponent::Component_Initialize(api_service *service)
{
int ret = jnl_init();
if (ret != NErr_Success)
return ret;
return NErr_Success;
}
int HTTPComponent::Component_RegisterServices(api_service *service)
{
WASABI2_API_SVC = service;
// get application API
WASABI2_API_SVC->GetService(&WASABI2_API_APP);
playback_factory.Register(WASABI2_API_SVC);
return NErr_Success;
}
void HTTPComponent::Component_DeregisterServices(api_service *service)
{
playback_factory.Deregister(WASABI2_API_SVC);
if (WASABI2_API_APP)
WASABI2_API_APP->Release();
}
int HTTPComponent::Component_Quit(api_service *_service_manager)
{
jnl_quit();
return NErr_Success;
}
extern "C" DLLEXPORT ifc_component *GetWasabi2Component()
{
return &http_component;
}
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include "jnetlib/jnetlib_defines.h"
#include "foundation/dispatch.h"
#include "foundation/error.h"
#include "http/ifc_http_demuxer.h"
// {5E3551B0-B0FF-4997-89E4-958545C3EC19}
static const GUID demuxer_service_type_guid =
{ 0x5E3551B0, 0xB0FF, 0x4997, { 0x89, 0xE4, 0x95, 0x85, 0x45, 0xC3, 0xEC, 0x19 } };
class svc_http_demuxer: public Wasabi2::Dispatchable
{
protected:
svc_http_demuxer() : Dispatchable(DISPATCHABLE_VERSION) {}
~svc_http_demuxer() {}
public:
static GUID GetServiceType() { return demuxer_service_type_guid; }
/* returns types to be added to "Accept" HTTP header */
const char *EnumerateAcceptedTypes(size_t i) { return HTTPDemuxerService_EnumerateAcceptedTypes(i); }
/* returns a string to be added to the user-agent (e.g. Ultravox/2.1) */
const char *GetUserAgent() { return HTTPDemuxerService_GetUserAgent(); }
/* allows service to do any necessary customization (mainly for adding headers) */
void CustomizeHTTP(jnl_http_t http) { HTTPDemuxerService_CustomizeHTTP(http); }
/* if you create a demuxer, you now own http and are expected to call jnl_http_release on it when you are done */
/* you can return NErr_TryAgain to let everyone else go first, you'll be called again with pass=1 */
NError CreateDemuxer(nx_uri_t uri, jnl_http_t http, ifc_http_demuxer **demuxer, int pass) { return HTTPDemuxerService_CreateDemuxer(uri, http, demuxer, pass); }
enum
{
DISPATCHABLE_VERSION,
};
protected:
virtual const char *WASABICALL HTTPDemuxerService_EnumerateAcceptedTypes(size_t i) = 0;
virtual const char *WASABICALL HTTPDemuxerService_GetUserAgent() = 0;
virtual void WASABICALL HTTPDemuxerService_CustomizeHTTP(jnl_http_t http) = 0;
virtual NError WASABICALL HTTPDemuxerService_CreateDemuxer(nx_uri_t uri, jnl_http_t http, ifc_http_demuxer **demuxer, int pass) = 0;
};
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include "jnetlib/jnetlib_defines.h"
#include "foundation/dispatch.h"
#include "foundation/error.h"
#include "player/svc_output.h"
#include "player/ifc_player.h"
#include "http/ifc_http.h"
#include "icy/ifc_icy_reader.h"
#include "player/ifc_playback_parameters.h"
class ifc_icy_playback: public Wasabi2::Dispatchable
{
protected:
ifc_icy_playback() : Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_icy_playback() {}
public:
enum
{
DISPATCHABLE_VERSION,
};
int Run(ifc_http *http_parent, ifc_player *player, ifc_icy_reader *reader) { return ICYPlayback_Run(http_parent, player, reader); }
protected:
virtual int WASABICALL ICYPlayback_Run(ifc_http *http_parent, ifc_player *player, ifc_icy_reader *reader)=0;
};
+37
View File
@@ -0,0 +1,37 @@
/*
* ifc_icy_reader.h
* shoutcast_player
*
* Created by Ben Allison on 2/1/08.
* Copyright 2008 Nullsoft, Inc. All rights reserved.
*
*/
#pragma once
#include "foundation/dispatch.h"
#include "foundation/types.h"
#include "foundation/error.h"
class ifc_icy_reader : public Wasabi2::Dispatchable
{
protected:
ifc_icy_reader() : Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_icy_reader() {}
public:
size_t BytesBuffered() { return ICYReader_BytesBuffered(); }
int Read(void *buffer, size_t length, size_t *readLength) { return ICYReader_Read(buffer, length, readLength); }
int Peek(void *buffer, size_t length, size_t *readLength) { return ICYReader_Peek(buffer, length, readLength); }
int IsClosed() { return ICYReader_IsClosed(); }
int Run() { return ICYReader_Run(); }
enum
{
DISPATCHABLE_VERSION,
};
protected:
virtual size_t WASABICALL ICYReader_BytesBuffered()=0;
virtual int WASABICALL ICYReader_Read(void *buffer, size_t length, size_t *readLength)=0;
virtual int WASABICALL ICYReader_Peek(void *buffer, size_t length, size_t *readLength)=0;
virtual int WASABICALL ICYReader_IsClosed()=0;
virtual int WASABICALL ICYReader_Run()=0;
};
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include "jnetlib/jnetlib_defines.h"
#include "foundation/dispatch.h"
#include "foundation/error.h"
#include "icy/ifc_icy_playback.h"
// {42E078D5-7D68-43b5-9AFD-0135558C799F}
static const GUID icy_playback_service_type_guid =
{ 0x42e078d5, 0x7d68, 0x43b5, { 0x9a, 0xfd, 0x1, 0x35, 0x55, 0x8c, 0x79, 0x9f } };
class svc_icy_playback : public Wasabi2::Dispatchable
{
protected:
svc_icy_playback() : Dispatchable(DISPATCHABLE_VERSION) {}
~svc_icy_playback() {}
public:
static GUID GetServiceType() { return icy_playback_service_type_guid; }
/* returns types to be added to "Accept" HTTP header */
const char *EnumerateAcceptedTypes(size_t i) { return ICYPlaybackService_EnumerateAcceptedTypes(i); }
NError CreatePlayback(jnl_http_t http, ifc_icy_playback **playback, int pass) { return ICYPlaybackService_CreateDemuxer(http, playback, pass); }
enum
{
DISPATCHABLE_VERSION,
};
protected:
virtual const char *WASABICALL ICYPlaybackService_EnumerateAcceptedTypes(size_t i) = 0;
virtual NError WASABICALL ICYPlaybackService_CreateDemuxer(jnl_http_t http, ifc_icy_playback **playback, int pass) = 0;
};
+1
View File
@@ -0,0 +1 @@
1.2
+314
View File
@@ -0,0 +1,314 @@
/*
** JNetLib
** Copyright (C) 2000-2007 Nullsoft, Inc.
** Author: Justin Frankel
** File: asyncdns.cpp - JNL portable asynchronous DNS implementation
** License: see jnetlib.h
*/
#include "netinc.h"
#include "util.h"
#include "asyncdns.h"
#include <time.h>
#ifdef _WIN32
#include <strsafe.h>
#endif
enum
{
MODE_RESOLVE=0,
MODE_REVERSE=1,
};
struct cache_entry
{
time_t last_used; // timestamp.
bool resolved;
int mode; // 1=reverse
unsigned short port;
char hostname[256];
addrinfo *addr;
int sockettype;
};
JNL_AsyncDNS::JNL_AsyncDNS(int max_cache_entries)
{
m_thread_kill=1;
m_thread=0;
m_cache_size=max_cache_entries;
m_cache=(cache_entry *)malloc(sizeof(cache_entry)*m_cache_size);
memset(m_cache, 0, sizeof(cache_entry)*m_cache_size);
}
JNL_AsyncDNS::~JNL_AsyncDNS()
{
m_thread_kill=1;
#ifdef _WIN32
if (m_thread)
{
WaitForSingleObject(m_thread,INFINITE);
CloseHandle(m_thread);
}
#else
if (m_thread)
{
void *p;
pthread_join(m_thread,&p);
}
#endif//!_WIN32
// free all the addrinfo stuff
for (int x = 0; x < m_cache_size; x ++)
{
if (m_cache[x].addr)
freeaddrinfo(m_cache[x].addr);
}
free(m_cache);
}
int JNL_AsyncDNS::resolvenow(const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
{
addrinfo hints;
memset(&hints,0,sizeof(hints));
hints.ai_family = PF_UNSPEC;
if (hostname)
hints.ai_flags = AI_NUMERICHOST;
else
hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
hints.ai_socktype = sockettype;
char portString[32] = {0};
sprintf(portString, "%u", (unsigned int)port);
if (getaddrinfo(hostname, portString, &hints, addr) == 0)
{
return 0;
}
else
{
hints.ai_flags = 0;
if (getaddrinfo(hostname, portString, &hints, addr) == 0)
{
return 0;
}
else
{
return -1;
}
}
}
#ifdef _WIN32
unsigned long WINAPI JNL_AsyncDNS::_threadfunc(LPVOID _d)
#else
unsigned int JNL_AsyncDNS::_threadfunc(void *_d)
#endif
{
int nowinsock=JNL::open_socketlib();
JNL_AsyncDNS *_this=(JNL_AsyncDNS*)_d;
int x;
for (x = 0; x < _this->m_cache_size && !_this->m_thread_kill; x ++)
{
if (_this->m_cache[x].last_used && !_this->m_cache[x].resolved)
{
if (!nowinsock)
{
if (_this->m_cache[x].mode==0)
{
addrinfo *res=0;
if (resolvenow(_this->m_cache[x].hostname, _this->m_cache[x].port, &res, _this->m_cache[x].sockettype) == 0)
{
_this->m_cache[x].addr=res;
}
else
{
_this->m_cache[x].addr=0;//INADDR_NONE;
}
}
else if (_this->m_cache[x].mode==1)
{
/*
hostent *ent;
// TODO: replace with getnameinfo for IPv6
ent=gethostbyaddr((const char *)&_this->m_cache[x].addr,4,AF_INET);
if (ent)
lstrcpyn(_this->m_cache[x].hostname, ent->h_name, 256);
else
_this->m_cache[x].hostname[0]=0;
*/
}
_this->m_cache[x].resolved=true;
}
else
{
if (_this->m_cache[x].mode==0)
{
_this->m_cache[x].addr=0;//INADDR_NONE;
_this->m_cache[x].resolved=true;
}
else if (_this->m_cache[x].mode==1)
{
_this->m_cache[x].hostname[0]=0;
_this->m_cache[x].resolved=true;
}
}
}
}
if (!nowinsock) JNL::close_socketlib();
_this->m_thread_kill=1;
return 0;
}
int JNL_AsyncDNS::resolve(const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
{
// return 0 on success, 1 on wait, -1 on unresolvable
int x;
for (x = 0; x < m_cache_size; x ++)
{
if (!strcasecmp(m_cache[x].hostname,hostname) && port == m_cache[x].port && m_cache[x].mode==0 && m_cache[x].sockettype==sockettype)
{
m_cache[x].last_used=time(0);
if (m_cache[x].resolved)
{
if (m_cache[x].addr == 0)//INADDR_NONE)
{
return DNS_RESOLVE_UNRESOLVABLE;
}
*addr =m_cache[x].addr;
return DNS_RESOLVE_SUCCESS;
}
makesurethreadisrunning();
return DNS_RESOLVE_WAIT;
}
}
// add to resolve list
int oi=-1;
for (x = 0; x < m_cache_size; x ++)
{
if (!m_cache[x].last_used)
{
oi=x;
break;
}
if ((oi==-1 || m_cache[x].last_used < m_cache[oi].last_used) && m_cache[x].resolved)
{
oi=x;
}
}
if (oi == -1)
{
return DNS_RESOLVE_UNRESOLVABLE;
}
#ifdef _WIN32
StringCchCopyA(m_cache[oi].hostname, 256, hostname);
#elif defined(__APPLE__)
strlcpy(m_cache[oi].hostname, hostname, 255);
#else
strncpy(m_cache[oi].hostname, hostname, 255);
m_cache[oi].hostname[255]=0;
#endif
m_cache[oi].port=port;
m_cache[oi].mode=0;
m_cache[oi].addr=0;//INADDR_NONE;
m_cache[oi].resolved=false;
m_cache[oi].last_used=time(0);
m_cache[oi].sockettype=sockettype;
makesurethreadisrunning();
return DNS_RESOLVE_WAIT;
}
/*
int JNL_AsyncDNS::reverse(unsigned long addr, char *hostname, size_t hostnameSize)
{
// return 0 on success, 1 on wait, -1 on unresolvable
int x;
if (addr == INADDR_NONE)
{
return DNS_REVERSE_UNRESOLVABLE;
}
#ifndef NO_DNS_SUPPORT
for (x = 0; x < m_cache_size; x ++)
{
if (m_cache[x].addr==addr && m_cache[x].mode==1)
{
m_cache[x].last_used=time(0);
if (m_cache[x].resolved)
{
if (!m_cache[x].hostname[0])
{
return DNS_REVERSE_UNRESOLVABLE;
}
lstrcpyn(hostname,m_cache[x].hostname, hostnameSize);
return DNS_REVERSE_SUCCESS;
}
makesurethreadisrunning();
return DNS_REVERSE_WAIT;
}
}
// add to resolve list
int oi=-1;
for (x = 0; x < m_cache_size; x ++)
{
if (!m_cache[x].last_used)
{
oi=x;
break;
}
if ((oi==-1 || m_cache[x].last_used < m_cache[oi].last_used) && m_cache[x].resolved)
{
oi=x;
}
}
if (oi == -1)
{
return DNS_REVERSE_UNRESOLVABLE;
}
m_cache[oi].addr=addr;
m_cache[oi].hostname[0]=0;
m_cache[oi].resolved=false;
m_cache[oi].mode=1;
m_cache[oi].last_used=time(0);
makesurethreadisrunning();
return DNS_REVERSE_WAIT;
#else
return DNS_REVERSE_UNRESOLVABLE;
#endif
}
*/
void JNL_AsyncDNS::makesurethreadisrunning(void)
{
if (m_thread_kill)
{
#ifdef _WIN32
if (m_thread)
{
WaitForSingleObject(m_thread,INFINITE);
CloseHandle(m_thread);
}
DWORD id;
m_thread_kill=0;
m_thread=CreateThread(NULL,0,_threadfunc,(LPVOID)this,0,&id);
if (!m_thread)
{
#else
if (m_thread)
{
void *p;
pthread_join(m_thread,&p);
}
m_thread_kill=0;
if (pthread_create(&m_thread,NULL,(void *(*) (void *))_threadfunc,(void*)this) != 0)
{
#endif
m_thread_kill=1;
}
}
}
+66
View File
@@ -0,0 +1,66 @@
/*
** JNetLib
** Copyright (C) 2000-2007 Nullsoft, Inc.
** Author: Justin Frankel
** File: asyncdns.h - JNL portable asynchronous DNS interface
** License: see jnetlib.h
**
** Usage:
** 1. Create JNL_AsyncDNS object, optionally with the number of cache entries.
** 2. call resolve() to resolve a hostname into an address. The return value of
** resolve is 0 on success (host successfully resolved), 1 on wait (meaning
** try calling resolve() with the same hostname in a few hundred milliseconds
** or so), or -1 on error (i.e. the host can't resolve).
** 3. call reverse() to do reverse dns (ala resolve()).
** 4. enjoy.
*/
#ifndef _ASYNCDNS_H_
#define _ASYNCDNS_H_
#include "netinc.h"
struct cache_entry;
#define JNL_AUTODNS ((JNL_AsyncDNS *)-1)
enum
{
DNS_RESOLVE_UNRESOLVABLE = -1,
DNS_RESOLVE_SUCCESS = 0,
DNS_RESOLVE_WAIT = 1,
};
enum
{
DNS_REVERSE_UNRESOLVABLE = -1,
DNS_REVERSE_SUCCESS = 0,
DNS_REVERSE_WAIT = 1,
};
class JNL_AsyncDNS
{
public:
JNL_AsyncDNS( int max_cache_entries = 64 );
~JNL_AsyncDNS();
int resolve( const char *hostname, unsigned short port, addrinfo **addr, int sockettype ); // return 0 on success, 1 on wait, -1 on unresolvable
static int resolvenow( const char *hostname, unsigned short port, addrinfo **addr, int sockettype ); // return 0 on success, -1 on unresolvable
//int reverse(unsigned long addr, char *hostname, size_t hostnameSize); // return 0 on success, 1 on wait, -1 on unresolvable. hostname must be at least 256 bytes.
private:
cache_entry *m_cache;
int m_cache_size;
volatile int m_thread_kill;
#ifdef _WIN32
HANDLE m_thread;
static unsigned long WINAPI _threadfunc( LPVOID _d );
#else
pthread_t m_thread;
static unsigned int _threadfunc( void *_d );
#endif
void makesurethreadisrunning( void );
};
#endif //_ASYNCDNS_H_
+533
View File
@@ -0,0 +1,533 @@
/*
** JNetLib
** Copyright (C) 2000-2007 Nullsoft, Inc.
** Author: Justin Frankel
** File: connection.cpp - JNL TCP connection implementation
** License: see jnetlib.h
*/
#include "netinc.h"
#include "util.h"
#include "connection.h"
#include "asyncdns.h"
#include "foundation\error.h"
#ifndef min
#define min(X,Y) ((X) < (Y) ? (X) : (Y))
#endif
JNL_Connection::JNL_Connection()
{
init();
}
JNL_Connection::JNL_Connection(JNL_AsyncDNS *dns, size_t sendbufsize, size_t recvbufsize)
{
init();
open(dns, sendbufsize, recvbufsize);
}
void JNL_Connection::init()
{
m_errorstr="";
address=0;
m_dns=0;
m_dns_owned=false;
m_socket=-1;
m_remote_port=0;
m_state=STATE_NOCONNECTION;
m_host[0]=0;
saddr=0;
}
JNL_Connection::~JNL_Connection()
{
/*
** Joshua Teitelbaum 1/27/2006
** virtualization for ssl, calling socket_shtudown()
*/
socket_shutdown();
if (!saddr) // free it if it was passed to us (by JNL_Listen, presumably)
free(address); // TODO: change this if we ever do round-robin DNS connecting or in any way change how we handle 'address'
if (m_dns_owned)
delete m_dns;
}
void JNL_Connection::set_dns(JNL_AsyncDNS *dns)
{
if (m_dns_owned)
delete static_cast<JNL_AsyncDNS *>(m_dns);
m_dns=dns;
m_dns_owned=false;
}
void JNL_Connection::open(JNL_AsyncDNS *dns, size_t sendbufsize, size_t recvbufsize)
{
if (dns != JNL_AUTODNS && dns)
{
m_dns=dns;
m_dns_owned=false;
}
else if (!m_dns)
{
m_dns=new JNL_AsyncDNS;
m_dns_owned=true;
}
recv_buffer.reserve(recvbufsize);
send_buffer.reserve(sendbufsize);
}
void JNL_Connection::connect(SOCKET s, sockaddr *addr, socklen_t length)
{
close(1);
m_socket=s;
address=(sockaddr *)malloc(length);
memcpy(address, addr, length);
m_remote_port=0;
if (m_socket != -1)
{
SET_SOCK_BLOCK(m_socket,0);
m_state=STATE_CONNECTED;
}
else
{
m_errorstr="invalid socket passed to connect";
m_state=STATE_ERROR;
}
}
void JNL_Connection::connect(const char *hostname, int port)
{
close(1);
m_remote_port=(unsigned short)port;
#ifdef _WIN32
lstrcpynA(m_host, hostname, sizeof(m_host));
#elif defined(__APPLE__)
strlcpy(m_host, hostname, sizeof(m_host));
#else
strncpy(m_host, hostname, sizeof(m_host)-1);
m_host[sizeof(m_host)-1]=0;
#endif
//memset(&m_saddr,0,sizeof(m_saddr));
if (!m_host[0])
{
m_errorstr="empty hostname";
m_state=STATE_ERROR;
}
else
{
m_state=STATE_RESOLVING;
}
}
/*
** Joshua Teitelbaum 1/27/2006
** socket_shutdown
** virtualization for ssl
*/
/* Virtual */
void JNL_Connection::socket_shutdown()
{
if (m_socket >= 0)
{
::shutdown(m_socket, SHUT_RDWR);
::closesocket(m_socket);
m_socket=-1;
}
}
/*
** Joshua Teitelbaum 1/27/2006
** socket_recv
** virtualization for ssl
*/
/* Virtual */
ssize_t JNL_Connection::socket_recv(char *buf, size_t len, int options)
{
return ::recv(m_socket,buf,(int)len,options);
}
/*
** Joshua Teitelbaum 1/27/2006
** socket_send
** virtualization for ssl
*/
/* Virtual */
ssize_t JNL_Connection::socket_send(const char *buf, size_t len, int options)
{
return ::send(m_socket,buf,(int)len,options);
}
int JNL_Connection::socket_connect()
{
return ::connect(m_socket, saddr->ai_addr, (int)saddr->ai_addrlen);
}
void JNL_Connection::run(size_t max_send_bytes, size_t max_recv_bytes, size_t *bytes_sent, size_t *bytes_rcvd)
{
socklen_t socket_buffer_size=0;
socklen_t socket_buffer_size_len = sizeof(socket_buffer_size);
socklen_t send_buffer_size;
socklen_t recv_buffer_size;
size_t bytes_allowed_to_send=(max_send_bytes==(size_t)-1)?send_buffer.size():max_send_bytes;
size_t bytes_allowed_to_recv=(max_recv_bytes==(size_t)-1)?recv_buffer.avail():max_recv_bytes;
if (bytes_sent) *bytes_sent=0;
if (bytes_rcvd) *bytes_rcvd=0;
switch (m_state)
{
case STATE_RESOLVING:
if (saddr==0)
{
int a=m_dns->resolve(m_host, m_remote_port, &saddr, SOCK_STREAM);
if (!a)
{
m_state=STATE_RESOLVED;
}
else if (a == 1)
{
m_state=STATE_RESOLVING;
break;
}
else
{
m_errorstr="resolving hostname";
m_state=STATE_ERROR;
return;
}
}
// fall through
case STATE_RESOLVED:
m_socket=::socket(saddr->ai_family, saddr->ai_socktype, saddr->ai_protocol);
if (m_socket==-1)
{
m_errorstr="creating socket";
m_state=STATE_ERROR;
}
else
{
SET_SOCK_BLOCK(m_socket,0);
}
socket_buffer_size=0;
socket_buffer_size_len = sizeof(socket_buffer_size);
getsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&socket_buffer_size, &socket_buffer_size_len);
send_buffer_size = (int)(send_buffer.avail()+send_buffer.size());
if (send_buffer_size > 65536)
send_buffer_size=65536;
if (socket_buffer_size < send_buffer_size)
setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&send_buffer_size, sizeof(send_buffer_size));
getsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&socket_buffer_size, &socket_buffer_size_len);
getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&socket_buffer_size, &socket_buffer_size_len);
recv_buffer_size = (int)recv_buffer.avail();
if (recv_buffer_size > 65536)
recv_buffer_size=65536;
if (socket_buffer_size < recv_buffer_size)
setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&recv_buffer_size, sizeof(recv_buffer_size));
getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&socket_buffer_size, &socket_buffer_size_len);
/*
** Joshua Teitelbaum 1/27/2006
** virtualization for ssl
*/
if(!socket_connect())
{
address=saddr->ai_addr;
m_state=STATE_CONNECTED;
on_socket_connected();
}
else if (ERRNO!=JNL_EINPROGRESS)
{
m_errorstr="Connecting to host";
m_state=STATE_ERROR;
}
else
{
m_state=STATE_CONNECTING;
}
break;
case STATE_CONNECTING:
{
fd_set f[3];
FD_ZERO(&f[0]);
FD_ZERO(&f[1]);
FD_ZERO(&f[2]);
FD_SET(m_socket,&f[0]);
FD_SET(m_socket,&f[1]);
FD_SET(m_socket,&f[2]);
struct timeval tv;
memset(&tv,0,sizeof(tv));
if (select((int)m_socket+1,&f[0],&f[1],&f[2],&tv)==-1)
{
m_errorstr="Connecting to host (calling select())";
m_state=STATE_ERROR;
}
else if (FD_ISSET(m_socket,&f[1]))
{
m_state=STATE_CONNECTED;
on_socket_connected();
}
else if (FD_ISSET(m_socket,&f[2]))
{
m_errorstr="Connecting to host";
m_state=STATE_ERROR;
}
}
break;
case STATE_CONNECTED:
case STATE_CLOSING:
/* --- send --- */
{
size_t sent = send_buffer.drain(this, bytes_allowed_to_send);
if (bytes_sent)
*bytes_sent+=sent;
if (m_state == STATE_CLOSED)
break;
/* --- receive --- */
size_t received = recv_buffer.fill(this, bytes_allowed_to_recv);
if (bytes_rcvd)
*bytes_rcvd+=received;
}
if (m_state == STATE_CLOSING)
{
if (send_buffer.empty()) m_state = STATE_CLOSED;
}
break;
default:
break;
}
}
void JNL_Connection::on_socket_connected(void)
{
return;
}
void JNL_Connection::close(int quick)
{
if (quick || m_state == STATE_RESOLVING || m_state == STATE_CONNECTING)
{
m_state=STATE_CLOSED;
/*
** Joshua Teitelbaum 1/27/2006
** virualization for ssl
*/
socket_shutdown();
m_socket=-1;
recv_buffer.clear();
send_buffer.clear();
m_remote_port=0;
m_host[0]=0;
//memset(&m_saddr,0,sizeof(m_saddr));
}
else
{
if (m_state == STATE_CONNECTED)
m_state=STATE_CLOSING;
}
}
size_t JNL_Connection::send_bytes_in_queue(void)
{
return send_buffer.size();
}
size_t JNL_Connection::send_bytes_available(void)
{
return send_buffer.avail();
}
int JNL_Connection::send(const void *data, size_t length)
{
if (length > send_bytes_available())
return -1;
send_buffer.write(data, length);
return 0;
}
int JNL_Connection::send_string(const char *line)
{
return send(line,strlen(line));
}
size_t JNL_Connection::recv_bytes_available(void)
{
return recv_buffer.size();
}
size_t JNL_Connection::peek_bytes(void *data, size_t maxlength)
{
if (data)
return recv_buffer.peek(data, maxlength);
else
return min(maxlength, recv_bytes_available());
}
size_t JNL_Connection::recv_bytes(void *data, size_t maxlength)
{
if (data)
return recv_buffer.read(data, maxlength);
else
return recv_buffer.advance(maxlength);
}
int JNL_Connection::recv_lines_available(void)
{
int l = (int)recv_bytes_available();
int lcount = 0;
int lastch = 0;
for (int pos = 0; pos < l; pos ++)
{
char t;
if (recv_buffer.at(pos, &t, 1) != 1)
return lcount;
if ((t=='\r' || t=='\n') &&( (lastch != '\r' && lastch != '\n') || lastch==t ))
lcount++;
lastch=t;
}
return lcount;
}
int JNL_Connection::recv_line(char *line, size_t maxlength)
{
while (maxlength--)
{
char t;
if (recv_buffer.read(&t, 1) == 0)
{
*line=0;
return 0;
}
if (t == '\r' || t == '\n')
{
char r;
if (recv_buffer.peek(&r, 1) != 0)
{
if ((r == '\r' || r == '\n') && r != t)
recv_buffer.advance(1);
}
*line=0;
return 0;
}
*line++=t;
}
return 1;
}
unsigned long JNL_Connection::get_interface(void)
{
if (m_socket==-1)
return 0;
struct sockaddr_in sin;
memset(&sin,0,sizeof(sin));
socklen_t len=sizeof(sin);
if (::getsockname(m_socket,(struct sockaddr *)&sin,&len))
return 0;
return (unsigned long) sin.sin_addr.s_addr;
}
unsigned long JNL_Connection::get_remote()
{
// TODO: IPv6
if (address)
{
sockaddr_in *ipv4 = (sockaddr_in *)address;
return ipv4->sin_addr.s_addr;
}
return 0;
}
unsigned short JNL_Connection::get_remote_port()
{
return m_remote_port;
}
/* RingBuffer client function */
size_t JNL_Connection::Read(void *dest, size_t len)
{
if (!len)
return 0;
int res=(int)socket_recv((char *)dest,len,0);
if (res == 0 || (res < 0 && ERRNO != JNL_EWOULDBLOCK))
{
m_state=STATE_CLOSED;
return 0;
}
if (res > 0)
return res;
else
return 0;
}
/* RingBuffer client function */
size_t JNL_Connection::Write(const void *dest, size_t len)
{
if (!len)
return 0;
int res=(int)socket_send((const char *)dest,len,0);
if (res==-1 && ERRNO != JNL_EWOULDBLOCK)
{
return 0;
// m_state=STATE_CLOSED;
}
if (res > 0)
return res;
else
return 0;
}
int JNL_Connection::set_recv_buffer_size(size_t new_buffer_size)
{
return recv_buffer.expand(new_buffer_size);
}
void JNL_Connection::reuse()
{
if (m_state == STATE_CLOSED)
{
m_state = STATE_CONNECTED;
recv_buffer.clear();
}
}
+168
View File
@@ -0,0 +1,168 @@
/*
** JNetLib
** Copyright (C) 2000-2007 Nullsoft, Inc.
** Author: Justin Frankel
** File: connection.h - JNL TCP connection interface
** License: see jnetlib.h
**
** Usage:
** 1. Create a JNL_Connection object, optionally specifying a JNL_AsyncDNS
** object to use (or NULL for none, or WAC_NETWORK_CONNECTION_AUTODNS for auto),
** and the send and receive buffer sizes.
** 2. Call connect() to have it connect to a host/port (the hostname will be
** resolved if possible).
** 3. call run() with the maximum send/recv amounts, and optionally parameters
** so you can tell how much has been send/received. You want to do this a lot, while:
** 4. check get_state() to check the state of the connection. The states are:
** JNL_Connection::STATE_ERROR
** - an error has occured on the connection. the connection has closed,
** and you can no longer write to the socket (there still might be
** data in the receive buffer - use recv_bytes_available()).
** JNL_Connection::STATE_NOCONNECTION
** - no connection has been made yet. call connect() already! :)
** JNL_Connection::STATE_RESOLVING
** - the connection is still waiting for a JNL_AsycnDNS to resolve the
** host.
** JNL_Connection::STATE_CONNECTING
** - the asynchronous call to connect() is still running.
** JNL_Connection::STATE_CONNECTED
** - the connection has connected, all is well.
** JNL_Connection::STATE_CLOSING
** - the connection is closing. This happens after a call to close,
** without the quick parameter set. This means that the connection
** will close once the data in the send buffer is sent (data could
** still be being received when it would be closed). After it is
** closed, the state will transition to:
** JNL_Connection::STATE_CLOSED
** - the connection has closed, generally without error. There still
** might be data in the receieve buffer, use recv_bytes_available().
** 5. Use send() and send_string() to send data. You can use
** send_bytes_in_queue() to see how much has yet to go out, or
** send_bytes_available() to see how much you can write. If you use send()
** or send_string() and not enough room is available, both functions will
** return error ( < 0)
** 6. Use recv() and recv_line() to get data. If you want to see how much data
** there is, use recv_bytes_available() and recv_lines_available(). If you
** call recv() and not enough data is available, recv() will return how much
** data was actually read. See comments at the function defs.
**
** 7. To close, call close(1) for a quick close, or close() for a close that will
** make the socket close after sending all the data sent.
**
** 8. delete ye' ol' object.
*/
#ifndef _CONNECTION_H_
#define _CONNECTION_H_
#include "netinc.h"
#include "asyncdns.h"
#include "../nu/RingBuffer.h"
#include "jnetlib_defines.h"
#include <stddef.h>
#include "nswasabi/ReferenceCounted.h"
#if defined(_MSC_VER) && (_MSC_VER < 1200)
typedef int intptr_t;
#endif
#define PACKET_SIZE 16384
class JNL_Connection : private Filler, private Drainer, public ReferenceCountedBase<JNL_Connection>
{
public:
typedef enum
{
STATE_ERROR = JNL_CONNECTION_STATE_ERROR,
STATE_NOCONNECTION = JNL_CONNECTION_STATE_NOCONNECTION,
STATE_RESOLVING = JNL_CONNECTION_STATE_RESOLVING,
STATE_CONNECTING = JNL_CONNECTION_STATE_CONNECTING,
STATE_CONNECTED = JNL_CONNECTION_STATE_CONNECTED,
STATE_CLOSING = JNL_CONNECTION_STATE_CLOSING,
STATE_CLOSED = JNL_CONNECTION_STATE_CLOSED,
STATE_RESOLVED = JNL_CONNECTION_STATE_RESOLVED,
} state;
/*
** Joshua Teitelbaum, 1/27/2006 adding virtual
*/
JNL_Connection();
JNL_Connection(JNL_AsyncDNS *dns, size_t sendbufsize, size_t recvbufsize);
virtual ~JNL_Connection();
void open( JNL_AsyncDNS *dns = JNL_AUTODNS, size_t sendbufsize = 8192, size_t recvbufsize = 8192 );
void connect( const char *hostname, int port );
virtual void connect( SOCKET sock, sockaddr *addr, socklen_t length /* of addr */ ); // used by the listen object, usually not needed by users.
int set_recv_buffer_size(size_t new_buffer_size);
/*
** Joshua Teitelbaum 2/2/2006
** Need to make this virtual to ensure SSL can init properly
*/
virtual void run( size_t max_send_bytes = -1, size_t max_recv_bytes = -1, size_t *bytes_sent = NULL, size_t *bytes_rcvd = NULL );
int get_state() { return m_state; }
char *get_errstr() { return m_errorstr; }
void close( int quick = 0 );
void flush_send( void ) { send_buffer.clear(); }
size_t send_bytes_in_queue( void );
size_t send_bytes_available( void );
int send( const void *data, size_t length ); // returns -1 if not enough room
inline int send_bytes( const void *data, size_t length ) { return send( data, length ); }
int send_string( const char *line ); // returns -1 if not enough room
size_t recv_bytes_available( void );
size_t recv_bytes( void *data, size_t maxlength ); // returns actual bytes read
unsigned int recv_int( void );
int recv_lines_available( void );
int recv_line( char *line, size_t maxlength ); // returns 0 if the line was terminated with a \r or \n, 1 if not.
// (i.e. if you specify maxlength=10, and the line is 12 bytes long
// it will return 1. or if there is no \r or \n and that's all the data
// the connection has.)
size_t peek_bytes( void *data, size_t maxlength ); // returns bytes peeked
unsigned long get_interface( void ); // this returns the interface the connection is on
unsigned long get_remote( void ); // remote host ip.
unsigned short get_remote_port( void ); // this returns the remote port of connection
void set_dns( JNL_AsyncDNS *dns );
void reuse();
protected:
SOCKET m_socket;
unsigned short m_remote_port;
RingBuffer recv_buffer;
RingBuffer send_buffer;
addrinfo *saddr;
sockaddr *address;
char m_host[256];
JNL_AsyncDNS *m_dns;
bool m_dns_owned;
state m_state;
char *m_errorstr;
/*
** Joshua Teitelbaum 1/27/2006 Adding new BSD socket analogues for SSL compatibility
*/
virtual void socket_shutdown();
virtual ssize_t socket_recv( char *buf, size_t len, int options );
virtual ssize_t socket_send( const char *buf, size_t len, int options );
virtual int socket_connect();
virtual void on_socket_connected();
private:
void init(); // constructor helper function
// functions for RingBuffer
size_t Read( void *dest, size_t len ) override;
size_t Write( const void *dest, size_t len ) override;
};
#endif // _Connection_H_
+119
View File
@@ -0,0 +1,119 @@
#include "foundation/error.h"
#include "foundation/types.h"
#include "headers.h"
#include "netinc.h"
#include <stdlib.h>
#include <string.h>
JNL_Headers::JNL_Headers()
{
m_recvheaders = NULL;
m_recvheaders_size = 0;
}
JNL_Headers::~JNL_Headers()
{
if ( m_recvheaders )
free( m_recvheaders );
}
void JNL_Headers::Reset()
{
if ( m_recvheaders )
free( m_recvheaders );
m_recvheaders = NULL;
m_recvheaders_size = 0;
}
const char *JNL_Headers::GetAllHeaders()
{
// double null terminated, null delimited list
if ( m_recvheaders )
return m_recvheaders;
else
return "\0\0";
}
const char *JNL_Headers::GetHeader( const char *headername )
{
char *ret = NULL;
if ( headername[ 0 ] == 0 || !m_recvheaders )
return NULL;
size_t headername_size = strlen( headername );
char *buf = (char *)malloc( headername_size + 2 );
strcpy( buf, headername );
if ( buf[ headername_size - 1 ] != ':' )
{
buf[ headername_size++ ] = ':';
buf[ headername_size ] = 0;
}
char *p = m_recvheaders;
while ( p && *p )
{
if ( !strncasecmp( buf, p, headername_size ) )
{
ret = p + headername_size;
while ( ret && *ret && *ret == ' ' )
ret++;
break;
}
p += strlen( p ) + 1;
}
free( buf );
return ret;
}
int JNL_Headers::Add( const char *buf )
{
if ( !m_recvheaders )
{
m_recvheaders_size = strlen( buf ) + 1;
if ( m_recvheaders_size == 0 || m_recvheaders_size == (size_t)-1 ) // check for overflow
{
return NErr_OutOfMemory;
}
m_recvheaders = (char *)malloc( m_recvheaders_size + 1 );
if ( m_recvheaders )
{
strcpy( m_recvheaders, buf ); // safe because we malloc'd specifically above
m_recvheaders[ m_recvheaders_size ] = 0;
}
else
{
return NErr_OutOfMemory;
}
}
else
{
size_t oldsize = m_recvheaders_size;
m_recvheaders_size += strlen( buf ) + 1;
if ( m_recvheaders_size + 1 < oldsize ) // check for overflow
{
return NErr_OutOfMemory;
}
char *n = (char *)realloc( m_recvheaders, m_recvheaders_size + 1 );
if ( !n )
{
return NErr_OutOfMemory;
}
strcpy( n + oldsize, buf ); // safe because we malloc specifially for the size
n[ m_recvheaders_size ] = 0; // double null terminate
m_recvheaders = n;
}
return NErr_Success;
}
+20
View File
@@ -0,0 +1,20 @@
#pragma once
// TODO: benski> change this to use a smarter data structure.
// this initial implementation is known to work, however
class JNL_Headers
{
public:
JNL_Headers();
~JNL_Headers();
const char *GetAllHeaders();
const char *GetHeader( const char *header_name );
int Add( const char *buf );
void Reset();
private:
char *m_recvheaders;
size_t m_recvheaders_size;
};
+845
View File
@@ -0,0 +1,845 @@
/*
** JNetLib
** Copyright (C) 2000-2007 Nullsoft, Inc.
** Author: Justin Frankel
** File: httpget.cpp - JNL HTTP GET implementation
** License: see jnetlib.h
*/
#include "netinc.h"
#include "util.h"
#include "httpget.h"
#include "foundation/error.h"
#ifdef USE_SSL
#include "sslconnection.h"
#endif
#include <stdio.h>
#define STRSAFE_NO_DEPRECATE
#include "nu/strsafe.h"
#include "nu/AutoLock.h"
char *JNL_HTTPGet::g_proxy = 0;
static nu::LockGuard proxy_guard;
char *JNL_HTTPGet::get_proxy()
{
nu::AutoLock auto_lock( proxy_guard );
if ( g_proxy )
return _strdup( g_proxy );
else
return 0;
}
void JNL_HTTPGet::set_proxy( const char *proxy )
{
nu::AutoLock auto_lock( proxy_guard );
free( g_proxy );
if ( proxy )
g_proxy = _strdup( proxy );
else
g_proxy = 0;
}
JNL_HTTPGet::JNL_HTTPGet( size_t recvbufsize, size_t sendbufsize )
{
persistent = false;
accept_all_reply_codes = false;
zlibStream = 0;
allowCompression = false;
m_dns = JNL_AUTODNS;
m_con = NULL;
m_http_proxylpinfo = 0;
m_http_proxyhost = 0;
m_http_proxyport = 0;
m_sendbufsize = sendbufsize;
m_sendheaders = NULL;
reinit();
m_recvbufsize = recvbufsize;
char *p = get_proxy();
if ( p )
{
char *r = NULL;
do_parse_url( p, &m_http_proxyhost, &m_http_proxyport, &r, &m_http_proxylpinfo );
free( r );
free( p );
}
}
JNL_HTTPGet::~JNL_HTTPGet()
{
deinit();
free( m_sendheaders );
free( m_http_proxylpinfo );
free( m_http_proxyhost );
}
void JNL_HTTPGet::reinit()
{
m_errstr = 0;
m_recvheaders = NULL;
m_recvheaders_size = 0;
m_http_state = 0;
m_http_port = 0;
m_http_url = 0;
m_reply = 0;
m_http_host = m_http_lpinfo = m_http_request = NULL;
}
void JNL_HTTPGet::deinit( bool full )
{
if ( !persistent || full || ( m_con && m_con->get_state() == JNL_Connection::STATE_ERROR ) )
{
delete m_con;
m_con = NULL;
}
free( m_recvheaders );
free( m_http_url );
free( m_http_host );
free( m_http_lpinfo );
free( m_http_request );
free( m_errstr );
free( m_reply );
if ( zlibStream )
inflateEnd( zlibStream );
free( zlibStream );
zlibStream = 0;
reinit();
}
void JNL_HTTPGet::set_sendbufsize(size_t sendbufsize)
{
m_sendbufsize = sendbufsize;
}
int JNL_HTTPGet::set_recv_buffer_size( size_t new_buffer_size )
{
if ( m_con )
{
int ret = m_con->set_recv_buffer_size( new_buffer_size );
if ( ret == NErr_NoAction )// this will get returned if new_buffer_size is smaller than existing.
return NErr_Success;
else if ( ret != NErr_Success )
return ret;
}
m_recvbufsize = new_buffer_size;
return NErr_Success;
}
void JNL_HTTPGet::addheader( const char *header )
{
if ( strstr( header, "\r" ) || strstr( header, "\n" ) )
return;
if ( !m_sendheaders )
{
size_t len = strlen( header ) + 3;
m_sendheaders = (char *)malloc( len );
if ( m_sendheaders )
{
char *itr = m_sendheaders;
StringCchCopyExA( itr, len, header, &itr, &len, 0 );
StringCchCatExA( itr, len, "\r\n", &itr, &len, 0 );
}
}
else
{
size_t len = strlen( header ) + strlen( m_sendheaders ) + 1 + 2;
char *t = (char *)malloc( len );
if ( t )
{
char *newHeaders = t;
StringCchCopyExA( t, len, m_sendheaders, &t, &len, 0 );
StringCchCatExA( t, len, header, &t, &len, 0 );
StringCchCatExA( t, len, "\r\n", &t, &len, 0 );
free( m_sendheaders );
m_sendheaders = newHeaders;
}
}
}
void JNL_HTTPGet::addheadervalue( const char *header, const char *value )
{
size_t additional = strlen( header ) + 2 + strlen( value ) + 2 + 1;
if ( !m_sendheaders )
{
m_sendheaders = (char *)malloc( additional );
if ( m_sendheaders )
{
char *p = m_sendheaders;
StringCchCopyExA( p, additional, header, &p, &additional, 0 );
StringCchCatExA( p, additional, ": ", &p, &additional, 0 );
StringCchCatExA( p, additional, value, &p, &additional, 0 );
StringCchCatExA( p, additional, "\r\n", &p, &additional, 0 );
}
}
else
{
size_t alloc_len = strlen( m_sendheaders ) + additional;
char *t = (char *)malloc( alloc_len );
if ( t )
{
char *p = t;
StringCchCopyExA( p, alloc_len, m_sendheaders, &p, &alloc_len, 0 );
StringCchCatExA( p, alloc_len, header, &p, &alloc_len, 0 );
StringCchCatExA( p, alloc_len, ": ", &p, &alloc_len, 0 );
StringCchCatExA( p, alloc_len, value, &p, &alloc_len, 0 );
StringCchCatExA( p, alloc_len, "\r\n", &p, &alloc_len, 0 );
free( m_sendheaders );
m_sendheaders = t;
}
}
}
void JNL_HTTPGet::do_encode_mimestr( char *in, char *out )
{
char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int shift = 0;
int accum = 0;
while ( in && *in )
{
if ( *in )
{
accum <<= 8;
shift += 8;
accum |= *in++;
}
while ( shift >= 6 )
{
shift -= 6;
*out++ = alphabet[ ( accum >> shift ) & 0x3F ];
}
}
if ( shift == 4 )
{
*out++ = alphabet[ ( accum & 0xF ) << 2 ];
*out++ = '=';
}
else if ( shift == 2 )
{
*out++ = alphabet[ ( accum & 0x3 ) << 4 ];
*out++ = '=';
*out++ = '=';
}
*out++ = 0;
}
void JNL_HTTPGet::connect( const char *url, int ver, const char *requestmethod )
{
deinit( false );
m_http_url = _strdup( url );
do_parse_url( m_http_url, &m_http_host, &m_http_port, &m_http_request, &m_http_lpinfo );
if ( !m_http_host || !m_http_host[ 0 ] || !m_http_port )
{
m_http_state = -1;
seterrstr( "invalid URL" );
return;
}
size_t sendbufferlen = 0;
if ( !m_http_proxyhost || !m_http_proxyhost[ 0 ] )
sendbufferlen += strlen( requestmethod ) + 1 /* GET */ + strlen( m_http_request ) + 9 /* HTTP/1.0 */ + 2;
else
{
sendbufferlen += strlen( requestmethod ) + 1 /* GET */ + strlen( m_http_url ) + 9 /* HTTP/1.0 */ + 2;
if ( m_http_proxylpinfo && m_http_proxylpinfo[ 0 ] )
sendbufferlen += 58 + strlen( m_http_proxylpinfo ) * 2; // being safe here
}
sendbufferlen += 5 /* Host: */ + strlen( m_http_host ) + 2;
if ( m_http_port != 80 )
sendbufferlen += 6;
if ( m_http_lpinfo && m_http_lpinfo[ 0 ] )
sendbufferlen += 46 + strlen( m_http_lpinfo ) * 2; // being safe here
if ( m_sendheaders )
sendbufferlen += strlen( m_sendheaders );
size_t strLen = sendbufferlen + 1024;
char *str = (char *)calloc( strLen, sizeof( char ) );
char *connectString = str;
if ( !str )
{
seterrstr( "error allocating memory" );
m_http_state = -1;
}
if ( !m_http_proxyhost || !m_http_proxyhost[ 0 ] )
{
StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s %s HTTP/1.%d\r\n", requestmethod, m_http_request, ver % 10 );
}
else
{
char *myp = NULL;
if ( strncasecmp( m_http_url, "uvox://", 7 ) == 0 )
{
myp = m_http_url + 7;
StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s http://%s HTTP/1.%d\r\n", requestmethod, myp, ver % 10 );
}
else if ( strncasecmp( m_http_url, "unsv://", 7 ) == 0 )
{
myp = m_http_url + 7;
StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s http://%s HTTP/1.%d\r\n", requestmethod, myp, ver % 10 );
}
else if ( strncasecmp( m_http_url, "uasf://", 7 ) == 0 )
{
myp = m_http_url + 7;
StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s http://%s HTTP/1.%d\r\n", requestmethod, myp, ver % 10 );
}
else
StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s %s HTTP/1.%d\r\n", requestmethod, m_http_url, ver % 10 );
}
if ( m_http_port == 80 )
StringCchPrintfExA( str, strLen, &str, &strLen, 0, "Host: %s\r\n", m_http_host );
else
StringCchPrintfExA( str, strLen, &str, &strLen, 0, "Host: %s:%d\r\n", m_http_host, m_http_port );
if ( m_http_lpinfo && m_http_lpinfo[ 0 ] )
{
StringCchCatExA( str, strLen, "Authorization: Basic ", &str, &strLen, 0 );
do_encode_mimestr( m_http_lpinfo, str );
StringCchCatExA( str, strLen, "\r\n", &str, &strLen, 0 );
}
if ( m_http_proxylpinfo && m_http_proxylpinfo[ 0 ] )
{
StringCchCatExA( str, strLen, "Proxy-Authorization: Basic ", &str, &strLen, 0 );
do_encode_mimestr( m_http_proxylpinfo, str );
StringCchCatExA( str, strLen, "\r\n", &str, &strLen, 0 );
}
if ( allowCompression )
StringCchCatExA( str, strLen, "Accept-Encoding: gzip\r\n", &str, &strLen, 0 );
if ( m_sendheaders )
StringCchCatExA( str, strLen, m_sendheaders, &str, &strLen, 0 );
StringCchCatExA( str, strLen, "\r\n", &str, &strLen, 0 );
int a = (int)m_recvbufsize;
if ( a < 4096 )
a = 4096;
if ( !m_con )
{
//m_con=new JNL_Connection(m_dns,strlen(str)+4,a);
/*
** Joshua Teitelbaum delta 1/15/2006
*/
#ifdef USE_SSL
/*
** Joshua Teitelbaum 1/27/2006
** Check for secure
*/
if ( !_strnicmp( m_http_url, "https:", strlen( "https:" ) ) )
{
size_t send_buffer_size = strlen( connectString ) + 4;
if ( send_buffer_size < 8192 )
send_buffer_size = 8192;
send_buffer_size += m_sendbufsize;
if ( m_sendbufsize == 0 && !strcmp( requestmethod, "POST" ) )
send_buffer_size += 8192; // some extra room for posting data if it wasn't explicitly defined
m_con = new JNL_SSL_Connection( NULL, m_dns, send_buffer_size, a );
}
else
{
#endif
size_t send_buffer_size = strlen( connectString ) + 4 + m_sendbufsize;
if ( m_sendbufsize == 0 && !strcmp( requestmethod, "POST" ) )
send_buffer_size += 8192; // some extra room for posting data if it wasn't explicitly defined
m_con = new JNL_Connection( m_dns, send_buffer_size, a );
#ifdef USE_SSL
}
#endif
if ( m_con )
{
if ( !m_http_proxyhost || !m_http_proxyhost[ 0 ] )
m_con->connect( m_http_host, m_http_port );
else
m_con->connect( m_http_proxyhost, m_http_proxyport );
m_con->send_string( connectString );
}
else
{
m_http_state = -1;
seterrstr( "could not create connection object" );
}
}
else
{
m_con->reuse();
m_con->send_string( connectString );
}
free(connectString);
}
void JNL_HTTPGet::do_parse_url( const char *url, char **host, unsigned short *port, char **req, char **lp )
{
char *l_port = 0;
JNL::parse_url( url, &l_port, host, port, req, lp );
if ( !*port )
{
if ( l_port )
{
addrinfo *res;
addrinfo hints;
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = PF_UNSPEC;
hints.ai_flags = 0;
hints.ai_socktype = SOCK_STREAM;
if ( getaddrinfo( 0, l_port, &hints, &res ) == 0 )
{
if ( res->ai_family == AF_INET )
*port = htons( ( (sockaddr_in *)res->ai_addr )->sin_port );
else if ( res->ai_family == AF_INET6 )
*port = htons( ( (sockaddr_in6 *)res->ai_addr )->sin6_port );
else // wtf?
*port = 80;
}
else
*port = 80;
}
else
*port = 80;
}
if ( l_port )
free( l_port );
if ( !*req )
*req = _strdup( "/" );
}
const char *JNL_HTTPGet::getallheaders()
{
// double null terminated, null delimited list
if (m_recvheaders)
return m_recvheaders;
else
return "\0\0";
}
const char *JNL_HTTPGet::getheader( const char *headername )
{
char *ret = NULL;
if ( headername[ 0 ] == 0 || !m_recvheaders )
return NULL;
size_t headername_size = strlen( headername );
char *buf = (char *)malloc( headername_size + 2 );
#ifdef _WIN32
StringCchCopyA( buf, headername_size + 2, headername );
#elif defined(__APPLE__)
strlcpy( buf, headername, headername_size + 2 );
#else
strncpy( buf, headername, headername_size + 1 );
buf[ headername_size + 1 ] = 0;
#endif
if ( buf[ headername_size - 1 ] != ':' )
{
buf[ headername_size++ ] = ':';
buf[ headername_size ] = 0;
}
char *p = m_recvheaders;
while ( p && *p )
{
if ( !strncasecmp( buf, p, headername_size ) )
{
ret = p + headername_size;
while ( ret && *ret && *ret == ' ' )
ret++;
break;
}
p += strlen( p ) + 1;
}
free( buf );
return ret;
}
int JNL_HTTPGet::run()
{
int cnt = 0;
if ( m_http_state == -1 || !m_con )
return HTTPGET_RUN_ERROR; // error
run_again:
m_con->run();
if ( m_con->get_state() == JNL_Connection::STATE_ERROR )
{
seterrstr( m_con->get_errstr() );
return HTTPGET_RUN_ERROR;
}
if ( m_con->get_state() == JNL_Connection::STATE_CLOSED )
return HTTPGET_RUN_CONNECTION_CLOSED;
if ( m_http_state == 0 ) // connected, waiting for reply
{
if ( m_con->recv_lines_available() > 0 )
{
char buf[ 4096 ] = { 0 };
m_con->recv_line( buf, 4096 );
buf[ 4095 ] = 0;
if ( m_reply && getreplycode() == 100 )
{
free( m_reply );
m_reply = 0;
goto run_again;
}
m_reply = _strdup( buf );
int code = getreplycode();
if ( code >= 200 && code <= 206 )
m_http_state = 2; // proceed to read headers normally
else if ( code == 301 || code == 302 || code == 303 || code == 307 )
{
m_http_state = 1; // redirect city
}
else if ( code != 100 ) // in case of HTTP 100 Continue code, we'll keep looping
{
if ( accept_all_reply_codes )
{
m_http_state = 2; // proceed to read headers normally
}
else
{
seterrstr( buf );
m_http_state = -1;
return HTTPGET_RUN_ERROR;
}
}
cnt = 0;
}
else if ( !cnt++ )
goto run_again;
}
if ( m_http_state == 1 ) // redirect
{
char *loc = 0;
while ( m_con->recv_lines_available() > 0 )
{
char buf[ 4096 ] = { 0 };
m_con->recv_line( buf, 4096 );
buf[ 4095 ] = 0;
if ( !buf[ 0 ] )
{
if ( !loc )
{
m_http_state = -1;
return HTTPGET_RUN_ERROR;
}
else
break;
}
if ( !strncasecmp( buf, "Location:", 9 ) )
{
char *p = buf + 9;
while ( p && *p && *p == ' ' ) p++;
if ( p && *p )
{
// TODO need to make this match the request type
loc = _strdup( p );
}
}
}
if ( loc )
{
connect( loc );
free( loc );
return HTTPGET_RUN_OK;
}
}
/* ----- read headers ----- */
if ( m_http_state == 2 )
{
if ( !cnt++ && m_con->recv_lines_available() < 1 )
goto run_again;
while ( m_con->recv_lines_available() > 0 )
{
char buf[ 8192 ] = { 0 };
m_con->recv_line( buf, 8192 );
buf[ 8191 ] = 0;
if ( !buf[ 0 ] )
{
const char *compression = getheader( "Content-Encoding" );
if ( compression && !strcmp( compression, "gzip" ) )
{
zlibStream = (z_stream *)malloc( sizeof( z_stream ) );
zlibStream->next_in = Z_NULL;
zlibStream->avail_in = Z_NULL;
zlibStream->next_out = Z_NULL;
zlibStream->avail_out = Z_NULL;
zlibStream->zalloc = (alloc_func)0;
zlibStream->zfree = (free_func)0;
zlibStream->opaque = 0;
int z_err = inflateInit2( zlibStream, 15 + 16 /* +16 for gzip */ );
if ( z_err != Z_OK )
{
free( zlibStream );
zlibStream = 0;
}
}
else
{
if ( zlibStream )
{
free( zlibStream );
zlibStream = 0;
}
}
m_http_state = 3;
break;
}
if ( !m_recvheaders )
{
m_recvheaders_size = strlen( buf ) + 1;
if ( m_recvheaders_size == 0 || m_recvheaders_size == (size_t)-1 ) // check for overflow
{
m_http_state = -1;
return HTTPGET_RUN_ERROR;
}
m_recvheaders = (char *)malloc( m_recvheaders_size + 1 );
if ( m_recvheaders )
{
strcpy( m_recvheaders, buf ); // safe because we malloc'd specifically above
m_recvheaders[ m_recvheaders_size ] = 0;
}
else
{
m_http_state = -1;
return HTTPGET_RUN_ERROR;
}
}
else
{
size_t oldsize = m_recvheaders_size;
m_recvheaders_size += strlen( buf ) + 1;
if ( m_recvheaders_size + 1 < oldsize ) // check for overflow
{
m_http_state = -1;
return HTTPGET_RUN_ERROR;
}
char *n = (char *)realloc( m_recvheaders, m_recvheaders_size + 1 );
if ( !n )
{
m_http_state = -1;
return HTTPGET_RUN_ERROR;
}
strcpy( n + oldsize, buf ); // safe because we malloc specifially for the size
n[ m_recvheaders_size ] = 0; // double null terminate
m_recvheaders = n;
}
}
}
return HTTPGET_RUN_OK;
}
int JNL_HTTPGet::get_status() // returns 0 if connecting, 1 if reading headers, 2 if reading content, -1 if error.
{
if ( m_http_state < 0 )
return HTTPGET_STATUS_ERROR;
if ( m_http_state < 2 )
return HTTPGET_STATUS_CONNECTING;
if ( m_http_state == 2 )
return HTTPGET_STATUS_READING_HEADERS;
if ( m_http_state == 3 )
return HTTPGET_STATUS_READING_CONTENT;
return HTTPGET_STATUS_ERROR;
}
int JNL_HTTPGet::getreplycode() // returns 0 if none yet, otherwise returns http reply code.
{
if ( !m_reply )
return 0;
char *p = m_reply;
while ( p && *p && *p != ' ' )
p++; // skip over HTTP/x.x
if ( !p || !*p )
return 0;
return atoi( ++p );
}
size_t JNL_HTTPGet::bytes_available()
{
if ( m_con && m_http_state == 3 )
return m_con->recv_bytes_available();
return 0;
}
size_t JNL_HTTPGet::get_bytes( char *buf, size_t len )
{
if ( m_con && m_http_state == 3 )
{
if ( zlibStream )
{
// TODO: benski> we need to pick a better buffer size
// either alloca() and use the passed in length
// or malloc a buffer based on the constructor-initted buffer size
char temp[ 8192 ] = { 0 };
int size = (int)m_con->peek_bytes( temp, 8192 );
if ( size )
{
zlibStream->next_in = reinterpret_cast<Bytef *>( temp );
zlibStream->avail_in = (uInt)size;
zlibStream->next_out = reinterpret_cast<Bytef *>( buf );
zlibStream->avail_out = (uInt)len;
int zlib_err = inflate( zlibStream, Z_SYNC_FLUSH );
if ( zlib_err == Z_OK || zlib_err == Z_STREAM_END )
{
m_con->recv_bytes( 0, size - zlibStream->avail_in ); // since we only peeked above
return len - zlibStream->avail_out;
}
else
return 0; // TODO: should we do something else here?
}
}
else
return m_con->recv_bytes( buf, len );
}
return 0;
}
size_t JNL_HTTPGet::peek_bytes( char *buf, size_t len )
{
if ( m_con && m_http_state == 3 )
{
if ( zlibStream )
return 0; // TODO: benski> how are we going to do peek_bytes, since the inflater saves state?
else
return m_con->peek_bytes( buf, len );
}
return 0;
}
uint64_t JNL_HTTPGet::content_length()
{
const char *p = getheader( "content-length" );
if ( p && *p )
return strtoull( p, 0, 10 );
else
{
// TODO need to check this further for reliability!
// Helps to handle responses without content-length
if ( m_recvheaders_size > 0 && bytes_available() > 0 )
return bytes_available() - m_recvheaders_size;
}
return 0;
}
void JNL_HTTPGet::seterrstr( const char *str )
{
if ( m_errstr )
free( m_errstr );
m_errstr = _strdup( str );
}
void JNL_HTTPGet::AllowCompression()
{
allowCompression = true;
}
void JNL_HTTPGet::reset_headers()
{
if ( m_sendheaders )
{
free( m_sendheaders );
m_sendheaders = 0;
}
}
void JNL_HTTPGet::set_accept_all_reply_codes()
{
accept_all_reply_codes = true;
}
void JNL_HTTPGet::set_persistent()
{
persistent = true;
}
+139
View File
@@ -0,0 +1,139 @@
/*
** JNetLib
** Copyright (C) 2000-2007 Nullsoft, Inc.
** Author: Justin Frankel
** File: httpget.h - JNL interface for doing HTTP GETs.
** License: see jnetlib.h
**
** Usage:
** 1. Create a JNL_HTTPGet object, optionally specifying a JNL_AsyncDNS
** object to use (or NULL for none, or WAC_NETWORK_CONNECTION_AUTODNS for auto),
** and the receive buffer size, and a string specifying proxy (or NULL
** for none). See note on proxy string below.
** 2. call addheader() to add whatever headers you want. It is recommended to
** add at least the following two:
** addheader("User-Agent:MyApp (Mozilla)");
*/// addheader("Accept:*/*");
/* ( the comment weirdness is there so I Can do the star-slash :)
** 3. Call connect() with the URL you wish to GET (see URL string note below)
** 4. Call run() once in a while, checking to see if it returns -1
** (if it does return -1, call geterrorstr() to see what the error is).
** (if it returns 1, no big deal, the connection has closed).
** 5. While you're at it, you can call bytes_available() to see if any data
** from the http stream is available, or getheader() to see if any headers
** are available, or getreply() to see the HTTP reply, or getallheaders()
** to get a double null terminated, null delimited list of headers returned.
** 6. If you want to read from the stream, call get_bytes (which returns how much
** was actually read).
** 7. content_length() is a helper function that uses getheader() to check the
** content-length header.
** 8. Delete ye' ol' object when done.
**
** Proxy String:
** should be in the format of host:port, or user@host:port, or
** user:password@host:port. if port is not specified, 80 is assumed.
** URL String:
** should be in the format of http://user:pass@host:port/requestwhatever
** note that user, pass, port, and /requestwhatever are all optional :)
** note that also, http:// is really not important. if you do poo://
** or even leave out the http:// altogether, it will still work.
*/
#ifndef _HTTPGET_H_
#define _HTTPGET_H_
#include "connection.h"
#include "asyncdns.h"
#include "jnetlib_defines.h"
#ifdef _WIN32
#include "minizip/unzip.h"
#else
#include <zlib.h>
#endif
#include "nswasabi/ReferenceCounted.h"
class JNL_HTTPGet : public ReferenceCountedBase<JNL_HTTPGet>
{
public:
JNL_HTTPGet(size_t recvbufsize=PACKET_SIZE, size_t sendbufsize=0);
~JNL_HTTPGet();
void set_sendbufsize( size_t sendbufsize = PACKET_SIZE ); // call if you're going to POST or do any kind of bidirectional communications
int set_recv_buffer_size(size_t new_buffer_size);
void addheader(const char *header);
void addheadervalue(const char *header, const char *value);
void connect(const char *url, int ver=0, const char *requestmethod="GET");
int run(); // returns: 0 if all is OK. -1 if error (call geterrorstr()). 1 if connection closed.
int get_status(); // returns 0 if connecting, 1 if reading headers,
// 2 if reading content, -1 if error.
const char *getallheaders(); // double null terminated, null delimited list
const char *getheader(const char *headername);
const char *getreply() { return m_reply; }
int getreplycode(); // returns 0 if none yet, otherwise returns http reply code.
const char *geterrorstr() { return m_errstr;}
size_t bytes_available();
size_t get_bytes(char *buf, size_t len);
size_t peek_bytes(char *buf, size_t len);
uint64_t content_length();
JNL_Connection *get_con() { return m_con; }
void AllowCompression();
void reset_headers();
void set_dns(JNL_AsyncDNS *dns);
const char *get_url() { return m_http_url; }
void set_accept_all_reply_codes(); // call this if you want to retrieve content even though a 404 (etc) was returned
void set_persistent();
static void set_proxy(const char *proxy);
protected:
static char *get_proxy();
void reinit();
void deinit(bool full=true);
void seterrstr(const char *str);
void do_parse_url(const char *url, char **host, unsigned short*port, char **req, char **lp);
void do_encode_mimestr(char *in, char *out);
JNL_AsyncDNS *m_dns;
JNL_Connection *m_con;
size_t m_recvbufsize;
int m_http_state;
unsigned short m_http_port;
char *m_http_url;
char *m_http_host;
char *m_http_lpinfo;
char *m_http_request;
char *m_http_proxylpinfo;
char *m_http_proxyhost;
unsigned short m_http_proxyport;
char *m_sendheaders;
char *m_recvheaders;
size_t m_recvheaders_size;
char *m_reply;
char *m_errstr;
bool allowCompression;
size_t m_sendbufsize;
/* gzip stuff */
z_stream *zlibStream;
bool accept_all_reply_codes;
bool persistent;
static char *g_proxy;
};
#endif // _HTTPGET_H_
+234
View File
@@ -0,0 +1,234 @@
/*
** JNetLib
** Copyright (C) 2001 Nullsoft, Inc.
** Author: Justin Frankel
** File: httpserv.cpp - JNL HTTP GET/POST serving implementation
** License: see jnetlib.h
**
** This class just manages the http reply/sending, not where the data
** comes from, etc.
*/
#include "netinc.h"
#include "util.h"
#include "httpserv.h"
/*
States for m_state:
-1 error (connection closed, etc)
0 not read request yet.
1 reading headers
2 headers read, have not sent reply
3 sent reply
4 closed
*/
JNL_HTTPServ::JNL_HTTPServ(JNL_Connection *con)
{
m_con=con;
m_state=0;
m_reply_headers=0;
m_reply_string=0;
m_recv_request=0;
m_errstr=0;
m_reply_ready=0;
m_method = 0;
http_ver = 0;
keep_alive = 0;
}
JNL_HTTPServ::~JNL_HTTPServ()
{
free(m_recv_request);
free(m_reply_string);
free(m_reply_headers);
free(m_errstr);
free(m_method);
m_con->Release();
}
static size_t strlen_whitespace(const char *str)
{
size_t size=0;
while (str && *str && *str != ' ' && *str != '\r' && *str!='\n')
{
str++;
size++;
}
return size;
}
int JNL_HTTPServ::run()
{ // returns: < 0 on error, 0 on connection close, 1 if reading request, 2 if reply not sent, 3 if reply sent, sending data.
int cnt=0;
run_again:
m_con->run();
if (m_con->get_state()==JNL_Connection::STATE_ERROR)
{
seterrstr(m_con->get_errstr());
return -1;
}
if (m_con->get_state()==JNL_Connection::STATE_CLOSED)
return 4;
if (m_state == 0)
{
if (m_con->recv_lines_available()>0)
{
char *buf=(char*)malloc(m_con->recv_bytes_available()-1);
m_con->recv_line(buf,m_con->recv_bytes_available()-1);
free(m_recv_request);
m_recv_request=(char*)malloc(strlen(buf)+2);
strcpy(m_recv_request,buf);
m_recv_request[strlen(m_recv_request)+1]=0;
free(buf);
buf=m_recv_request;
while (buf && *buf) buf++;
while (buf >= m_recv_request && *buf != ' ') buf--;
if (strncmp(buf+1,"HTTP",4))// || strncmp(m_recv_request,"GET ",3))
{
seterrstr("malformed HTTP request");
m_state=-1;
}
else
{
http_ver = atoi(buf+8);
size_t method_len = strlen_whitespace(m_recv_request);
m_method = (char *)malloc(method_len + 1);
memcpy(m_method, m_recv_request, method_len);
m_method[method_len]=0;
m_state=1;
cnt=0;
if (buf >= m_recv_request) buf[0]=buf[1]=0;
buf=strstr(m_recv_request,"?");
if (buf)
{
*buf++=0; // change &'s into 0s now.
char *t=buf;
int stat=1;
while (t && *t)
{
if (*t == '&' && !stat) { stat=1; *t=0; }
else stat=0;
t++;
}
}
}
}
else if (!cnt++) goto run_again;
}
if (m_state == 1)
{
if (!cnt++ && m_con->recv_lines_available()<1) goto run_again;
while (m_con->recv_lines_available()>0)
{
char buf[4096] = {0};
m_con->recv_line(buf,4096);
if (!buf[0])
{
m_state=2;
break;
}
recvheaders.Add(buf);
}
}
if (m_state == 2)
{
if (m_reply_ready)
{
// send reply
m_con->send_string((char*)(m_reply_string?m_reply_string:"HTTP/1.1 200 OK"));
m_con->send_string("\r\n");
if (m_reply_headers) m_con->send_string(m_reply_headers);
m_con->send_string("\r\n");
m_state=3;
}
}
if (m_state == 3)
{
// nothing.
}
return m_state;
}
const char *JNL_HTTPServ::get_request_file()
{
// file portion of http request
if (!m_recv_request) return NULL;
char *t=m_recv_request;
while (t && *t && *t != ' ') t++;
if (!t || !*t) return NULL;
while (t && *t && *t == ' ') t++;
return t;
}
const char *JNL_HTTPServ::get_request_parm(const char *parmname) // parameter portion (after ?)
{
const char *t=m_recv_request;
while (t && *t) t++;
if (t) t++;
while (t && *t)
{
while (t && *t && *t == '&') t++;
if (!_strnicmp(t,parmname,strlen(parmname)) && t[strlen(parmname)] == '=')
{
return t+strlen(parmname)+1;
}
t+=strlen(t)+1;
}
return NULL;
}
const char *JNL_HTTPServ::getheader(const char *headername)
{
return recvheaders.GetHeader(headername);
}
void JNL_HTTPServ::set_reply_string(const char *reply_string) // should be HTTP/1.1 OK or the like
{
free(m_reply_string);
m_reply_string=(char*)malloc(strlen(reply_string)+1);
strcpy(m_reply_string,reply_string);
}
void JNL_HTTPServ::add_reply_header(const char *header) // "Connection: close" for example
{
// if they've specified a content-length, then we can keep alive an HTTP/1.1 connection
if (!keep_alive && http_ver == 1 && !_strnicmp(header, "Content-Length", 14))
keep_alive = 1;
if (m_reply_headers)
{
char *tmp=(char*)malloc(strlen(m_reply_headers)+strlen(header)+3);
strcpy(tmp,m_reply_headers);
strcat(tmp,header);
strcat(tmp,"\r\n");
free(m_reply_headers);
m_reply_headers=tmp;
}
else
{
m_reply_headers=(char*)malloc(strlen(header)+3);
strcpy(m_reply_headers,header);
strcat(m_reply_headers,"\r\n");
}
}
void JNL_HTTPServ::reset()
{
free(m_recv_request); m_recv_request = 0;
free(m_reply_string); m_reply_string = 0;
free(m_reply_headers); m_reply_headers = 0;
free(m_errstr); m_errstr = 0;
free(m_method); m_method =0;
m_reply_ready=0;
m_state = 0;
keep_alive = 0;
}
+71
View File
@@ -0,0 +1,71 @@
/*
** JNetLib
** Copyright (C) 2001 Nullsoft, Inc.
** Author: Justin Frankel
** File: httpserv.h - JNL interface for doing HTTP GET/POST serving.
** License: see jnetlib.h
** This class just manages the http reply/sending, not where the data
** comes from, etc.
** for a mini-web server see webserver.h
*/
#ifndef _HTTPSERV_H_
#define _HTTPSERV_H_
#include "connection.h"
#include "headers.h"
#include "nswasabi/ReferenceCounted.h"
class JNL_HTTPServ : public ReferenceCountedBase<JNL_HTTPServ>
{
public:
JNL_HTTPServ(JNL_Connection *con=NULL);
~JNL_HTTPServ();
int run(); // returns: < 0 on error, 0 on request not read yet, 1 if reading headers, 2 if reply not sent, 3 if reply sent, sending data. 4 on connection closed.
const char *geterrorstr() { return m_errstr;}
// use these when state returned by run() is 2
const char *get_request_file(); // file portion of http request
const char *get_request_parm(const char *parmname); // parameter portion (after ?)
const char *getallheaders() { return recvheaders.GetAllHeaders(); } // double null terminated, null delimited list
const char *getheader(const char *headername);
const char *get_method() { return m_method; };
void set_reply_string(const char *reply_string); // should be HTTP/1.1 OK or the like
void add_reply_header(const char *header); // i.e. "content-size: 12345"
void send_reply() { m_reply_ready=1; } // send reply, state will advance to 3.
////////// sending data ///////////////
int bytes_inqueue() { if (m_state == 3 || m_state == -1 || m_state ==4) return (int)m_con->send_bytes_in_queue(); else return 0; }
int bytes_cansend() { if (m_state == 3) return (int)m_con->send_bytes_available(); else return 0; }
void write_bytes(char *bytes, int length) { m_con->send(bytes,length); }
void close(int quick) { m_con->close(quick); m_state=4; }
JNL_Connection *get_con() { return m_con; }
void reset(); // prepare for another request on the same connection (HTTP/1.1)
int get_http_version() { return http_ver; }
int get_keep_alive() { return keep_alive; }
protected:
void seterrstr(const char *str) { if (m_errstr) free(m_errstr); m_errstr=_strdup(str); }
int m_reply_ready;
int m_state;
int http_ver;
int keep_alive;
char *m_errstr;
char *m_reply_headers;
char *m_reply_string;
JNL_Headers recvheaders;
char *m_recv_request; // either double-null terminated, or may contain parameters after first null.
char *m_method;
JNL_Connection *m_con;
};
#endif // _HTTPSERV_H_
+216
View File
@@ -0,0 +1,216 @@
/*
** JNetLib
** Copyright (C) 2012 Nullsoft, Inc.
** Author: Ben Allison
** File: httpuserv.cpp - JNL HTTPU (HTTP over UDP) serving implementation
** License: see jnetlib.h
*/
#include "netinc.h"
#include "util.h"
#include "httpuserv.h"
#include "foundation/error.h"
/*
States for m_state:
-1 error (connection closed, etc)
0 not read request yet.
1 reading headers
2 headers read, have not sent reply
3 sent reply
4 closed
*/
JNL_HTTPUServ::JNL_HTTPUServ()
{
m_reply_headers=0;
m_reply_string=0;
m_recv_request=0;
m_errstr=0;
m_reply_ready=0;
m_method = 0;
http_ver = 0;
}
JNL_HTTPUServ::~JNL_HTTPUServ()
{
free(m_recv_request);
free(m_reply_string);
free(m_reply_headers);
free(m_errstr);
free(m_method);
}
static size_t strlen_whitespace(const char *str)
{
size_t size=0;
while (str && *str && *str != ' ' && *str != '\r' && *str!='\n')
{
str++;
size++;
}
return size;
}
int JNL_HTTPUServ::process(JNL_UDPConnection *m_con)
{ // returns: < 0 on error, 0 on connection close, 1 if reading request, 2 if reply not sent, 3 if reply sent, sending data.
reset();
if (m_con->get_state()==JNL_CONNECTION_STATE_ERROR)
{
seterrstr(m_con->get_errstr());
return -1;
}
if (m_con->get_state()==JNL_CONNECTION_STATE_CLOSED)
return 4;
if (m_con->recv_lines_available()>0)
{
char *buf=(char*)malloc(m_con->recv_bytes_available()-1);
m_con->recv_line(buf,m_con->recv_bytes_available()-1);
free(m_recv_request);
m_recv_request=(char*)malloc(strlen(buf)+2);
strcpy(m_recv_request,buf);
m_recv_request[strlen(m_recv_request)+1]=0;
free(buf);
buf=m_recv_request;
while (buf && *buf) buf++;
while (buf >= m_recv_request && *buf != ' ') buf--;
if (strncmp(buf+1,"HTTP",4))// || strncmp(m_recv_request,"GET ",3))
{
seterrstr("malformed HTTP request");
}
else
{
http_ver = atoi(buf+8);
size_t method_len = strlen_whitespace(m_recv_request);
m_method = (char *)malloc(method_len + 1);
if (m_method)
{
memcpy(m_method, m_recv_request, method_len);
m_method[method_len]=0;
}
else
{
seterrstr("malformed HTTP request");
return -1;
}
if (buf >= m_recv_request) buf[0]=buf[1]=0;
buf=strstr(m_recv_request,"?");
if (buf)
{
*buf++=0; // change &'s into 0s now.
char *t=buf;
int stat=1;
while (t && *t)
{
if (*t == '&' && !stat) { stat=1; *t=0; }
else stat=0;
t++;
}
}
}
}
else
{
seterrstr("malformed HTTP request");
return -1;
}
while (m_con->recv_lines_available()>0)
{
char buf[8192] = {0};
m_con->recv_line(buf, 8192);
if (!buf[0])
break;
recvheaders.Add(buf);
}
return NErr_Success;
}
void JNL_HTTPUServ::send_reply(JNL_UDPConnection *m_con)
{
m_con->send_string((char*)(m_reply_string?m_reply_string:"HTTP/1.1 200 OK"));
m_con->send_string("\r\n");
if (m_reply_headers) m_con->send_string(m_reply_headers);
m_con->send_string("\r\n");
}
const char *JNL_HTTPUServ::get_request_uri()
{
// file portion of http request
if (!m_recv_request) return NULL;
char *t=m_recv_request;
while (t && *t && *t != ' ') t++;
if (!t || !*t) return NULL;
while (t && *t && *t == ' ') t++;
return t;
}
const char *JNL_HTTPUServ::get_request_parm(const char *parmname) // parameter portion (after ?)
{
const char *t=m_recv_request;
while (*t) t++;
t++;
while (t && *t)
{
while (t && *t && *t == '&') t++;
if (!strncasecmp(t,parmname,strlen(parmname)) && t[strlen(parmname)] == '=')
{
return t+strlen(parmname)+1;
}
t+=strlen(t)+1;
}
return NULL;
}
const char *JNL_HTTPUServ::getheader(const char *headername)
{
return recvheaders.GetHeader(headername);
}
void JNL_HTTPUServ::set_reply_string(const char *reply_string) // should be HTTP/1.1 OK or the like
{
free(m_reply_string);
m_reply_string=(char*)malloc(strlen(reply_string)+1);
strcpy(m_reply_string,reply_string);
}
void JNL_HTTPUServ::set_reply_header(const char *header) // "Connection: close" for example
{
if (m_reply_headers)
{
char *tmp=(char*)malloc(strlen(m_reply_headers)+strlen(header)+3);
strcpy(tmp,m_reply_headers);
strcat(tmp,header);
strcat(tmp,"\r\n");
free(m_reply_headers);
m_reply_headers=tmp;
}
else
{
m_reply_headers=(char*)malloc(strlen(header)+3);
strcpy(m_reply_headers,header);
strcat(m_reply_headers,"\r\n");
}
}
void JNL_HTTPUServ::reset()
{
free(m_recv_request); m_recv_request = 0;
free(m_reply_string); m_reply_string = 0;
free(m_reply_headers); m_reply_headers = 0;
free(m_errstr); m_errstr = 0;
free(m_method); m_method =0;
recvheaders.Reset();
m_reply_ready=0;
}
+55
View File
@@ -0,0 +1,55 @@
/*
** JNetLib
** Copyright (C) 2012 Nullsoft, Inc.
** Author: Ben Allison
** File: httpuserv.h - JNL interface for doing HTTPU (HTTP over UDP)
** This is half-baked so far. Need to think things through a touch more
*/
#pragma once
#include "udpconnection.h"
#include "headers.h"
class JNL_HTTPUServ
{
public:
JNL_HTTPUServ();
~JNL_HTTPUServ();
// pass this a connection that has just received a packet
int process( JNL_UDPConnection *m_con );
const char *geterrorstr() { return m_errstr; }
// use these when state returned by run() is 2
const char *get_request_uri(); // file portion of http request
const char *get_request_parm( const char *parmname ); // parameter portion (after ?)
const char *getallheaders() { return recvheaders.GetAllHeaders(); } // double null terminated, null delimited list
const char *getheader( const char *headername );
const char *get_method() { return m_method; }
void set_reply_string( const char *reply_string ); // should be HTTP/1.1 OK or the like
void set_reply_header( const char *header ); // i.e. "content-size: 12345"
void send_reply( JNL_UDPConnection *m_con ); // sends a reply to the given UDP socket. it must have been setup beforehand with the appropriate peer
void reset(); // prepare for another request
int get_http_version() { return http_ver; }
protected:
void seterrstr( const char *str ) { if ( m_errstr ) free( m_errstr ); m_errstr = _strdup( str ); }
int m_reply_ready;
int http_ver;
char *m_errstr;
char *m_reply_headers;
char *m_reply_string;
JNL_Headers recvheaders;
char *m_recv_request; // either double-null terminated, or may contain parameters after first null.
char *m_method;
};
@@ -0,0 +1,76 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (U.K.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.K.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
@@ -0,0 +1,491 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="jnetlib-replicant"
ProjectGUID="{AAE8BF3C-AD6B-405C-A216-BF62E2D49E95}"
RootNamespace="jnetlib"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..;../../openssl/include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;USE_SSL"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
DisableSpecificWarnings="4995;4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
OutputFile="$(ProgramFiles)\Winamp\Shared\jnetlib.dll"
LinkIncremental="2"
GenerateManifest="false"
IgnoreDefaultLibraryNames="msvcprt.lib"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb"
SubSystem="2"
ImportLibrary="$(IntDir)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="1"
FavorSizeOrSpeed="2"
AdditionalIncludeDirectories="..;../../openssl/include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;USE_SSL;WIN32_LEAN_AND_MEAN"
StringPooling="true"
RuntimeLibrary="2"
BufferSecurityCheck="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
DisableSpecificWarnings="4995;4996;4244"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
OutputFile="$(ProgramFiles)\Winamp\Shared\jnetlib.dll"
LinkIncremental="1"
GenerateManifest="false"
IgnoreDefaultLibraryNames="msvcprt.lib"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/$(TargetName).pdb"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
ImportLibrary="$(IntDir)\$(TargetName).lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..;../../openssl/include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;USE_SSL"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
DisableSpecificWarnings="4995;4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
OutputFile="$(ProgramFiles)\Winamp\Shared\jnetlib.dll"
LinkIncremental="2"
GenerateManifest="false"
IgnoreDefaultLibraryNames="msvcprt.lib"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb"
SubSystem="2"
ImportLibrary="$(IntDir)\$(TargetName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="1"
FavorSizeOrSpeed="2"
AdditionalIncludeDirectories="..;../../openssl/include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;USE_SSL;WIN32_LEAN_AND_MEAN"
StringPooling="true"
RuntimeLibrary="2"
BufferSecurityCheck="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
DisableSpecificWarnings="4995;4996;4244"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
OutputFile="$(ProgramFiles)\Winamp\Shared\jnetlib.dll"
LinkIncremental="1"
GenerateManifest="false"
IgnoreDefaultLibraryNames="msvcprt.lib"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/$(TargetName).pdb"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
ImportLibrary="$(IntDir)\$(TargetName).lib"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
<ProjectReference
ReferencedProjectIdentifier="{EFC75A79-269F-44FC-BAC5-D7D4FD4EC92C}"
RelativePathToProject="..\replicant\nu\nu.vcproj"
/>
<ProjectReference
ReferencedProjectIdentifier="{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}"
RelativePathToProject="..\replicant\zlib\zlib.vcproj"
/>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\asyncdns.cpp"
>
</File>
<File
RelativePath=".\connection.cpp"
>
</File>
<File
RelativePath=".\headers.cpp"
>
</File>
<File
RelativePath=".\httpget.cpp"
>
</File>
<File
RelativePath=".\httpserv.cpp"
>
</File>
<File
RelativePath=".\httpuserv.cpp"
>
</File>
<File
RelativePath=".\jnetlib.cpp"
>
</File>
<File
RelativePath=".\listen.cpp"
>
</File>
<File
RelativePath=".\multicastlisten.cpp"
>
</File>
<File
RelativePath=".\sslconnection.cpp"
>
</File>
<File
RelativePath=".\udpconnection.cpp"
>
</File>
<File
RelativePath=".\util.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\asyncdns.h"
>
</File>
<File
RelativePath=".\connection.h"
>
</File>
<File
RelativePath=".\headers.h"
>
</File>
<File
RelativePath=".\httpget.h"
>
</File>
<File
RelativePath=".\httpserv.h"
>
</File>
<File
RelativePath=".\httpuserv.h"
>
</File>
<File
RelativePath=".\jnetlib.h"
>
</File>
<File
RelativePath=".\listen.h"
>
</File>
<File
RelativePath=".\multicastlisten.h"
>
</File>
<File
RelativePath=".\netinc.h"
>
</File>
<File
RelativePath=".\precomp.h"
>
</File>
<File
RelativePath=".\sslconnection.h"
>
</File>
<File
RelativePath=".\udpconnection.h"
>
</File>
<File
RelativePath=".\util.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
>
<File
RelativePath=".\jnetlib-replicant.rc"
>
</File>
<File
RelativePath=".\resource.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+630
View File
@@ -0,0 +1,630 @@
#include "jnetlib.h"
#include "httpget.h"
#include "sslconnection.h"
#include "asyncdns.h"
#include "util.h"
#include "httpserv.h"
#include "httpuserv.h"
#include "listen.h"
#include "multicastlisten.h"
#include "foundation/error.h"
#include <new>
int jnl_init()
{
return JNL::open_socketlib();
}
void jnl_quit()
{
JNL::close_socketlib();
}
/* --- Connection --- */
jnl_connection_t jnl_connection_create(jnl_dns_t dns, size_t sendbufsize, size_t recvbufsize)
{
JNL_Connection *connection = new (std::nothrow) JNL_Connection((JNL_AsyncDNS *)dns, sendbufsize, recvbufsize);
return (jnl_connection_t)connection;
}
jnl_connection_t jnl_sslconnection_create(jnl_dns_t dns, size_t sendbufsize, size_t recvbufsize)
{
JNL_SSL_Connection *connection = new (std::nothrow) JNL_SSL_Connection(NULL, (JNL_AsyncDNS *)dns, sendbufsize, recvbufsize);
return (jnl_connection_t)connection;
}
void jnl_connection_run(jnl_connection_t _connection, size_t max_send_bytes, size_t max_receive_bytes, size_t *bytes_sent, size_t *bytes_received)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
connection->run(max_send_bytes, max_receive_bytes, bytes_sent, bytes_received);
}
int jnl_connection_get_state(jnl_connection_t _connection)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
return connection->get_state();
}
size_t jnl_connection_send_bytes_available(jnl_connection_t _connection)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
return connection->send_bytes_available();
}
size_t jnl_connection_receive_bytes_available(jnl_connection_t _connection)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
return connection->recv_bytes_available();
}
int jnl_connection_send(jnl_connection_t _connection, const void *bytes, size_t size)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
return connection->send(bytes, size);
}
JNL_API int jnl_connection_send_string(jnl_connection_t _connection, const char *str)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
return connection->send_string(str);
}
size_t jnl_connection_send_bytes_in_queue(jnl_connection_t _connection)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
return connection->send_bytes_in_queue();
}
size_t jnl_connection_receive(jnl_connection_t _connection, void *bytes, size_t size)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
return connection->recv_bytes(bytes, size);
}
size_t jnl_connection_peek(jnl_connection_t _connection, void *bytes, size_t size)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
return connection->peek_bytes(bytes, size);
}
void jnl_connection_release(jnl_connection_t _connection)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
if (connection)
connection->Release();
}
int jnl_connection_receive_line(jnl_connection_t _connection, void *bytes, size_t size)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
return connection->recv_line((char *)bytes, size);
}
size_t jnl_connection_receive_lines_available(jnl_connection_t _connection)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
return connection->recv_lines_available();
}
void jnl_connection_close(jnl_connection_t _connection, int fast)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
connection->close(fast);
}
void jnl_connection_connect(jnl_connection_t _connection, const char *hostname, int port)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
connection->connect(hostname, port);
}
const char *jnl_connection_get_error(jnl_connection_t _connection)
{
JNL_Connection *connection = (JNL_Connection *)_connection;
return connection->get_errstr();
}
/* ---- UDP ----- */
int jnl_udp_create_multicast_listener(jnl_udp_t *connection, const char *mcast_ip, unsigned short port)
{
JNL_UDPConnection *udp = 0;
JNL::open_socketlib(); // TODO: cut
int ret = CreateMulticastListener(&udp, mcast_ip, port);
if (ret != NErr_Success)
{
JNL::close_socketlib(); // TODO: cut
return ret;
}
*connection = (jnl_udp_t)udp;
return NErr_Success;
}
void jnl_udp_release(jnl_udp_t _connection)
{
JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
delete connection; // TODO: reference count
JNL::close_socketlib(); // TODO: cut
}
void jnl_udp_run(jnl_udp_t _connection, size_t max_send_bytes, size_t max_recv_bytes, size_t *bytes_sent, size_t *bytes_rcvd)
{
JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
if (connection)
{
connection->run(max_send_bytes, max_recv_bytes, bytes_sent, bytes_rcvd);
}
}
size_t jnl_udp_recv_bytes(jnl_udp_t _connection, void *buf, size_t len)
{
JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
if (connection)
{
return connection->recv_bytes(buf, len);
}
else
return 0;
}
int jnl_udp_send(jnl_udp_t _connection, const void *bytes, size_t size)
{
JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
return connection->send(bytes, size);
}
void jnl_udp_set_peer(jnl_udp_t _connection, const char *hostname, unsigned short port)
{
JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
connection->setpeer(hostname, port);
}
void jnl_udp_set_peer_address(jnl_udp_t _connection, sockaddr *addr, socklen_t length)
{
JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
connection->setpeer(addr, length);
}
int jnl_udp_get_address(jnl_udp_t _connection, sockaddr **addr, socklen_t *length)
{
JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
connection->get_last_recv_msg_addr(addr, length);
return NErr_Success;
}
/* ---- HTTP ---- */
jnl_http_t jnl_http_create(int recvbufsize, int sendbufsize)
{
JNL_HTTPGet *http = new (std::nothrow) JNL_HTTPGet(recvbufsize, sendbufsize);
return (jnl_http_t)http;
}
int jnl_http_set_recv_buffer_size(jnl_http_t _http, size_t new_size)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->set_recv_buffer_size(new_size);
}
int jnl_http_run(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->run();
}
size_t jnl_http_get_bytes(jnl_http_t _http, void *buf, size_t len)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->get_bytes(static_cast<char *>(buf), len);
}
size_t jnl_http_peek_bytes(jnl_http_t _http, void *buf, size_t len)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->peek_bytes(static_cast<char *>(buf), len);
}
size_t jnl_http_bytes_available(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->bytes_available();
}
uint64_t jnl_http_content_length(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->content_length();
}
int jnl_http_get_status(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->get_status();
}
int jnl_http_getreplycode(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->getreplycode();
}
const char *jnl_http_getreply(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->getreply();
}
const char *jnl_http_getheader(jnl_http_t _http, const char *header)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->getheader(header);
}
const char *jnl_http_get_all_headers(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->getallheaders();
}
void jnl_http_addheader(jnl_http_t _http, const char *header)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
http->addheader(header);
}
void jnl_http_addheadervalue(jnl_http_t _http, const char *header, const char *value)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
http->addheadervalue(header, value);
}
void jnl_http_connect(jnl_http_t _http, const char *url, int http_version, const char *method)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
http->connect(url, http_version, method);
}
void jnl_http_release(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
if (http)
http->Release();
}
jnl_http_t jnl_http_retain(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
if (http)
http->Retain();
return _http;
}
const char *jnl_http_get_url(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return http->get_url();
}
void jnl_http_reset_headers(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
http->reset_headers();
}
void jnl_http_set_persistent(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
http->set_persistent();
}
void jnl_http_allow_compression(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
http->AllowCompression();
}
void jnl_http_allow_accept_all_reply_codes(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
http->set_accept_all_reply_codes();
}
jnl_connection_t jnl_http_get_connection(jnl_http_t _http)
{
JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
return (jnl_connection_t)http->get_con();
}
void jnl_http_set_proxy(const char *proxy)
{
JNL_HTTPGet::set_proxy(proxy);
}
/* ------- HTTP Request Parser ------- */
int jnl_http_request_create(jnl_http_request_t *_http, jnl_connection_t _connection)
{
JNL_HTTPServ *http = new (std::nothrow) JNL_HTTPServ((JNL_Connection *)_connection);;
if (!http)
return NErr_OutOfMemory;
*_http = (jnl_http_request_t) http;
return NErr_Success;
}
void jnl_http_request_release(jnl_http_request_t _http)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
if (http)
http->Release();
}
int jnl_http_request_run(jnl_http_request_t _http)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
return http->run();
}
int jnl_htt_request_get_keep_alive(jnl_http_request_t _http)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
return http->get_keep_alive();
}
const char *jnl_http_request_get_header(jnl_http_request_t _http, const char *header)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
return http->getheader(header);
}
void jnl_http_request_reset(jnl_http_request_t _http)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
http->reset();
}
void jnl_http_request_addheader(jnl_http_request_t _http, const char *header)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
http->add_reply_header(header);
}
void jnl_http_request_set_reply_string(jnl_http_request_t _http, const char *reply)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
http->set_reply_string(reply);
}
void jnl_http_request_send_reply(jnl_http_request_t _http)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
http->send_reply();
}
const char *jnl_http_request_get_uri(jnl_http_request_t _http)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
return http->get_request_file();
}
const char *jnl_http_request_get_parameter(jnl_http_request_t _http, const char *parameter)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
return http->get_request_parm(parameter);
}
jnl_connection_t jnl_http_request_get_connection(jnl_http_request_t _http)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
JNL_Connection *connection = http->get_con();
if (connection)
{
connection->Retain();
return (jnl_connection_t)connection;
}
else
return 0;
}
const char *jnl_http_request_get_method(jnl_http_request_t _http)
{
JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
return http->get_method();
}
/* ------- HTTPU Request Parser ------- */
int jnl_httpu_request_create(jnl_httpu_request_t *_httpu)
{
JNL_HTTPUServ *httpu = new (std::nothrow) JNL_HTTPUServ;
if (!httpu)
return NErr_OutOfMemory;
*_httpu = (jnl_httpu_request_t) httpu;
return NErr_Success;
}
void jnl_httpu_request_release(jnl_httpu_request_t _httpu)
{
JNL_HTTPUServ *httpu = (JNL_HTTPUServ *)_httpu;
delete httpu; // TODO: reference count
}
int jnl_httpu_request_process(jnl_httpu_request_t _httpu, jnl_udp_t _udp)
{
JNL_HTTPUServ *httpu = (JNL_HTTPUServ *)_httpu;
return httpu->process((JNL_UDPConnection *)_udp);
}
const char *jnl_httpu_request_get_method(jnl_httpu_request_t _httpu)
{
JNL_HTTPUServ *httpu = (JNL_HTTPUServ *)_httpu;
return httpu->get_method();
}
const char *jnl_httpu_request_get_uri(jnl_httpu_request_t _httpu)
{
JNL_HTTPUServ *httpu = (JNL_HTTPUServ *)_httpu;
return httpu->get_request_uri();
}
const char *jnl_httpu_request_get_header(jnl_httpu_request_t _httpu, const char *header)
{
JNL_HTTPUServ *httpu = (JNL_HTTPUServ *)_httpu;
return httpu->getheader(header);
}
/* ----- DNS ----- */
int jnl_dns_create(jnl_dns_t *out_dns)
{
JNL_AsyncDNS *dns = new (std::nothrow)JNL_AsyncDNS;
if (!dns)
return NErr_OutOfMemory;
*out_dns = (jnl_dns_t)dns;
return NErr_Success;
}
void jnl_dns_release(jnl_dns_t _dns)
{
JNL_AsyncDNS *dns = (JNL_AsyncDNS *)_dns;
delete dns; // TODO: reference counting
}
int jnl_dns_resolve(jnl_dns_t _dns, const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
{
JNL_AsyncDNS *dns = (JNL_AsyncDNS *)_dns;
int ret = dns->resolve(hostname, port, addr, sockettype);
if (ret == 0)
return NErr_Success;
else if (ret == -1)
return NErr_TryAgain;
else
return NErr_Unknown;
}
int jnl_dns_resolve_now(const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
{
int ret = JNL_AsyncDNS::resolvenow(hostname, port, addr, sockettype);
if (ret == 0)
return NErr_Success;
else
return NErr_Unknown;
}
void jnl_dns_freeaddrinfo(addrinfo *addr)
{
freeaddrinfo(addr);
}
void jnl_dns_gethostname(char *name, size_t cch)
{
gethostname(name, (int)cch);
}
#ifdef _WIN32
PCSTR WSAAPI inet_ntop_xp(INT af, PVOID src, PSTR dst, size_t cnt)
{
struct sockaddr_in srcaddr;
memset(&srcaddr, 0, sizeof(struct sockaddr_in));
memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
srcaddr.sin_family = af;
if (WSAAddressToStringA((struct sockaddr*) &srcaddr, sizeof(struct sockaddr_in), 0, dst, (LPDWORD) &cnt) != 0) {
return NULL;
}
return dst;
}
PCSTR WSAAPI inet_ntop_win32(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize) {
typedef PCSTR (WSAAPI * win32_inet_ntop)(INT, PVOID, PSTR, size_t);
static win32_inet_ntop pwin32_inet_ntop = NULL;
if (!pwin32_inet_ntop){
HMODULE hlib = LoadLibrary(L"WS2_32.DLL");
pwin32_inet_ntop = (win32_inet_ntop)GetProcAddress(hlib, "inet_ntop");
if (!pwin32_inet_ntop) {
pwin32_inet_ntop = inet_ntop_xp;
}
}
return (*pwin32_inet_ntop)(Family, pAddr, pStringBuf, StringBufSize);
}
#endif
void jnl_dns_ntop(int af, const void *src, char *dst, socklen_t size)
{
#ifdef _WIN32
// TODO need to revist this at a later date
// [22:01:08] audiodsp: i will make a tweak for IPv6 compatability at some point
// [22:01:49] audiodsp: just change references from sockaddr_in to sockaddr_storage
// [22:02:24] audiodsp: keep it as is
// [22:02:32] audiodsp: we're only using it in IPv4 mode at the moment
// [22:02:40] audiodsp: i will fix when we need IPv6 server support
// [22:03:58] audiodsp: the memcpy is what makes it non-trivial
// [22:04:05] audiodsp: i have to switch on family and do different memcpy's accordingly
// [22:04:16] audiodsp: or change the method to require a length
// [22:04:19] audiodsp: which makes more sense
// [22:04:29] audiodsp: and just not pass it to the linux function
// [22:05:08] audiodsp: anyway not important.
inet_ntop_win32(af, (PVOID)src, dst, size);
#else
inet_ntop(af, src, dst, size);
#endif
}
/* Listen */
int jnl_listen_create(jnl_listen_t *_listen, unsigned short port)
{
JNL_Listen *l = new (std::nothrow) JNL_Listen();
if (!l)
return NErr_OutOfMemory;
int ret = l->Initialize(port);
if (ret != NErr_Success)
{
delete l;
return ret;
}
*_listen = (jnl_listen_t)l;
return NErr_Success;
}
int jnl_listen_create_from_address(jnl_listen_t *_listen, struct addrinfo *addr, size_t index)
{
JNL_Listen *l = new (std::nothrow) JNL_Listen();
if (!l)
return NErr_OutOfMemory;
int ret = l->Initialize(addr, index);
if (ret != NErr_Success)
{
delete l;
return ret;
}
*_listen = (jnl_listen_t)l;
return NErr_Success;
}
jnl_connection_t jnl_listen_get_connection(jnl_listen_t _listen)
{
JNL_Listen *listen = (JNL_Listen *)_listen;
JNL_Connection *connection = listen->get_connect();
return (jnl_connection_t)connection;
}
unsigned short jnl_listen_get_port(jnl_listen_t _listen)
{
JNL_Listen *listen = (JNL_Listen *)_listen;
return listen->get_port();
}
void jnl_listen_release(jnl_listen_t _listen)
{
JNL_Listen *listen = (JNL_Listen *)_listen;
if (listen)
listen->Release();
}
+177
View File
@@ -0,0 +1,177 @@
/*
** JNetLib
** Copyright (C) 2000-2006 Nullsoft, Inc.
** Author: Justin Frankel
** File: jnetlib.h - JNL main include file (not really necessary).
**
** For documentation, look at the following files:
** Generic network initialization: netinc.h
** DNS: asyncdns.h
** TCP connections: connection.h
** HTTP GET connections: httpget.h
** TCP listen: listen.h
**
** license:
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
**
*/
#ifndef _JNETLIB_H_
#define _JNETLIB_H_
#include "netinc.h"
#include "../foundation/types.h"
#include "jnetlib_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _MSC_VER
#ifdef JNETLIB_EXPORTS
#define JNL_API __declspec(dllexport)
#else
#define JNL_API __declspec(dllimport)
#endif
#elif defined(__ANDROID__) || defined(__APPLE__)
#define JNL_API __attribute__ ((visibility("default")))
#elif defined(__linux__)
#if __GNUC__ >= 4
#define JNL_API __attribute__ ((visibility ("default")))
#else
#define JNL_API
#endif
#else
#error port me
#endif
/* these are reference counted. so make sure to match init/quit calls. */
JNL_API int jnl_init();
JNL_API void jnl_quit();
/* ----- Connection ----- */
JNL_API jnl_connection_t jnl_connection_create( jnl_dns_t dns, size_t sendbufsize, size_t recvbufsize );
JNL_API jnl_connection_t jnl_sslconnection_create( jnl_dns_t dns, size_t sendbufsize, size_t recvbufsize );
JNL_API void jnl_connection_run( jnl_connection_t connection, size_t max_send_bytes, size_t max_receive_bytes, size_t *bytes_sent, size_t *bytes_received );
JNL_API int jnl_connection_get_state( jnl_connection_t connection );
JNL_API size_t jnl_connection_send_bytes_available( jnl_connection_t connection );
JNL_API size_t jnl_connection_receive_bytes_available( jnl_connection_t connection );
JNL_API int jnl_connection_receive_line( jnl_connection_t _connection, void *bytes, size_t size );
JNL_API int jnl_connection_send( jnl_connection_t connection, const void *bytes, size_t size );
JNL_API int jnl_connection_send_string( jnl_connection_t connection, const char *str );
JNL_API size_t jnl_connection_receive( jnl_connection_t connection, void *bytes, size_t size );
JNL_API size_t jnl_connection_send_bytes_in_queue( jnl_connection_t connection );
JNL_API void jnl_connection_release( jnl_connection_t connection );
JNL_API size_t jnl_connection_receive_lines_available( jnl_connection_t connection );
JNL_API void jnl_connection_close( jnl_connection_t _connection, int fast );
JNL_API void jnl_connection_connect( jnl_connection_t connection, const char *hostname, int port );
JNL_API const char *jnl_connection_get_error( jnl_connection_t connection );
JNL_API size_t jnl_connection_peek( jnl_connection_t _connection, void *bytes, size_t size );
/* ----- UDP ----- */
JNL_API int jnl_udp_create_multicast_listener( jnl_udp_t *connection, const char *mcast_ip, unsigned short port );
JNL_API void jnl_udp_release( jnl_udp_t connection );
JNL_API void jnl_udp_run( jnl_udp_t connection, size_t max_send_bytes, size_t max_recv_bytes, size_t *bytes_sent, size_t *bytes_rcvd );
JNL_API size_t jnl_udp_recv_bytes( jnl_udp_t connection, void *buf, size_t len );
JNL_API int jnl_udp_send( jnl_udp_t connection, const void *bytes, size_t size );
JNL_API void jnl_udp_set_peer( jnl_udp_t connection, const char *hostname, unsigned short port );
JNL_API void jnl_udp_set_peer_address( jnl_udp_t connection, struct sockaddr *addr, socklen_t length );
// gets the address of whomever sent the last message
JNL_API int jnl_udp_get_address( jnl_udp_t connection, struct sockaddr **addr, socklen_t *length );
/* ----- HTTP ----- */
/* creation/destruction */
JNL_API jnl_http_t jnl_http_create( int recvbufsize, int sendbufsize );
JNL_API int jnl_http_set_recv_buffer_size( jnl_http_t http, size_t new_size ); /* increases the receive buffer size */
JNL_API jnl_http_t jnl_http_retain( jnl_http_t http );
JNL_API void jnl_http_release( jnl_http_t http );
JNL_API jnl_connection_t jnl_http_get_connection( jnl_http_t http );
/* TODO: replace these with a jnl_http_configure(jnl_http_t http) function */
JNL_API void jnl_http_set_persistent( jnl_http_t http );
JNL_API void jnl_http_allow_compression( jnl_http_t http );
JNL_API void jnl_http_allow_accept_all_reply_codes( jnl_http_t http );
/* run & status stuff */
JNL_API void jnl_http_connect( jnl_http_t http, const char *url, int http_version, const char *method );
JNL_API int jnl_http_run( jnl_http_t http );
JNL_API int jnl_http_get_status( jnl_http_t http );
JNL_API int jnl_http_getreplycode( jnl_http_t http );
JNL_API const char *jnl_http_getreply( jnl_http_t http );
/* reading data */
JNL_API size_t jnl_http_get_bytes( jnl_http_t http, void *buf, size_t len );
JNL_API size_t jnl_http_peek_bytes( jnl_http_t http, void *buf, size_t len );
JNL_API size_t jnl_http_bytes_available( jnl_http_t http );
JNL_API uint64_t jnl_http_content_length( jnl_http_t http );
/* HTTP headers */
JNL_API const char *jnl_http_getheader( jnl_http_t http, const char *header );
JNL_API void jnl_http_addheader( jnl_http_t http, const char *header );
JNL_API void jnl_http_addheadervalue( jnl_http_t http, const char *header, const char *value );
JNL_API void jnl_http_reset_headers( jnl_http_t http );
JNL_API const char *jnl_http_get_all_headers( jnl_http_t http );
/* other information */
JNL_API const char *jnl_http_get_url( jnl_http_t http );
JNL_API void jnl_http_set_proxy( const char *proxy );
/* ----- HTTP Request Parsing ----- */
JNL_API int jnl_http_request_create( jnl_http_request_t *http, jnl_connection_t connection );
JNL_API void jnl_http_request_release( jnl_http_request_t http );
JNL_API int jnl_http_request_run( jnl_http_request_t http );
JNL_API int jnl_htt_request_get_keep_alive( jnl_http_request_t http );
JNL_API const char *jnl_http_request_get_header( jnl_http_request_t http, const char *header );
JNL_API void jnl_http_request_reset( jnl_http_request_t http );
JNL_API void jnl_http_request_addheader( jnl_http_request_t http, const char *header );
JNL_API void jnl_http_request_set_reply_string( jnl_http_request_t http, const char *reply );
JNL_API void jnl_http_request_send_reply( jnl_http_request_t http );
JNL_API const char *jnl_http_request_get_uri( jnl_http_request_t http );
JNL_API const char *jnl_http_request_get_parameter( jnl_http_request_t _http, const char *parameter );
JNL_API jnl_connection_t jnl_http_request_get_connection( jnl_http_request_t http );
JNL_API const char *jnl_http_request_get_method( jnl_http_request_t http );
/* ----- HTTPU Request Parsing ----- */
JNL_API int jnl_httpu_request_create( jnl_httpu_request_t *httpu );
JNL_API void jnl_httpu_request_release( jnl_httpu_request_t httpu );
JNL_API int jnl_httpu_request_process( jnl_httpu_request_t httpu, jnl_udp_t udp );
JNL_API const char *jnl_httpu_request_get_method( jnl_httpu_request_t httpu );
JNL_API const char *jnl_httpu_request_get_uri( jnl_httpu_request_t httpu );
JNL_API const char *jnl_httpu_request_get_header( jnl_httpu_request_t httpu, const char *header );
/* ----- DNS ------ */
JNL_API int jnl_dns_create( jnl_dns_t *dns );
JNL_API void jnl_dns_release( jnl_dns_t dns );
JNL_API int jnl_dns_resolve( jnl_dns_t dns, const char *hostname, unsigned short port, struct addrinfo **addr, int sockettype );
// when you call jnl_dns_resolve_now, you need to call jnl_dns_freeaddrinfo
JNL_API int jnl_dns_resolve_now( const char *hostname, unsigned short port, struct addrinfo **addr, int sockettype );
JNL_API void jnl_dns_freeaddrinfo( struct addrinfo *addr );
JNL_API void jnl_dns_gethostname( char *name, size_t cch );
JNL_API void jnl_dns_ntop( int af, const void *src, char *dst, socklen_t size );
/* listen */
JNL_API int jnl_listen_create( jnl_listen_t *listen, unsigned short port );
JNL_API int jnl_listen_create_from_address( jnl_listen_t *listen, struct addrinfo *addr, size_t index );
JNL_API void jnl_listen_release( jnl_listen_t listen );
JNL_API jnl_connection_t jnl_listen_get_connection( jnl_listen_t listen );
JNL_API unsigned short jnl_listen_get_port( jnl_listen_t listen );
#ifdef __cplusplus
}
#endif
#endif//_JNETLIB_H_
+54
View File
@@ -0,0 +1,54 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29509.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jnetlib", "jnetlib.vcxproj", "{E105A0A2-7391-47C5-86AC-718003524C3D}"
ProjectSection(ProjectDependencies) = postProject
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nu", "..\nu\nu.vcxproj", "{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\zlib\zlib.vcxproj", "{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.ActiveCfg = Debug|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.Build.0 = Debug|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.ActiveCfg = Debug|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.Build.0 = Debug|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.ActiveCfg = Release|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.Build.0 = Release|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.ActiveCfg = Release|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.Build.0 = Release|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.ActiveCfg = Debug|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.Build.0 = Debug|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.ActiveCfg = Debug|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.Build.0 = Debug|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.ActiveCfg = Release|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.Build.0 = Release|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.ActiveCfg = Release|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.Build.0 = Release|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.ActiveCfg = Debug|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.Build.0 = Debug|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.ActiveCfg = Debug|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.Build.0 = Debug|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.ActiveCfg = Release|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.Build.0 = Release|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.ActiveCfg = Release|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C4E799C1-027B-487B-8E1A-31F2D26A1AFE}
EndGlobalSection
EndGlobal
+281
View File
@@ -0,0 +1,281 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{E105A0A2-7391-47C5-86AC-718003524C3D}</ProjectGuid>
<RootNamespace>jnetlib</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalDependencies>ws2_32.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalDependencies>ws2_32.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>ws2_32.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>ws2_32.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="asyncdns.cpp" />
<ClCompile Include="connection.cpp" />
<ClCompile Include="Headers.cpp" />
<ClCompile Include="httpget.cpp" />
<ClCompile Include="httpserv.cpp" />
<ClCompile Include="httpuserv.cpp" />
<ClCompile Include="jnetlib.cpp" />
<ClCompile Include="listen.cpp" />
<ClCompile Include="multicastlisten.cpp" />
<ClCompile Include="sslconnection.cpp" />
<ClCompile Include="udpconnection.cpp" />
<ClCompile Include="util.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="asyncdns.h" />
<ClInclude Include="connection.h" />
<ClInclude Include="Headers.h" />
<ClInclude Include="httpget.h" />
<ClInclude Include="httpserv.h" />
<ClInclude Include="httpuserv.h" />
<ClInclude Include="jnetlib.h" />
<ClInclude Include="jnetlib_defines.h" />
<ClInclude Include="listen.h" />
<ClInclude Include="multicastlisten.h" />
<ClInclude Include="netinc.h" />
<ClInclude Include="sslconnection.h" />
<ClInclude Include="udpconnection.h" />
<ClInclude Include="util.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="jnetlib-replicant.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\nu\nu.vcxproj">
<Project>{f1f5cd60-0d5b-4cea-9eeb-2f87ff9aa915}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Headers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="jnetlib.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="multicastlisten.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="connection.cpp">
<Filter>Source Files\Connection</Filter>
</ClCompile>
<ClCompile Include="asyncdns.cpp">
<Filter>Source Files\DNS</Filter>
</ClCompile>
<ClCompile Include="sslconnection.cpp">
<Filter>Source Files\Connection</Filter>
</ClCompile>
<ClCompile Include="httpget.cpp">
<Filter>Source Files\HTTP Receiver</Filter>
</ClCompile>
<ClCompile Include="httpserv.cpp">
<Filter>Source Files\HTTP Server</Filter>
</ClCompile>
<ClCompile Include="udpconnection.cpp">
<Filter>Source Files\UDP Connection</Filter>
</ClCompile>
<ClCompile Include="listen.cpp">
<Filter>Source Files\Web Server</Filter>
</ClCompile>
<ClCompile Include="httpuserv.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Headers.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="httpuserv.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="jnetlib.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="jnetlib_defines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="netinc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="connection.h">
<Filter>Header Files\Connection</Filter>
</ClInclude>
<ClInclude Include="asyncdns.h">
<Filter>Header Files\DNS</Filter>
</ClInclude>
<ClInclude Include="sslconnection.h">
<Filter>Header Files\Connection</Filter>
</ClInclude>
<ClInclude Include="httpget.h">
<Filter>Header Files\HTTP Receiver</Filter>
</ClInclude>
<ClInclude Include="httpserv.h">
<Filter>Header Files\HTTP Server</Filter>
</ClInclude>
<ClInclude Include="listen.h">
<Filter>Header Files\Web Server</Filter>
</ClInclude>
<ClInclude Include="udpconnection.h">
<Filter>Header Files\UDP Connection</Filter>
</ClInclude>
<ClInclude Include="multicastlisten.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{bcdc816d-5cef-49ce-bcae-e765d84d9d0d}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{22cf6f69-c499-4eb0-851c-e405c0343744}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{ebc9b8af-fa9f-4cb3-bd28-a6f2fa43f47a}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Connection">
<UniqueIdentifier>{08aa3960-7673-4eee-a554-f75b30f6ca9d}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\DNS">
<UniqueIdentifier>{2194f281-7614-4fce-ae5b-14ebe64c75df}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\HTTP Receiver">
<UniqueIdentifier>{2a2b5cdf-93f4-4228-ab77-50138a1df782}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\HTTP Server">
<UniqueIdentifier>{c3f9a1b8-ab75-4d41-b614-df702b4a9113}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\UDP Connection">
<UniqueIdentifier>{080bb148-d8bc-41d5-b2a2-405b3068b15f}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Web Server">
<UniqueIdentifier>{2208b2ff-bd0e-42a9-b60b-fb6c1be6bad8}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Connection">
<UniqueIdentifier>{ab26ced4-713d-4b15-bea7-49219fe68955}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\DNS">
<UniqueIdentifier>{336ee3a1-044b-42c0-9f39-f03f381c73ee}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\HTTP Receiver">
<UniqueIdentifier>{b7051bc5-90cf-4673-8274-02c12e3da56c}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\HTTP Server">
<UniqueIdentifier>{48e64e69-bc76-467b-8fd3-3430694896ee}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Web Server">
<UniqueIdentifier>{ad8b2861-d8e2-4737-b293-124ad361f20c}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\UDP Connection">
<UniqueIdentifier>{60bab4c5-d369-4284-b314-dd8c3c4dcd37}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="jnetlib-replicant.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
+66
View File
@@ -0,0 +1,66 @@
#pragma once
#include "../foundation/types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Connection */
typedef struct jnl_connection_struct jnl_connection_struct;
typedef jnl_connection_struct *jnl_connection_t;
enum
{
JNL_CONNECTION_STATE_ERROR = 0,
JNL_CONNECTION_STATE_NOCONNECTION = 1,
JNL_CONNECTION_STATE_RESOLVING = 2,
JNL_CONNECTION_STATE_CONNECTING = 3,
JNL_CONNECTION_STATE_CONNECTED = 4,
JNL_CONNECTION_STATE_CLOSING = 5,
JNL_CONNECTION_STATE_CLOSED = 6,
JNL_CONNECTION_STATE_RESOLVED = 7, // happens after RESOLVING, but going here for compatability
};
/* UDP */
typedef struct jnl_udp_struct jnl_udp_struct;
typedef jnl_udp_struct *jnl_udp_t;
/* HTTP */
typedef struct jnl_http_struct jnl_http_struct;
typedef jnl_http_struct *jnl_http_t;
enum
{
HTTPGET_STATUS_ERROR = -1,
JNL_HTTP_STATUS_ERROR = HTTPGET_STATUS_ERROR,
HTTPGET_STATUS_CONNECTING = 0,
JNL_HTTP_STATUS_CONNECTING = HTTPGET_STATUS_CONNECTING,
HTTPGET_STATUS_READING_HEADERS = 1,
JNL_HTTP_STATUS_READING_HEADERS = HTTPGET_STATUS_READING_HEADERS,
HTTPGET_STATUS_READING_CONTENT = 2,
JNL_HTTP_STATUS_READING_CONTENT = HTTPGET_STATUS_READING_CONTENT,
};
enum
{
HTTPGET_RUN_ERROR = -1,
HTTPGET_RUN_OK = 0,
JNL_HTTP_RUN_OK = HTTPGET_RUN_OK,
HTTPGET_RUN_CONNECTION_CLOSED = 1,
};
/* DNS */
typedef struct jnl_dns_struct jnl_dns_struct;
typedef jnl_dns_struct *jnl_dns_t;
typedef struct jnl_httpu_request_struct jnl_httpu_request_struct;
typedef jnl_httpu_request_struct *jnl_httpu_request_t;
typedef struct jnl_http_request_struct jnl_http_request_struct;
typedef jnl_http_request_struct *jnl_http_request_t;
typedef struct jnl_listen_struct jnl_listen_struct;
typedef jnl_listen_struct *jnl_listen_t;
#ifdef __cplusplus
}
#endif
+131
View File
@@ -0,0 +1,131 @@
/*
** JNetLib
** Copyright (C) 2000-2013 Nullsoft, Inc.
** Author: Justin Frankel, Ben Allison
** File: listen.cpp - JNL TCP listen implementation
** License: see jnetlib.h
*/
#include "netinc.h"
#include "util.h"
#include "listen.h"
#include "foundation/error.h"
JNL_Listen::JNL_Listen()
{
m_port=0;
m_socket=-1;
}
int JNL_Listen::Initialize(unsigned short port, sockaddr *which_interface, int family)
{
m_port = port;
char portString[32] = {0};
sprintf(portString, "%d", (int)port);
addrinfo *res;
addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
hints.ai_addr = which_interface?which_interface:INADDR_ANY;
if (getaddrinfo(NULL, portString, &hints, &res) == 0)
{
int ret = Initialize(res, 0);
freeaddrinfo(res);
return ret;
}
else
{
return NErr_Error;
}
}
int JNL_Listen::Initialize(addrinfo *address, size_t index)
{
addrinfo *res = address;
while (index--)
{
res = res->ai_next;
if (!res)
return NErr_EndOfEnumeration;
}
m_socket = ::socket(res->ai_family,res->ai_socktype, res->ai_protocol);
if (m_socket < 0)
{
freeaddrinfo(res);
return NErr_Error;
}
else
{
SET_SOCK_BLOCK(m_socket,0);
#ifndef _WIN32
int bflag = 1;
setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &bflag, sizeof(bflag));
#endif
if (::bind(m_socket, res->ai_addr, (int)res->ai_addrlen))
{
closesocket(m_socket);
m_socket=-1;
return NErr_Error;
}
else if (::listen(m_socket,8)==-1)
{
closesocket(m_socket);
m_socket=-1;
return NErr_Error;
}
}
return NErr_Success;
}
JNL_Listen::~JNL_Listen()
{
if (m_socket>=0)
{
closesocket(m_socket);
}
}
JNL_Connection *JNL_Listen::get_connect(size_t sendbufsize, size_t recvbufsize)
{
if (m_socket < 0)
{
return NULL;
}
sockaddr_storage saddr;
socklen_t length = sizeof(saddr);
SOCKET s = accept(m_socket, (sockaddr *)&saddr, &length);
if (s != -1)
{
JNL_Connection *c=new JNL_Connection(NULL,sendbufsize, recvbufsize);
c->connect(s, (sockaddr *)&saddr, length);
return c;
}
return NULL;
}
socklen_t JNL_Listen::get_address(sockaddr* address, socklen_t *address_len)
{
return getsockname(m_socket, address, address_len);
}
unsigned short JNL_Listen::get_port()
{
if (!m_port)
{
sockaddr_in address;
socklen_t namelen = sizeof(address);
if (getsockname(m_socket, (sockaddr *)&address, &namelen) == 0)
m_port = ntohs(address.sin_port);
}
return m_port;
}
+44
View File
@@ -0,0 +1,44 @@
/*
** JNetLib
** Copyright (C) 2000-2013 Nullsoft, Inc.
** Author: Justin Frankel, Ben Allison
** File: listen.h - JNL interface for opening a TCP listen
** License: see jnetlib.h
**
** Usage:
** 1. create a JNL_Listen object with the port and (optionally) the interface
** to listen on.
** 2. call get_connect() to get any new connections (optionally specifying what
** buffer sizes the connection should be created with)
** 3. check is_error() to see if an error has occured
** 4. call port() if you forget what port the listener is on.
**
*/
#ifndef _LISTEN_H_
#define _LISTEN_H_
#include "connection.h"
#include "nswasabi/ReferenceCounted.h"
class JNL_Listen : public ReferenceCountedBase<JNL_Listen>
{
public:
JNL_Listen();
~JNL_Listen();
int Initialize( unsigned short port, sockaddr *which_interface = 0, int family = PF_UNSPEC );
int Initialize( struct addrinfo *address, size_t index );
JNL_Connection *get_connect( size_t sendbufsize = 8192, size_t recvbufsize = 8192 );
unsigned short get_port();
int is_error( void ) { return ( m_socket < 0 ); }
socklen_t get_address( sockaddr *address, socklen_t *address_len );
protected:
SOCKET m_socket;
unsigned short m_port;
};
#endif //_LISTEN_H_
+123
View File
@@ -0,0 +1,123 @@
/*
** JNetLib
** Copyright (C) 2008 Nullsoft, Inc.
** Author: Ben Allison
** File: multicastlisten.cpp - JNL Multicast UDP listen implementation
** License: see jnetlib.h
*/
#include "netinc.h"
#include "util.h"
#include "multicastlisten.h"
#include "foundation/error.h"
#include <new>
int CreateMulticastListener(JNL_UDPConnection **connection, const char *mcast_ip, unsigned short port, size_t sendbufsize, size_t recvbufsize)
{
char portString[32] = {0};
if (port)
sprintf(portString, "%d", (int)port);
addrinfo *res=0;
addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; /* IPv4 only for now until we get IPv6 multicast registration working */
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
hints.ai_protocol = IPPROTO_UDP;
if (getaddrinfo(NULL, port?portString:0, &hints, &res) == 0)
{
SOCKET m_socket = ::socket(res->ai_family,res->ai_socktype, res->ai_protocol);
if (m_socket < 0)
{
freeaddrinfo(res);
return NErr_Error;
}
else
{
SET_SOCK_BLOCK(m_socket,0);
int bflag = 1;
if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&bflag, sizeof(bflag)))
{
/*int err = ERRNO;
err=err;
printf("SO_REUSEADDR error: %d\n", err);*/
}
#if defined(__FreeBSD__) || defined(__APPLE__)
bflag=1; // in case it magically got unset above
setsockopt(m_socket, SOL_SOCKET, SO_REUSEPORT, (const char *)&bflag, sizeof(bflag));
#endif
if (::bind(m_socket, res->ai_addr, (int)res->ai_addrlen))
{
closesocket(m_socket);
return NErr_Error;
}
else
{
// TODO: ipv6 with IPV6_ADD_MEMBERSHIP and ipv6_mreq
sockaddr_in *ipv4 = (sockaddr_in *)res->ai_addr;
/* join multicast group */
ip_mreq ssdpMcastAddr;
memset(&ssdpMcastAddr, 0, sizeof(ssdpMcastAddr));
ssdpMcastAddr.imr_interface = ipv4->sin_addr;
ssdpMcastAddr.imr_multiaddr.s_addr = inet_addr(mcast_ip);
if (setsockopt(m_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&ssdpMcastAddr, sizeof(ssdpMcastAddr)))
{
closesocket(m_socket);
freeaddrinfo(res);
return NErr_Error;
}
/* Set multicast interface. */
in_addr addr;
memset(&addr, 0, sizeof(addr));
addr = ipv4->sin_addr;
if (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&addr, sizeof(addr)))
{
/*int err = ERRNO;
err=err;
printf("IP_MULTICAST_IF error: %d\n", err);*/
/* This is probably not a critical error, so let's continue. */
}
/* set TTL to 4 */
uint8_t ttl=4;
if (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&ttl, sizeof(ttl)))
{
/*int err = ERRNO;
err=err;
printf("IP_MULTICAST_TTL error: %d\n", err);*/
/* This is probably not a critical error, so let's continue. */
}
int option = 1;
if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (const char *)&option, sizeof(option)) != 0)
{
closesocket(m_socket);
freeaddrinfo(res);
return NErr_Error;
}
}
}
freeaddrinfo(res);
JNL_UDPConnection *c=new (std::nothrow) JNL_UDPConnection();
if (!c)
{
closesocket(m_socket);
return NErr_OutOfMemory;
}
c->open((int)m_socket, NULL, sendbufsize, recvbufsize);
*connection = c;
return NErr_Success;
}
else
{
return NErr_Error;
}
}

Some files were not shown because too many files have changed in this diff Show More