Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 28d20814f6 | |||
| 4c385f6e89 | |||
| 8708e04c0d | |||
| e47f3154a8 | |||
| 7062cdcf7c | |||
| bbe11292de | |||
| 2b51c69007 |
+1
-3
@@ -2,7 +2,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = "LFLiveKit"
|
||||
s.version = "1.9.0"
|
||||
s.version = "1.9.2"
|
||||
s.summary = "LaiFeng ios Live. LFLiveKit."
|
||||
s.homepage = "https://github.com/chenliming777"
|
||||
s.license = { :type => "MIT", :file => "LICENSE" }
|
||||
@@ -19,6 +19,4 @@ Pod::Spec.new do |s|
|
||||
s.requires_arc = true
|
||||
|
||||
s.dependency 'LMGPUImage', '~> 0.1.9'
|
||||
s.dependency "YYDispatchQueuePool"
|
||||
s.dependency "pili-librtmp", '1.0.3'
|
||||
end
|
||||
|
||||
@@ -46,6 +46,22 @@
|
||||
84001FFD1D0017680026C63F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84001FFC1D0017680026C63F /* AudioToolbox.framework */; };
|
||||
84001FFF1D00176C0026C63F /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84001FFE1D00176C0026C63F /* VideoToolbox.framework */; };
|
||||
840020011D0017850026C63F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 840020001D0017850026C63F /* libz.tbd */; };
|
||||
849005B01D4B5C8400D2A3D5 /* amf.c in Sources */ = {isa = PBXBuildFile; fileRef = 849005A01D4B5C8400D2A3D5 /* amf.c */; };
|
||||
849005B11D4B5C8400D2A3D5 /* amf.h in Headers */ = {isa = PBXBuildFile; fileRef = 849005A11D4B5C8400D2A3D5 /* amf.h */; };
|
||||
849005B21D4B5C8400D2A3D5 /* bytes.h in Headers */ = {isa = PBXBuildFile; fileRef = 849005A21D4B5C8400D2A3D5 /* bytes.h */; };
|
||||
849005B31D4B5C8400D2A3D5 /* dh.h in Headers */ = {isa = PBXBuildFile; fileRef = 849005A31D4B5C8400D2A3D5 /* dh.h */; };
|
||||
849005B41D4B5C8400D2A3D5 /* dhgroups.h in Headers */ = {isa = PBXBuildFile; fileRef = 849005A41D4B5C8400D2A3D5 /* dhgroups.h */; };
|
||||
849005B51D4B5C8400D2A3D5 /* error.c in Sources */ = {isa = PBXBuildFile; fileRef = 849005A51D4B5C8400D2A3D5 /* error.c */; };
|
||||
849005B61D4B5C8400D2A3D5 /* error.h in Headers */ = {isa = PBXBuildFile; fileRef = 849005A61D4B5C8400D2A3D5 /* error.h */; };
|
||||
849005B71D4B5C8400D2A3D5 /* handshake.h in Headers */ = {isa = PBXBuildFile; fileRef = 849005A71D4B5C8400D2A3D5 /* handshake.h */; };
|
||||
849005B81D4B5C8400D2A3D5 /* hashswf.c in Sources */ = {isa = PBXBuildFile; fileRef = 849005A81D4B5C8400D2A3D5 /* hashswf.c */; };
|
||||
849005B91D4B5C8400D2A3D5 /* http.h in Headers */ = {isa = PBXBuildFile; fileRef = 849005A91D4B5C8400D2A3D5 /* http.h */; };
|
||||
849005BA1D4B5C8400D2A3D5 /* log.c in Sources */ = {isa = PBXBuildFile; fileRef = 849005AA1D4B5C8400D2A3D5 /* log.c */; };
|
||||
849005BB1D4B5C8400D2A3D5 /* log.h in Headers */ = {isa = PBXBuildFile; fileRef = 849005AB1D4B5C8400D2A3D5 /* log.h */; };
|
||||
849005BC1D4B5C8400D2A3D5 /* parseurl.c in Sources */ = {isa = PBXBuildFile; fileRef = 849005AC1D4B5C8400D2A3D5 /* parseurl.c */; };
|
||||
849005BD1D4B5C8400D2A3D5 /* rtmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 849005AD1D4B5C8400D2A3D5 /* rtmp.c */; };
|
||||
849005BE1D4B5C8400D2A3D5 /* rtmp.h in Headers */ = {isa = PBXBuildFile; fileRef = 849005AE1D4B5C8400D2A3D5 /* rtmp.h */; };
|
||||
849005BF1D4B5C8400D2A3D5 /* rtmp_sys.h in Headers */ = {isa = PBXBuildFile; fileRef = 849005AF1D4B5C8400D2A3D5 /* rtmp_sys.h */; };
|
||||
AD7F89B4621A7EFEBEA72D49 /* libPods-LFLiveKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B8CB02D2A92EA1F5A262F154 /* libPods-LFLiveKit.a */; };
|
||||
B289F1DB1D3DE77F00D9C7A5 /* LFStreamingBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = B289F1D41D3DE77F00D9C7A5 /* LFStreamingBuffer.h */; };
|
||||
B289F1DC1D3DE77F00D9C7A5 /* LFStreamingBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = B289F1D51D3DE77F00D9C7A5 /* LFStreamingBuffer.m */; };
|
||||
@@ -65,7 +81,6 @@
|
||||
B2CD14751D45F18B008082E8 /* VideoEncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = B2CD146A1D45F18B008082E8 /* VideoEncoder.m */; };
|
||||
B2CD14761D45F18B008082E8 /* LFH264VideoEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = B2CD146B1D45F18B008082E8 /* LFH264VideoEncoder.h */; };
|
||||
B2CD14771D45F18B008082E8 /* LFH264VideoEncoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = B2CD146C1D45F18B008082E8 /* LFH264VideoEncoder.mm */; };
|
||||
BE55DA79155500CDEF87FB5C /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B5758EB2A15DAA132D8BF380 /* libPods.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -121,6 +136,22 @@
|
||||
84001FFC1D0017680026C63F /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
|
||||
84001FFE1D00176C0026C63F /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; };
|
||||
840020001D0017850026C63F /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
849005A01D4B5C8400D2A3D5 /* amf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amf.c; sourceTree = "<group>"; };
|
||||
849005A11D4B5C8400D2A3D5 /* amf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = amf.h; sourceTree = "<group>"; };
|
||||
849005A21D4B5C8400D2A3D5 /* bytes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bytes.h; sourceTree = "<group>"; };
|
||||
849005A31D4B5C8400D2A3D5 /* dh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dh.h; sourceTree = "<group>"; };
|
||||
849005A41D4B5C8400D2A3D5 /* dhgroups.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dhgroups.h; sourceTree = "<group>"; };
|
||||
849005A51D4B5C8400D2A3D5 /* error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = error.c; sourceTree = "<group>"; };
|
||||
849005A61D4B5C8400D2A3D5 /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error.h; sourceTree = "<group>"; };
|
||||
849005A71D4B5C8400D2A3D5 /* handshake.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = handshake.h; sourceTree = "<group>"; };
|
||||
849005A81D4B5C8400D2A3D5 /* hashswf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hashswf.c; sourceTree = "<group>"; };
|
||||
849005A91D4B5C8400D2A3D5 /* http.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http.h; sourceTree = "<group>"; };
|
||||
849005AA1D4B5C8400D2A3D5 /* log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = log.c; sourceTree = "<group>"; };
|
||||
849005AB1D4B5C8400D2A3D5 /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = "<group>"; };
|
||||
849005AC1D4B5C8400D2A3D5 /* parseurl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parseurl.c; sourceTree = "<group>"; };
|
||||
849005AD1D4B5C8400D2A3D5 /* rtmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rtmp.c; sourceTree = "<group>"; };
|
||||
849005AE1D4B5C8400D2A3D5 /* rtmp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rtmp.h; sourceTree = "<group>"; };
|
||||
849005AF1D4B5C8400D2A3D5 /* rtmp_sys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rtmp_sys.h; sourceTree = "<group>"; };
|
||||
A17586B27CD6843997425CCF /* Pods-LFLiveKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LFLiveKit.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LFLiveKit/Pods-LFLiveKit.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
B289F1D41D3DE77F00D9C7A5 /* LFStreamingBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LFStreamingBuffer.h; path = LFLiveKit/publish/LFStreamingBuffer.h; sourceTree = SOURCE_ROOT; };
|
||||
B289F1D51D3DE77F00D9C7A5 /* LFStreamingBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = LFStreamingBuffer.m; path = LFLiveKit/publish/LFStreamingBuffer.m; sourceTree = SOURCE_ROOT; };
|
||||
@@ -140,7 +171,6 @@
|
||||
B2CD146A1D45F18B008082E8 /* VideoEncoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VideoEncoder.m; sourceTree = "<group>"; };
|
||||
B2CD146B1D45F18B008082E8 /* LFH264VideoEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFH264VideoEncoder.h; sourceTree = "<group>"; };
|
||||
B2CD146C1D45F18B008082E8 /* LFH264VideoEncoder.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LFH264VideoEncoder.mm; sourceTree = "<group>"; };
|
||||
B5758EB2A15DAA132D8BF380 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B75B965E6B94DE4CBCC82EA7 /* Pods-LFLiveKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LFLiveKit.release.xcconfig"; path = "Pods/Target Support Files/Pods-LFLiveKit/Pods-LFLiveKit.release.xcconfig"; sourceTree = "<group>"; };
|
||||
B8CB02D2A92EA1F5A262F154 /* libPods-LFLiveKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LFLiveKit.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -157,7 +187,6 @@
|
||||
84001FF91D00175D0026C63F /* Foundation.framework in Frameworks */,
|
||||
84001FF71D0017590026C63F /* AVFoundation.framework in Frameworks */,
|
||||
AD7F89B4621A7EFEBEA72D49 /* libPods-LFLiveKit.a in Frameworks */,
|
||||
BE55DA79155500CDEF87FB5C /* libPods.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -182,7 +211,6 @@
|
||||
84001FF81D00175D0026C63F /* Foundation.framework */,
|
||||
84001FF61D0017590026C63F /* AVFoundation.framework */,
|
||||
B8CB02D2A92EA1F5A262F154 /* libPods-LFLiveKit.a */,
|
||||
B5758EB2A15DAA132D8BF380 /* libPods.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -302,6 +330,7 @@
|
||||
84001FC91D0016380026C63F /* publish */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8490059F1D4B5C8400D2A3D5 /* pili-librtmp */,
|
||||
B289F1D41D3DE77F00D9C7A5 /* LFStreamingBuffer.h */,
|
||||
B289F1D51D3DE77F00D9C7A5 /* LFStreamingBuffer.m */,
|
||||
B289F1D61D3DE77F00D9C7A5 /* LFStreamRtmpSocket.h */,
|
||||
@@ -314,6 +343,30 @@
|
||||
path = upload;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8490059F1D4B5C8400D2A3D5 /* pili-librtmp */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
849005A01D4B5C8400D2A3D5 /* amf.c */,
|
||||
849005A11D4B5C8400D2A3D5 /* amf.h */,
|
||||
849005A21D4B5C8400D2A3D5 /* bytes.h */,
|
||||
849005A31D4B5C8400D2A3D5 /* dh.h */,
|
||||
849005A41D4B5C8400D2A3D5 /* dhgroups.h */,
|
||||
849005A51D4B5C8400D2A3D5 /* error.c */,
|
||||
849005A61D4B5C8400D2A3D5 /* error.h */,
|
||||
849005A71D4B5C8400D2A3D5 /* handshake.h */,
|
||||
849005A81D4B5C8400D2A3D5 /* hashswf.c */,
|
||||
849005A91D4B5C8400D2A3D5 /* http.h */,
|
||||
849005AA1D4B5C8400D2A3D5 /* log.c */,
|
||||
849005AB1D4B5C8400D2A3D5 /* log.h */,
|
||||
849005AC1D4B5C8400D2A3D5 /* parseurl.c */,
|
||||
849005AD1D4B5C8400D2A3D5 /* rtmp.c */,
|
||||
849005AE1D4B5C8400D2A3D5 /* rtmp.h */,
|
||||
849005AF1D4B5C8400D2A3D5 /* rtmp_sys.h */,
|
||||
);
|
||||
name = "pili-librtmp";
|
||||
path = "LFLiveKit/publish/pili-librtmp";
|
||||
sourceTree = SOURCE_ROOT;
|
||||
};
|
||||
B2CD14611D45F18B008082E8 /* H264 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -346,12 +399,16 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
849005B21D4B5C8400D2A3D5 /* bytes.h in Headers */,
|
||||
84001FDB1D0016380026C63F /* LFLiveAudioConfiguration.h in Headers */,
|
||||
B289F1DD1D3DE77F00D9C7A5 /* LFStreamRtmpSocket.h in Headers */,
|
||||
84001FDD1D0016380026C63F /* LFLiveVideoConfiguration.h in Headers */,
|
||||
849005B61D4B5C8400D2A3D5 /* error.h in Headers */,
|
||||
B2CD14701D45F18B008082E8 /* MP4Atom.h in Headers */,
|
||||
84001FE31D0016380026C63F /* LFLiveSession.h in Headers */,
|
||||
B289F1DB1D3DE77F00D9C7A5 /* LFStreamingBuffer.h in Headers */,
|
||||
849005B71D4B5C8400D2A3D5 /* handshake.h in Headers */,
|
||||
849005BB1D4B5C8400D2A3D5 /* log.h in Headers */,
|
||||
84001FEB1D0016380026C63F /* LFLiveStreamInfo.h in Headers */,
|
||||
84001FE91D0016380026C63F /* LFLiveDebug.h in Headers */,
|
||||
84001FE71D0016380026C63F /* LFFrame.h in Headers */,
|
||||
@@ -361,15 +418,21 @@
|
||||
84001FDF1D0016380026C63F /* LFGPUImageBeautyFilter.h in Headers */,
|
||||
84001FD31D0016380026C63F /* LFVideoCapture.h in Headers */,
|
||||
84001FD11D0016380026C63F /* LFAudioCapture.h in Headers */,
|
||||
849005B91D4B5C8400D2A3D5 /* http.h in Headers */,
|
||||
84001FE11D0016380026C63F /* LFGPUImageEmptyFilter.h in Headers */,
|
||||
849005B31D4B5C8400D2A3D5 /* dh.h in Headers */,
|
||||
84001FDA1D0016380026C63F /* LFVideoEncoding.h in Headers */,
|
||||
84001FE51D0016380026C63F /* LFAudioFrame.h in Headers */,
|
||||
84001FED1D0016380026C63F /* LFVideoFrame.h in Headers */,
|
||||
849005BF1D4B5C8400D2A3D5 /* rtmp_sys.h in Headers */,
|
||||
849005BE1D4B5C8400D2A3D5 /* rtmp.h in Headers */,
|
||||
B2CD14741D45F18B008082E8 /* VideoEncoder.h in Headers */,
|
||||
B2CD14731D45F18B008082E8 /* NALUnit.h in Headers */,
|
||||
84001FD81D0016380026C63F /* LFHardwareVideoEncoder.h in Headers */,
|
||||
849005B41D4B5C8400D2A3D5 /* dhgroups.h in Headers */,
|
||||
B289F1DF1D3DE77F00D9C7A5 /* LFStreamSocket.h in Headers */,
|
||||
84001FD51D0016380026C63F /* LFAudioEncoding.h in Headers */,
|
||||
849005B11D4B5C8400D2A3D5 /* amf.h in Headers */,
|
||||
B2CD146D1D45F18B008082E8 /* AVEncoder.h in Headers */,
|
||||
84001F8E1D0015D10026C63F /* LFLiveKit.h in Headers */,
|
||||
);
|
||||
@@ -382,14 +445,12 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 84001F9E1D0015D10026C63F /* Build configuration list for PBXNativeTarget "LFLiveKit" */;
|
||||
buildPhases = (
|
||||
8EE9401DCA9508E918B7FB68 /* 📦 Check Pods Manifest.lock */,
|
||||
98F2C3F394BD79A6D6B8424F /* Check Pods Manifest.lock */,
|
||||
5ED199EAC89EE599F1E56B19 /* 📦 Check Pods Manifest.lock */,
|
||||
84001F851D0015D10026C63F /* Sources */,
|
||||
84001F861D0015D10026C63F /* Frameworks */,
|
||||
84001F871D0015D10026C63F /* Headers */,
|
||||
84001F881D0015D10026C63F /* Resources */,
|
||||
817C22141AD3F2EB34365AA3 /* 📦 Copy Pods Resources */,
|
||||
8A5D8B623E50AAC1575D1741 /* Copy Pods Resources */,
|
||||
36D0848EAED7999C442A99BD /* 📦 Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -471,7 +532,7 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
817C22141AD3F2EB34365AA3 /* 📦 Copy Pods Resources */ = {
|
||||
36D0848EAED7999C442A99BD /* 📦 Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -486,22 +547,7 @@
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LFLiveKit/Pods-LFLiveKit-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
8A5D8B623E50AAC1575D1741 /* Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
8EE9401DCA9508E918B7FB68 /* 📦 Check Pods Manifest.lock */ = {
|
||||
5ED199EAC89EE599F1E56B19 /* 📦 Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -516,21 +562,6 @@
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
98F2C3F394BD79A6D6B8424F /* Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@@ -540,6 +571,7 @@
|
||||
files = (
|
||||
84001FE21D0016380026C63F /* LFGPUImageEmptyFilter.m in Sources */,
|
||||
84001FE41D0016380026C63F /* LFLiveSession.m in Sources */,
|
||||
849005B81D4B5C8400D2A3D5 /* hashswf.c in Sources */,
|
||||
B2CD14711D45F18B008082E8 /* MP4Atom.m in Sources */,
|
||||
84001FE61D0016380026C63F /* LFAudioFrame.m in Sources */,
|
||||
84001FDC1D0016380026C63F /* LFLiveAudioConfiguration.m in Sources */,
|
||||
@@ -547,18 +579,23 @@
|
||||
84001FE81D0016380026C63F /* LFFrame.m in Sources */,
|
||||
B2CD14721D45F18B008082E8 /* NALUnit.cpp in Sources */,
|
||||
B289F1DC1D3DE77F00D9C7A5 /* LFStreamingBuffer.m in Sources */,
|
||||
849005B51D4B5C8400D2A3D5 /* error.c in Sources */,
|
||||
B289F1E11D3DE77F00D9C7A5 /* NSMutableArray+LFAdd.m in Sources */,
|
||||
B2CD14771D45F18B008082E8 /* LFH264VideoEncoder.mm in Sources */,
|
||||
849005BC1D4B5C8400D2A3D5 /* parseurl.c in Sources */,
|
||||
84001FDE1D0016380026C63F /* LFLiveVideoConfiguration.m in Sources */,
|
||||
84001FD21D0016380026C63F /* LFAudioCapture.m in Sources */,
|
||||
B2CD14751D45F18B008082E8 /* VideoEncoder.m in Sources */,
|
||||
B2CD146F1D45F18B008082E8 /* LICENSE.markdown in Sources */,
|
||||
B289F1DE1D3DE77F00D9C7A5 /* LFStreamRtmpSocket.m in Sources */,
|
||||
849005BA1D4B5C8400D2A3D5 /* log.c in Sources */,
|
||||
84001FD91D0016380026C63F /* LFHardwareVideoEncoder.m in Sources */,
|
||||
84001FEC1D0016380026C63F /* LFLiveStreamInfo.m in Sources */,
|
||||
849005B01D4B5C8400D2A3D5 /* amf.c in Sources */,
|
||||
84001FEA1D0016380026C63F /* LFLiveDebug.m in Sources */,
|
||||
84001FEE1D0016380026C63F /* LFVideoFrame.m in Sources */,
|
||||
84001FD71D0016380026C63F /* LFHardwareAudioEncoder.m in Sources */,
|
||||
849005BD1D4B5C8400D2A3D5 /* rtmp.c in Sources */,
|
||||
84001FE01D0016380026C63F /* LFGPUImageBeautyFilter.m in Sources */,
|
||||
B2CD146E1D45F18B008082E8 /* AVEncoder.mm in Sources */,
|
||||
);
|
||||
@@ -686,6 +723,10 @@
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/LFLiveKit/publish/libpili-librtmp",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.youku.LFLiveKit.LFLiveKit;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
@@ -705,6 +746,10 @@
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/LFLiveKit/publish/libpili-librtmp",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.youku.LFLiveKit.LFLiveKit;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.9.0</string>
|
||||
<string>1.9.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
- (void)stopLive {
|
||||
self.uploading = NO;
|
||||
[self.socket stop];
|
||||
self.socket = nil;
|
||||
}
|
||||
|
||||
#pragma mark -- CaptureDelegate
|
||||
|
||||
@@ -46,8 +46,8 @@ NSString *const LFAudioComponentFailedToCreateNotification = @"LFAudioComponentF
|
||||
NSError *error = nil;
|
||||
|
||||
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
|
||||
|
||||
[session setMode:AVAudioSessionModeVideoRecording error:&error];
|
||||
|
||||
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
|
||||
|
||||
if (![session setActive:YES error:&error]) {
|
||||
[self handleAudioComponentCreationFailure];
|
||||
@@ -55,7 +55,7 @@ NSString *const LFAudioComponentFailedToCreateNotification = @"LFAudioComponentF
|
||||
|
||||
AudioComponentDescription acd;
|
||||
acd.componentType = kAudioUnitType_Output;
|
||||
acd.componentSubType = kAudioUnitSubType_RemoteIO;
|
||||
acd.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
|
||||
acd.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
acd.componentFlags = 0;
|
||||
acd.componentFlagsMask = 0;
|
||||
|
||||
@@ -33,22 +33,23 @@
|
||||
- (instancetype)initWithVideoConfiguration:(LFLiveVideoConfiguration *)configuration {
|
||||
if (self = [super init]) {
|
||||
_configuration = configuration;
|
||||
if([self pixelBufferImageSize].width < configuration.videoSize.width || [self pixelBufferImageSize].height < configuration.videoSize.height){
|
||||
@throw [NSException exceptionWithName:@"当前videoSize大小出错" reason:@"LFLiveVideoConfiguration videoSize error" userInfo:nil];
|
||||
return nil;
|
||||
}
|
||||
|
||||
_videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:_configuration.avSessionPreset cameraPosition:AVCaptureDevicePositionFront];
|
||||
UIInterfaceOrientation statusBar = [[UIApplication sharedApplication] statusBarOrientation];
|
||||
if (configuration.landscape) {
|
||||
if (statusBar != UIInterfaceOrientationLandscapeLeft && statusBar != UIInterfaceOrientationLandscapeRight) {
|
||||
NSLog(@"当前设置方向出错");
|
||||
NSLog(@"当前设置方向出错");
|
||||
NSLog(@"当前设置方向出错");
|
||||
@throw [NSException exceptionWithName:@"当前设置方向出错" reason:@"LFLiveVideoConfiguration landscape error" userInfo:nil];
|
||||
_videoCamera.outputImageOrientation = UIInterfaceOrientationLandscapeLeft;
|
||||
} else {
|
||||
_videoCamera.outputImageOrientation = statusBar;
|
||||
}
|
||||
} else {
|
||||
if (statusBar != UIInterfaceOrientationPortrait && statusBar != UIInterfaceOrientationPortraitUpsideDown) {
|
||||
NSLog(@"当前设置方向出错");
|
||||
NSLog(@"当前设置方向出错");
|
||||
NSLog(@"当前设置方向出错");
|
||||
@throw [NSException exceptionWithName:@"当前设置方向出错" reason:@"LFLiveVideoConfiguration landscape error" userInfo:nil];
|
||||
_videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
|
||||
} else {
|
||||
_videoCamera.outputImageOrientation = statusBar;
|
||||
@@ -203,7 +204,6 @@
|
||||
}
|
||||
|
||||
- (void)setBeautyFace:(BOOL)beautyFace {
|
||||
if (_beautyFace == beautyFace) return;
|
||||
|
||||
_beautyFace = beautyFace;
|
||||
[_filter removeAllTargets];
|
||||
@@ -227,18 +227,18 @@
|
||||
}];
|
||||
}
|
||||
|
||||
if (_configuration.isClipVideo) {
|
||||
if (_configuration.landscape) {
|
||||
_cropfilter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(0.125, 0, 0.75, 1)];
|
||||
} else {
|
||||
_cropfilter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(0, 0.125, 1, 0.75)];
|
||||
}
|
||||
CGSize imageSize = [self pixelBufferImageSize];
|
||||
CGFloat cropLeft = (imageSize.width - self.configuration.videoSize.width)/2.0/imageSize.width;
|
||||
CGFloat cropTop = (imageSize.height - self.configuration.videoSize.height)/2.0/imageSize.height;
|
||||
|
||||
if(cropLeft == 0 && cropTop == 0){
|
||||
[_videoCamera addTarget:_filter];
|
||||
}else{
|
||||
_cropfilter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(cropLeft, cropTop, 1 - cropLeft*2, 1 - cropTop*2)];
|
||||
[_videoCamera addTarget:_cropfilter];
|
||||
[_cropfilter addTarget:_filter];
|
||||
} else {
|
||||
[_videoCamera addTarget:_filter];
|
||||
}
|
||||
|
||||
|
||||
if (_beautyFace) {
|
||||
[_filter addTarget:_output];
|
||||
[_output addTarget:_gpuImageView];
|
||||
@@ -300,4 +300,34 @@
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark --
|
||||
- (CGSize)pixelBufferImageSize{
|
||||
CGSize videoSize = CGSizeZero;
|
||||
switch (self.configuration.sessionPreset) {
|
||||
case LFCaptureSessionPreset360x640:
|
||||
{
|
||||
videoSize = CGSizeMake(480, 640);
|
||||
}
|
||||
break;
|
||||
case LFCaptureSessionPreset540x960:
|
||||
{
|
||||
videoSize = CGSizeMake(540, 960);
|
||||
}
|
||||
break;
|
||||
case LFCaptureSessionPreset720x1280:
|
||||
{
|
||||
videoSize = CGSizeMake(720, 1280);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(self.configuration.landscape){
|
||||
return CGSizeMake(videoSize.height, videoSize.width);
|
||||
}
|
||||
return videoSize;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -90,7 +90,4 @@ typedef NS_ENUM (NSUInteger, LFLiveVideoQuality){
|
||||
///< ≈sde3分辨率
|
||||
@property (nonatomic, assign, readonly) NSString *avSessionPreset;
|
||||
|
||||
///< 是否裁剪
|
||||
@property (nonatomic, assign, readonly) BOOL isClipVideo;
|
||||
|
||||
@end
|
||||
|
||||
@@ -213,10 +213,6 @@
|
||||
return sessionPreset;
|
||||
}
|
||||
|
||||
- (BOOL)isClipVideo {
|
||||
return self.sessionPreset == LFCaptureSessionPreset360x640 ? YES : NO;
|
||||
}
|
||||
|
||||
#pragma mark -- encoder
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder {
|
||||
[aCoder encodeObject:[NSValue valueWithCGSize:self.videoSize] forKey:@"videoSize"];
|
||||
@@ -248,7 +244,6 @@
|
||||
@(self.videoBitRate),
|
||||
@(self.videoMaxBitRate),
|
||||
@(self.videoMinBitRate),
|
||||
@(self.isClipVideo),
|
||||
self.avSessionPreset,
|
||||
@(self.sessionPreset),
|
||||
@(self.landscape), ];
|
||||
@@ -274,7 +269,6 @@
|
||||
object.videoBitRate == self.videoBitRate &&
|
||||
object.videoMaxBitRate == self.videoMaxBitRate &&
|
||||
object.videoMinBitRate == self.videoMinBitRate &&
|
||||
object.isClipVideo == self.isClipVideo &&
|
||||
[object.avSessionPreset isEqualToString:self.avSessionPreset] &&
|
||||
object.sessionPreset == self.sessionPreset &&
|
||||
object.landscape == self.landscape;
|
||||
@@ -297,7 +291,6 @@
|
||||
[desc appendFormat:@" videoBitRate:%zi", self.videoBitRate];
|
||||
[desc appendFormat:@" videoMaxBitRate:%zi", self.videoMaxBitRate];
|
||||
[desc appendFormat:@" videoMinBitRate:%zi", self.videoMinBitRate];
|
||||
[desc appendFormat:@" isClipVideo:%zi", self.isClipVideo];
|
||||
[desc appendFormat:@" avSessionPreset:%@", self.avSessionPreset];
|
||||
[desc appendFormat:@" sessionPreset:%zi", self.sessionPreset];
|
||||
[desc appendFormat:@" landscape:%zi", self.landscape];
|
||||
|
||||
Executable
+1037
File diff suppressed because it is too large
Load Diff
Executable
+180
@@ -0,0 +1,180 @@
|
||||
#ifndef __AMF_H__
|
||||
#define __AMF_H__
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.org
|
||||
* Copyright (C) 2008-2009 Andrej Stepanchuk
|
||||
* Copyright (C) 2009-2010 Howard Chu
|
||||
*
|
||||
* This file is part of librtmp.
|
||||
*
|
||||
* librtmp is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* librtmp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with librtmp see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
AMF_NUMBER = 0,
|
||||
AMF_BOOLEAN,
|
||||
AMF_STRING,
|
||||
AMF_OBJECT,
|
||||
AMF_MOVIECLIP, /* reserved, not used */
|
||||
AMF_NULL,
|
||||
AMF_UNDEFINED,
|
||||
AMF_REFERENCE,
|
||||
AMF_ECMA_ARRAY,
|
||||
AMF_OBJECT_END,
|
||||
AMF_STRICT_ARRAY,
|
||||
AMF_DATE,
|
||||
AMF_LONG_STRING,
|
||||
AMF_UNSUPPORTED,
|
||||
AMF_RECORDSET, /* reserved, not used */
|
||||
AMF_XML_DOC,
|
||||
AMF_TYPED_OBJECT,
|
||||
AMF_AVMPLUS, /* switch to AMF3 */
|
||||
AMF_INVALID = 0xff
|
||||
} AMFDataType;
|
||||
|
||||
typedef enum {
|
||||
AMF3_UNDEFINED = 0,
|
||||
AMF3_NULL,
|
||||
AMF3_FALSE,
|
||||
AMF3_TRUE,
|
||||
AMF3_INTEGER,
|
||||
AMF3_DOUBLE,
|
||||
AMF3_STRING,
|
||||
AMF3_XML_DOC,
|
||||
AMF3_DATE,
|
||||
AMF3_ARRAY,
|
||||
AMF3_OBJECT,
|
||||
AMF3_XML,
|
||||
AMF3_BYTE_ARRAY
|
||||
} AMF3DataType;
|
||||
|
||||
typedef struct AVal {
|
||||
char *av_val;
|
||||
int av_len;
|
||||
} AVal;
|
||||
#define AVC(str) \
|
||||
{ str, sizeof(str) - 1 }
|
||||
#define AVMATCH(a1, a2) \
|
||||
((a1)->av_len == (a2)->av_len && \
|
||||
!memcmp((a1)->av_val, (a2)->av_val, (a1)->av_len))
|
||||
|
||||
struct AMFObjectProperty;
|
||||
|
||||
typedef struct AMFObject {
|
||||
int o_num;
|
||||
struct AMFObjectProperty *o_props;
|
||||
} AMFObject;
|
||||
|
||||
typedef struct AMFObjectProperty {
|
||||
AVal p_name;
|
||||
AMFDataType p_type;
|
||||
union {
|
||||
double p_number;
|
||||
AVal p_aval;
|
||||
AMFObject p_object;
|
||||
} p_vu;
|
||||
int16_t p_UTCoffset;
|
||||
} AMFObjectProperty;
|
||||
|
||||
char *AMF_EncodeString(char *output, char *outend, const AVal *str);
|
||||
char *AMF_EncodeNumber(char *output, char *outend, double dVal);
|
||||
char *AMF_EncodeInt16(char *output, char *outend, short nVal);
|
||||
char *AMF_EncodeInt24(char *output, char *outend, int nVal);
|
||||
char *AMF_EncodeInt32(char *output, char *outend, int nVal);
|
||||
char *AMF_EncodeBoolean(char *output, char *outend, int bVal);
|
||||
|
||||
/* Shortcuts for AMFProp_Encode */
|
||||
char *AMF_EncodeNamedString(char *output, char *outend, const AVal *name,
|
||||
const AVal *value);
|
||||
char *AMF_EncodeNamedNumber(char *output, char *outend, const AVal *name,
|
||||
double dVal);
|
||||
char *AMF_EncodeNamedBoolean(char *output, char *outend, const AVal *name,
|
||||
int bVal);
|
||||
|
||||
unsigned short AMF_DecodeInt16(const char *data);
|
||||
unsigned int AMF_DecodeInt24(const char *data);
|
||||
unsigned int AMF_DecodeInt32(const char *data);
|
||||
void AMF_DecodeString(const char *data, AVal *str);
|
||||
void AMF_DecodeLongString(const char *data, AVal *str);
|
||||
int AMF_DecodeBoolean(const char *data);
|
||||
double AMF_DecodeNumber(const char *data);
|
||||
|
||||
char *AMF_Encode(AMFObject *obj, char *pBuffer, char *pBufEnd);
|
||||
int AMF_Decode(AMFObject *obj, const char *pBuffer, int nSize, int bDecodeName);
|
||||
int AMF_DecodeArray(AMFObject *obj, const char *pBuffer, int nSize,
|
||||
int nArrayLen, int bDecodeName);
|
||||
int AMF3_Decode(AMFObject *obj, const char *pBuffer, int nSize,
|
||||
int bDecodeName);
|
||||
void AMF_Dump(AMFObject *obj);
|
||||
void AMF_Reset(AMFObject *obj);
|
||||
|
||||
void AMF_AddProp(AMFObject *obj, const AMFObjectProperty *prop);
|
||||
int AMF_CountProp(AMFObject *obj);
|
||||
AMFObjectProperty *AMF_GetProp(AMFObject *obj, const AVal *name, int nIndex);
|
||||
|
||||
AMFDataType AMFProp_GetType(AMFObjectProperty *prop);
|
||||
void AMFProp_SetNumber(AMFObjectProperty *prop, double dval);
|
||||
void AMFProp_SetBoolean(AMFObjectProperty *prop, int bflag);
|
||||
void AMFProp_SetString(AMFObjectProperty *prop, AVal *str);
|
||||
void AMFProp_SetObject(AMFObjectProperty *prop, AMFObject *obj);
|
||||
|
||||
void AMFProp_GetName(AMFObjectProperty *prop, AVal *name);
|
||||
void AMFProp_SetName(AMFObjectProperty *prop, AVal *name);
|
||||
double AMFProp_GetNumber(AMFObjectProperty *prop);
|
||||
int AMFProp_GetBoolean(AMFObjectProperty *prop);
|
||||
void AMFProp_GetString(AMFObjectProperty *prop, AVal *str);
|
||||
void AMFProp_GetObject(AMFObjectProperty *prop, AMFObject *obj);
|
||||
|
||||
int AMFProp_IsValid(AMFObjectProperty *prop);
|
||||
|
||||
char *AMFProp_Encode(AMFObjectProperty *prop, char *pBuffer, char *pBufEnd);
|
||||
int AMF3Prop_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize,
|
||||
int bDecodeName);
|
||||
int AMFProp_Decode(AMFObjectProperty *prop, const char *pBuffer, int nSize,
|
||||
int bDecodeName);
|
||||
|
||||
void AMFProp_Dump(AMFObjectProperty *prop);
|
||||
void AMFProp_Reset(AMFObjectProperty *prop);
|
||||
|
||||
typedef struct AMF3ClassDef {
|
||||
AVal cd_name;
|
||||
char cd_externalizable;
|
||||
char cd_dynamic;
|
||||
int cd_num;
|
||||
AVal *cd_props;
|
||||
} AMF3ClassDef;
|
||||
|
||||
void AMF3CD_AddProp(AMF3ClassDef *cd, AVal *prop);
|
||||
AVal *AMF3CD_GetProp(AMF3ClassDef *cd, int idx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __AMF_H__ */
|
||||
Executable
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.org
|
||||
* Copyright (C) 2008-2009 Andrej Stepanchuk
|
||||
* Copyright (C) 2009-2010 Howard Chu
|
||||
*
|
||||
* This file is part of librtmp.
|
||||
*
|
||||
* librtmp is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* librtmp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with librtmp see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#ifndef __BYTES_H__
|
||||
#define __BYTES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Windows is little endian only */
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#define __BIG_ENDIAN 4321
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#define __FLOAT_WORD_ORDER __BYTE_ORDER
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
|
||||
#else /* !_WIN32 */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#if defined(BYTE_ORDER) && !defined(__BYTE_ORDER)
|
||||
#define __BYTE_ORDER BYTE_ORDER
|
||||
#endif
|
||||
|
||||
#if defined(BIG_ENDIAN) && !defined(__BIG_ENDIAN)
|
||||
#define __BIG_ENDIAN BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#if defined(LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN)
|
||||
#define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
/* define default endianness */
|
||||
#ifndef __LITTLE_ENDIAN
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
|
||||
#ifndef __BIG_ENDIAN
|
||||
#define __BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
#ifndef __BYTE_ORDER
|
||||
#warning "Byte order not defined on your system, assuming little endian!"
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
/* ok, we assume to have the same float word order and byte order if float word
|
||||
* order is not defined */
|
||||
#ifndef __FLOAT_WORD_ORDER
|
||||
#warning "Float word order not defined, assuming the same as byte order!"
|
||||
#define __FLOAT_WORD_ORDER __BYTE_ORDER
|
||||
#endif
|
||||
|
||||
#if !defined(__BYTE_ORDER) || !defined(__FLOAT_WORD_ORDER)
|
||||
#error "Undefined byte or float word order!"
|
||||
#endif
|
||||
|
||||
#if __FLOAT_WORD_ORDER != __BIG_ENDIAN && __FLOAT_WORD_ORDER != __LITTLE_ENDIAN
|
||||
#error "Unknown/unsupported float word order!"
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN
|
||||
#error "Unknown/unsupported byte order!"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Executable
+345
@@ -0,0 +1,345 @@
|
||||
/* RTMPDump - Diffie-Hellmann Key Exchange
|
||||
* Copyright (C) 2009 Andrej Stepanchuk
|
||||
* Copyright (C) 2009-2010 Howard Chu
|
||||
*
|
||||
* This file is part of librtmp.
|
||||
*
|
||||
* librtmp is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* librtmp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with librtmp see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE_POLARSSL
|
||||
#include <polarssl/dhm.h>
|
||||
typedef mpi *MP_t;
|
||||
#define MP_new(m) \
|
||||
m = malloc(sizeof(mpi)); \
|
||||
mpi_init(m, NULL)
|
||||
#define MP_set_w(mpi, w) mpi_lset(mpi, w)
|
||||
#define MP_cmp(u, v) mpi_cmp_mpi(u, v)
|
||||
#define MP_set(u, v) mpi_copy(u, v)
|
||||
#define MP_sub_w(mpi, w) mpi_sub_int(mpi, mpi, w)
|
||||
#define MP_cmp_1(mpi) mpi_cmp_int(mpi, 1)
|
||||
#define MP_modexp(r, y, q, p) mpi_exp_mod(r, y, q, p, NULL)
|
||||
#define MP_free(mpi) \
|
||||
mpi_free(mpi, NULL); \
|
||||
free(mpi)
|
||||
#define MP_gethex(u, hex, res) \
|
||||
MP_new(u); \
|
||||
res = mpi_read_string(u, 16, hex) == 0
|
||||
#define MP_bytes(u) mpi_size(u)
|
||||
#define MP_setbin(u, buf, len) mpi_write_binary(u, buf, len)
|
||||
#define MP_getbin(u, buf, len) \
|
||||
MP_new(u); \
|
||||
mpi_read_binary(u, buf, len)
|
||||
|
||||
typedef struct MDH {
|
||||
MP_t p;
|
||||
MP_t g;
|
||||
MP_t pub_key;
|
||||
MP_t priv_key;
|
||||
long length;
|
||||
dhm_context ctx;
|
||||
} MDH;
|
||||
|
||||
#define MDH_new() calloc(1, sizeof(MDH))
|
||||
#define MDH_free(vp) \
|
||||
{ \
|
||||
MDH *dh = vp; \
|
||||
dhm_free(&dh->ctx); \
|
||||
MP_free(dh->p); \
|
||||
MP_free(dh->g); \
|
||||
MP_free(dh->pub_key); \
|
||||
MP_free(dh->priv_key); \
|
||||
free(dh); \
|
||||
}
|
||||
|
||||
static int MDH_generate_key(MDH *dh) {
|
||||
unsigned char out[2];
|
||||
MP_set(&dh->ctx.P, dh->p);
|
||||
MP_set(&dh->ctx.G, dh->g);
|
||||
dh->ctx.len = 128;
|
||||
dhm_make_public(&dh->ctx, 1024, out, 1, havege_rand, &RTMP_TLS_ctx->hs);
|
||||
MP_new(dh->pub_key);
|
||||
MP_new(dh->priv_key);
|
||||
MP_set(dh->pub_key, &dh->ctx.GX);
|
||||
MP_set(dh->priv_key, &dh->ctx.X);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh) {
|
||||
int n = len;
|
||||
MP_set(&dh->ctx.GY, pub);
|
||||
dhm_calc_secret(&dh->ctx, secret, &n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(USE_GNUTLS)
|
||||
#include <gcrypt.h>
|
||||
typedef gcry_mpi_t MP_t;
|
||||
#define MP_new(m) m = gcry_mpi_new(1)
|
||||
#define MP_set_w(mpi, w) gcry_mpi_set_ui(mpi, w)
|
||||
#define MP_cmp(u, v) gcry_mpi_cmp(u, v)
|
||||
#define MP_set(u, v) gcry_mpi_set(u, v)
|
||||
#define MP_sub_w(mpi, w) gcry_mpi_sub_ui(mpi, mpi, w)
|
||||
#define MP_cmp_1(mpi) gcry_mpi_cmp_ui(mpi, 1)
|
||||
#define MP_modexp(r, y, q, p) gcry_mpi_powm(r, y, q, p)
|
||||
#define MP_free(mpi) gcry_mpi_release(mpi)
|
||||
#define MP_gethex(u, hex, res) \
|
||||
res = (gcry_mpi_scan(&u, GCRYMPI_FMT_HEX, hex, 0, 0) == 0)
|
||||
#define MP_bytes(u) (gcry_mpi_get_nbits(u) + 7) / 8
|
||||
#define MP_setbin(u, buf, len) \
|
||||
gcry_mpi_print(GCRYMPI_FMT_USG, buf, len, NULL, u)
|
||||
#define MP_getbin(u, buf, len) \
|
||||
gcry_mpi_scan(&u, GCRYMPI_FMT_USG, buf, len, NULL)
|
||||
|
||||
typedef struct MDH {
|
||||
MP_t p;
|
||||
MP_t g;
|
||||
MP_t pub_key;
|
||||
MP_t priv_key;
|
||||
long length;
|
||||
} MDH;
|
||||
|
||||
#define MDH_new() calloc(1, sizeof(MDH))
|
||||
#define MDH_free(dh) \
|
||||
do { \
|
||||
MP_free(((MDH *)(dh))->p); \
|
||||
MP_free(((MDH *)(dh))->g); \
|
||||
MP_free(((MDH *)(dh))->pub_key); \
|
||||
MP_free(((MDH *)(dh))->priv_key); \
|
||||
free(dh); \
|
||||
} while (0)
|
||||
|
||||
extern MP_t gnutls_calc_dh_secret(MP_t *priv, MP_t g, MP_t p);
|
||||
extern MP_t gnutls_calc_dh_key(MP_t y, MP_t x, MP_t p);
|
||||
|
||||
#define MDH_generate_key(dh) \
|
||||
(dh->pub_key = gnutls_calc_dh_secret(&dh->priv_key, dh->g, dh->p))
|
||||
static int MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh) {
|
||||
MP_t sec = gnutls_calc_dh_key(pub, dh->priv_key, dh->p);
|
||||
if (sec) {
|
||||
MP_setbin(sec, secret, len);
|
||||
MP_free(sec);
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else /* USE_OPENSSL */
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
typedef BIGNUM *MP_t;
|
||||
#define MP_new(m) m = BN_new()
|
||||
#define MP_set_w(mpi, w) BN_set_word(mpi, w)
|
||||
#define MP_cmp(u, v) BN_cmp(u, v)
|
||||
#define MP_set(u, v) BN_copy(u, v)
|
||||
#define MP_sub_w(mpi, w) BN_sub_word(mpi, w)
|
||||
#define MP_cmp_1(mpi) BN_cmp(mpi, BN_value_one())
|
||||
#define MP_modexp(r, y, q, p) \
|
||||
do { \
|
||||
BN_CTX *ctx = BN_CTX_new(); \
|
||||
BN_mod_exp(r, y, q, p, ctx); \
|
||||
BN_CTX_free(ctx); \
|
||||
} while (0)
|
||||
#define MP_free(mpi) BN_free(mpi)
|
||||
#define MP_gethex(u, hex, res) res = BN_hex2bn(&u, hex)
|
||||
#define MP_bytes(u) BN_num_bytes(u)
|
||||
#define MP_setbin(u, buf, len) BN_bn2bin(u, buf)
|
||||
#define MP_getbin(u, buf, len) u = BN_bin2bn(buf, len, 0)
|
||||
|
||||
#define MDH DH
|
||||
#define MDH_new() DH_new()
|
||||
#define MDH_free(dh) DH_free(dh)
|
||||
#define MDH_generate_key(dh) DH_generate_key(dh)
|
||||
#define MDH_compute_key(secret, seclen, pub, dh) DH_compute_key(secret, pub, dh)
|
||||
|
||||
#endif
|
||||
|
||||
#include "dhgroups.h"
|
||||
#include "log.h"
|
||||
|
||||
/* RFC 2631, Section 2.1.5, http://www.ietf.org/rfc/rfc2631.txt */
|
||||
static int isValidPublicKey(MP_t y, MP_t p, MP_t q) {
|
||||
int ret = TRUE;
|
||||
MP_t bn;
|
||||
assert(y);
|
||||
|
||||
MP_new(bn);
|
||||
assert(bn);
|
||||
|
||||
/* y must lie in [2,p-1] */
|
||||
MP_set_w(bn, 1);
|
||||
if (MP_cmp(y, bn) < 0) {
|
||||
RTMP_Log(RTMP_LOGERROR, "DH public key must be at least 2");
|
||||
ret = FALSE;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* bn = p-2 */
|
||||
MP_set(bn, p);
|
||||
MP_sub_w(bn, 1);
|
||||
if (MP_cmp(y, bn) > 0) {
|
||||
RTMP_Log(RTMP_LOGERROR, "DH public key must be at most p-2");
|
||||
ret = FALSE;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Verify with Sophie-Germain prime
|
||||
*
|
||||
* This is a nice test to make sure the public key position is calculated
|
||||
* correctly. This test will fail in about 50% of the cases if applied to
|
||||
* random data.
|
||||
*/
|
||||
if (q) {
|
||||
/* y must fulfill y^q mod p = 1 */
|
||||
MP_modexp(bn, y, q, p);
|
||||
|
||||
if (MP_cmp_1(bn) != 0) {
|
||||
RTMP_Log(RTMP_LOGWARNING, "DH public key does not fulfill y^q mod p = 1");
|
||||
}
|
||||
}
|
||||
|
||||
failed:
|
||||
MP_free(bn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static MDH *DHInit(int nKeyBits) {
|
||||
size_t res;
|
||||
MDH *dh = MDH_new();
|
||||
|
||||
if (!dh)
|
||||
goto failed;
|
||||
|
||||
MP_new(dh->g);
|
||||
|
||||
if (!dh->g)
|
||||
goto failed;
|
||||
|
||||
MP_gethex(dh->p, P1024, res); /* prime P1024, see dhgroups.h */
|
||||
if (!res) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
MP_set_w(dh->g, 2); /* base 2 */
|
||||
|
||||
dh->length = nKeyBits;
|
||||
return dh;
|
||||
|
||||
failed:
|
||||
if (dh)
|
||||
MDH_free(dh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DHGenerateKey(MDH *dh) {
|
||||
size_t res = 0;
|
||||
if (!dh)
|
||||
return 0;
|
||||
|
||||
while (!res) {
|
||||
MP_t q1 = NULL;
|
||||
|
||||
if (!MDH_generate_key(dh))
|
||||
return 0;
|
||||
|
||||
MP_gethex(q1, Q1024, res);
|
||||
assert(res);
|
||||
|
||||
res = isValidPublicKey(dh->pub_key, dh->p, q1);
|
||||
if (!res) {
|
||||
MP_free(dh->pub_key);
|
||||
MP_free(dh->priv_key);
|
||||
dh->pub_key = dh->priv_key = 0;
|
||||
}
|
||||
|
||||
MP_free(q1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* fill pubkey with the public key in BIG ENDIAN order
|
||||
* 00 00 00 00 00 x1 x2 x3 .....
|
||||
*/
|
||||
|
||||
static int DHGetPublicKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen) {
|
||||
int len;
|
||||
if (!dh || !dh->pub_key)
|
||||
return 0;
|
||||
|
||||
len = MP_bytes(dh->pub_key);
|
||||
if (len <= 0 || len > (int)nPubkeyLen)
|
||||
return 0;
|
||||
|
||||
memset(pubkey, 0, nPubkeyLen);
|
||||
MP_setbin(dh->pub_key, pubkey + (nPubkeyLen - len), len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0 /* unused */
|
||||
static int
|
||||
DHGetPrivateKey(MDH *dh, uint8_t *privkey, size_t nPrivkeyLen)
|
||||
{
|
||||
if (!dh || !dh->priv_key)
|
||||
return 0;
|
||||
|
||||
int len = MP_bytes(dh->priv_key);
|
||||
if (len <= 0 || len > (int) nPrivkeyLen)
|
||||
return 0;
|
||||
|
||||
memset(privkey, 0, nPrivkeyLen);
|
||||
MP_setbin(dh->priv_key, privkey + (nPrivkeyLen - len), len);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* computes the shared secret key from the private MDH value and the
|
||||
* other party's public key (pubkey)
|
||||
*/
|
||||
static int DHComputeSharedSecretKey(MDH *dh, uint8_t *pubkey, size_t nPubkeyLen,
|
||||
uint8_t *secret) {
|
||||
MP_t q1 = NULL, pubkeyBn = NULL;
|
||||
size_t len;
|
||||
int res;
|
||||
|
||||
if (!dh || !secret || nPubkeyLen >= INT_MAX)
|
||||
return -1;
|
||||
|
||||
MP_getbin(pubkeyBn, pubkey, nPubkeyLen);
|
||||
if (!pubkeyBn)
|
||||
return -1;
|
||||
|
||||
MP_gethex(q1, Q1024, len);
|
||||
assert(len);
|
||||
|
||||
if (isValidPublicKey(pubkeyBn, dh->p, q1))
|
||||
res = MDH_compute_key(secret, nPubkeyLen, pubkeyBn, dh);
|
||||
else
|
||||
res = -1;
|
||||
|
||||
MP_free(q1);
|
||||
MP_free(pubkeyBn);
|
||||
|
||||
return res;
|
||||
}
|
||||
Executable
+198
@@ -0,0 +1,198 @@
|
||||
/* librtmp - Diffie-Hellmann Key Exchange
|
||||
* Copyright (C) 2009 Andrej Stepanchuk
|
||||
*
|
||||
* This file is part of librtmp.
|
||||
*
|
||||
* librtmp is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* librtmp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with librtmp see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
/* from RFC 3526, see http://www.ietf.org/rfc/rfc3526.txt */
|
||||
|
||||
/* 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 } */
|
||||
#define P768 \
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
||||
"E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
|
||||
|
||||
/* 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } */
|
||||
#define P1024 \
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
|
||||
"FFFFFFFFFFFFFFFF"
|
||||
|
||||
/* Group morder largest prime factor: */
|
||||
#define Q1024 \
|
||||
"7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68" \
|
||||
"948127044533E63A0105DF531D89CD9128A5043CC71A026E" \
|
||||
"F7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122" \
|
||||
"F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6" \
|
||||
"F71C35FDAD44CFD2D74F9208BE258FF324943328F67329C0" \
|
||||
"FFFFFFFFFFFFFFFF"
|
||||
|
||||
/* 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } */
|
||||
#define P1536 \
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
|
||||
"670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
|
||||
|
||||
/* 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } */
|
||||
#define P2048 \
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \
|
||||
"15728E5A8AACAA68FFFFFFFFFFFFFFFF"
|
||||
|
||||
/* 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } */
|
||||
#define P3072 \
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \
|
||||
"43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
|
||||
|
||||
/* 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } */
|
||||
#define P4096 \
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \
|
||||
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \
|
||||
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \
|
||||
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \
|
||||
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \
|
||||
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \
|
||||
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \
|
||||
"FFFFFFFFFFFFFFFF"
|
||||
|
||||
/* 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } */
|
||||
#define P6144 \
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \
|
||||
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \
|
||||
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \
|
||||
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \
|
||||
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \
|
||||
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \
|
||||
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" \
|
||||
"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" \
|
||||
"F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" \
|
||||
"179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" \
|
||||
"DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" \
|
||||
"5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" \
|
||||
"D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" \
|
||||
"23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" \
|
||||
"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" \
|
||||
"06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" \
|
||||
"DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" \
|
||||
"12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF"
|
||||
|
||||
/* 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } */
|
||||
#define P8192 \
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \
|
||||
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \
|
||||
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \
|
||||
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \
|
||||
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \
|
||||
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \
|
||||
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" \
|
||||
"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" \
|
||||
"F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" \
|
||||
"179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" \
|
||||
"DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" \
|
||||
"5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" \
|
||||
"D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" \
|
||||
"23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" \
|
||||
"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" \
|
||||
"06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" \
|
||||
"DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" \
|
||||
"12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" \
|
||||
"38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" \
|
||||
"741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" \
|
||||
"3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" \
|
||||
"22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" \
|
||||
"4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" \
|
||||
"062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" \
|
||||
"4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" \
|
||||
"B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" \
|
||||
"4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" \
|
||||
"9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" \
|
||||
"60C980DD98EDD3DFFFFFFFFFFFFFFFFF"
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#include "error.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void RTMPError_Alloc(RTMPError *error, size_t msg_size) {
|
||||
RTMPError_Free(error);
|
||||
|
||||
error->code = 0;
|
||||
error->message = (char *)malloc(msg_size + 1);
|
||||
memset(error->message, 0, msg_size);
|
||||
}
|
||||
|
||||
void RTMPError_Free(RTMPError *error) {
|
||||
if (error) {
|
||||
if (error->message) {
|
||||
free(error->message);
|
||||
error->message = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RTMPError_Message(RTMPError *error, int code, const char *message) {
|
||||
RTMPError_Alloc(error, strlen(message));
|
||||
error->code = code;
|
||||
strcpy(error->message, message);
|
||||
}
|
||||
Executable
+46
@@ -0,0 +1,46 @@
|
||||
#ifndef __ERROR_H__
|
||||
#define __ERROR_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct RTMPError {
|
||||
int code;
|
||||
char *message;
|
||||
} RTMPError;
|
||||
|
||||
void RTMPError_Alloc(RTMPError *error, size_t msg_size);
|
||||
void RTMPError_Free(RTMPError *error);
|
||||
void RTMPError_Message(RTMPError *error, int code, const char *message);
|
||||
|
||||
// error defines
|
||||
enum {
|
||||
RTMPErrorUnknow = -1, // "Unknow error"
|
||||
RTMPErrorUnknowOption = -999, // "Unknown option %s"
|
||||
RTMPErrorAccessDNSFailed = -1000, // "Failed to access the DNS. (addr: %s)"
|
||||
RTMPErrorFailedToConnectSocket =
|
||||
-1001, // "Failed to connect socket. %d (%s)"
|
||||
RTMPErrorSocksNegotiationFailed = -1002, // "Socks negotiation failed"
|
||||
RTMPErrorFailedToCreateSocket =
|
||||
-1003, // "Failed to create socket. %d (%s)"
|
||||
RTMPErrorHandshakeFailed = -1004, // "Handshake failed"
|
||||
RTMPErrorRTMPConnectFailed = -1005, // "RTMP connect failed"
|
||||
RTMPErrorSendFailed = -1006, // "Send error %d (%s), (%d bytes)"
|
||||
RTMPErrorServerRequestedClose = -1007, // "RTMP server requested close"
|
||||
RTMPErrorNetStreamFailed = -1008, // "NetStream failed"
|
||||
RTMPErrorNetStreamPlayFailed = -1009, // "NetStream play failed"
|
||||
RTMPErrorNetStreamPlayStreamNotFound =
|
||||
-1010, // "NetStream play stream not found"
|
||||
RTMPErrorNetConnectionConnectInvalidApp =
|
||||
-1011, // "NetConnection connect invalip app"
|
||||
RTMPErrorSanityFailed =
|
||||
-1012, // "Sanity failed. Trying to send header of type: 0x%02X"
|
||||
RTMPErrorSocketClosedByPeer = -1013, // "RTMP socket closed by peer"
|
||||
RTMPErrorRTMPConnectStreamFailed = -1014, // "RTMP connect stream failed"
|
||||
RTMPErrorSocketTimeout = -1015, // "RTMP socket timeout"
|
||||
|
||||
// SSL errors
|
||||
RTMPErrorTLSConnectFailed = -1200, // "TLS_Connect failed"
|
||||
RTMPErrorNoSSLOrTLSSupport = -1201, // "No SSL/TLS support"
|
||||
};
|
||||
|
||||
#endif
|
||||
Executable
+1034
File diff suppressed because it is too large
Load Diff
Executable
+626
@@ -0,0 +1,626 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2010 Howard Chu
|
||||
*
|
||||
* This file is part of librtmp.
|
||||
*
|
||||
* librtmp is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* librtmp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with librtmp see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "http.h"
|
||||
#include "log.h"
|
||||
#include "rtmp_sys.h"
|
||||
|
||||
#ifdef CRYPTO
|
||||
#ifdef USE_POLARSSL
|
||||
#include <polarssl/sha2.h>
|
||||
#ifndef SHA256_DIGEST_LENGTH
|
||||
#define SHA256_DIGEST_LENGTH 32
|
||||
#endif
|
||||
#define HMAC_CTX sha2_context
|
||||
#define HMAC_setup(ctx, key, len) sha2_hmac_starts(&ctx, (unsigned char *)key, len, 0)
|
||||
#define HMAC_crunch(ctx, buf, len) sha2_hmac_update(&ctx, buf, len)
|
||||
#define HMAC_finish(ctx, dig, dlen) \
|
||||
dlen = SHA256_DIGEST_LENGTH; \
|
||||
sha2_hmac_finish(&ctx, dig)
|
||||
#define HMAC_close(ctx)
|
||||
#elif defined(USE_GNUTLS)
|
||||
#include <gcrypt.h>
|
||||
#include <gnutls/gnutls.h>
|
||||
#ifndef SHA256_DIGEST_LENGTH
|
||||
#define SHA256_DIGEST_LENGTH 32
|
||||
#endif
|
||||
#define HMAC_CTX gcry_md_hd_t
|
||||
#define HMAC_setup(ctx, key, len) \
|
||||
gcry_md_open(&ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); \
|
||||
gcry_md_setkey(ctx, key, len)
|
||||
#define HMAC_crunch(ctx, buf, len) gcry_md_write(ctx, buf, len)
|
||||
#define HMAC_finish(ctx, dig, dlen) \
|
||||
dlen = SHA256_DIGEST_LENGTH; \
|
||||
memcpy(dig, gcry_md_read(ctx, 0), dlen)
|
||||
#define HMAC_close(ctx) gcry_md_close(ctx)
|
||||
#else /* USE_OPENSSL */
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/rc4.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/ssl.h>
|
||||
#define HMAC_setup(ctx, key, len) \
|
||||
HMAC_CTX_init(&ctx); \
|
||||
HMAC_Init_ex(&ctx, (unsigned char *)key, len, EVP_sha256(), 0)
|
||||
#define HMAC_crunch(ctx, buf, len) HMAC_Update(&ctx, (unsigned char *)buf, len)
|
||||
#define HMAC_finish(ctx, dig, dlen) HMAC_Final(&ctx, (unsigned char *)dig, &dlen);
|
||||
#define HMAC_close(ctx) HMAC_CTX_cleanup(&ctx)
|
||||
#endif
|
||||
|
||||
extern void RTMP_TLS_Init();
|
||||
extern TLS_CTX RTMP_TLS_ctx;
|
||||
|
||||
#endif /* CRYPTO */
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#define AGENT "Mozilla/5.0"
|
||||
|
||||
HTTPResult
|
||||
HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb) {
|
||||
char *host, *path;
|
||||
char *p1, *p2;
|
||||
char hbuf[256];
|
||||
int port = 80;
|
||||
#ifdef CRYPTO
|
||||
int ssl = 0;
|
||||
#endif
|
||||
int hlen, flen = 0;
|
||||
int rc, i;
|
||||
int len_known;
|
||||
HTTPResult ret = HTTPRES_OK;
|
||||
// struct sockaddr_in sa;
|
||||
PILI_RTMPSockBuf sb = {0};
|
||||
|
||||
http->status = -1;
|
||||
|
||||
// memset(&sa, 0, sizeof(struct sockaddr_in));
|
||||
// sa.sin_family = AF_INET;
|
||||
|
||||
/* we only handle http here */
|
||||
if (strncasecmp(url, "http", 4))
|
||||
return HTTPRES_BAD_REQUEST;
|
||||
|
||||
if (url[4] == 's') {
|
||||
#ifdef CRYPTO
|
||||
ssl = 1;
|
||||
port = 443;
|
||||
if (!RTMP_TLS_ctx)
|
||||
RTMP_TLS_Init();
|
||||
#else
|
||||
return HTTPRES_BAD_REQUEST;
|
||||
#endif
|
||||
}
|
||||
|
||||
p1 = strchr(url + 4, ':');
|
||||
if (!p1 || strncmp(p1, "://", 3))
|
||||
return HTTPRES_BAD_REQUEST;
|
||||
|
||||
host = p1 + 3;
|
||||
path = strchr(host, '/');
|
||||
hlen = path - host;
|
||||
strncpy(hbuf, host, hlen);
|
||||
hbuf[hlen] = '\0';
|
||||
host = hbuf;
|
||||
p1 = strrchr(host, ':');
|
||||
if (p1) {
|
||||
*p1++ = '\0';
|
||||
port = atoi(p1);
|
||||
}
|
||||
|
||||
// sa.sin_addr.s_addr = inet_addr(host);
|
||||
// if (sa.sin_addr.s_addr == INADDR_NONE)
|
||||
// {
|
||||
// struct hostent *hp = gethostbyname(host);
|
||||
// if (!hp || !hp->h_addr)
|
||||
// return HTTPRES_LOST_CONNECTION;
|
||||
// sa.sin_addr = *(struct in_addr *)hp->h_addr;
|
||||
// }
|
||||
// sa.sin_port = htons(port);
|
||||
struct addrinfo hints = {0}, *ai, *cur_ai;
|
||||
char portstr[10];
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
snprintf(portstr, sizeof(portstr), "%d", port);
|
||||
ret = getaddrinfo(host, portstr, &hints, &ai);
|
||||
if (ret != 0) {
|
||||
return HTTPRES_LOST_CONNECTION;
|
||||
}
|
||||
|
||||
cur_ai = ai;
|
||||
|
||||
sb.sb_socket = socket(cur_ai->ai_family,
|
||||
cur_ai->ai_socktype,
|
||||
cur_ai->ai_protocol);
|
||||
// sb.sb_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sb.sb_socket == -1) {
|
||||
freeaddrinfo(ai);
|
||||
return HTTPRES_LOST_CONNECTION;
|
||||
}
|
||||
i = sprintf(sb.sb_buf,
|
||||
"GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\nReferrer: %.*s\r\n",
|
||||
path, AGENT, host, (int)(path - url + 1), url);
|
||||
if (http->date[0])
|
||||
i += sprintf(sb.sb_buf + i, "If-Modified-Since: %s\r\n", http->date);
|
||||
i += sprintf(sb.sb_buf + i, "\r\n");
|
||||
|
||||
if (cur_ai->ai_family == AF_INET6) {
|
||||
struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)cur_ai->ai_addr;
|
||||
in6->sin6_port = htons(port);
|
||||
}
|
||||
|
||||
if (connect(sb.sb_socket, cur_ai->ai_addr, cur_ai->ai_addrlen) < 0) {
|
||||
ret = HTTPRES_LOST_CONNECTION;
|
||||
goto leave;
|
||||
}
|
||||
#ifdef CRYPTO
|
||||
if (ssl) {
|
||||
#ifdef NO_SSL
|
||||
RTMP_Log(RTMP_LOGERROR, "%s, No SSL/TLS support", __FUNCTION__);
|
||||
ret = HTTPRES_BAD_REQUEST;
|
||||
goto leave;
|
||||
#else
|
||||
TLS_client(RTMP_TLS_ctx, sb.sb_ssl);
|
||||
TLS_setfd(sb.sb_ssl, sb.sb_socket);
|
||||
if ((i = TLS_connect(sb.sb_ssl)) < 0) {
|
||||
RTMP_Log(RTMP_LOGERROR, "%s, TLS_Connect failed", __FUNCTION__);
|
||||
ret = HTTPRES_LOST_CONNECTION;
|
||||
goto leave;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
PILI_RTMPSockBuf_Send(&sb, sb.sb_buf, i);
|
||||
|
||||
/* set timeout */
|
||||
#define HTTP_TIMEOUT 5
|
||||
{
|
||||
SET_RCVTIMEO(tv, HTTP_TIMEOUT);
|
||||
if (setsockopt(sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv))) {
|
||||
RTMP_Log(RTMP_LOGERROR, "%s, Setting socket timeout to %ds failed!",
|
||||
__FUNCTION__, HTTP_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
sb.sb_size = 0;
|
||||
sb.sb_timedout = FALSE;
|
||||
if (PILI_RTMPSockBuf_Fill(&sb, HTTP_TIMEOUT) < 1) {
|
||||
ret = HTTPRES_LOST_CONNECTION;
|
||||
goto leave;
|
||||
}
|
||||
if (strncmp(sb.sb_buf, "HTTP/1", 6)) {
|
||||
ret = HTTPRES_BAD_REQUEST;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
p1 = strchr(sb.sb_buf, ' ');
|
||||
rc = atoi(p1 + 1);
|
||||
http->status = rc;
|
||||
|
||||
if (rc >= 300) {
|
||||
if (rc == 304) {
|
||||
ret = HTTPRES_OK_NOT_MODIFIED;
|
||||
goto leave;
|
||||
} else if (rc == 404)
|
||||
ret = HTTPRES_NOT_FOUND;
|
||||
else if (rc >= 500)
|
||||
ret = HTTPRES_SERVER_ERROR;
|
||||
else if (rc >= 400)
|
||||
ret = HTTPRES_BAD_REQUEST;
|
||||
else
|
||||
ret = HTTPRES_REDIRECTED;
|
||||
}
|
||||
|
||||
p1 = memchr(sb.sb_buf, '\n', sb.sb_size);
|
||||
if (!p1) {
|
||||
ret = HTTPRES_BAD_REQUEST;
|
||||
goto leave;
|
||||
}
|
||||
sb.sb_start = p1 + 1;
|
||||
sb.sb_size -= sb.sb_start - sb.sb_buf;
|
||||
|
||||
while ((p2 = memchr(sb.sb_start, '\r', sb.sb_size))) {
|
||||
if (*sb.sb_start == '\r') {
|
||||
sb.sb_start += 2;
|
||||
sb.sb_size -= 2;
|
||||
break;
|
||||
} else if (!strncasecmp(sb.sb_start, "Content-Length: ", sizeof("Content-Length: ") - 1)) {
|
||||
flen = atoi(sb.sb_start + sizeof("Content-Length: ") - 1);
|
||||
} else if (!strncasecmp(sb.sb_start, "Last-Modified: ", sizeof("Last-Modified: ") - 1)) {
|
||||
*p2 = '\0';
|
||||
strcpy(http->date, sb.sb_start + sizeof("Last-Modified: ") - 1);
|
||||
}
|
||||
p2 += 2;
|
||||
sb.sb_size -= p2 - sb.sb_start;
|
||||
sb.sb_start = p2;
|
||||
if (sb.sb_size < 1) {
|
||||
if (PILI_RTMPSockBuf_Fill(&sb, HTTP_TIMEOUT) < 1) {
|
||||
ret = HTTPRES_LOST_CONNECTION;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len_known = flen > 0;
|
||||
while ((!len_known || flen > 0) &&
|
||||
(sb.sb_size > 0 || PILI_RTMPSockBuf_Fill(&sb, HTTP_TIMEOUT) > 0)) {
|
||||
cb(sb.sb_start, 1, sb.sb_size, http->data);
|
||||
if (len_known)
|
||||
flen -= sb.sb_size;
|
||||
http->size += sb.sb_size;
|
||||
sb.sb_size = 0;
|
||||
}
|
||||
|
||||
if (flen > 0)
|
||||
ret = HTTPRES_LOST_CONNECTION;
|
||||
|
||||
leave:
|
||||
PILI_RTMPSockBuf_Close(&sb);
|
||||
freeaddrinfo(ai);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CRYPTO
|
||||
|
||||
#define CHUNK 16384
|
||||
|
||||
struct info {
|
||||
z_stream *zs;
|
||||
HMAC_CTX ctx;
|
||||
int first;
|
||||
int zlib;
|
||||
int size;
|
||||
};
|
||||
|
||||
static size_t
|
||||
swfcrunch(void *ptr, size_t size, size_t nmemb, void *stream) {
|
||||
struct info *i = stream;
|
||||
char *p = ptr;
|
||||
size_t len = size * nmemb;
|
||||
|
||||
if (i->first) {
|
||||
i->first = 0;
|
||||
/* compressed? */
|
||||
if (!strncmp(p, "CWS", 3)) {
|
||||
*p = 'F';
|
||||
i->zlib = 1;
|
||||
}
|
||||
HMAC_crunch(i->ctx, (unsigned char *)p, 8);
|
||||
p += 8;
|
||||
len -= 8;
|
||||
i->size = 8;
|
||||
}
|
||||
|
||||
if (i->zlib) {
|
||||
unsigned char out[CHUNK];
|
||||
i->zs->next_in = (unsigned char *)p;
|
||||
i->zs->avail_in = len;
|
||||
do {
|
||||
i->zs->avail_out = CHUNK;
|
||||
i->zs->next_out = out;
|
||||
inflate(i->zs, Z_NO_FLUSH);
|
||||
len = CHUNK - i->zs->avail_out;
|
||||
i->size += len;
|
||||
HMAC_crunch(i->ctx, out, len);
|
||||
} while (i->zs->avail_out == 0);
|
||||
} else {
|
||||
i->size += len;
|
||||
HMAC_crunch(i->ctx, (unsigned char *)p, len);
|
||||
}
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
static int tzoff;
|
||||
static int tzchecked;
|
||||
|
||||
#define JAN02_1980 318340800
|
||||
|
||||
static const char *monthtab[12] = {"Jan", "Feb", "Mar",
|
||||
"Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep",
|
||||
"Oct", "Nov", "Dec"};
|
||||
static const char *days[] =
|
||||
{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
||||
|
||||
/* Parse an HTTP datestamp into Unix time */
|
||||
static time_t
|
||||
make_unix_time(char *s) {
|
||||
struct tm time;
|
||||
int i, ysub = 1900, fmt = 0;
|
||||
char *month;
|
||||
char *n;
|
||||
time_t res;
|
||||
|
||||
if (s[3] != ' ') {
|
||||
fmt = 1;
|
||||
if (s[3] != ',')
|
||||
ysub = 0;
|
||||
}
|
||||
for (n = s; *n; ++n)
|
||||
if (*n == '-' || *n == ':')
|
||||
*n = ' ';
|
||||
|
||||
time.tm_mon = 0;
|
||||
n = strchr(s, ' ');
|
||||
if (fmt) {
|
||||
/* Day, DD-MMM-YYYY HH:MM:SS GMT */
|
||||
time.tm_mday = strtol(n + 1, &n, 0);
|
||||
month = n + 1;
|
||||
n = strchr(month, ' ');
|
||||
time.tm_year = strtol(n + 1, &n, 0);
|
||||
time.tm_hour = strtol(n + 1, &n, 0);
|
||||
time.tm_min = strtol(n + 1, &n, 0);
|
||||
time.tm_sec = strtol(n + 1, NULL, 0);
|
||||
} else {
|
||||
/* Unix ctime() format. Does not conform to HTTP spec. */
|
||||
/* Day MMM DD HH:MM:SS YYYY */
|
||||
month = n + 1;
|
||||
n = strchr(month, ' ');
|
||||
while (isspace(*n))
|
||||
n++;
|
||||
time.tm_mday = strtol(n, &n, 0);
|
||||
time.tm_hour = strtol(n + 1, &n, 0);
|
||||
time.tm_min = strtol(n + 1, &n, 0);
|
||||
time.tm_sec = strtol(n + 1, &n, 0);
|
||||
time.tm_year = strtol(n + 1, NULL, 0);
|
||||
}
|
||||
if (time.tm_year > 100)
|
||||
time.tm_year -= ysub;
|
||||
|
||||
for (i = 0; i < 12; i++)
|
||||
if (!strncasecmp(month, monthtab[i], 3)) {
|
||||
time.tm_mon = i;
|
||||
break;
|
||||
}
|
||||
time.tm_isdst = 0; /* daylight saving is never in effect in GMT */
|
||||
|
||||
/* this is normally the value of extern int timezone, but some
|
||||
* braindead C libraries don't provide it.
|
||||
*/
|
||||
if (!tzchecked) {
|
||||
struct tm *tc;
|
||||
time_t then = JAN02_1980;
|
||||
tc = localtime(&then);
|
||||
tzoff = (12 - tc->tm_hour) * 3600 + tc->tm_min * 60 + tc->tm_sec;
|
||||
tzchecked = 1;
|
||||
}
|
||||
res = mktime(&time);
|
||||
/* Unfortunately, mktime() assumes the input is in local time,
|
||||
* not GMT, so we have to correct it here.
|
||||
*/
|
||||
if (res != -1)
|
||||
res += tzoff;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Convert a Unix time to a network time string
|
||||
* Weekday, DD-MMM-YYYY HH:MM:SS GMT
|
||||
*/
|
||||
void strtime(time_t *t, char *s) {
|
||||
struct tm *tm;
|
||||
|
||||
tm = gmtime((time_t *)t);
|
||||
sprintf(s, "%s, %02d %s %d %02d:%02d:%02d GMT",
|
||||
days[tm->tm_wday], tm->tm_mday, monthtab[tm->tm_mon],
|
||||
tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
}
|
||||
|
||||
#define HEX2BIN(a) (((a)&0x40) ? ((a)&0xf) + 9 : ((a)&0xf))
|
||||
|
||||
int RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash,
|
||||
int age) {
|
||||
FILE *f = NULL;
|
||||
char *path, date[64], cctim[64];
|
||||
long pos = 0;
|
||||
time_t ctim = -1, cnow;
|
||||
int i, got = 0, ret = 0;
|
||||
unsigned int hlen;
|
||||
struct info in = {0};
|
||||
struct HTTP_ctx http = {0};
|
||||
HTTPResult httpres;
|
||||
z_stream zs = {0};
|
||||
AVal home, hpre;
|
||||
|
||||
date[0] = '\0';
|
||||
#ifdef _WIN32
|
||||
#ifdef _XBOX
|
||||
hpre.av_val = "Q:";
|
||||
hpre.av_len = 2;
|
||||
home.av_val = "\\UserData";
|
||||
#else
|
||||
hpre.av_val = getenv("HOMEDRIVE");
|
||||
hpre.av_len = strlen(hpre.av_val);
|
||||
home.av_val = getenv("HOMEPATH");
|
||||
#endif
|
||||
#define DIRSEP "\\"
|
||||
|
||||
#else /* !_WIN32 */
|
||||
hpre.av_val = "";
|
||||
hpre.av_len = 0;
|
||||
home.av_val = getenv("HOME");
|
||||
#define DIRSEP "/"
|
||||
#endif
|
||||
if (!home.av_val)
|
||||
home.av_val = ".";
|
||||
home.av_len = strlen(home.av_val);
|
||||
|
||||
/* SWF hash info is cached in a fixed-format file.
|
||||
* url: <url of SWF file>
|
||||
* ctim: HTTP datestamp of when we last checked it.
|
||||
* date: HTTP datestamp of the SWF's last modification.
|
||||
* size: SWF size in hex
|
||||
* hash: SWF hash in hex
|
||||
*
|
||||
* These fields must be present in this order. All fields
|
||||
* besides URL are fixed size.
|
||||
*/
|
||||
path = malloc(hpre.av_len + home.av_len + sizeof(DIRSEP ".swfinfo"));
|
||||
sprintf(path, "%s%s" DIRSEP ".swfinfo", hpre.av_val, home.av_val);
|
||||
|
||||
f = fopen(path, "r+");
|
||||
while (f) {
|
||||
char buf[4096], *file, *p;
|
||||
|
||||
file = strchr(url, '/');
|
||||
if (!file)
|
||||
break;
|
||||
file += 2;
|
||||
file = strchr(file, '/');
|
||||
if (!file)
|
||||
break;
|
||||
file++;
|
||||
hlen = file - url;
|
||||
p = strrchr(file, '/');
|
||||
if (p)
|
||||
file = p;
|
||||
else
|
||||
file--;
|
||||
|
||||
while (fgets(buf, sizeof(buf), f)) {
|
||||
char *r1;
|
||||
|
||||
got = 0;
|
||||
|
||||
if (strncmp(buf, "url: ", 5))
|
||||
continue;
|
||||
if (strncmp(buf + 5, url, hlen))
|
||||
continue;
|
||||
r1 = strrchr(buf, '/');
|
||||
i = strlen(r1);
|
||||
r1[--i] = '\0';
|
||||
if (strncmp(r1, file, i))
|
||||
continue;
|
||||
pos = ftell(f);
|
||||
while (got < 4 && fgets(buf, sizeof(buf), f)) {
|
||||
if (!strncmp(buf, "size: ", 6)) {
|
||||
*size = strtol(buf + 6, NULL, 16);
|
||||
got++;
|
||||
} else if (!strncmp(buf, "hash: ", 6)) {
|
||||
unsigned char *ptr = hash, *in = (unsigned char *)buf + 6;
|
||||
int l = strlen((char *)in) - 1;
|
||||
for (i = 0; i < l; i += 2)
|
||||
*ptr++ = (HEX2BIN(in[i]) << 4) | HEX2BIN(in[i + 1]);
|
||||
got++;
|
||||
} else if (!strncmp(buf, "date: ", 6)) {
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
strncpy(date, buf + 6, sizeof(date));
|
||||
got++;
|
||||
} else if (!strncmp(buf, "ctim: ", 6)) {
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
ctim = make_unix_time(buf + 6);
|
||||
got++;
|
||||
} else if (!strncmp(buf, "url: ", 5))
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cnow = time(NULL);
|
||||
/* If we got a cache time, see if it's young enough to use directly */
|
||||
if (age && ctim > 0) {
|
||||
ctim = cnow - ctim;
|
||||
ctim /= 3600 * 24; /* seconds to days */
|
||||
if (ctim < age) /* ok, it's new enough */
|
||||
goto out;
|
||||
}
|
||||
|
||||
in.first = 1;
|
||||
HMAC_setup(in.ctx, "Genuine Adobe Flash Player 001", 30);
|
||||
inflateInit(&zs);
|
||||
in.zs = &zs;
|
||||
|
||||
http.date = date;
|
||||
http.data = ∈
|
||||
|
||||
httpres = HTTP_get(&http, url, swfcrunch);
|
||||
|
||||
inflateEnd(&zs);
|
||||
|
||||
if (httpres != HTTPRES_OK && httpres != HTTPRES_OK_NOT_MODIFIED) {
|
||||
ret = -1;
|
||||
if (httpres == HTTPRES_LOST_CONNECTION)
|
||||
RTMP_Log(RTMP_LOGERROR, "%s: connection lost while downloading swfurl %s",
|
||||
__FUNCTION__, url);
|
||||
else if (httpres == HTTPRES_NOT_FOUND)
|
||||
RTMP_Log(RTMP_LOGERROR, "%s: swfurl %s not found", __FUNCTION__, url);
|
||||
else
|
||||
RTMP_Log(RTMP_LOGERROR, "%s: couldn't contact swfurl %s (HTTP error %d)",
|
||||
__FUNCTION__, url, http.status);
|
||||
} else {
|
||||
if (got && pos)
|
||||
fseek(f, pos, SEEK_SET);
|
||||
else {
|
||||
char *q;
|
||||
if (!f)
|
||||
f = fopen(path, "w");
|
||||
if (!f) {
|
||||
int err = errno;
|
||||
RTMP_Log(RTMP_LOGERROR,
|
||||
"%s: couldn't open %s for writing, errno %d (%s)",
|
||||
__FUNCTION__, path, err, strerror(err));
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
fseek(f, 0, SEEK_END);
|
||||
q = strchr(url, '?');
|
||||
if (q)
|
||||
i = q - url;
|
||||
else
|
||||
i = strlen(url);
|
||||
|
||||
fprintf(f, "url: %.*s\n", i, url);
|
||||
}
|
||||
strtime(&cnow, cctim);
|
||||
fprintf(f, "ctim: %s\n", cctim);
|
||||
|
||||
if (!in.first) {
|
||||
HMAC_finish(in.ctx, hash, hlen);
|
||||
*size = in.size;
|
||||
|
||||
fprintf(f, "date: %s\n", date);
|
||||
fprintf(f, "size: %08x\n", in.size);
|
||||
fprintf(f, "hash: ");
|
||||
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
||||
fprintf(f, "%02x", hash[i]);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
}
|
||||
HMAC_close(in.ctx);
|
||||
out:
|
||||
free(path);
|
||||
if (f)
|
||||
fclose(f);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
int RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash,
|
||||
int age) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
#ifndef __RTMP_HTTP_H__
|
||||
#define __RTMP_HTTP_H__
|
||||
/*
|
||||
* Copyright (C) 2010 Howard Chu
|
||||
* Copyright (C) 2010 Antti Ajanki
|
||||
*
|
||||
* This file is part of librtmp.
|
||||
*
|
||||
* librtmp is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* librtmp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with librtmp see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
HTTPRES_OK, /* result OK */
|
||||
HTTPRES_OK_NOT_MODIFIED, /* not modified since last request */
|
||||
HTTPRES_NOT_FOUND, /* not found */
|
||||
HTTPRES_BAD_REQUEST, /* client error */
|
||||
HTTPRES_SERVER_ERROR, /* server reported an error */
|
||||
HTTPRES_REDIRECTED, /* resource has been moved */
|
||||
HTTPRES_LOST_CONNECTION /* connection lost while waiting for data */
|
||||
} HTTPResult;
|
||||
|
||||
struct HTTP_ctx {
|
||||
char *date;
|
||||
int size;
|
||||
int status;
|
||||
void *data;
|
||||
};
|
||||
|
||||
typedef size_t(HTTP_read_callback)(void *ptr, size_t size, size_t nmemb,
|
||||
void *stream);
|
||||
|
||||
HTTPResult HTTP_get(struct HTTP_ctx *http, const char *url,
|
||||
HTTP_read_callback *cb);
|
||||
|
||||
#endif
|
||||
Executable
+209
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2009 Andrej Stepanchuk
|
||||
* Copyright (C) 2009-2010 Howard Chu
|
||||
*
|
||||
* This file is part of librtmp.
|
||||
*
|
||||
* librtmp is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* librtmp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with librtmp see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "rtmp_sys.h"
|
||||
|
||||
#define MAX_PRINT_LEN 2048
|
||||
|
||||
RTMP_LogLevel RTMP_debuglevel = RTMP_LOGERROR;
|
||||
|
||||
static int neednl;
|
||||
|
||||
static FILE *fmsg;
|
||||
|
||||
static RTMP_LogCallback rtmp_log_default, *cb = rtmp_log_default;
|
||||
|
||||
static const char *levels[] = {
|
||||
"CRIT", "ERROR", "WARNING", "INFO",
|
||||
"DEBUG", "DEBUG2"};
|
||||
|
||||
static void rtmp_log_default(int level, const char *format, va_list vl) {
|
||||
char str[MAX_PRINT_LEN] = "";
|
||||
|
||||
vsnprintf(str, MAX_PRINT_LEN - 1, format, vl);
|
||||
|
||||
/* Filter out 'no-name' */
|
||||
if (RTMP_debuglevel < RTMP_LOGALL && strstr(str, "no-name") != NULL)
|
||||
return;
|
||||
|
||||
if (!fmsg) fmsg = stderr;
|
||||
|
||||
if (level <= RTMP_debuglevel) {
|
||||
if (neednl) {
|
||||
putc('\n', fmsg);
|
||||
neednl = 0;
|
||||
}
|
||||
fprintf(fmsg, "%s: %s\n", levels[level], str);
|
||||
#ifdef _DEBUG
|
||||
fflush(fmsg);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void RTMP_LogSetOutput(FILE *file) {
|
||||
fmsg = file;
|
||||
}
|
||||
|
||||
void RTMP_LogSetLevel(RTMP_LogLevel level) {
|
||||
RTMP_debuglevel = level;
|
||||
}
|
||||
|
||||
void RTMP_LogSetCallback(RTMP_LogCallback *cbp) {
|
||||
cb = cbp;
|
||||
}
|
||||
|
||||
RTMP_LogLevel RTMP_LogGetLevel() {
|
||||
return RTMP_debuglevel;
|
||||
}
|
||||
|
||||
void RTMP_Log(int level, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
cb(level, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static const char hexdig[] = "0123456789abcdef";
|
||||
|
||||
void RTMP_LogHex(int level, const uint8_t *data, unsigned long len) {
|
||||
unsigned long i;
|
||||
char line[50], *ptr;
|
||||
|
||||
if (level > RTMP_debuglevel)
|
||||
return;
|
||||
|
||||
ptr = line;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
*ptr++ = hexdig[0x0f & (data[i] >> 4)];
|
||||
*ptr++ = hexdig[0x0f & data[i]];
|
||||
if ((i & 0x0f) == 0x0f) {
|
||||
*ptr = '\0';
|
||||
ptr = line;
|
||||
RTMP_Log(level, "%s", line);
|
||||
} else {
|
||||
*ptr++ = ' ';
|
||||
}
|
||||
}
|
||||
if (i & 0x0f) {
|
||||
*ptr = '\0';
|
||||
RTMP_Log(level, "%s", line);
|
||||
}
|
||||
}
|
||||
|
||||
void RTMP_LogHexString(int level, const uint8_t *data, unsigned long len) {
|
||||
#define BP_OFFSET 9
|
||||
#define BP_GRAPH 60
|
||||
#define BP_LEN 80
|
||||
char line[BP_LEN];
|
||||
unsigned long i;
|
||||
|
||||
if (!data || level > RTMP_debuglevel)
|
||||
return;
|
||||
|
||||
/* in case len is zero */
|
||||
line[0] = '\0';
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
int n = i % 16;
|
||||
unsigned off;
|
||||
|
||||
if (!n) {
|
||||
if (i) RTMP_Log(level, "%s", line);
|
||||
memset(line, ' ', sizeof(line) - 2);
|
||||
line[sizeof(line) - 2] = '\0';
|
||||
|
||||
off = i % 0x0ffffU;
|
||||
|
||||
line[2] = hexdig[0x0f & (off >> 12)];
|
||||
line[3] = hexdig[0x0f & (off >> 8)];
|
||||
line[4] = hexdig[0x0f & (off >> 4)];
|
||||
line[5] = hexdig[0x0f & off];
|
||||
line[6] = ':';
|
||||
}
|
||||
|
||||
off = BP_OFFSET + n * 3 + ((n >= 8) ? 1 : 0);
|
||||
line[off] = hexdig[0x0f & (data[i] >> 4)];
|
||||
line[off + 1] = hexdig[0x0f & data[i]];
|
||||
|
||||
off = BP_GRAPH + n + ((n >= 8) ? 1 : 0);
|
||||
|
||||
if (isprint(data[i])) {
|
||||
line[BP_GRAPH + n] = data[i];
|
||||
} else {
|
||||
line[BP_GRAPH + n] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
RTMP_Log(level, "%s", line);
|
||||
}
|
||||
|
||||
/* These should only be used by apps, never by the library itself */
|
||||
void RTMP_LogPrintf(const char *format, ...) {
|
||||
char str[MAX_PRINT_LEN] = "";
|
||||
int len;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
len = vsnprintf(str, MAX_PRINT_LEN - 1, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (RTMP_debuglevel == RTMP_LOGCRIT)
|
||||
return;
|
||||
|
||||
if (!fmsg) fmsg = stderr;
|
||||
|
||||
if (neednl) {
|
||||
putc('\n', fmsg);
|
||||
neednl = 0;
|
||||
}
|
||||
|
||||
if (len > MAX_PRINT_LEN - 1)
|
||||
len = MAX_PRINT_LEN - 1;
|
||||
fprintf(fmsg, "%s", str);
|
||||
if (str[len - 1] == '\n')
|
||||
fflush(fmsg);
|
||||
}
|
||||
|
||||
void RTMP_LogStatus(const char *format, ...) {
|
||||
char str[MAX_PRINT_LEN] = "";
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsnprintf(str, MAX_PRINT_LEN - 1, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (RTMP_debuglevel == RTMP_LOGCRIT)
|
||||
return;
|
||||
|
||||
if (!fmsg) fmsg = stderr;
|
||||
|
||||
fprintf(fmsg, "%s", str);
|
||||
fflush(fmsg);
|
||||
neednl = 1;
|
||||
}
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2009 Andrej Stepanchuk
|
||||
* Copyright (C) 2009-2010 Howard Chu
|
||||
*
|
||||
* This file is part of librtmp.
|
||||
*
|
||||
* librtmp is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* librtmp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with librtmp see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#ifndef __RTMP_LOG_H__
|
||||
#define __RTMP_LOG_H__
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* Enable this to get full debugging output */
|
||||
/* #define _DEBUG */
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef NODEBUG
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
RTMP_LOGCRIT = 0,
|
||||
RTMP_LOGERROR,
|
||||
RTMP_LOGWARNING,
|
||||
RTMP_LOGINFO,
|
||||
RTMP_LOGDEBUG,
|
||||
RTMP_LOGDEBUG2,
|
||||
RTMP_LOGALL
|
||||
} RTMP_LogLevel;
|
||||
|
||||
extern RTMP_LogLevel RTMP_debuglevel;
|
||||
|
||||
typedef void(RTMP_LogCallback)(int level, const char *fmt, va_list);
|
||||
void RTMP_LogSetCallback(RTMP_LogCallback *cb);
|
||||
void RTMP_LogSetOutput(FILE *file);
|
||||
void RTMP_LogPrintf(const char *format, ...);
|
||||
void RTMP_LogStatus(const char *format, ...);
|
||||
void RTMP_Log(int level, const char *format, ...);
|
||||
void RTMP_LogHex(int level, const uint8_t *data, unsigned long len);
|
||||
void RTMP_LogHexString(int level, const uint8_t *data, unsigned long len);
|
||||
void RTMP_LogSetLevel(RTMP_LogLevel lvl);
|
||||
RTMP_LogLevel RTMP_LogGetLevel(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Executable
+312
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright (C) 2009 Andrej Stepanchuk
|
||||
* Copyright (C) 2009-2010 Howard Chu
|
||||
*
|
||||
* This file is part of librtmp.
|
||||
*
|
||||
* librtmp is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* librtmp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with librtmp see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "rtmp_sys.h"
|
||||
|
||||
int PILI_RTMP_ParseURL2(const char *url, int *protocol, AVal *host, unsigned int *port,
|
||||
AVal *playpath, AVal *app, AVal *domainName) {
|
||||
char *p, *end, *col, *ques, *slash;
|
||||
|
||||
RTMP_Log(RTMP_LOGDEBUG, "Parsing...");
|
||||
|
||||
*protocol = RTMP_PROTOCOL_RTMP;
|
||||
*port = 0;
|
||||
playpath->av_len = 0;
|
||||
playpath->av_val = NULL;
|
||||
app->av_len = 0;
|
||||
app->av_val = NULL;
|
||||
|
||||
/* Old School Parsing */
|
||||
|
||||
/* look for usual :// pattern */
|
||||
p = strstr(url, "://");
|
||||
if (!p) {
|
||||
RTMP_Log(RTMP_LOGERROR, "RTMP URL: No :// in url!");
|
||||
return FALSE;
|
||||
}
|
||||
{
|
||||
int len = (int)(p - url);
|
||||
|
||||
if (len == 4 && strncasecmp(url, "rtmp", 4) == 0)
|
||||
*protocol = RTMP_PROTOCOL_RTMP;
|
||||
else if (len == 5 && strncasecmp(url, "rtmpt", 5) == 0)
|
||||
*protocol = RTMP_PROTOCOL_RTMPT;
|
||||
else if (len == 5 && strncasecmp(url, "rtmps", 5) == 0)
|
||||
*protocol = RTMP_PROTOCOL_RTMPS;
|
||||
else if (len == 5 && strncasecmp(url, "rtmpe", 5) == 0)
|
||||
*protocol = RTMP_PROTOCOL_RTMPE;
|
||||
else if (len == 5 && strncasecmp(url, "rtmfp", 5) == 0)
|
||||
*protocol = RTMP_PROTOCOL_RTMFP;
|
||||
else if (len == 6 && strncasecmp(url, "rtmpte", 6) == 0)
|
||||
*protocol = RTMP_PROTOCOL_RTMPTE;
|
||||
else if (len == 6 && strncasecmp(url, "rtmpts", 6) == 0)
|
||||
*protocol = RTMP_PROTOCOL_RTMPTS;
|
||||
else {
|
||||
RTMP_Log(RTMP_LOGWARNING, "Unknown protocol!\n");
|
||||
goto parsehost;
|
||||
}
|
||||
}
|
||||
|
||||
RTMP_Log(RTMP_LOGDEBUG, "Parsed protocol: %d", *protocol);
|
||||
|
||||
parsehost:
|
||||
/* let's get the hostname */
|
||||
p += 3;
|
||||
|
||||
/* check for sudden death */
|
||||
if (*p == 0) {
|
||||
RTMP_Log(RTMP_LOGWARNING, "No hostname in URL!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
end = p + strlen(p);
|
||||
col = strchr(p, ':');
|
||||
ques = strchr(p, '?');
|
||||
slash = strchr(p, '/');
|
||||
|
||||
{
|
||||
int hostlen;
|
||||
if (slash)
|
||||
hostlen = slash - p;
|
||||
else
|
||||
hostlen = end - p;
|
||||
if (col && col - p < hostlen)
|
||||
hostlen = col - p;
|
||||
|
||||
if (hostlen < 256) {
|
||||
host->av_val = p;
|
||||
host->av_len = hostlen;
|
||||
RTMP_Log(RTMP_LOGDEBUG, "Parsed host : %.*s", hostlen, host->av_val);
|
||||
} else {
|
||||
RTMP_Log(RTMP_LOGWARNING, "Hostname exceeds 255 characters!");
|
||||
}
|
||||
|
||||
p += hostlen;
|
||||
}
|
||||
|
||||
/* get the port number if available */
|
||||
if (*p == ':') {
|
||||
unsigned int p2;
|
||||
p++;
|
||||
p2 = atoi(p);
|
||||
if (p2 > 65535) {
|
||||
RTMP_Log(RTMP_LOGWARNING, "Invalid port number!");
|
||||
} else {
|
||||
*port = p2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!slash) {
|
||||
RTMP_Log(RTMP_LOGWARNING, "No application or playpath in URL!");
|
||||
return TRUE;
|
||||
}
|
||||
p = slash + 1;
|
||||
|
||||
/** parse domain
|
||||
+ * rtmp://host:[port]/app/...?domain=a.com
|
||||
+ * use domain to replace host
|
||||
+ */
|
||||
|
||||
if (domainName != NULL && ques != NULL) {
|
||||
char *domain = strstr(ques, "domain=");
|
||||
if (domain) {
|
||||
end = domain - 1;
|
||||
domain += 7; //skip "domain="
|
||||
char *domain_end = strchr(domain, '&');
|
||||
int host_len = 0;
|
||||
if (domain_end) {
|
||||
host_len = domain_end - domain;
|
||||
} else {
|
||||
host_len = strlen(domain);
|
||||
}
|
||||
if (host_len < 256) {
|
||||
domainName->av_val = domain;
|
||||
domainName->av_len = host_len;
|
||||
RTMP_Log(RTMP_LOGDEBUG, "Parsed host and domain : %.*s", host_len, host->av_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* parse application
|
||||
*
|
||||
* rtmp://host[:port]/app[/appinstance][/...]
|
||||
* application = app[/appinstance]
|
||||
*/
|
||||
|
||||
char *slash2, *slash3 = NULL;
|
||||
int applen, appnamelen;
|
||||
|
||||
slash2 = strchr(p, '/');
|
||||
if (slash2)
|
||||
slash3 = strchr(slash2 + 1, '/');
|
||||
|
||||
applen = end - p; /* ondemand, pass all parameters as app */
|
||||
appnamelen = applen; /* ondemand length */
|
||||
|
||||
if (ques && strstr(p, "slist=")) { /* whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist= */
|
||||
appnamelen = ques - p;
|
||||
} else if (strncmp(p, "ondemand/", 9) == 0) {
|
||||
/* app = ondemand/foobar, only pass app=ondemand */
|
||||
applen = 8;
|
||||
appnamelen = 8;
|
||||
} else { /* app!=ondemand, so app is app[/appinstance] */
|
||||
if (slash3)
|
||||
appnamelen = slash3 - p;
|
||||
else if (slash2)
|
||||
appnamelen = slash2 - p;
|
||||
|
||||
applen = appnamelen;
|
||||
}
|
||||
|
||||
app->av_val = p;
|
||||
app->av_len = applen;
|
||||
RTMP_Log(RTMP_LOGDEBUG, "Parsed app : %.*s", applen, p);
|
||||
|
||||
p += appnamelen;
|
||||
}
|
||||
|
||||
if (*p == '/')
|
||||
p++;
|
||||
|
||||
if (end - p) {
|
||||
AVal av = {p, end - p};
|
||||
PILI_RTMP_ParsePlaypath(&av, playpath);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extracts playpath from RTMP URL. playpath is the file part of the
|
||||
* URL, i.e. the part that comes after rtmp://host:port/app/
|
||||
*
|
||||
* Returns the stream name in a format understood by FMS. The name is
|
||||
* the playpath part of the URL with formatting depending on the stream
|
||||
* type:
|
||||
*
|
||||
* mp4 streams: prepend "mp4:", remove extension
|
||||
* mp3 streams: prepend "mp3:", remove extension
|
||||
* flv streams: remove extension
|
||||
*/
|
||||
void PILI_RTMP_ParsePlaypath(AVal *in, AVal *out) {
|
||||
int addMP4 = 0;
|
||||
int addMP3 = 0;
|
||||
int subExt = 0;
|
||||
const char *playpath = in->av_val;
|
||||
const char *temp, *q, *ext = NULL;
|
||||
const char *ppstart = playpath;
|
||||
char *streamname, *destptr, *p;
|
||||
|
||||
int pplen = in->av_len;
|
||||
|
||||
out->av_val = NULL;
|
||||
out->av_len = 0;
|
||||
|
||||
if ((*ppstart == '?') &&
|
||||
(temp = strstr(ppstart, "slist=")) != 0) {
|
||||
ppstart = temp + 6;
|
||||
pplen = strlen(ppstart);
|
||||
|
||||
temp = strchr(ppstart, '&');
|
||||
if (temp) {
|
||||
pplen = temp - ppstart;
|
||||
}
|
||||
}
|
||||
|
||||
q = strchr(ppstart, '?');
|
||||
if (pplen >= 4) {
|
||||
if (q)
|
||||
ext = q - 4;
|
||||
else
|
||||
ext = &ppstart[pplen - 4];
|
||||
if ((strncmp(ext, ".f4v", 4) == 0) ||
|
||||
(strncmp(ext, ".mp4", 4) == 0)) {
|
||||
addMP4 = 1;
|
||||
subExt = 1;
|
||||
/* Only remove .flv from rtmp URL, not slist params */
|
||||
} else if ((ppstart == playpath) &&
|
||||
(strncmp(ext, ".flv", 4) == 0)) {
|
||||
subExt = 1;
|
||||
} else if (strncmp(ext, ".mp3", 4) == 0) {
|
||||
addMP3 = 1;
|
||||
subExt = 1;
|
||||
}
|
||||
}
|
||||
|
||||
streamname = (char *)malloc((pplen + 4 + 1) * sizeof(char));
|
||||
if (!streamname)
|
||||
return;
|
||||
|
||||
destptr = streamname;
|
||||
if (addMP4) {
|
||||
if (strncmp(ppstart, "mp4:", 4)) {
|
||||
strcpy(destptr, "mp4:");
|
||||
destptr += 4;
|
||||
} else {
|
||||
subExt = 0;
|
||||
}
|
||||
} else if (addMP3) {
|
||||
if (strncmp(ppstart, "mp3:", 4)) {
|
||||
strcpy(destptr, "mp3:");
|
||||
destptr += 4;
|
||||
} else {
|
||||
subExt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (p = (char *)ppstart; pplen > 0;) {
|
||||
/* skip extension */
|
||||
if (subExt && p == ext) {
|
||||
p += 4;
|
||||
pplen -= 4;
|
||||
continue;
|
||||
}
|
||||
if (*p == '%') {
|
||||
unsigned int c;
|
||||
sscanf(p + 1, "%02x", &c);
|
||||
*destptr++ = c;
|
||||
pplen -= 3;
|
||||
p += 3;
|
||||
} else {
|
||||
*destptr++ = *p++;
|
||||
pplen--;
|
||||
}
|
||||
}
|
||||
*destptr = '\0';
|
||||
|
||||
out->av_val = streamname;
|
||||
out->av_len = destptr - streamname;
|
||||
}
|
||||
|
||||
int PILI_RTMP_ParseURL(const char *url, int *protocol, AVal *host,
|
||||
unsigned int *port, AVal *playpath, AVal *app) {
|
||||
return PILI_RTMP_ParseURL2(url, protocol, host, port, playpath, app, NULL);
|
||||
}
|
||||
Executable
+4331
File diff suppressed because it is too large
Load Diff
Executable
+365
@@ -0,0 +1,365 @@
|
||||
#ifndef __RTMP_H__
|
||||
#define __RTMP_H__
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Team XBMC
|
||||
* http://www.xbmc.org
|
||||
* Copyright (C) 2008-2009 Andrej Stepanchuk
|
||||
* Copyright (C) 2009-2010 Howard Chu
|
||||
*
|
||||
* This file is part of librtmp.
|
||||
*
|
||||
* librtmp is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* librtmp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with librtmp see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#define NO_CRYPTO
|
||||
|
||||
#if !defined(NO_CRYPTO) && !defined(CRYPTO)
|
||||
#define CRYPTO
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "amf.h"
|
||||
#include "error.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RTMP_LIB_VERSION 0x020300 /* 2.3 */
|
||||
|
||||
#define RTMP_FEATURE_HTTP 0x01
|
||||
#define RTMP_FEATURE_ENC 0x02
|
||||
#define RTMP_FEATURE_SSL 0x04
|
||||
#define RTMP_FEATURE_MFP 0x08 /* not yet supported */
|
||||
#define RTMP_FEATURE_WRITE 0x10 /* publish, not play */
|
||||
#define RTMP_FEATURE_HTTP2 0x20 /* server-side rtmpt */
|
||||
#define RTMP_FEATURE_NONBLOCK 0x40 /* non block socket */
|
||||
|
||||
#define RTMP_PROTOCOL_UNDEFINED -1
|
||||
#define RTMP_PROTOCOL_RTMP 0
|
||||
#define RTMP_PROTOCOL_RTMPE RTMP_FEATURE_ENC
|
||||
#define RTMP_PROTOCOL_RTMPT RTMP_FEATURE_HTTP
|
||||
#define RTMP_PROTOCOL_RTMPS RTMP_FEATURE_SSL
|
||||
#define RTMP_PROTOCOL_RTMPTE (RTMP_FEATURE_HTTP | RTMP_FEATURE_ENC)
|
||||
#define RTMP_PROTOCOL_RTMPTS (RTMP_FEATURE_HTTP | RTMP_FEATURE_SSL)
|
||||
#define RTMP_PROTOCOL_RTMFP RTMP_FEATURE_MFP
|
||||
|
||||
#define RTMP_DEFAULT_CHUNKSIZE 128
|
||||
|
||||
/* needs to fit largest number of bytes recv() may return */
|
||||
#define RTMP_BUFFER_CACHE_SIZE (16 * 1024)
|
||||
|
||||
#define RTMP_CHANNELS 65600
|
||||
|
||||
extern const char PILI_RTMPProtocolStringsLower[][7];
|
||||
extern const AVal PILI_RTMP_DefaultFlashVer;
|
||||
extern int PILI_RTMP_ctrlC;
|
||||
|
||||
uint32_t PILI_RTMP_GetTime(void);
|
||||
|
||||
#define RTMP_PACKET_TYPE_AUDIO 0x08
|
||||
#define RTMP_PACKET_TYPE_VIDEO 0x09
|
||||
#define RTMP_PACKET_TYPE_INFO 0x12
|
||||
|
||||
#define RTMP_MAX_HEADER_SIZE 18
|
||||
|
||||
#define RTMP_PACKET_SIZE_LARGE 0
|
||||
#define RTMP_PACKET_SIZE_MEDIUM 1
|
||||
#define RTMP_PACKET_SIZE_SMALL 2
|
||||
#define RTMP_PACKET_SIZE_MINIMUM 3
|
||||
|
||||
typedef struct PILI_RTMPChunk {
|
||||
int c_headerSize;
|
||||
int c_chunkSize;
|
||||
char *c_chunk;
|
||||
char c_header[RTMP_MAX_HEADER_SIZE];
|
||||
} PILI_RTMPChunk;
|
||||
|
||||
typedef struct PILI_RTMPPacket {
|
||||
uint8_t m_headerType;
|
||||
uint8_t m_packetType;
|
||||
uint8_t m_hasAbsTimestamp; /* timestamp absolute or relative? */
|
||||
int m_nChannel;
|
||||
uint32_t m_nTimeStamp; /* timestamp */
|
||||
int32_t m_nInfoField2; /* last 4 bytes in a long header */
|
||||
uint32_t m_nBodySize;
|
||||
uint32_t m_nBytesRead;
|
||||
PILI_RTMPChunk *m_chunk;
|
||||
char *m_body;
|
||||
} PILI_RTMPPacket;
|
||||
|
||||
typedef struct PILI_RTMPSockBuf {
|
||||
int sb_socket;
|
||||
int sb_size; /* number of unprocessed bytes in buffer */
|
||||
char *sb_start; /* pointer into sb_pBuffer of next byte to process */
|
||||
char sb_buf[RTMP_BUFFER_CACHE_SIZE]; /* data read from socket */
|
||||
int sb_timedout;
|
||||
void *sb_ssl;
|
||||
} PILI_RTMPSockBuf;
|
||||
|
||||
void PILI_RTMPPacket_Reset(PILI_RTMPPacket *p);
|
||||
void PILI_RTMPPacket_Dump(PILI_RTMPPacket *p);
|
||||
int PILI_RTMPPacket_Alloc(PILI_RTMPPacket *p, int nSize);
|
||||
void PILI_RTMPPacket_Free(PILI_RTMPPacket *p);
|
||||
|
||||
#define RTMPPacket_IsReady(a) ((a)->m_nBytesRead == (a)->m_nBodySize)
|
||||
|
||||
typedef struct PILI_RTMP_LNK {
|
||||
AVal hostname;
|
||||
AVal domain;
|
||||
AVal sockshost;
|
||||
|
||||
AVal playpath0; /* parsed from URL */
|
||||
AVal playpath; /* passed in explicitly */
|
||||
AVal tcUrl;
|
||||
AVal swfUrl;
|
||||
AVal pageUrl;
|
||||
AVal app;
|
||||
AVal auth;
|
||||
AVal flashVer;
|
||||
AVal subscribepath;
|
||||
AVal token;
|
||||
AMFObject extras;
|
||||
int edepth;
|
||||
|
||||
int seekTime;
|
||||
int stopTime;
|
||||
|
||||
#define RTMP_LF_AUTH 0x0001 /* using auth param */
|
||||
#define RTMP_LF_LIVE 0x0002 /* stream is live */
|
||||
#define RTMP_LF_SWFV 0x0004 /* do SWF verification */
|
||||
#define RTMP_LF_PLST 0x0008 /* send playlist before play */
|
||||
#define RTMP_LF_BUFX 0x0010 /* toggle stream on BufferEmpty msg */
|
||||
#define RTMP_LF_FTCU 0x0020 /* free tcUrl on close */
|
||||
int lFlags;
|
||||
|
||||
int swfAge;
|
||||
|
||||
int protocol;
|
||||
int timeout; /* connection timeout in seconds */
|
||||
int send_timeout; /* send data timeout */
|
||||
|
||||
unsigned short socksport;
|
||||
unsigned short port;
|
||||
|
||||
#ifdef CRYPTO
|
||||
#define RTMP_SWF_HASHLEN 32
|
||||
void *dh; /* for encryption */
|
||||
void *rc4keyIn;
|
||||
void *rc4keyOut;
|
||||
|
||||
uint32_t SWFSize;
|
||||
uint8_t SWFHash[RTMP_SWF_HASHLEN];
|
||||
char SWFVerificationResponse[RTMP_SWF_HASHLEN + 10];
|
||||
#endif
|
||||
} PILI_RTMP_LNK;
|
||||
|
||||
/* state for read() wrapper */
|
||||
typedef struct PILI_RTMP_READ {
|
||||
char *buf;
|
||||
char *bufpos;
|
||||
unsigned int buflen;
|
||||
uint32_t timestamp;
|
||||
uint8_t dataType;
|
||||
uint8_t flags;
|
||||
#define RTMP_READ_HEADER 0x01
|
||||
#define RTMP_READ_RESUME 0x02
|
||||
#define RTMP_READ_NO_IGNORE 0x04
|
||||
#define RTMP_READ_GOTKF 0x08
|
||||
#define RTMP_READ_GOTFLVK 0x10
|
||||
#define RTMP_READ_SEEKING 0x20
|
||||
int8_t status;
|
||||
#define RTMP_READ_COMPLETE -3
|
||||
#define RTMP_READ_ERROR -2
|
||||
#define RTMP_READ_EOF -1
|
||||
#define RTMP_READ_IGNORE 0
|
||||
|
||||
/* if bResume == TRUE */
|
||||
uint8_t initialFrameType;
|
||||
uint32_t nResumeTS;
|
||||
char *metaHeader;
|
||||
char *initialFrame;
|
||||
uint32_t nMetaHeaderSize;
|
||||
uint32_t nInitialFrameSize;
|
||||
uint32_t nIgnoredFrameCounter;
|
||||
uint32_t nIgnoredFlvFrameCounter;
|
||||
} PILI_RTMP_READ;
|
||||
|
||||
typedef struct PILI_RTMP_METHOD {
|
||||
AVal name;
|
||||
int num;
|
||||
} PILI_RTMP_METHOD;
|
||||
|
||||
typedef void (*PILI_RTMPErrorCallback)(RTMPError *error, void *userData);
|
||||
|
||||
typedef struct PILI_CONNECTION_TIME {
|
||||
uint32_t connect_time;
|
||||
uint32_t handshake_time;
|
||||
} PILI_CONNECTION_TIME;
|
||||
|
||||
typedef void (*PILI_RTMP_ConnectionTimeCallback)(
|
||||
PILI_CONNECTION_TIME *conn_time, void *userData);
|
||||
|
||||
typedef struct PILI_RTMP {
|
||||
int m_inChunkSize;
|
||||
int m_outChunkSize;
|
||||
int m_nBWCheckCounter;
|
||||
int m_nBytesIn;
|
||||
int m_nBytesInSent;
|
||||
int m_nBufferMS;
|
||||
int m_stream_id; /* returned in _result from createStream */
|
||||
int m_mediaChannel;
|
||||
uint32_t m_mediaStamp;
|
||||
uint32_t m_pauseStamp;
|
||||
int m_pausing;
|
||||
int m_nServerBW;
|
||||
int m_nClientBW;
|
||||
uint8_t m_nClientBW2;
|
||||
uint8_t m_bPlaying;
|
||||
uint8_t m_bSendEncoding;
|
||||
uint8_t m_bSendCounter;
|
||||
|
||||
int m_numInvokes;
|
||||
int m_numCalls;
|
||||
PILI_RTMP_METHOD *m_methodCalls; /* remote method calls queue */
|
||||
|
||||
PILI_RTMPPacket *m_vecChannelsIn[RTMP_CHANNELS];
|
||||
PILI_RTMPPacket *m_vecChannelsOut[RTMP_CHANNELS];
|
||||
int m_channelTimestamp[RTMP_CHANNELS]; /* abs timestamp of last packet */
|
||||
|
||||
double m_fAudioCodecs; /* audioCodecs for the connect packet */
|
||||
double m_fVideoCodecs; /* videoCodecs for the connect packet */
|
||||
double m_fEncoding; /* AMF0 or AMF3 */
|
||||
|
||||
double m_fDuration; /* duration of stream in seconds */
|
||||
|
||||
int m_msgCounter; /* RTMPT stuff */
|
||||
int m_polling;
|
||||
int m_resplen;
|
||||
int m_unackd;
|
||||
AVal m_clientID;
|
||||
|
||||
PILI_RTMP_READ m_read;
|
||||
PILI_RTMPPacket m_write;
|
||||
PILI_RTMPSockBuf m_sb;
|
||||
PILI_RTMP_LNK Link;
|
||||
|
||||
PILI_RTMPErrorCallback m_errorCallback;
|
||||
PILI_RTMP_ConnectionTimeCallback m_connCallback;
|
||||
RTMPError *m_error;
|
||||
void *m_userData;
|
||||
int m_is_closing;
|
||||
int m_tcp_nodelay;
|
||||
uint32_t ip;
|
||||
} PILI_RTMP;
|
||||
|
||||
int PILI_RTMP_ParseURL(const char *url, int *protocol, AVal *host,
|
||||
unsigned int *port, AVal *playpath, AVal *app);
|
||||
|
||||
int PILI_RTMP_ParseURL2(const char *url, int *protocol, AVal *host,
|
||||
unsigned int *port, AVal *playpath, AVal *app, AVal *domain);
|
||||
|
||||
void PILI_RTMP_ParsePlaypath(AVal *in, AVal *out);
|
||||
void PILI_RTMP_SetBufferMS(PILI_RTMP *r, int size);
|
||||
void PILI_RTMP_UpdateBufferMS(PILI_RTMP *r, RTMPError *error);
|
||||
|
||||
int PILI_RTMP_SetOpt(PILI_RTMP *r, const AVal *opt, AVal *arg,
|
||||
RTMPError *error);
|
||||
int PILI_RTMP_SetupURL(PILI_RTMP *r, const char *url, RTMPError *error);
|
||||
void PILI_RTMP_SetupStream(PILI_RTMP *r, int protocol, AVal *hostname,
|
||||
unsigned int port, AVal *sockshost, AVal *playpath,
|
||||
AVal *tcUrl, AVal *swfUrl, AVal *pageUrl, AVal *app,
|
||||
AVal *auth, AVal *swfSHA256Hash, uint32_t swfSize,
|
||||
AVal *flashVer, AVal *subscribepath, int dStart,
|
||||
int dStop, int bLiveStream, long int timeout);
|
||||
|
||||
int PILI_RTMP_Connect(PILI_RTMP *r, PILI_RTMPPacket *cp, RTMPError *error);
|
||||
struct sockaddr;
|
||||
int PILI_RTMP_Connect0(PILI_RTMP *r, struct addrinfo *ai, unsigned short port,
|
||||
RTMPError *error);
|
||||
int PILI_RTMP_Connect1(PILI_RTMP *r, PILI_RTMPPacket *cp, RTMPError *error);
|
||||
int PILI_RTMP_Serve(PILI_RTMP *r, RTMPError *error);
|
||||
|
||||
int PILI_RTMP_ReadPacket(PILI_RTMP *r, PILI_RTMPPacket *packet);
|
||||
int PILI_RTMP_SendPacket(PILI_RTMP *r, PILI_RTMPPacket *packet, int queue,
|
||||
RTMPError *error);
|
||||
int PILI_RTMP_SendChunk(PILI_RTMP *r, PILI_RTMPChunk *chunk, RTMPError *error);
|
||||
int PILI_RTMP_IsConnected(PILI_RTMP *r);
|
||||
int PILI_RTMP_Socket(PILI_RTMP *r);
|
||||
int PILI_RTMP_IsTimedout(PILI_RTMP *r);
|
||||
double PILI_RTMP_GetDuration(PILI_RTMP *r);
|
||||
int PILI_RTMP_ToggleStream(PILI_RTMP *r, RTMPError *error);
|
||||
|
||||
int PILI_RTMP_ConnectStream(PILI_RTMP *r, int seekTime, RTMPError *error);
|
||||
int PILI_RTMP_ReconnectStream(PILI_RTMP *r, int seekTime, RTMPError *error);
|
||||
void PILI_RTMP_DeleteStream(PILI_RTMP *r, RTMPError *error);
|
||||
int PILI_RTMP_GetNextMediaPacket(PILI_RTMP *r, PILI_RTMPPacket *packet);
|
||||
int PILI_RTMP_ClientPacket(PILI_RTMP *r, PILI_RTMPPacket *packet);
|
||||
|
||||
void PILI_RTMP_Init(PILI_RTMP *r);
|
||||
void PILI_RTMP_Close(PILI_RTMP *r, RTMPError *error);
|
||||
PILI_RTMP *PILI_RTMP_Alloc(void);
|
||||
void PILI_RTMP_Free(PILI_RTMP *r);
|
||||
void PILI_RTMP_EnableWrite(PILI_RTMP *r);
|
||||
|
||||
int PILI_RTMP_LibVersion(void);
|
||||
void PILI_RTMP_UserInterrupt(void); /* user typed Ctrl-C */
|
||||
|
||||
int PILI_RTMP_SendCtrl(PILI_RTMP *r, short nType, unsigned int nObject,
|
||||
unsigned int nTime, RTMPError *error);
|
||||
|
||||
/* caller probably doesn't know current timestamp, should
|
||||
* just use RTMP_Pause instead
|
||||
*/
|
||||
int PILI_RTMP_SendPause(PILI_RTMP *r, int DoPause, int dTime, RTMPError *error);
|
||||
int PILI_RTMP_Pause(PILI_RTMP *r, int DoPause, RTMPError *error);
|
||||
|
||||
int PILI_RTMP_FindFirstMatchingProperty(AMFObject *obj, const AVal *name,
|
||||
AMFObjectProperty *p);
|
||||
|
||||
int PILI_RTMPSockBuf_Fill(PILI_RTMPSockBuf *sb, int timeout);
|
||||
int PILI_RTMPSockBuf_Send(PILI_RTMPSockBuf *sb, const char *buf, int len);
|
||||
int PILI_RTMPSockBuf_Close(PILI_RTMPSockBuf *sb);
|
||||
|
||||
int PILI_RTMP_SendCreateStream(PILI_RTMP *r, RTMPError *error);
|
||||
int PILI_RTMP_SendSeek(PILI_RTMP *r, int dTime, RTMPError *error);
|
||||
int PILI_RTMP_SendServerBW(PILI_RTMP *r, RTMPError *error);
|
||||
int PILI_RTMP_SendClientBW(PILI_RTMP *r, RTMPError *error);
|
||||
void PILI_RTMP_DropRequest(PILI_RTMP *r, int i, int freeit);
|
||||
int PILI_RTMP_Read(PILI_RTMP *r, char *buf, int size);
|
||||
int PILI_RTMP_Write(PILI_RTMP *r, const char *buf, int size, RTMPError *error);
|
||||
|
||||
#define MAJOR 1
|
||||
#define MINOR 0
|
||||
#define PATCH 4
|
||||
|
||||
int PILI_RTMP_Version();
|
||||
|
||||
const char * PILI_RTMP_GetReqId();
|
||||
|
||||
/* hashswf.c */
|
||||
int PILI_RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash,
|
||||
int age);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Executable
+123
@@ -0,0 +1,123 @@
|
||||
#ifndef __RTMP_SYS_H__
|
||||
#define __RTMP_SYS_H__
|
||||
/*
|
||||
* Copyright (C) 2010 Howard Chu
|
||||
*
|
||||
* This file is part of librtmp.
|
||||
*
|
||||
* librtmp is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* librtmp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with librtmp see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifdef _XBOX
|
||||
#include <winsockx.h>
|
||||
#include <xtl.h>
|
||||
#define snprintf _snprintf
|
||||
#define strcasecmp stricmp
|
||||
#define strncasecmp strnicmp
|
||||
#define vsnprintf _vsnprintf
|
||||
|
||||
#else /* !_XBOX */
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#define GetSockError() WSAGetLastError()
|
||||
#define SetSockError(e) WSASetLastError(e)
|
||||
#define setsockopt(a, b, c, d, e) (setsockopt)(a, b, c, (const char *)d, (int)e)
|
||||
#define EWOULDBLOCK \
|
||||
WSAETIMEDOUT /* we don't use nonblocking, but we do use timeouts */
|
||||
#define sleep(n) Sleep(n * 1000)
|
||||
#define msleep(n) Sleep(n)
|
||||
#define SET_RCVTIMEO(tv, s) int tv = s * 1000
|
||||
#else /* !_WIN32 */
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#define GetSockError() errno
|
||||
#define SetSockError(e) errno = e
|
||||
#undef closesocket
|
||||
#define closesocket(s) close(s)
|
||||
#define msleep(n) usleep(n * 1000)
|
||||
#define SET_RCVTIMEO(tv, s) struct timeval tv = {s, 0}
|
||||
#endif
|
||||
|
||||
#include "rtmp.h"
|
||||
|
||||
#ifdef USE_POLARSSL
|
||||
#include <polarssl/havege.h>
|
||||
#include <polarssl/net.h>
|
||||
#include <polarssl/ssl.h>
|
||||
typedef struct tls_ctx {
|
||||
havege_state hs;
|
||||
ssl_session ssn;
|
||||
} tls_ctx;
|
||||
#define TLS_CTX tls_ctx *
|
||||
#define TLS_client(ctx, s) \
|
||||
s = malloc(sizeof(ssl_context)); \
|
||||
ssl_init(s); \
|
||||
ssl_set_endpoint(s, SSL_IS_CLIENT); \
|
||||
ssl_set_authmode(s, SSL_VERIFY_NONE); \
|
||||
ssl_set_rng(s, havege_rand, &ctx->hs); \
|
||||
ssl_set_ciphers(s, ssl_default_ciphers); \
|
||||
ssl_set_session(s, 1, 600, &ctx->ssn)
|
||||
#define TLS_setfd(s, fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd)
|
||||
#define TLS_connect(s) ssl_handshake(s)
|
||||
#define TLS_read(s, b, l) ssl_read(s, (unsigned char *)b, l)
|
||||
#define TLS_write(s, b, l) ssl_write(s, (unsigned char *)b, l)
|
||||
#define TLS_shutdown(s) ssl_close_notify(s)
|
||||
#define TLS_close(s) \
|
||||
ssl_free(s); \
|
||||
free(s)
|
||||
|
||||
#elif defined(USE_GNUTLS)
|
||||
#include <gnutls/gnutls.h>
|
||||
typedef struct tls_ctx {
|
||||
gnutls_certificate_credentials_t cred;
|
||||
gnutls_priority_t prios;
|
||||
} tls_ctx;
|
||||
#define TLS_CTX tls_ctx *
|
||||
#define TLS_client(ctx, s) \
|
||||
gnutls_init((gnutls_session_t *)(&s), GNUTLS_CLIENT); \
|
||||
gnutls_priority_set(s, ctx->prios); \
|
||||
gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx->cred)
|
||||
#define TLS_setfd(s, fd) \
|
||||
gnutls_transport_set_ptr(s, (gnutls_transport_ptr_t)(long)fd)
|
||||
#define TLS_connect(s) gnutls_handshake(s)
|
||||
#define TLS_read(s, b, l) gnutls_record_recv(s, b, l)
|
||||
#define TLS_write(s, b, l) gnutls_record_send(s, b, l)
|
||||
#define TLS_shutdown(s) gnutls_bye(s, GNUTLS_SHUT_RDWR)
|
||||
#define TLS_close(s) gnutls_deinit(s)
|
||||
|
||||
#else /* USE_OPENSSL */
|
||||
#define TLS_CTX SSL_CTX *
|
||||
#define TLS_client(ctx, s) s = SSL_new(ctx)
|
||||
#define TLS_setfd(s, fd) SSL_set_fd(s, fd)
|
||||
#define TLS_connect(s) SSL_connect(s)
|
||||
#define TLS_read(s, b, l) SSL_read(s, b, l)
|
||||
#define TLS_write(s, b, l) SSL_write(s, b, l)
|
||||
#define TLS_shutdown(s) SSL_shutdown(s)
|
||||
#define TLS_close(s) SSL_free(s)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -7,7 +7,6 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
7ACB1193D70CF46C9676CB29 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C04F65629D3881D5F25ADE1 /* libPods.a */; };
|
||||
81E848D8BD2C446C2DD4876A /* libPods-LFLiveKitDemo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6FD9F92833FE7856CDDD3CED /* libPods-LFLiveKitDemo.a */; };
|
||||
B2D23E7F1D348F3D00B34CA8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B2D23E7E1D348F3D00B34CA8 /* main.m */; };
|
||||
B2D23E821D348F3D00B34CA8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B2D23E811D348F3D00B34CA8 /* AppDelegate.m */; };
|
||||
@@ -31,7 +30,6 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
5C04F65629D3881D5F25ADE1 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6FD9F92833FE7856CDDD3CED /* libPods-LFLiveKitDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LFLiveKitDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8FAAEBE1A4F099C69588B394 /* Pods-LFLiveKitDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LFLiveKitDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-LFLiveKitDemo/Pods-LFLiveKitDemo.release.xcconfig"; sourceTree = "<group>"; };
|
||||
AFD491825C5DB2AD871189B5 /* Pods-LFLiveKitDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LFLiveKitDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LFLiveKitDemo/Pods-LFLiveKitDemo.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
@@ -69,7 +67,6 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
81E848D8BD2C446C2DD4876A /* libPods-LFLiveKitDemo.a in Frameworks */,
|
||||
7ACB1193D70CF46C9676CB29 /* libPods.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -171,7 +168,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6FD9F92833FE7856CDDD3CED /* libPods-LFLiveKitDemo.a */,
|
||||
5C04F65629D3881D5F25ADE1 /* libPods.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -183,11 +179,12 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = B2D23E911D348F3D00B34CA8 /* Build configuration list for PBXNativeTarget "LFLiveKitDemo" */;
|
||||
buildPhases = (
|
||||
6A9D2ED37E623D4A31A8D2C9 /* Check Pods Manifest.lock */,
|
||||
6A9D2ED37E623D4A31A8D2C9 /* 📦 Check Pods Manifest.lock */,
|
||||
B2D23E761D348F3D00B34CA8 /* Sources */,
|
||||
B2D23E771D348F3D00B34CA8 /* Frameworks */,
|
||||
B2D23E781D348F3D00B34CA8 /* Resources */,
|
||||
34EEB2C8F5E0D371D13B66CA /* Copy Pods Resources */,
|
||||
34EEB2C8F5E0D371D13B66CA /* 📦 Copy Pods Resources */,
|
||||
7336E9C92EDCA6C7449F2624 /* 📦 Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -254,29 +251,29 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
34EEB2C8F5E0D371D13B66CA /* Copy Pods Resources */ = {
|
||||
34EEB2C8F5E0D371D13B66CA /* 📦 Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Copy Pods Resources";
|
||||
name = "📦 Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LFLiveKitDemo/Pods-LFLiveKitDemo-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
6A9D2ED37E623D4A31A8D2C9 /* Check Pods Manifest.lock */ = {
|
||||
6A9D2ED37E623D4A31A8D2C9 /* 📦 Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Check Pods Manifest.lock";
|
||||
name = "📦 Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -284,6 +281,21 @@
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
7336E9C92EDCA6C7449F2624 /* 📦 Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "📦 Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LFLiveKitDemo/Pods-LFLiveKitDemo-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
||||
Generated
BIN
Binary file not shown.
@@ -2,7 +2,6 @@ source 'https://github.com/CocoaPods/Specs.git'
|
||||
platform :ios,'7.0'
|
||||
|
||||
target 'LFLiveKitDemo' do
|
||||
|
||||
pod 'LFLiveKit', path: '../'
|
||||
end
|
||||
|
||||
pod 'LFLiveKit', path: '../'
|
||||
Reference in New Issue
Block a user