├── .clang-format ├── .gitignore ├── COPYING ├── LICENSE ├── Makefile ├── Pod ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ └── pili-librtmp │ ├── amf.c │ ├── amf.h │ ├── bytes.h │ ├── dh.h │ ├── dhgroups.h │ ├── error.c │ ├── error.h │ ├── handshake.h │ ├── hashswf.c │ ├── http.h │ ├── log.c │ ├── log.h │ ├── parseurl.c │ ├── rtmp.c │ ├── rtmp.h │ └── rtmp_sys.h ├── README.md ├── format.sh ├── librtmp.3 ├── librtmp.3.html ├── librtmp.pc.in ├── pili-librtmp.podspec └── pili-librtmp └── pili-librtmp.xcodeproj ├── project.pbxproj ├── project.xcworkspace ├── contents.xcworkspacedata ├── xcshareddata │ └── pili-librtmp.xcscmblueprint └── xcuserdata │ └── wangsiyu.xcuserdatad │ └── UserInterfaceState.xcuserstate └── xcuserdata └── wangsiyu.xcuserdatad └── xcschemes ├── pili-librtmp.xcscheme └── xcschememanagement.plist /.clang-format: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2015-present, Parse, LLC. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. An additional grant 6 | # of patent rights can be found in the PATENTS file in the same directory. 7 | 8 | --- 9 | Language: Cpp 10 | BasedOnStyle: LLVM 11 | AccessModifierOffset: -2 12 | AlignAfterOpenBracket: true 13 | AlignEscapedNewlinesLeft: true 14 | AlignOperands: true 15 | AlignTrailingComments: false 16 | AllowAllParametersOfDeclarationOnNextLine: false 17 | AllowShortBlocksOnASingleLine: false 18 | AllowShortCaseLabelsOnASingleLine: false 19 | AllowShortIfStatementsOnASingleLine: true 20 | AllowShortLoopsOnASingleLine: false 21 | AllowShortFunctionsOnASingleLine: false 22 | AlwaysBreakAfterDefinitionReturnType: false 23 | AlwaysBreakTemplateDeclarations: false 24 | AlwaysBreakBeforeMultilineStrings: false 25 | BreakBeforeBinaryOperators: None 26 | BreakBeforeTernaryOperators: true 27 | BreakConstructorInitializersBeforeComma: true 28 | BinPackParameters: true 29 | BinPackArguments: true 30 | ColumnLimit: 0 31 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 32 | ConstructorInitializerIndentWidth: 4 33 | DerivePointerAlignment: true 34 | ExperimentalAutoDetectBinPacking: true 35 | IndentCaseLabels: true 36 | IndentWrappedFunctionNames: true 37 | IndentFunctionDeclarationAfterType: true 38 | MaxEmptyLinesToKeep: 1 39 | KeepEmptyLinesAtTheStartOfBlocks: true 40 | NamespaceIndentation: None 41 | ObjCBlockIndentWidth: 4 42 | ObjCSpaceAfterProperty: true 43 | ObjCSpaceBeforeProtocolList: true 44 | PenaltyBreakBeforeFirstCallParameter: 19 45 | PenaltyBreakComment: 300 46 | PenaltyBreakString: 1000 47 | PenaltyBreakFirstLessLess: 140 48 | PenaltyExcessCharacter: 1000000 49 | PenaltyReturnTypeOnItsOwnLine: 120 50 | PointerAlignment: Right 51 | SpacesBeforeTrailingComments: 1 52 | Cpp11BracedListStyle: true 53 | Standard: Cpp11 54 | IndentWidth: 4 55 | TabWidth: 4 56 | UseTab: Never 57 | BreakBeforeBraces: Attach 58 | SpacesInParentheses: false 59 | SpacesInSquareBrackets: false 60 | SpacesInAngles: false 61 | SpaceInEmptyParentheses: false 62 | SpacesInCStyleCastParentheses: false 63 | SpaceAfterCStyleCast: false 64 | SpacesInContainerLiterals: true 65 | SpaceBeforeAssignmentOperators: true 66 | ContinuationIndentWidth: 4 67 | CommentPragmas: '^ IWYU pragma:' 68 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] 69 | SpaceBeforeParens: ControlStatements 70 | DisableFormat: false 71 | ... 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | 34 | # Android Studio 35 | .idea 36 | .gradle 37 | build/ 38 | 39 | # Xcode 40 | xcuserdata 41 | xcshareddata 42 | *.xccheckout 43 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | 504 | 505 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 0dayZh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION=v2.3 2 | 3 | prefix=/usr/local 4 | 5 | CC=$(CROSS_COMPILE)gcc 6 | LD=$(CROSS_COMPILE)ld 7 | AR=$(CROSS_COMPILE)ar 8 | 9 | SYS=posix 10 | CRYPTO=OPENSSL 11 | #CRYPTO=GNUTLS 12 | DEF_POLARSSL=-DUSE_POLARSSL 13 | DEF_OPENSSL=-DUSE_OPENSSL 14 | DEF_GNUTLS=-DUSE_GNUTLS 15 | DEF_=-DNO_CRYPTO 16 | REQ_GNUTLS=gnutls 17 | REQ_OPENSSL=libssl,libcrypto 18 | LIBZ=-lz 19 | LIBS_posix= 20 | LIBS_mingw=-lws2_32 -lwinmm -lgdi32 21 | LIB_GNUTLS=-lgnutls -lgcrypt $(LIBZ) 22 | LIB_OPENSSL=-lssl -lcrypto $(LIBZ) 23 | LIB_POLARSSL=-lpolarssl $(LIBZ) 24 | CRYPTO_LIB=$(LIB_$(CRYPTO)) $(LIBS_$(SYS)) 25 | CRYPTO_REQ=$(REQ_$(CRYPTO)) 26 | CRYPTO_DEF=$(DEF_$(CRYPTO)) 27 | 28 | SO_posix=so.0 29 | SO_mingw=dll 30 | SO_EXT=$(SO_$(SYS)) 31 | 32 | SHARED=yes 33 | SODEF_yes=-fPIC 34 | SOLIB_yes=librtmp.$(SO_EXT) 35 | SOINST_yes=install_$(SO_EXT) 36 | SO_DEF=$(SODEF_$(SHARED)) 37 | SO_LIB=$(SOLIB_$(SHARED)) 38 | SO_INST=$(SOINST_$(SHARED)) 39 | 40 | DEF=-DRTMPDUMP_VERSION=\"$(VERSION)\" $(CRYPTO_DEF) $(XDEF) 41 | OPT=-O2 42 | CFLAGS=-Wall $(XCFLAGS) $(INC) $(DEF) $(OPT) $(SO_DEF) 43 | 44 | incdir=$(prefix)/include/librtmp 45 | bindir=$(prefix)/bin 46 | libdir=$(prefix)/lib 47 | mandir=$(prefix)/man 48 | BINDIR=$(DESTDIR)$(bindir) 49 | INCDIR=$(DESTDIR)$(incdir) 50 | LIBDIR=$(DESTDIR)$(libdir) 51 | MANDIR=$(DESTDIR)$(mandir) 52 | 53 | OBJS=rtmp.o log.o amf.o hashswf.o parseurl.o 54 | 55 | all: librtmp.a $(SO_LIB) 56 | 57 | clean: 58 | rm -f *.o *.a *.so *.$(SO_EXT) 59 | 60 | librtmp.a: $(OBJS) 61 | $(AR) rs $@ $? 62 | 63 | librtmp.$(SO_EXT): $(OBJS) 64 | $(CC) -shared -Wl,-soname,$@ $(LDFLAGS) -o $@ $^ $> $(CRYPTO_LIB) 65 | ln -sf $@ librtmp.so 66 | 67 | log.o: log.c log.h Makefile 68 | rtmp.o: rtmp.c rtmp.h rtmp_sys.h handshake.h dh.h log.h amf.h Makefile 69 | amf.o: amf.c amf.h bytes.h log.h Makefile 70 | hashswf.o: hashswf.c http.h rtmp.h rtmp_sys.h Makefile 71 | parseurl.o: parseurl.c rtmp.h rtmp_sys.h log.h Makefile 72 | 73 | librtmp.pc: librtmp.pc.in Makefile 74 | sed -e "s;@prefix@;$(prefix);" -e "s;@VERSION@;$(VERSION);" \ 75 | -e "s;@CRYPTO_REQ@;$(CRYPTO_REQ);" librtmp.pc.in > $@ 76 | 77 | install: install_base $(SO_INST) 78 | 79 | install_base: librtmp.a librtmp.pc 80 | -mkdir -p $(INCDIR) $(LIBDIR)/pkgconfig $(MANDIR)/man3 81 | cp amf.h http.h log.h rtmp.h $(INCDIR) 82 | cp librtmp.a $(LIBDIR) 83 | cp librtmp.pc $(LIBDIR)/pkgconfig 84 | cp librtmp.3 $(MANDIR)/man3 85 | 86 | install_so.0: librtmp.so.0 87 | cp librtmp.so.0 $(LIBDIR) 88 | cd $(LIBDIR); ln -sf librtmp.so.0 librtmp.so 89 | 90 | install_dll: librtmp.dll 91 | cp librtmp.dll $(BINDIR) 92 | -------------------------------------------------------------------------------- /Pod/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pili-engineering/pili-librtmp/e814f73f122f626f15e21d6dc8ade72f65bcb96f/Pod/Assets/.gitkeep -------------------------------------------------------------------------------- /Pod/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pili-engineering/pili-librtmp/e814f73f122f626f15e21d6dc8ade72f65bcb96f/Pod/Classes/.gitkeep -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/amf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2005-2008 Team XBMC 3 | * http://www.xbmc.org 4 | * Copyright (C) 2008-2009 Andrej Stepanchuk 5 | * Copyright (C) 2009-2010 Howard Chu 6 | * 7 | * This file is part of librtmp. 8 | * 9 | * librtmp is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as 11 | * published by the Free Software Foundation; either version 2.1, 12 | * or (at your option) any later version. 13 | * 14 | * librtmp is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with librtmp see the file COPYING. If not, write to 21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 | * Boston, MA 02110-1301, USA. 23 | * http://www.gnu.org/copyleft/lgpl.html 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "amf.h" 31 | #include "bytes.h" 32 | #include "log.h" 33 | #include "rtmp_sys.h" 34 | 35 | static const PILI_AMFObjectProperty AMFProp_Invalid = {{0, 0}, PILI_AMF_INVALID}; 36 | static const PILI_AVal AV_empty = {0, 0}; 37 | 38 | /* Data is Big-Endian */ 39 | unsigned short 40 | PILI_AMF_DecodeInt16(const char *data) { 41 | unsigned char *c = (unsigned char *)data; 42 | unsigned short val; 43 | val = (c[0] << 8) | c[1]; 44 | return val; 45 | } 46 | 47 | unsigned int 48 | PILI_AMF_DecodeInt24(const char *data) { 49 | unsigned char *c = (unsigned char *)data; 50 | unsigned int val; 51 | val = (c[0] << 16) | (c[1] << 8) | c[2]; 52 | return val; 53 | } 54 | 55 | unsigned int 56 | PILI_AMF_DecodeInt32(const char *data) { 57 | unsigned char *c = (unsigned char *)data; 58 | unsigned int val; 59 | val = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; 60 | return val; 61 | } 62 | 63 | void PILI_AMF_DecodeString(const char *data, PILI_AVal *bv) { 64 | bv->av_len = PILI_AMF_DecodeInt16(data); 65 | bv->av_val = (bv->av_len > 0) ? (char *)data + 2 : NULL; 66 | } 67 | 68 | void PILI_AMF_DecodeLongString(const char *data, PILI_AVal *bv) { 69 | bv->av_len = PILI_AMF_DecodeInt32(data); 70 | bv->av_val = (bv->av_len > 0) ? (char *)data + 4 : NULL; 71 | } 72 | 73 | double 74 | PILI_AMF_DecodeNumber(const char *data) { 75 | double dVal; 76 | #if __FLOAT_WORD_ORDER == __BYTE_ORDER 77 | #if __BYTE_ORDER == __BIG_ENDIAN 78 | memcpy(&dVal, data, 8); 79 | #elif __BYTE_ORDER == __LITTLE_ENDIAN 80 | unsigned char *ci, *co; 81 | ci = (unsigned char *)data; 82 | co = (unsigned char *)&dVal; 83 | co[0] = ci[7]; 84 | co[1] = ci[6]; 85 | co[2] = ci[5]; 86 | co[3] = ci[4]; 87 | co[4] = ci[3]; 88 | co[5] = ci[2]; 89 | co[6] = ci[1]; 90 | co[7] = ci[0]; 91 | #endif 92 | #else 93 | #if __BYTE_ORDER == __LITTLE_ENDIAN /* __FLOAT_WORD_ORER == __BIG_ENDIAN */ 94 | unsigned char *ci, *co; 95 | ci = (unsigned char *)data; 96 | co = (unsigned char *)&dVal; 97 | co[0] = ci[3]; 98 | co[1] = ci[2]; 99 | co[2] = ci[1]; 100 | co[3] = ci[0]; 101 | co[4] = ci[7]; 102 | co[5] = ci[6]; 103 | co[6] = ci[5]; 104 | co[7] = ci[4]; 105 | #else /* __BYTE_ORDER == __BIG_ENDIAN && __FLOAT_WORD_ORER == __LITTLE_ENDIAN */ 106 | unsigned char *ci, *co; 107 | ci = (unsigned char *)data; 108 | co = (unsigned char *)&dVal; 109 | co[0] = ci[4]; 110 | co[1] = ci[5]; 111 | co[2] = ci[6]; 112 | co[3] = ci[7]; 113 | co[4] = ci[0]; 114 | co[5] = ci[1]; 115 | co[6] = ci[2]; 116 | co[7] = ci[3]; 117 | #endif 118 | #endif 119 | return dVal; 120 | } 121 | 122 | int PILI_AMF_DecodeBoolean(const char *data) { 123 | return *data != 0; 124 | } 125 | 126 | char * 127 | PILI_AMF_EncodeInt16(char *output, char *outend, short nVal) { 128 | if (output + 2 > outend) 129 | return NULL; 130 | 131 | output[1] = nVal & 0xff; 132 | output[0] = nVal >> 8; 133 | return output + 2; 134 | } 135 | 136 | char * 137 | PILI_AMF_EncodeInt24(char *output, char *outend, int nVal) { 138 | if (output + 3 > outend) 139 | return NULL; 140 | 141 | output[2] = nVal & 0xff; 142 | output[1] = nVal >> 8; 143 | output[0] = nVal >> 16; 144 | return output + 3; 145 | } 146 | 147 | char * 148 | PILI_AMF_EncodeInt32(char *output, char *outend, int nVal) { 149 | if (output + 4 > outend) 150 | return NULL; 151 | 152 | output[3] = nVal & 0xff; 153 | output[2] = nVal >> 8; 154 | output[1] = nVal >> 16; 155 | output[0] = nVal >> 24; 156 | return output + 4; 157 | } 158 | 159 | char * 160 | PILI_AMF_EncodeString(char *output, char *outend, const PILI_AVal *bv) { 161 | if ((bv->av_len < 65536 && output + 1 + 2 + bv->av_len > outend) || 162 | output + 1 + 4 + bv->av_len > outend) 163 | return NULL; 164 | 165 | if (bv->av_len < 65536) { 166 | *output++ = PILI_AMF_STRING; 167 | 168 | output = PILI_AMF_EncodeInt16(output, outend, bv->av_len); 169 | } else { 170 | *output++ = PILI_AMF_LONG_STRING; 171 | 172 | output = PILI_AMF_EncodeInt32(output, outend, bv->av_len); 173 | } 174 | memcpy(output, bv->av_val, bv->av_len); 175 | output += bv->av_len; 176 | 177 | return output; 178 | } 179 | 180 | char * 181 | PILI_AMF_EncodeNumber(char *output, char *outend, double dVal) { 182 | if (output + 1 + 8 > outend) 183 | return NULL; 184 | 185 | *output++ = PILI_AMF_NUMBER; /* type: Number */ 186 | 187 | #if __FLOAT_WORD_ORDER == __BYTE_ORDER 188 | #if __BYTE_ORDER == __BIG_ENDIAN 189 | memcpy(output, &dVal, 8); 190 | #elif __BYTE_ORDER == __LITTLE_ENDIAN 191 | { 192 | unsigned char *ci, *co; 193 | ci = (unsigned char *)&dVal; 194 | co = (unsigned char *)output; 195 | co[0] = ci[7]; 196 | co[1] = ci[6]; 197 | co[2] = ci[5]; 198 | co[3] = ci[4]; 199 | co[4] = ci[3]; 200 | co[5] = ci[2]; 201 | co[6] = ci[1]; 202 | co[7] = ci[0]; 203 | } 204 | #endif 205 | #else 206 | #if __BYTE_ORDER == __LITTLE_ENDIAN /* __FLOAT_WORD_ORER == __BIG_ENDIAN */ 207 | { 208 | unsigned char *ci, *co; 209 | ci = (unsigned char *)&dVal; 210 | co = (unsigned char *)output; 211 | co[0] = ci[3]; 212 | co[1] = ci[2]; 213 | co[2] = ci[1]; 214 | co[3] = ci[0]; 215 | co[4] = ci[7]; 216 | co[5] = ci[6]; 217 | co[6] = ci[5]; 218 | co[7] = ci[4]; 219 | } 220 | #else /* __BYTE_ORDER == __BIG_ENDIAN && __FLOAT_WORD_ORER == __LITTLE_ENDIAN */ 221 | { 222 | unsigned char *ci, *co; 223 | ci = (unsigned char *)&dVal; 224 | co = (unsigned char *)output; 225 | co[0] = ci[4]; 226 | co[1] = ci[5]; 227 | co[2] = ci[6]; 228 | co[3] = ci[7]; 229 | co[4] = ci[0]; 230 | co[5] = ci[1]; 231 | co[6] = ci[2]; 232 | co[7] = ci[3]; 233 | } 234 | #endif 235 | #endif 236 | 237 | return output + 8; 238 | } 239 | 240 | char * 241 | PILI_AMF_EncodeBoolean(char *output, char *outend, int bVal) { 242 | if (output + 2 > outend) 243 | return NULL; 244 | 245 | *output++ = PILI_AMF_BOOLEAN; 246 | 247 | *output++ = bVal ? 0x01 : 0x00; 248 | 249 | return output; 250 | } 251 | 252 | char * 253 | PILI_AMF_EncodeNamedString(char *output, char *outend, const PILI_AVal *strName, const PILI_AVal *strValue) { 254 | if (output + 2 + strName->av_len > outend) 255 | return NULL; 256 | output = PILI_AMF_EncodeInt16(output, outend, strName->av_len); 257 | 258 | memcpy(output, strName->av_val, strName->av_len); 259 | output += strName->av_len; 260 | 261 | return PILI_AMF_EncodeString(output, outend, strValue); 262 | } 263 | 264 | char * 265 | PILI_AMF_EncodeNamedNumber(char *output, char *outend, const PILI_AVal *strName, double dVal) { 266 | if (output + 2 + strName->av_len > outend) 267 | return NULL; 268 | output = PILI_AMF_EncodeInt16(output, outend, strName->av_len); 269 | 270 | memcpy(output, strName->av_val, strName->av_len); 271 | output += strName->av_len; 272 | 273 | return PILI_AMF_EncodeNumber(output, outend, dVal); 274 | } 275 | 276 | char * 277 | PILI_AMF_EncodeNamedBoolean(char *output, char *outend, const PILI_AVal *strName, int bVal) { 278 | if (output + 2 + strName->av_len > outend) 279 | return NULL; 280 | output = PILI_AMF_EncodeInt16(output, outend, strName->av_len); 281 | 282 | memcpy(output, strName->av_val, strName->av_len); 283 | output += strName->av_len; 284 | 285 | return PILI_AMF_EncodeBoolean(output, outend, bVal); 286 | } 287 | 288 | void PILI_AMFProp_GetName(PILI_AMFObjectProperty *prop, PILI_AVal *name) { 289 | *name = prop->p_name; 290 | } 291 | 292 | void PILI_AMFProp_SetName(PILI_AMFObjectProperty *prop, PILI_AVal *name) { 293 | prop->p_name = *name; 294 | } 295 | 296 | PILI_AMFDataType 297 | PILI_AMFProp_GetType(PILI_AMFObjectProperty *prop) { 298 | return prop->p_type; 299 | } 300 | 301 | double 302 | PILI_AMFProp_GetNumber(PILI_AMFObjectProperty *prop) { 303 | return prop->p_vu.p_number; 304 | } 305 | 306 | int PILI_AMFProp_GetBoolean(PILI_AMFObjectProperty *prop) { 307 | return prop->p_vu.p_number != 0; 308 | } 309 | 310 | void PILI_AMFProp_GetString(PILI_AMFObjectProperty *prop, PILI_AVal *str) { 311 | *str = prop->p_vu.p_aval; 312 | } 313 | 314 | void PILI_AMFProp_GetObject(PILI_AMFObjectProperty *prop, PILI_AMFObject *obj) { 315 | *obj = prop->p_vu.p_object; 316 | } 317 | 318 | int PILI_AMFProp_IsValid(PILI_AMFObjectProperty *prop) { 319 | return prop->p_type != PILI_AMF_INVALID; 320 | } 321 | 322 | char * 323 | PILI_AMFProp_Encode(PILI_AMFObjectProperty *prop, char *pBuffer, char *pBufEnd) { 324 | if (prop->p_type == PILI_AMF_INVALID) 325 | return NULL; 326 | 327 | if (prop->p_type != PILI_AMF_NULL && pBuffer + prop->p_name.av_len + 2 + 1 >= pBufEnd) 328 | return NULL; 329 | 330 | if (prop->p_type != PILI_AMF_NULL && prop->p_name.av_len) { 331 | *pBuffer++ = prop->p_name.av_len >> 8; 332 | *pBuffer++ = prop->p_name.av_len & 0xff; 333 | memcpy(pBuffer, prop->p_name.av_val, prop->p_name.av_len); 334 | pBuffer += prop->p_name.av_len; 335 | } 336 | 337 | switch (prop->p_type) { 338 | case PILI_AMF_NUMBER: 339 | pBuffer = PILI_AMF_EncodeNumber(pBuffer, pBufEnd, prop->p_vu.p_number); 340 | break; 341 | 342 | case PILI_AMF_BOOLEAN: 343 | pBuffer = PILI_AMF_EncodeBoolean(pBuffer, pBufEnd, prop->p_vu.p_number != 0); 344 | break; 345 | 346 | case PILI_AMF_STRING: 347 | pBuffer = PILI_AMF_EncodeString(pBuffer, pBufEnd, &prop->p_vu.p_aval); 348 | break; 349 | 350 | case PILI_AMF_NULL: 351 | if (pBuffer + 1 >= pBufEnd) 352 | return NULL; 353 | *pBuffer++ = PILI_AMF_NULL; 354 | break; 355 | 356 | case PILI_AMF_OBJECT: 357 | pBuffer = PILI_AMF_Encode(&prop->p_vu.p_object, pBuffer, pBufEnd); 358 | break; 359 | 360 | default: 361 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "%s, invalid type. %d", __FUNCTION__, prop->p_type); 362 | pBuffer = NULL; 363 | }; 364 | 365 | return pBuffer; 366 | } 367 | 368 | #define PILI_AMF3_INTEGER_MAX 268435455 369 | #define PILI_AMF3_INTEGER_MIN -268435456 370 | 371 | int PILI_AMF3ReadInteger(const char *data, int32_t *valp) { 372 | int i = 0; 373 | int32_t val = 0; 374 | 375 | while (i <= 2) { /* handle first 3 bytes */ 376 | if (data[i] & 0x80) { /* byte used */ 377 | val <<= 7; /* shift up */ 378 | val |= (data[i] & 0x7f); /* add bits */ 379 | i++; 380 | } else { 381 | break; 382 | } 383 | } 384 | 385 | if (i > 2) { /* use 4th byte, all 8bits */ 386 | val <<= 8; 387 | val |= data[3]; 388 | 389 | /* range check */ 390 | if (val > PILI_AMF3_INTEGER_MAX) 391 | val -= (1 << 29); 392 | } else { /* use 7bits of last unparsed byte (0xxxxxxx) */ 393 | val <<= 7; 394 | val |= data[i]; 395 | } 396 | 397 | *valp = val; 398 | 399 | return i > 2 ? 4 : i + 1; 400 | } 401 | 402 | int PILI_AMF3ReadString(const char *data, PILI_AVal *str) { 403 | int32_t ref = 0; 404 | int len; 405 | assert(str != 0); 406 | 407 | len = PILI_AMF3ReadInteger(data, &ref); 408 | data += len; 409 | 410 | if ((ref & 0x1) == 0) { /* reference: 0xxx */ 411 | uint32_t refIndex = (ref >> 1); 412 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, 413 | "%s, string reference, index: %d, not supported, ignoring!", 414 | __FUNCTION__, refIndex); 415 | return len; 416 | } else { 417 | uint32_t nSize = (ref >> 1); 418 | 419 | str->av_val = (char *)data; 420 | str->av_len = nSize; 421 | 422 | return len + nSize; 423 | } 424 | return len; 425 | } 426 | 427 | int PILI_AMF3Prop_Decode(PILI_AMFObjectProperty *prop, const char *pBuffer, int nSize, 428 | int bDecodeName) { 429 | int nOriginalSize = nSize; 430 | PILI_AMF3DataType type; 431 | 432 | prop->p_name.av_len = 0; 433 | prop->p_name.av_val = NULL; 434 | 435 | if (nSize == 0 || !pBuffer) { 436 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "empty buffer/no buffer pointer!"); 437 | return -1; 438 | } 439 | 440 | /* decode name */ 441 | if (bDecodeName) { 442 | PILI_AVal name; 443 | int nRes = PILI_AMF3ReadString(pBuffer, &name); 444 | 445 | if (name.av_len <= 0) 446 | return nRes; 447 | 448 | prop->p_name = name; 449 | pBuffer += nRes; 450 | nSize -= nRes; 451 | } 452 | 453 | /* decode */ 454 | type = *pBuffer++; 455 | nSize--; 456 | 457 | switch (type) { 458 | case PILI_AMF3_UNDEFINED: 459 | case PILI_AMF3_NULL: 460 | prop->p_type = PILI_AMF_NULL; 461 | break; 462 | case PILI_AMF3_FALSE: 463 | prop->p_type = PILI_AMF_BOOLEAN; 464 | prop->p_vu.p_number = 0.0; 465 | break; 466 | case PILI_AMF3_TRUE: 467 | prop->p_type = PILI_AMF_BOOLEAN; 468 | prop->p_vu.p_number = 1.0; 469 | break; 470 | case PILI_AMF3_INTEGER: { 471 | int32_t res = 0; 472 | int len = PILI_AMF3ReadInteger(pBuffer, &res); 473 | prop->p_vu.p_number = (double)res; 474 | prop->p_type = PILI_AMF_NUMBER; 475 | nSize -= len; 476 | break; 477 | } 478 | case PILI_AMF3_DOUBLE: 479 | if (nSize < 8) 480 | return -1; 481 | prop->p_vu.p_number = PILI_AMF_DecodeNumber(pBuffer); 482 | prop->p_type = PILI_AMF_NUMBER; 483 | nSize -= 8; 484 | break; 485 | case PILI_AMF3_STRING: 486 | case PILI_AMF3_XML_DOC: 487 | case PILI_AMF3_XML: { 488 | int len = PILI_AMF3ReadString(pBuffer, &prop->p_vu.p_aval); 489 | prop->p_type = PILI_AMF_STRING; 490 | nSize -= len; 491 | break; 492 | } 493 | case PILI_AMF3_DATE: { 494 | int32_t res = 0; 495 | int len = PILI_AMF3ReadInteger(pBuffer, &res); 496 | 497 | nSize -= len; 498 | pBuffer += len; 499 | 500 | if ((res & 0x1) == 0) { /* reference */ 501 | uint32_t nIndex = (res >> 1); 502 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "PILI_AMF3_DATE reference: %d, not supported!", nIndex); 503 | } else { 504 | if (nSize < 8) 505 | return -1; 506 | 507 | prop->p_vu.p_number = PILI_AMF_DecodeNumber(pBuffer); 508 | nSize -= 8; 509 | prop->p_type = PILI_AMF_NUMBER; 510 | } 511 | break; 512 | } 513 | case PILI_AMF3_OBJECT: { 514 | int nRes = PILI_AMF3_Decode(&prop->p_vu.p_object, pBuffer, nSize, TRUE); 515 | if (nRes == -1) 516 | return -1; 517 | nSize -= nRes; 518 | prop->p_type = PILI_AMF_OBJECT; 519 | break; 520 | } 521 | case PILI_AMF3_ARRAY: 522 | case PILI_AMF3_BYTE_ARRAY: 523 | default: 524 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "%s - AMF3 unknown/unsupported datatype 0x%02x, @0x%08X", 525 | __FUNCTION__, (unsigned char)(*pBuffer), pBuffer); 526 | return -1; 527 | } 528 | 529 | return nOriginalSize - nSize; 530 | } 531 | 532 | int PILI_AMFProp_Decode(PILI_AMFObjectProperty *prop, const char *pBuffer, int nSize, 533 | int bDecodeName) { 534 | int nOriginalSize = nSize; 535 | int nRes; 536 | 537 | prop->p_name.av_len = 0; 538 | prop->p_name.av_val = NULL; 539 | 540 | if (nSize == 0 || !pBuffer) { 541 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "%s: Empty buffer/no buffer pointer!", __FUNCTION__); 542 | return -1; 543 | } 544 | 545 | if (bDecodeName && nSize < 4) { /* at least name (length + at least 1 byte) and 1 byte of data */ 546 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, 547 | "%s: Not enough data for decoding with name, less than 4 bytes!", 548 | __FUNCTION__); 549 | return -1; 550 | } 551 | 552 | if (bDecodeName) { 553 | unsigned short nNameSize = PILI_AMF_DecodeInt16(pBuffer); 554 | if (nNameSize > nSize - 2) { 555 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, 556 | "%s: Name size out of range: namesize (%d) > len (%d) - 2", 557 | __FUNCTION__, nNameSize, nSize); 558 | return -1; 559 | } 560 | 561 | PILI_AMF_DecodeString(pBuffer, &prop->p_name); 562 | nSize -= 2 + nNameSize; 563 | pBuffer += 2 + nNameSize; 564 | } 565 | 566 | if (nSize == 0) { 567 | return -1; 568 | } 569 | 570 | nSize--; 571 | 572 | prop->p_type = *pBuffer++; 573 | switch (prop->p_type) { 574 | case PILI_AMF_NUMBER: 575 | if (nSize < 8) 576 | return -1; 577 | prop->p_vu.p_number = PILI_AMF_DecodeNumber(pBuffer); 578 | nSize -= 8; 579 | break; 580 | case PILI_AMF_BOOLEAN: 581 | if (nSize < 1) 582 | return -1; 583 | prop->p_vu.p_number = (double)PILI_AMF_DecodeBoolean(pBuffer); 584 | nSize--; 585 | break; 586 | case PILI_AMF_STRING: { 587 | unsigned short nStringSize = PILI_AMF_DecodeInt16(pBuffer); 588 | 589 | if (nSize < (long)nStringSize + 2) 590 | return -1; 591 | PILI_AMF_DecodeString(pBuffer, &prop->p_vu.p_aval); 592 | nSize -= (2 + nStringSize); 593 | break; 594 | } 595 | case PILI_AMF_OBJECT: { 596 | int nRes = PILI_AMF_Decode(&prop->p_vu.p_object, pBuffer, nSize, TRUE); 597 | if (nRes == -1) 598 | return -1; 599 | nSize -= nRes; 600 | break; 601 | } 602 | case PILI_AMF_MOVIECLIP: { 603 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "PILI_AMF_MOVIECLIP reserved!"); 604 | return -1; 605 | break; 606 | } 607 | case PILI_AMF_NULL: 608 | case PILI_AMF_UNDEFINED: 609 | case PILI_AMF_UNSUPPORTED: 610 | prop->p_type = PILI_AMF_NULL; 611 | break; 612 | case PILI_AMF_REFERENCE: { 613 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "PILI_AMF_REFERENCE not supported!"); 614 | return -1; 615 | break; 616 | } 617 | case PILI_AMF_ECMA_ARRAY: { 618 | nSize -= 4; 619 | 620 | /* next comes the rest, mixed array has a final 0x000009 mark and names, so its an object */ 621 | nRes = PILI_AMF_Decode(&prop->p_vu.p_object, pBuffer + 4, nSize, TRUE); 622 | if (nRes == -1) 623 | return -1; 624 | nSize -= nRes; 625 | prop->p_type = PILI_AMF_OBJECT; 626 | break; 627 | } 628 | case PILI_AMF_OBJECT_END: { 629 | return -1; 630 | break; 631 | } 632 | case PILI_AMF_STRICT_ARRAY: { 633 | unsigned int nArrayLen = PILI_AMF_DecodeInt32(pBuffer); 634 | nSize -= 4; 635 | 636 | nRes = PILI_AMF_DecodeArray(&prop->p_vu.p_object, pBuffer + 4, nSize, 637 | nArrayLen, FALSE); 638 | if (nRes == -1) 639 | return -1; 640 | nSize -= nRes; 641 | prop->p_type = PILI_AMF_OBJECT; 642 | break; 643 | } 644 | case PILI_AMF_DATE: { 645 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "PILI_AMF_DATE"); 646 | 647 | if (nSize < 10) 648 | return -1; 649 | 650 | prop->p_vu.p_number = PILI_AMF_DecodeNumber(pBuffer); 651 | prop->p_UTCoffset = PILI_AMF_DecodeInt16(pBuffer + 8); 652 | 653 | nSize -= 10; 654 | break; 655 | } 656 | case PILI_AMF_LONG_STRING: { 657 | unsigned int nStringSize = PILI_AMF_DecodeInt32(pBuffer); 658 | if (nSize < (long)nStringSize + 4) 659 | return -1; 660 | PILI_AMF_DecodeLongString(pBuffer, &prop->p_vu.p_aval); 661 | nSize -= (4 + nStringSize); 662 | prop->p_type = PILI_AMF_STRING; 663 | break; 664 | } 665 | case PILI_AMF_RECORDSET: { 666 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "PILI_AMF_RECORDSET reserved!"); 667 | return -1; 668 | break; 669 | } 670 | case PILI_AMF_XML_DOC: { 671 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "PILI_AMF_XML_DOC not supported!"); 672 | return -1; 673 | break; 674 | } 675 | case PILI_AMF_TYPED_OBJECT: { 676 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "PILI_AMF_TYPED_OBJECT not supported!"); 677 | return -1; 678 | break; 679 | } 680 | case PILI_AMF_AVMPLUS: { 681 | int nRes = PILI_AMF3_Decode(&prop->p_vu.p_object, pBuffer, nSize, TRUE); 682 | if (nRes == -1) 683 | return -1; 684 | nSize -= nRes; 685 | prop->p_type = PILI_AMF_OBJECT; 686 | break; 687 | } 688 | default: 689 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "%s - unknown datatype 0x%02x, @0x%08X", __FUNCTION__, 690 | prop->p_type, pBuffer - 1); 691 | return -1; 692 | } 693 | 694 | return nOriginalSize - nSize; 695 | } 696 | 697 | void PILI_AMFProp_Dump(PILI_AMFObjectProperty *prop) { 698 | char strRes[256]; 699 | char str[256]; 700 | PILI_AVal name; 701 | 702 | if (prop->p_type == PILI_AMF_INVALID) { 703 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Property: INVALID"); 704 | return; 705 | } 706 | 707 | if (prop->p_type == PILI_AMF_NULL) { 708 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Property: NULL"); 709 | return; 710 | } 711 | 712 | if (prop->p_name.av_len) { 713 | name = prop->p_name; 714 | } else { 715 | name.av_val = "no-name."; 716 | name.av_len = sizeof("no-name.") - 1; 717 | } 718 | if (name.av_len > 18) 719 | name.av_len = 18; 720 | 721 | snprintf(strRes, 255, "Name: %18.*s, ", name.av_len, name.av_val); 722 | 723 | if (prop->p_type == PILI_AMF_OBJECT) { 724 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Property: <%sOBJECT>", strRes); 725 | PILI_AMF_Dump(&prop->p_vu.p_object); 726 | return; 727 | } 728 | 729 | switch (prop->p_type) { 730 | case PILI_AMF_NUMBER: 731 | snprintf(str, 255, "NUMBER:\t%.2f", prop->p_vu.p_number); 732 | break; 733 | case PILI_AMF_BOOLEAN: 734 | snprintf(str, 255, "BOOLEAN:\t%s", 735 | prop->p_vu.p_number != 0.0 ? "TRUE" : "FALSE"); 736 | break; 737 | case PILI_AMF_STRING: 738 | snprintf(str, 255, "STRING:\t%.*s", prop->p_vu.p_aval.av_len, 739 | prop->p_vu.p_aval.av_val); 740 | break; 741 | case PILI_AMF_DATE: 742 | snprintf(str, 255, "DATE:\ttimestamp: %.2f, UTC offset: %d", 743 | prop->p_vu.p_number, prop->p_UTCoffset); 744 | break; 745 | default: 746 | snprintf(str, 255, "INVALID TYPE 0x%02x", (unsigned char)prop->p_type); 747 | } 748 | 749 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Property: <%s%s>", strRes, str); 750 | } 751 | 752 | void PILI_AMFProp_Reset(PILI_AMFObjectProperty *prop) { 753 | if (prop->p_type == PILI_AMF_OBJECT) 754 | PILI_AMF_Reset(&prop->p_vu.p_object); 755 | else { 756 | prop->p_vu.p_aval.av_len = 0; 757 | prop->p_vu.p_aval.av_val = NULL; 758 | } 759 | prop->p_type = PILI_AMF_INVALID; 760 | } 761 | 762 | /* PILI_AMFObject */ 763 | 764 | char * 765 | PILI_AMF_Encode(PILI_AMFObject *obj, char *pBuffer, char *pBufEnd) { 766 | int i; 767 | 768 | if (pBuffer + 4 >= pBufEnd) 769 | return NULL; 770 | 771 | *pBuffer++ = PILI_AMF_OBJECT; 772 | 773 | for (i = 0; i < obj->o_num; i++) { 774 | char *res = PILI_AMFProp_Encode(&obj->o_props[i], pBuffer, pBufEnd); 775 | if (res == NULL) { 776 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "PILI_AMF_Encode - failed to encode property in index %d", 777 | i); 778 | break; 779 | } else { 780 | pBuffer = res; 781 | } 782 | } 783 | 784 | if (pBuffer + 3 >= pBufEnd) 785 | return NULL; /* no room for the end marker */ 786 | 787 | pBuffer = PILI_AMF_EncodeInt24(pBuffer, pBufEnd, PILI_AMF_OBJECT_END); 788 | 789 | return pBuffer; 790 | } 791 | 792 | int PILI_AMF_DecodeArray(PILI_AMFObject *obj, const char *pBuffer, int nSize, 793 | int nArrayLen, int bDecodeName) { 794 | int nOriginalSize = nSize; 795 | int bError = FALSE; 796 | 797 | obj->o_num = 0; 798 | obj->o_props = NULL; 799 | while (nArrayLen > 0) { 800 | PILI_AMFObjectProperty prop; 801 | int nRes; 802 | nArrayLen--; 803 | 804 | nRes = PILI_AMFProp_Decode(&prop, pBuffer, nSize, bDecodeName); 805 | if (nRes == -1) 806 | bError = TRUE; 807 | else { 808 | nSize -= nRes; 809 | pBuffer += nRes; 810 | PILI_AMF_AddProp(obj, &prop); 811 | } 812 | } 813 | if (bError) 814 | return -1; 815 | 816 | return nOriginalSize - nSize; 817 | } 818 | 819 | int PILI_AMF3_Decode(PILI_AMFObject *obj, const char *pBuffer, int nSize, int bAMFData) { 820 | int nOriginalSize = nSize; 821 | int32_t ref; 822 | int len; 823 | 824 | obj->o_num = 0; 825 | obj->o_props = NULL; 826 | if (bAMFData) { 827 | if (*pBuffer != PILI_AMF3_OBJECT) 828 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, 829 | "AMF3 Object encapsulated in AMF stream does not start with PILI_AMF3_OBJECT!"); 830 | pBuffer++; 831 | nSize--; 832 | } 833 | 834 | ref = 0; 835 | len = PILI_AMF3ReadInteger(pBuffer, &ref); 836 | pBuffer += len; 837 | nSize -= len; 838 | 839 | if ((ref & 1) == 0) { /* object reference, 0xxx */ 840 | uint32_t objectIndex = (ref >> 1); 841 | 842 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Object reference, index: %d", objectIndex); 843 | } else /* object instance */ 844 | { 845 | int32_t classRef = (ref >> 1); 846 | 847 | PILI_AMF3ClassDef cd = {{0, 0}}; 848 | PILI_AMFObjectProperty prop; 849 | 850 | if ((classRef & 0x1) == 0) { /* class reference */ 851 | uint32_t classIndex = (classRef >> 1); 852 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Class reference: %d", classIndex); 853 | } else { 854 | int32_t classExtRef = (classRef >> 1); 855 | int i; 856 | 857 | cd.cd_externalizable = (classExtRef & 0x1) == 1; 858 | cd.cd_dynamic = ((classExtRef >> 1) & 0x1) == 1; 859 | 860 | cd.cd_num = classExtRef >> 2; 861 | 862 | /* class name */ 863 | 864 | len = PILI_AMF3ReadString(pBuffer, &cd.cd_name); 865 | nSize -= len; 866 | pBuffer += len; 867 | 868 | /*std::string str = className; */ 869 | 870 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, 871 | "Class name: %s, externalizable: %d, dynamic: %d, classMembers: %d", 872 | cd.cd_name.av_val, cd.cd_externalizable, cd.cd_dynamic, 873 | cd.cd_num); 874 | 875 | for (i = 0; i < cd.cd_num; i++) { 876 | PILI_AVal memberName; 877 | len = PILI_AMF3ReadString(pBuffer, &memberName); 878 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Member: %s", memberName.av_val); 879 | PILI_AMF3CD_AddProp(&cd, &memberName); 880 | nSize -= len; 881 | pBuffer += len; 882 | } 883 | } 884 | 885 | /* add as referencable object */ 886 | 887 | if (cd.cd_externalizable) { 888 | int nRes; 889 | PILI_AVal name = AVC("DEFAULT_ATTRIBUTE"); 890 | 891 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Externalizable, TODO check"); 892 | 893 | nRes = PILI_AMF3Prop_Decode(&prop, pBuffer, nSize, FALSE); 894 | if (nRes == -1) 895 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "%s, failed to decode AMF3 property!", 896 | __FUNCTION__); 897 | else { 898 | nSize -= nRes; 899 | pBuffer += nRes; 900 | } 901 | 902 | PILI_AMFProp_SetName(&prop, &name); 903 | PILI_AMF_AddProp(obj, &prop); 904 | } else { 905 | int nRes, i; 906 | for (i = 0; i < cd.cd_num; i++) /* non-dynamic */ 907 | { 908 | nRes = PILI_AMF3Prop_Decode(&prop, pBuffer, nSize, FALSE); 909 | if (nRes == -1) 910 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "%s, failed to decode AMF3 property!", 911 | __FUNCTION__); 912 | 913 | PILI_AMFProp_SetName(&prop, PILI_AMF3CD_GetProp(&cd, i)); 914 | PILI_AMF_AddProp(obj, &prop); 915 | 916 | pBuffer += nRes; 917 | nSize -= nRes; 918 | } 919 | if (cd.cd_dynamic) { 920 | int len = 0; 921 | 922 | do { 923 | nRes = PILI_AMF3Prop_Decode(&prop, pBuffer, nSize, TRUE); 924 | PILI_AMF_AddProp(obj, &prop); 925 | 926 | pBuffer += nRes; 927 | nSize -= nRes; 928 | 929 | len = prop.p_name.av_len; 930 | } while (len > 0); 931 | } 932 | } 933 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "class object!"); 934 | } 935 | return nOriginalSize - nSize; 936 | } 937 | 938 | int PILI_AMF_Decode(PILI_AMFObject *obj, const char *pBuffer, int nSize, int bDecodeName) { 939 | int nOriginalSize = nSize; 940 | int bError = FALSE; /* if there is an error while decoding - try to at least find the end mark PILI_AMF_OBJECT_END */ 941 | 942 | obj->o_num = 0; 943 | obj->o_props = NULL; 944 | while (nSize > 0) { 945 | PILI_AMFObjectProperty prop; 946 | int nRes; 947 | 948 | if (nSize >= 3 && PILI_AMF_DecodeInt24(pBuffer) == PILI_AMF_OBJECT_END) { 949 | nSize -= 3; 950 | bError = FALSE; 951 | break; 952 | } 953 | 954 | if (bError) { 955 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, 956 | "DECODING ERROR, IGNORING BYTES UNTIL NEXT KNOWN PATTERN!"); 957 | nSize--; 958 | pBuffer++; 959 | continue; 960 | } 961 | 962 | nRes = PILI_AMFProp_Decode(&prop, pBuffer, nSize, bDecodeName); 963 | if (nRes == -1) 964 | bError = TRUE; 965 | else { 966 | nSize -= nRes; 967 | pBuffer += nRes; 968 | PILI_AMF_AddProp(obj, &prop); 969 | } 970 | } 971 | 972 | if (bError) 973 | return -1; 974 | 975 | return nOriginalSize - nSize; 976 | } 977 | 978 | void PILI_AMF_AddProp(PILI_AMFObject *obj, const PILI_AMFObjectProperty *prop) { 979 | if (!(obj->o_num & 0x0f)) 980 | obj->o_props = 981 | realloc(obj->o_props, (obj->o_num + 16) * sizeof(PILI_AMFObjectProperty)); 982 | obj->o_props[obj->o_num++] = *prop; 983 | } 984 | 985 | int PILI_AMF_CountProp(PILI_AMFObject *obj) { 986 | return obj->o_num; 987 | } 988 | 989 | PILI_AMFObjectProperty * 990 | PILI_AMF_GetProp(PILI_AMFObject *obj, const PILI_AVal *name, int nIndex) { 991 | if (nIndex >= 0) { 992 | if (nIndex <= obj->o_num) 993 | return &obj->o_props[nIndex]; 994 | } else { 995 | int n; 996 | for (n = 0; n < obj->o_num; n++) { 997 | if (AVMATCH(&obj->o_props[n].p_name, name)) 998 | return &obj->o_props[n]; 999 | } 1000 | } 1001 | 1002 | return (PILI_AMFObjectProperty *)&AMFProp_Invalid; 1003 | } 1004 | 1005 | void PILI_AMF_Dump(PILI_AMFObject *obj) { 1006 | int n; 1007 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "(object begin)"); 1008 | for (n = 0; n < obj->o_num; n++) { 1009 | PILI_AMFProp_Dump(&obj->o_props[n]); 1010 | } 1011 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "(object end)"); 1012 | } 1013 | 1014 | void PILI_AMF_Reset(PILI_AMFObject *obj) { 1015 | int n; 1016 | for (n = 0; n < obj->o_num; n++) { 1017 | PILI_AMFProp_Reset(&obj->o_props[n]); 1018 | } 1019 | free(obj->o_props); 1020 | obj->o_props = NULL; 1021 | obj->o_num = 0; 1022 | } 1023 | 1024 | /* PILI_AMF3ClassDefinition */ 1025 | 1026 | void PILI_AMF3CD_AddProp(PILI_AMF3ClassDef *cd, PILI_AVal *prop) { 1027 | if (!(cd->cd_num & 0x0f)) 1028 | cd->cd_props = realloc(cd->cd_props, (cd->cd_num + 16) * sizeof(PILI_AVal)); 1029 | cd->cd_props[cd->cd_num++] = *prop; 1030 | } 1031 | 1032 | PILI_AVal * 1033 | PILI_AMF3CD_GetProp(PILI_AMF3ClassDef *cd, int nIndex) { 1034 | if (nIndex >= cd->cd_num) 1035 | return (PILI_AVal *)&AV_empty; 1036 | return &cd->cd_props[nIndex]; 1037 | } 1038 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/amf.h: -------------------------------------------------------------------------------- 1 | #ifndef __AMF_H__ 2 | #define __AMF_H__ 3 | /* 4 | * Copyright (C) 2005-2008 Team XBMC 5 | * http://www.xbmc.org 6 | * Copyright (C) 2008-2009 Andrej Stepanchuk 7 | * Copyright (C) 2009-2010 Howard Chu 8 | * 9 | * This file is part of librtmp. 10 | * 11 | * librtmp is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU Lesser General Public License as 13 | * published by the Free Software Foundation; either version 2.1, 14 | * or (at your option) any later version. 15 | * 16 | * librtmp is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Lesser General Public License 22 | * along with librtmp see the file COPYING. If not, write to 23 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 24 | * Boston, MA 02110-1301, USA. 25 | * http://www.gnu.org/copyleft/lgpl.html 26 | */ 27 | 28 | #include 29 | 30 | #ifndef TRUE 31 | #define TRUE 1 32 | #define FALSE 0 33 | #endif 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | typedef enum { 40 | PILI_AMF_NUMBER = 0, 41 | PILI_AMF_BOOLEAN, 42 | PILI_AMF_STRING, 43 | PILI_AMF_OBJECT, 44 | PILI_AMF_MOVIECLIP, /* reserved, not used */ 45 | PILI_AMF_NULL, 46 | PILI_AMF_UNDEFINED, 47 | PILI_AMF_REFERENCE, 48 | PILI_AMF_ECMA_ARRAY, 49 | PILI_AMF_OBJECT_END, 50 | PILI_AMF_STRICT_ARRAY, 51 | PILI_AMF_DATE, 52 | PILI_AMF_LONG_STRING, 53 | PILI_AMF_UNSUPPORTED, 54 | PILI_AMF_RECORDSET, /* reserved, not used */ 55 | PILI_AMF_XML_DOC, 56 | PILI_AMF_TYPED_OBJECT, 57 | PILI_AMF_AVMPLUS, /* switch to AMF3 */ 58 | PILI_AMF_INVALID = 0xff 59 | } PILI_AMFDataType; 60 | 61 | typedef enum { 62 | PILI_AMF3_UNDEFINED = 0, 63 | PILI_AMF3_NULL, 64 | PILI_AMF3_FALSE, 65 | PILI_AMF3_TRUE, 66 | PILI_AMF3_INTEGER, 67 | PILI_AMF3_DOUBLE, 68 | PILI_AMF3_STRING, 69 | PILI_AMF3_XML_DOC, 70 | PILI_AMF3_DATE, 71 | PILI_AMF3_ARRAY, 72 | PILI_AMF3_OBJECT, 73 | PILI_AMF3_XML, 74 | PILI_AMF3_BYTE_ARRAY 75 | } PILI_AMF3DataType; 76 | 77 | typedef struct PILI_AVal { 78 | char *av_val; 79 | int av_len; 80 | } PILI_AVal; 81 | #define AVC(str) \ 82 | { str, sizeof(str) - 1 } 83 | #define AVMATCH(a1, a2) \ 84 | ((a1)->av_len == (a2)->av_len && \ 85 | !memcmp((a1)->av_val, (a2)->av_val, (a1)->av_len)) 86 | 87 | struct PILI_AMFObjectProperty; 88 | 89 | typedef struct PILI_AMFObject { 90 | int o_num; 91 | struct PILI_AMFObjectProperty *o_props; 92 | } PILI_AMFObject; 93 | 94 | typedef struct PILI_AMFObjectProperty { 95 | PILI_AVal p_name; 96 | PILI_AMFDataType p_type; 97 | union { 98 | double p_number; 99 | PILI_AVal p_aval; 100 | PILI_AMFObject p_object; 101 | } p_vu; 102 | int16_t p_UTCoffset; 103 | } PILI_AMFObjectProperty; 104 | 105 | char *PILI_AMF_EncodeString(char *output, char *outend, const PILI_AVal *str); 106 | char *PILI_AMF_EncodeNumber(char *output, char *outend, double dVal); 107 | char *PILI_AMF_EncodeInt16(char *output, char *outend, short nVal); 108 | char *PILI_AMF_EncodeInt24(char *output, char *outend, int nVal); 109 | char *PILI_AMF_EncodeInt32(char *output, char *outend, int nVal); 110 | char *PILI_AMF_EncodeBoolean(char *output, char *outend, int bVal); 111 | 112 | /* Shortcuts for PILI_AMFProp_Encode */ 113 | char *PILI_AMF_EncodeNamedString(char *output, char *outend, const PILI_AVal *name, 114 | const PILI_AVal *value); 115 | char *PILI_AMF_EncodeNamedNumber(char *output, char *outend, const PILI_AVal *name, 116 | double dVal); 117 | char *PILI_AMF_EncodeNamedBoolean(char *output, char *outend, const PILI_AVal *name, 118 | int bVal); 119 | 120 | unsigned short PILI_AMF_DecodeInt16(const char *data); 121 | unsigned int PILI_AMF_DecodeInt24(const char *data); 122 | unsigned int PILI_AMF_DecodeInt32(const char *data); 123 | void PILI_AMF_DecodeString(const char *data, PILI_AVal *str); 124 | void PILI_AMF_DecodeLongString(const char *data, PILI_AVal *str); 125 | int PILI_AMF_DecodeBoolean(const char *data); 126 | double PILI_AMF_DecodeNumber(const char *data); 127 | 128 | char *PILI_AMF_Encode(PILI_AMFObject *obj, char *pBuffer, char *pBufEnd); 129 | int PILI_AMF_Decode(PILI_AMFObject *obj, const char *pBuffer, int nSize, int bDecodeName); 130 | int PILI_AMF_DecodeArray(PILI_AMFObject *obj, const char *pBuffer, int nSize, 131 | int nArrayLen, int bDecodeName); 132 | int PILI_AMF3_Decode(PILI_AMFObject *obj, const char *pBuffer, int nSize, 133 | int bDecodeName); 134 | void PILI_AMF_Dump(PILI_AMFObject *obj); 135 | void PILI_AMF_Reset(PILI_AMFObject *obj); 136 | 137 | void PILI_AMF_AddProp(PILI_AMFObject *obj, const PILI_AMFObjectProperty *prop); 138 | int PILI_AMF_CountProp(PILI_AMFObject *obj); 139 | PILI_AMFObjectProperty *PILI_AMF_GetProp(PILI_AMFObject *obj, const PILI_AVal *name, int nIndex); 140 | 141 | PILI_AMFDataType PILI_AMFProp_GetType(PILI_AMFObjectProperty *prop); 142 | void PILI_AMFProp_SetNumber(PILI_AMFObjectProperty *prop, double dval); 143 | void PILI_AMFProp_SetBoolean(PILI_AMFObjectProperty *prop, int bflag); 144 | void PILI_AMFProp_SetString(PILI_AMFObjectProperty *prop, PILI_AVal *str); 145 | void PILI_AMFProp_SetObject(PILI_AMFObjectProperty *prop, PILI_AMFObject *obj); 146 | 147 | void PILI_AMFProp_GetName(PILI_AMFObjectProperty *prop, PILI_AVal *name); 148 | void PILI_AMFProp_SetName(PILI_AMFObjectProperty *prop, PILI_AVal *name); 149 | double PILI_AMFProp_GetNumber(PILI_AMFObjectProperty *prop); 150 | int PILI_AMFProp_GetBoolean(PILI_AMFObjectProperty *prop); 151 | void PILI_AMFProp_GetString(PILI_AMFObjectProperty *prop, PILI_AVal *str); 152 | void PILI_AMFProp_GetObject(PILI_AMFObjectProperty *prop, PILI_AMFObject *obj); 153 | 154 | int PILI_AMFProp_IsValid(PILI_AMFObjectProperty *prop); 155 | 156 | char *PILI_AMFProp_Encode(PILI_AMFObjectProperty *prop, char *pBuffer, char *pBufEnd); 157 | int PILI_AMF3Prop_Decode(PILI_AMFObjectProperty *prop, const char *pBuffer, int nSize, 158 | int bDecodeName); 159 | int PILI_AMFProp_Decode(PILI_AMFObjectProperty *prop, const char *pBuffer, int nSize, 160 | int bDecodeName); 161 | 162 | void PILI_AMFProp_Dump(PILI_AMFObjectProperty *prop); 163 | void PILI_AMFProp_Reset(PILI_AMFObjectProperty *prop); 164 | 165 | typedef struct PILI_AMF3ClassDef { 166 | PILI_AVal cd_name; 167 | char cd_externalizable; 168 | char cd_dynamic; 169 | int cd_num; 170 | PILI_AVal *cd_props; 171 | } PILI_AMF3ClassDef; 172 | 173 | void PILI_AMF3CD_AddProp(PILI_AMF3ClassDef *cd, PILI_AVal *prop); 174 | PILI_AVal *PILI_AMF3CD_GetProp(PILI_AMF3ClassDef *cd, int idx); 175 | 176 | #ifdef __cplusplus 177 | } 178 | #endif 179 | 180 | #endif /* __AMF_H__ */ 181 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/bytes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2005-2008 Team XBMC 3 | * http://www.xbmc.org 4 | * Copyright (C) 2008-2009 Andrej Stepanchuk 5 | * Copyright (C) 2009-2010 Howard Chu 6 | * 7 | * This file is part of librtmp. 8 | * 9 | * librtmp is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as 11 | * published by the Free Software Foundation; either version 2.1, 12 | * or (at your option) any later version. 13 | * 14 | * librtmp is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with librtmp see the file COPYING. If not, write to 21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 | * Boston, MA 02110-1301, USA. 23 | * http://www.gnu.org/copyleft/lgpl.html 24 | */ 25 | 26 | #ifndef __BYTES_H__ 27 | #define __BYTES_H__ 28 | 29 | #include 30 | 31 | #ifdef _WIN32 32 | /* Windows is little endian only */ 33 | #define __LITTLE_ENDIAN 1234 34 | #define __BIG_ENDIAN 4321 35 | #define __BYTE_ORDER __LITTLE_ENDIAN 36 | #define __FLOAT_WORD_ORDER __BYTE_ORDER 37 | 38 | typedef unsigned char uint8_t; 39 | 40 | #else /* !_WIN32 */ 41 | 42 | #include 43 | 44 | #if defined(BYTE_ORDER) && !defined(__BYTE_ORDER) 45 | #define __BYTE_ORDER BYTE_ORDER 46 | #endif 47 | 48 | #if defined(BIG_ENDIAN) && !defined(__BIG_ENDIAN) 49 | #define __BIG_ENDIAN BIG_ENDIAN 50 | #endif 51 | 52 | #if defined(LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN) 53 | #define __LITTLE_ENDIAN LITTLE_ENDIAN 54 | #endif 55 | 56 | #endif /* !_WIN32 */ 57 | 58 | /* define default endianness */ 59 | #ifndef __LITTLE_ENDIAN 60 | #define __LITTLE_ENDIAN 1234 61 | #endif 62 | 63 | #ifndef __BIG_ENDIAN 64 | #define __BIG_ENDIAN 4321 65 | #endif 66 | 67 | #ifndef __BYTE_ORDER 68 | #warning "Byte order not defined on your system, assuming little endian!" 69 | #define __BYTE_ORDER __LITTLE_ENDIAN 70 | #endif 71 | 72 | /* ok, we assume to have the same float word order and byte order if float word 73 | * order is not defined */ 74 | #ifndef __FLOAT_WORD_ORDER 75 | #warning "Float word order not defined, assuming the same as byte order!" 76 | #define __FLOAT_WORD_ORDER __BYTE_ORDER 77 | #endif 78 | 79 | #if !defined(__BYTE_ORDER) || !defined(__FLOAT_WORD_ORDER) 80 | #error "Undefined byte or float word order!" 81 | #endif 82 | 83 | #if __FLOAT_WORD_ORDER != __BIG_ENDIAN && __FLOAT_WORD_ORDER != __LITTLE_ENDIAN 84 | #error "Unknown/unsupported float word order!" 85 | #endif 86 | 87 | #if __BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN 88 | #error "Unknown/unsupported byte order!" 89 | #endif 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/dh.h: -------------------------------------------------------------------------------- 1 | /* RTMPDump - Diffie-Hellmann Key Exchange 2 | * Copyright (C) 2009 Andrej Stepanchuk 3 | * Copyright (C) 2009-2010 Howard Chu 4 | * 5 | * This file is part of librtmp. 6 | * 7 | * librtmp is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1, 10 | * or (at your option) any later version. 11 | * 12 | * librtmp is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with librtmp see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | * Boston, MA 02110-1301, USA. 21 | * http://www.gnu.org/copyleft/lgpl.html 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #ifdef USE_POLARSSL 31 | #include 32 | typedef mpi *MP_t; 33 | #define PILI_MP_new(m) \ 34 | m = malloc(sizeof(mpi)); \ 35 | mpi_init(m, NULL) 36 | #define PILI_MP_set_w(mpi, w) mpi_lset(mpi, w) 37 | #define PILI_MP_cmp(u, v) mpi_cmp_mpi(u, v) 38 | #define PILI_MP_set(u, v) mpi_copy(u, v) 39 | #define PILI_MP_sub_w(mpi, w) mpi_sub_int(mpi, mpi, w) 40 | #define PILI_MP_cmp_1(mpi) mpi_cmp_int(mpi, 1) 41 | #define PILI_MP_modexp(r, y, q, p) mpi_exp_mod(r, y, q, p, NULL) 42 | #define PILI_MP_free(mpi) \ 43 | mpi_free(mpi, NULL); \ 44 | free(mpi) 45 | #define PILI_MP_gethex(u, hex, res) \ 46 | PILI_MP_new(u); \ 47 | res = mpi_read_string(u, 16, hex) == 0 48 | #define PILI_MP_bytes(u) mpi_size(u) 49 | #define PILI_MP_setbin(u, buf, len) mpi_write_binary(u, buf, len) 50 | #define PILI_MP_getbin(u, buf, len) \ 51 | PILI_MP_new(u); \ 52 | mpi_read_binary(u, buf, len) 53 | 54 | typedef struct PILI_MDH { 55 | MP_t p; 56 | MP_t g; 57 | MP_t pub_key; 58 | MP_t priv_key; 59 | long length; 60 | dhm_context ctx; 61 | } PILI_MDH; 62 | 63 | #define PILI_MDH_new() calloc(1, sizeof(PILI_MDH)) 64 | #define PILI_MDH_free(vp) \ 65 | { \ 66 | PILI_MDH *dh = vp; \ 67 | dhm_free(&dh->ctx); \ 68 | PILI_MP_free(dh->p); \ 69 | PILI_MP_free(dh->g); \ 70 | PILI_MP_free(dh->pub_key); \ 71 | PILI_MP_free(dh->priv_key); \ 72 | free(dh); \ 73 | } 74 | 75 | static int PILI_MDH_generate_key(MDH *dh) { 76 | unsigned char out[2]; 77 | PILI_MP_set(&dh->ctx.P, dh->p); 78 | PILI_MP_set(&dh->ctx.G, dh->g); 79 | dh->ctx.len = 128; 80 | dhm_make_public(&dh->ctx, 1024, out, 1, havege_rand, &RTMP_TLS_ctx->hs); 81 | PILI_MP_new(dh->pub_key); 82 | PILI_MP_new(dh->priv_key); 83 | PILI_MP_set(dh->pub_key, &dh->ctx.GX); 84 | PILI_MP_set(dh->priv_key, &dh->ctx.X); 85 | return 1; 86 | } 87 | 88 | static int PILI_MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh) { 89 | int n = len; 90 | PILI_MP_set(&dh->ctx.GY, pub); 91 | dhm_calc_secret(&dh->ctx, secret, &n); 92 | return 0; 93 | } 94 | 95 | #elif defined(USE_GNUTLS) 96 | #include 97 | typedef gcry_mpi_t MP_t; 98 | #define PILI_MP_new(m) m = gcry_mpi_new(1) 99 | #define PILI_MP_set_w(mpi, w) gcry_mpi_set_ui(mpi, w) 100 | #define PILI_MP_cmp(u, v) gcry_mpi_cmp(u, v) 101 | #define PILI_MP_set(u, v) gcry_mpi_set(u, v) 102 | #define PILI_MP_sub_w(mpi, w) gcry_mpi_sub_ui(mpi, mpi, w) 103 | #define PILI_MP_cmp_1(mpi) gcry_mpi_cmp_ui(mpi, 1) 104 | #define PILI_MP_modexp(r, y, q, p) gcry_mpi_powm(r, y, q, p) 105 | #define PILI_MP_free(mpi) gcry_mpi_release(mpi) 106 | #define PILI_MP_gethex(u, hex, res) \ 107 | res = (gcry_mpi_scan(&u, GCRYMPI_FMT_HEX, hex, 0, 0) == 0) 108 | #define PILI_MP_bytes(u) (gcry_mpi_get_nbits(u) + 7) / 8 109 | #define PILI_MP_setbin(u, buf, len) \ 110 | gcry_mpi_print(GCRYMPI_FMT_USG, buf, len, NULL, u) 111 | #define PILI_MP_getbin(u, buf, len) \ 112 | gcry_mpi_scan(&u, GCRYMPI_FMT_USG, buf, len, NULL) 113 | 114 | typedef struct PILI_MDH { 115 | MP_t p; 116 | MP_t g; 117 | MP_t pub_key; 118 | MP_t priv_key; 119 | long length; 120 | } PILI_MDH; 121 | 122 | #define PILI_MDH_new() calloc(1, sizeof(MDH)) 123 | #define PILI_MDH_free(dh) \ 124 | do { \ 125 | PILI_MP_free(((PILI_MDH *)(dh))->p); \ 126 | PILI_MP_free(((PILI_MDH *)(dh))->g); \ 127 | PILI_MP_free(((PILI_MDH *)(dh))->pub_key); \ 128 | PILI_MP_free(((PILI_MDH *)(dh))->priv_key); \ 129 | free(dh); \ 130 | } while (0) 131 | 132 | extern MP_t gnutls_calc_dh_secret(MP_t *priv, MP_t g, MP_t p); 133 | extern MP_t gnutls_calc_dh_key(MP_t y, MP_t x, MP_t p); 134 | 135 | #define PILI_MDH_generate_key(dh) \ 136 | (dh->pub_key = gnutls_calc_dh_secret(&dh->priv_key, dh->g, dh->p)) 137 | static int PILI_MDH_compute_key(uint8_t *secret, size_t len, MP_t pub, MDH *dh) { 138 | MP_t sec = gnutls_calc_dh_key(pub, dh->priv_key, dh->p); 139 | if (sec) { 140 | PILI_MP_setbin(sec, secret, len); 141 | PILI_MP_free(sec); 142 | return 0; 143 | } else 144 | return -1; 145 | } 146 | 147 | #else /* USE_OPENSSL */ 148 | #include 149 | #include 150 | 151 | typedef BIGNUM *MP_t; 152 | #define PILI_MP_new(m) m = BN_new() 153 | #define PILI_MP_set_w(mpi, w) BN_set_word(mpi, w) 154 | #define PILI_MP_cmp(u, v) BN_cmp(u, v) 155 | #define PILI_MP_set(u, v) BN_copy(u, v) 156 | #define PILI_MP_sub_w(mpi, w) BN_sub_word(mpi, w) 157 | #define PILI_MP_cmp_1(mpi) BN_cmp(mpi, BN_value_one()) 158 | #define PILI_MP_modexp(r, y, q, p) \ 159 | do { \ 160 | BN_CTX *ctx = BN_CTX_new(); \ 161 | BN_mod_exp(r, y, q, p, ctx); \ 162 | BN_CTX_free(ctx); \ 163 | } while (0) 164 | #define PILI_MP_free(mpi) BN_free(mpi) 165 | #define PILI_MP_gethex(u, hex, res) res = BN_hex2bn(&u, hex) 166 | #define PILI_MP_bytes(u) BN_num_bytes(u) 167 | #define PILI_MP_setbin(u, buf, len) BN_bn2bin(u, buf) 168 | #define PILI_MP_getbin(u, buf, len) u = BN_bin2bn(buf, len, 0) 169 | 170 | #define PILI_MDH DH 171 | #define PILI_MDH_new() DH_new() 172 | #define PILI_MDH_free(dh) DH_free(dh) 173 | #define PILI_MDH_generate_key(dh) DH_generate_key(dh) 174 | #define PILI_MDH_compute_key(secret, seclen, pub, dh) DH_compute_key(secret, pub, dh) 175 | 176 | #endif 177 | 178 | #include "dhgroups.h" 179 | #include "log.h" 180 | 181 | /* RFC 2631, Section 2.1.5, http://www.ietf.org/rfc/rfc2631.txt */ 182 | static int PILI_isValidPublicKey(MP_t y, MP_t p, MP_t q) { 183 | int ret = TRUE; 184 | MP_t bn; 185 | assert(y); 186 | 187 | PILI_MP_new(bn); 188 | assert(bn); 189 | 190 | /* y must lie in [2,p-1] */ 191 | PILI_MP_set_w(bn, 1); 192 | if (PILI_MP_cmp(y, bn) < 0) { 193 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "DH public key must be at least 2"); 194 | ret = FALSE; 195 | goto failed; 196 | } 197 | 198 | /* bn = p-2 */ 199 | PILI_MP_set(bn, p); 200 | PILI_MP_sub_w(bn, 1); 201 | if (PILI_MP_cmp(y, bn) > 0) { 202 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "DH public key must be at most p-2"); 203 | ret = FALSE; 204 | goto failed; 205 | } 206 | 207 | /* Verify with Sophie-Germain prime 208 | * 209 | * This is a nice test to make sure the public key position is calculated 210 | * correctly. This test will fail in about 50% of the cases if applied to 211 | * random data. 212 | */ 213 | if (q) { 214 | /* y must fulfill y^q mod p = 1 */ 215 | PILI_MP_modexp(bn, y, q, p); 216 | 217 | if (PILI_MP_cmp_1(bn) != 0) { 218 | PILI_RTMP_Log(PILI_RTMP_LOGWARNING, "DH public key does not fulfill y^q mod p = 1"); 219 | } 220 | } 221 | 222 | failed: 223 | PILI_MP_free(bn); 224 | return ret; 225 | } 226 | 227 | static PILI_MDH *PILI_DHInit(int nKeyBits) { 228 | size_t res; 229 | PILI_MDH *dh = PILI_MDH_new(); 230 | 231 | if (!dh) 232 | goto failed; 233 | 234 | PILI_MP_new(dh->g); 235 | 236 | if (!dh->g) 237 | goto failed; 238 | 239 | PILI_MP_gethex(dh->p, P1024, res); /* prime P1024, see dhgroups.h */ 240 | if (!res) { 241 | goto failed; 242 | } 243 | 244 | PILI_MP_set_w(dh->g, 2); /* base 2 */ 245 | 246 | dh->length = nKeyBits; 247 | return dh; 248 | 249 | failed: 250 | if (dh) 251 | PILI_MDH_free(dh); 252 | 253 | return 0; 254 | } 255 | 256 | static int PILI_DHGenerateKey(PILI_MDH *dh) { 257 | size_t res = 0; 258 | if (!dh) 259 | return 0; 260 | 261 | while (!res) { 262 | MP_t q1 = NULL; 263 | 264 | if (!PILI_MDH_generate_key(dh)) 265 | return 0; 266 | 267 | PILI_MP_gethex(q1, Q1024, res); 268 | assert(res); 269 | 270 | res = PILI_isValidPublicKey(dh->pub_key, dh->p, q1); 271 | if (!res) { 272 | PILI_MP_free(dh->pub_key); 273 | PILI_MP_free(dh->priv_key); 274 | dh->pub_key = dh->priv_key = 0; 275 | } 276 | 277 | PILI_MP_free(q1); 278 | } 279 | return 1; 280 | } 281 | 282 | /* fill pubkey with the public key in BIG ENDIAN order 283 | * 00 00 00 00 00 x1 x2 x3 ..... 284 | */ 285 | 286 | static int PILI_DHGetPublicKey(PILI_MDH *dh, uint8_t *pubkey, size_t nPubkeyLen) { 287 | int len; 288 | if (!dh || !dh->pub_key) 289 | return 0; 290 | 291 | len = PILI_MP_bytes(dh->pub_key); 292 | if (len <= 0 || len > (int)nPubkeyLen) 293 | return 0; 294 | 295 | memset(pubkey, 0, nPubkeyLen); 296 | PILI_MP_setbin(dh->pub_key, pubkey + (nPubkeyLen - len), len); 297 | return 1; 298 | } 299 | 300 | #if 0 /* unused */ 301 | static int 302 | PILI_DHGetPrivateKey(PILI_MDH *dh, uint8_t *privkey, size_t nPrivkeyLen) 303 | { 304 | if (!dh || !dh->priv_key) 305 | return 0; 306 | 307 | int len = PILI_MP_bytes(dh->priv_key); 308 | if (len <= 0 || len > (int) nPrivkeyLen) 309 | return 0; 310 | 311 | memset(privkey, 0, nPrivkeyLen); 312 | PILI_MP_setbin(dh->priv_key, privkey + (nPrivkeyLen - len), len); 313 | return 1; 314 | } 315 | #endif 316 | 317 | /* computes the shared secret key from the private MDH value and the 318 | * other party's public key (pubkey) 319 | */ 320 | static int PILI_DHComputeSharedSecretKey(PILI_MDH *dh, uint8_t *pubkey, size_t nPubkeyLen, 321 | uint8_t *secret) { 322 | MP_t q1 = NULL, pubkeyBn = NULL; 323 | size_t len; 324 | int res; 325 | 326 | if (!dh || !secret || nPubkeyLen >= INT_MAX) 327 | return -1; 328 | 329 | PILI_MP_getbin(pubkeyBn, pubkey, nPubkeyLen); 330 | if (!pubkeyBn) 331 | return -1; 332 | 333 | PILI_MP_gethex(q1, Q1024, len); 334 | assert(len); 335 | 336 | if (PILI_isValidPublicKey(pubkeyBn, dh->p, q1)) 337 | res = PILI_MDH_compute_key(secret, nPubkeyLen, pubkeyBn, dh); 338 | else 339 | res = -1; 340 | 341 | PILI_MP_free(q1); 342 | PILI_MP_free(pubkeyBn); 343 | 344 | return res; 345 | } 346 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/dhgroups.h: -------------------------------------------------------------------------------- 1 | /* librtmp - Diffie-Hellmann Key Exchange 2 | * Copyright (C) 2009 Andrej Stepanchuk 3 | * 4 | * This file is part of librtmp. 5 | * 6 | * librtmp is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as 8 | * published by the Free Software Foundation; either version 2.1, 9 | * or (at your option) any later version. 10 | * 11 | * librtmp is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with librtmp see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | * http://www.gnu.org/copyleft/lgpl.html 21 | */ 22 | 23 | /* from RFC 3526, see http://www.ietf.org/rfc/rfc3526.txt */ 24 | 25 | /* 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 } */ 26 | #define P768 \ 27 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 28 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 29 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 30 | "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF" 31 | 32 | /* 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } */ 33 | #define P1024 \ 34 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 35 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 36 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 37 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 38 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \ 39 | "FFFFFFFFFFFFFFFF" 40 | 41 | /* Group morder largest prime factor: */ 42 | #define Q1024 \ 43 | "7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68" \ 44 | "948127044533E63A0105DF531D89CD9128A5043CC71A026E" \ 45 | "F7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122" \ 46 | "F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6" \ 47 | "F71C35FDAD44CFD2D74F9208BE258FF324943328F67329C0" \ 48 | "FFFFFFFFFFFFFFFF" 49 | 50 | /* 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } */ 51 | #define P1536 \ 52 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 53 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 54 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 55 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 56 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 57 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 58 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 59 | "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" 60 | 61 | /* 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } */ 62 | #define P2048 \ 63 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 64 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 65 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 66 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 67 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 68 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 69 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 70 | "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ 71 | "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ 72 | "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ 73 | "15728E5A8AACAA68FFFFFFFFFFFFFFFF" 74 | 75 | /* 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } */ 76 | #define P3072 \ 77 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 78 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 79 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 80 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 81 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 82 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 83 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 84 | "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ 85 | "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ 86 | "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ 87 | "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ 88 | "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ 89 | "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ 90 | "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ 91 | "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ 92 | "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" 93 | 94 | /* 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } */ 95 | #define P4096 \ 96 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 97 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 98 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 99 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 100 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 101 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 102 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 103 | "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ 104 | "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ 105 | "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ 106 | "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ 107 | "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ 108 | "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ 109 | "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ 110 | "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ 111 | "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ 112 | "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ 113 | "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ 114 | "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ 115 | "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ 116 | "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ 117 | "FFFFFFFFFFFFFFFF" 118 | 119 | /* 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } */ 120 | #define P6144 \ 121 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 122 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 123 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 124 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 125 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 126 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 127 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 128 | "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ 129 | "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ 130 | "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ 131 | "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ 132 | "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ 133 | "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ 134 | "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ 135 | "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ 136 | "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ 137 | "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ 138 | "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ 139 | "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ 140 | "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ 141 | "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" \ 142 | "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" \ 143 | "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" \ 144 | "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" \ 145 | "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" \ 146 | "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" \ 147 | "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" \ 148 | "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" \ 149 | "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" \ 150 | "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" \ 151 | "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" \ 152 | "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF" 153 | 154 | /* 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } */ 155 | #define P8192 \ 156 | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ 157 | "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ 158 | "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ 159 | "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ 160 | "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ 161 | "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ 162 | "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ 163 | "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ 164 | "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ 165 | "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ 166 | "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ 167 | "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ 168 | "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ 169 | "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ 170 | "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ 171 | "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ 172 | "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ 173 | "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ 174 | "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ 175 | "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ 176 | "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" \ 177 | "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" \ 178 | "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" \ 179 | "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" \ 180 | "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" \ 181 | "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" \ 182 | "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" \ 183 | "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" \ 184 | "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" \ 185 | "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" \ 186 | "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" \ 187 | "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" \ 188 | "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" \ 189 | "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" \ 190 | "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" \ 191 | "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" \ 192 | "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" \ 193 | "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" \ 194 | "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" \ 195 | "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" \ 196 | "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" \ 197 | "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" \ 198 | "60C980DD98EDD3DFFFFFFFFFFFFFFFFF" 199 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/error.c: -------------------------------------------------------------------------------- 1 | #include "error.h" 2 | #include 3 | #include 4 | 5 | void PILI_RTMPError_Alloc(RTMPError *error, size_t msg_size) { 6 | if (error) { 7 | PILI_RTMPError_Free(error); 8 | 9 | error->code = 0; 10 | error->message = (char *)malloc(msg_size + 1); 11 | memset(error->message, 0, msg_size); 12 | } 13 | } 14 | 15 | void PILI_RTMPError_Free(RTMPError *error) { 16 | if (error) { 17 | if (error->message) { 18 | free(error->message); 19 | error->message = NULL; 20 | } 21 | } 22 | } 23 | 24 | void PILI_RTMPError_Message(RTMPError *error, int code, const char *message) { 25 | if (error && message) { 26 | PILI_RTMPError_Alloc(error, strlen(message)); 27 | error->code = code; 28 | strcpy(error->message, message); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/error.h: -------------------------------------------------------------------------------- 1 | #ifndef __ERROR_H__ 2 | #define __ERROR_H__ 3 | 4 | #include 5 | 6 | typedef struct RTMPError { 7 | int code; 8 | char *message; 9 | } RTMPError; 10 | 11 | void PILI_RTMPError_Alloc(RTMPError *error, size_t msg_size); 12 | void PILI_RTMPError_Free(RTMPError *error); 13 | void PILI_RTMPError_Message(RTMPError *error, int code, const char *message); 14 | 15 | // error defines 16 | enum { 17 | PILI_RTMPErrorUnknow = -1, // "Unknow error" 18 | PILI_RTMPErrorUnknowOption = -999, // "Unknown option %s" 19 | PILI_RTMPErrorAccessDNSFailed = -1000, // "Failed to access the DNS. (addr: %s)" 20 | PILI_RTMPErrorFailedToConnectSocket = 21 | -1001, // "Failed to connect socket. %d (%s)" 22 | PILI_RTMPErrorSocksNegotiationFailed = -1002, // "Socks negotiation failed" 23 | PILI_RTMPErrorFailedToCreateSocket = 24 | -1003, // "Failed to create socket. %d (%s)" 25 | PILI_RTMPErrorHandshakeFailed = -1004, // "Handshake failed" 26 | PILI_RTMPErrorRTMPConnectFailed = -1005, // "RTMP connect failed" 27 | PILI_RTMPErrorSendFailed = -1006, // "Send error %d (%s), (%d bytes)" 28 | PILI_RTMPErrorServerRequestedClose = -1007, // "RTMP server requested close" 29 | PILI_RTMPErrorNetStreamFailed = -1008, // "NetStream failed" 30 | PILI_RTMPErrorNetStreamPlayFailed = -1009, // "NetStream play failed" 31 | PILI_RTMPErrorNetStreamPlayStreamNotFound = 32 | -1010, // "NetStream play stream not found" 33 | PILI_RTMPErrorNetConnectionConnectInvalidApp = 34 | -1011, // "NetConnection connect invalip app" 35 | PILI_RTMPErrorSanityFailed = 36 | -1012, // "Sanity failed. Trying to send header of type: 0x%02X" 37 | PILI_RTMPErrorSocketClosedByPeer = -1013, // "RTMP socket closed by peer" 38 | PILI_RTMPErrorRTMPConnectStreamFailed = -1014, // "RTMP connect stream failed" 39 | PILI_RTMPErrorSocketTimeout = -1015, // "RTMP socket timeout" 40 | 41 | // SSL errors 42 | PILI_RTMPErrorTLSConnectFailed = -1200, // "TLS_Connect failed" 43 | PILI_RTMPErrorNoSSLOrTLSSupport = -1201, // "No SSL/TLS support" 44 | }; 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/hashswf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009-2010 Howard Chu 3 | * 4 | * This file is part of librtmp. 5 | * 6 | * librtmp is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as 8 | * published by the Free Software Foundation; either version 2.1, 9 | * or (at your option) any later version. 10 | * 11 | * librtmp is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with librtmp see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 | * Boston, MA 02110-1301, USA. 20 | * http://www.gnu.org/copyleft/lgpl.html 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "http.h" 30 | #include "log.h" 31 | #include "rtmp_sys.h" 32 | 33 | #ifdef CRYPTO 34 | #ifdef USE_POLARSSL 35 | #include 36 | #ifndef SHA256_DIGEST_LENGTH 37 | #define SHA256_DIGEST_LENGTH 32 38 | #endif 39 | #define HMAC_CTX sha2_context 40 | #define HMAC_setup(ctx, key, len) sha2_hmac_starts(&ctx, (unsigned char *)key, len, 0) 41 | #define HMAC_crunch(ctx, buf, len) sha2_hmac_update(&ctx, buf, len) 42 | #define HMAC_finish(ctx, dig, dlen) \ 43 | dlen = SHA256_DIGEST_LENGTH; \ 44 | sha2_hmac_finish(&ctx, dig) 45 | #define HMAC_close(ctx) 46 | #elif defined(USE_GNUTLS) 47 | #include 48 | #include 49 | #ifndef SHA256_DIGEST_LENGTH 50 | #define SHA256_DIGEST_LENGTH 32 51 | #endif 52 | #define HMAC_CTX gcry_md_hd_t 53 | #define HMAC_setup(ctx, key, len) \ 54 | gcry_md_open(&ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); \ 55 | gcry_md_setkey(ctx, key, len) 56 | #define HMAC_crunch(ctx, buf, len) gcry_md_write(ctx, buf, len) 57 | #define HMAC_finish(ctx, dig, dlen) \ 58 | dlen = SHA256_DIGEST_LENGTH; \ 59 | memcpy(dig, gcry_md_read(ctx, 0), dlen) 60 | #define HMAC_close(ctx) gcry_md_close(ctx) 61 | #else /* USE_OPENSSL */ 62 | #include 63 | #include 64 | #include 65 | #include 66 | #define HMAC_setup(ctx, key, len) \ 67 | HMAC_CTX_init(&ctx); \ 68 | HMAC_Init_ex(&ctx, (unsigned char *)key, len, EVP_sha256(), 0) 69 | #define HMAC_crunch(ctx, buf, len) HMAC_Update(&ctx, (unsigned char *)buf, len) 70 | #define HMAC_finish(ctx, dig, dlen) HMAC_Final(&ctx, (unsigned char *)dig, &dlen); 71 | #define HMAC_close(ctx) HMAC_CTX_cleanup(&ctx) 72 | #endif 73 | 74 | extern void PILI_RTMP_TLS_Init(); 75 | extern TLS_CTX RTMP_TLS_ctx; 76 | 77 | #endif /* CRYPTO */ 78 | 79 | #include 80 | 81 | #define AGENT "Mozilla/5.0" 82 | 83 | HTTPResult 84 | PILI_HTTP_get(struct HTTP_ctx *http, const char *url, PILI_HTTP_read_callback *cb) { 85 | char *host, *path; 86 | char *p1, *p2; 87 | char hbuf[256]; 88 | int port = 80; 89 | #ifdef CRYPTO 90 | int ssl = 0; 91 | #endif 92 | int hlen, flen = 0; 93 | int rc, i; 94 | int len_known; 95 | HTTPResult ret = HTTPRES_OK; 96 | // struct sockaddr_in sa; 97 | PILI_RTMPSockBuf sb = {0}; 98 | 99 | http->status = -1; 100 | 101 | // memset(&sa, 0, sizeof(struct sockaddr_in)); 102 | // sa.sin_family = AF_INET; 103 | 104 | /* we only handle http here */ 105 | if (strncasecmp(url, "http", 4)) 106 | return HTTPRES_BAD_REQUEST; 107 | 108 | if (url[4] == 's') { 109 | #ifdef CRYPTO 110 | ssl = 1; 111 | port = 443; 112 | if (!RTMP_TLS_ctx) 113 | PILI_RTMP_TLS_Init(); 114 | #else 115 | return HTTPRES_BAD_REQUEST; 116 | #endif 117 | } 118 | 119 | p1 = strchr(url + 4, ':'); 120 | if (!p1 || strncmp(p1, "://", 3)) 121 | return HTTPRES_BAD_REQUEST; 122 | 123 | host = p1 + 3; 124 | path = strchr(host, '/'); 125 | hlen = path - host; 126 | strncpy(hbuf, host, hlen); 127 | hbuf[hlen] = '\0'; 128 | host = hbuf; 129 | p1 = strrchr(host, ':'); 130 | if (p1) { 131 | *p1++ = '\0'; 132 | port = atoi(p1); 133 | } 134 | 135 | // sa.sin_addr.s_addr = inet_addr(host); 136 | // if (sa.sin_addr.s_addr == INADDR_NONE) 137 | // { 138 | // struct hostent *hp = gethostbyname(host); 139 | // if (!hp || !hp->h_addr) 140 | // return HTTPRES_LOST_CONNECTION; 141 | // sa.sin_addr = *(struct in_addr *)hp->h_addr; 142 | // } 143 | // sa.sin_port = htons(port); 144 | struct addrinfo hints = {0}, *ai, *cur_ai; 145 | char portstr[10]; 146 | hints.ai_family = AF_UNSPEC; 147 | hints.ai_socktype = SOCK_STREAM; 148 | snprintf(portstr, sizeof(portstr), "%d", port); 149 | ret = getaddrinfo(host, portstr, &hints, &ai); 150 | if (ret != 0) { 151 | return HTTPRES_LOST_CONNECTION; 152 | } 153 | 154 | cur_ai = ai; 155 | 156 | sb.sb_socket = socket(cur_ai->ai_family, 157 | cur_ai->ai_socktype, 158 | cur_ai->ai_protocol); 159 | // sb.sb_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 160 | if (sb.sb_socket == -1) { 161 | freeaddrinfo(ai); 162 | return HTTPRES_LOST_CONNECTION; 163 | } 164 | i = sprintf(sb.sb_buf, 165 | "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\nReferrer: %.*s\r\n", 166 | path, AGENT, host, (int)(path - url + 1), url); 167 | if (http->date[0]) 168 | i += sprintf(sb.sb_buf + i, "If-Modified-Since: %s\r\n", http->date); 169 | i += sprintf(sb.sb_buf + i, "\r\n"); 170 | 171 | if (cur_ai->ai_family == AF_INET6) { 172 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)cur_ai->ai_addr; 173 | in6->sin6_port = htons(port); 174 | } 175 | 176 | if (connect(sb.sb_socket, cur_ai->ai_addr, cur_ai->ai_addrlen) < 0) { 177 | ret = HTTPRES_LOST_CONNECTION; 178 | goto leave; 179 | } 180 | #ifdef CRYPTO 181 | if (ssl) { 182 | #ifdef NO_SSL 183 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "%s, No SSL/TLS support", __FUNCTION__); 184 | ret = HTTPRES_BAD_REQUEST; 185 | goto leave; 186 | #else 187 | TLS_client(RTMP_TLS_ctx, sb.sb_ssl); 188 | TLS_setfd(sb.sb_ssl, sb.sb_socket); 189 | if ((i = TLS_connect(sb.sb_ssl)) < 0) { 190 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "%s, TLS_Connect failed", __FUNCTION__); 191 | ret = HTTPRES_LOST_CONNECTION; 192 | goto leave; 193 | } 194 | #endif 195 | } 196 | #endif 197 | PILI_RTMPSockBuf_Send(&sb, sb.sb_buf, i); 198 | 199 | /* set timeout */ 200 | #define HTTP_TIMEOUT 5 201 | { 202 | SET_RCVTIMEO(tv, HTTP_TIMEOUT); 203 | if (setsockopt(sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv))) { 204 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "%s, Setting socket timeout to %ds failed!", 205 | __FUNCTION__, HTTP_TIMEOUT); 206 | } 207 | } 208 | 209 | sb.sb_size = 0; 210 | sb.sb_timedout = FALSE; 211 | if (PILI_RTMPSockBuf_Fill(&sb, HTTP_TIMEOUT) < 1) { 212 | ret = HTTPRES_LOST_CONNECTION; 213 | goto leave; 214 | } 215 | if (strncmp(sb.sb_buf, "HTTP/1", 6)) { 216 | ret = HTTPRES_BAD_REQUEST; 217 | goto leave; 218 | } 219 | 220 | p1 = strchr(sb.sb_buf, ' '); 221 | rc = atoi(p1 + 1); 222 | http->status = rc; 223 | 224 | if (rc >= 300) { 225 | if (rc == 304) { 226 | ret = HTTPRES_OK_NOT_MODIFIED; 227 | goto leave; 228 | } else if (rc == 404) 229 | ret = HTTPRES_NOT_FOUND; 230 | else if (rc >= 500) 231 | ret = HTTPRES_SERVER_ERROR; 232 | else if (rc >= 400) 233 | ret = HTTPRES_BAD_REQUEST; 234 | else 235 | ret = HTTPRES_REDIRECTED; 236 | } 237 | 238 | p1 = memchr(sb.sb_buf, '\n', sb.sb_size); 239 | if (!p1) { 240 | ret = HTTPRES_BAD_REQUEST; 241 | goto leave; 242 | } 243 | sb.sb_start = p1 + 1; 244 | sb.sb_size -= sb.sb_start - sb.sb_buf; 245 | 246 | while ((p2 = memchr(sb.sb_start, '\r', sb.sb_size))) { 247 | if (*sb.sb_start == '\r') { 248 | sb.sb_start += 2; 249 | sb.sb_size -= 2; 250 | break; 251 | } else if (!strncasecmp(sb.sb_start, "Content-Length: ", sizeof("Content-Length: ") - 1)) { 252 | flen = atoi(sb.sb_start + sizeof("Content-Length: ") - 1); 253 | } else if (!strncasecmp(sb.sb_start, "Last-Modified: ", sizeof("Last-Modified: ") - 1)) { 254 | *p2 = '\0'; 255 | strcpy(http->date, sb.sb_start + sizeof("Last-Modified: ") - 1); 256 | } 257 | p2 += 2; 258 | sb.sb_size -= p2 - sb.sb_start; 259 | sb.sb_start = p2; 260 | if (sb.sb_size < 1) { 261 | if (PILI_RTMPSockBuf_Fill(&sb, HTTP_TIMEOUT) < 1) { 262 | ret = HTTPRES_LOST_CONNECTION; 263 | goto leave; 264 | } 265 | } 266 | } 267 | 268 | len_known = flen > 0; 269 | while ((!len_known || flen > 0) && 270 | (sb.sb_size > 0 || PILI_RTMPSockBuf_Fill(&sb, HTTP_TIMEOUT) > 0)) { 271 | cb(sb.sb_start, 1, sb.sb_size, http->data); 272 | if (len_known) 273 | flen -= sb.sb_size; 274 | http->size += sb.sb_size; 275 | sb.sb_size = 0; 276 | } 277 | 278 | if (flen > 0) 279 | ret = HTTPRES_LOST_CONNECTION; 280 | 281 | leave: 282 | PILI_RTMPSockBuf_Close(&sb); 283 | freeaddrinfo(ai); 284 | return ret; 285 | } 286 | 287 | #ifdef CRYPTO 288 | 289 | #define CHUNK 16384 290 | 291 | struct PILI_info { 292 | z_stream *zs; 293 | HMAC_CTX ctx; 294 | int first; 295 | int zlib; 296 | int size; 297 | }; 298 | 299 | static size_t 300 | PILI_swfcrunch(void *ptr, size_t size, size_t nmemb, void *stream) { 301 | struct info *i = stream; 302 | char *p = ptr; 303 | size_t len = size * nmemb; 304 | 305 | if (i->first) { 306 | i->first = 0; 307 | /* compressed? */ 308 | if (!strncmp(p, "CWS", 3)) { 309 | *p = 'F'; 310 | i->zlib = 1; 311 | } 312 | HMAC_crunch(i->ctx, (unsigned char *)p, 8); 313 | p += 8; 314 | len -= 8; 315 | i->size = 8; 316 | } 317 | 318 | if (i->zlib) { 319 | unsigned char out[CHUNK]; 320 | i->zs->next_in = (unsigned char *)p; 321 | i->zs->avail_in = len; 322 | do { 323 | i->zs->avail_out = CHUNK; 324 | i->zs->next_out = out; 325 | inflate(i->zs, Z_NO_FLUSH); 326 | len = CHUNK - i->zs->avail_out; 327 | i->size += len; 328 | HMAC_crunch(i->ctx, out, len); 329 | } while (i->zs->avail_out == 0); 330 | } else { 331 | i->size += len; 332 | HMAC_crunch(i->ctx, (unsigned char *)p, len); 333 | } 334 | return size * nmemb; 335 | } 336 | 337 | static int tzoff; 338 | static int tzchecked; 339 | 340 | #define JAN02_1980 318340800 341 | 342 | static const char *monthtab[12] = {"Jan", "Feb", "Mar", 343 | "Apr", "May", "Jun", 344 | "Jul", "Aug", "Sep", 345 | "Oct", "Nov", "Dec"}; 346 | static const char *days[] = 347 | {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; 348 | 349 | /* Parse an HTTP datestamp into Unix time */ 350 | static time_t 351 | PILI_make_unix_time(char *s) { 352 | struct tm time; 353 | int i, ysub = 1900, fmt = 0; 354 | char *month; 355 | char *n; 356 | time_t res; 357 | 358 | if (s[3] != ' ') { 359 | fmt = 1; 360 | if (s[3] != ',') 361 | ysub = 0; 362 | } 363 | for (n = s; *n; ++n) 364 | if (*n == '-' || *n == ':') 365 | *n = ' '; 366 | 367 | time.tm_mon = 0; 368 | n = strchr(s, ' '); 369 | if (fmt) { 370 | /* Day, DD-MMM-YYYY HH:MM:SS GMT */ 371 | time.tm_mday = strtol(n + 1, &n, 0); 372 | month = n + 1; 373 | n = strchr(month, ' '); 374 | time.tm_year = strtol(n + 1, &n, 0); 375 | time.tm_hour = strtol(n + 1, &n, 0); 376 | time.tm_min = strtol(n + 1, &n, 0); 377 | time.tm_sec = strtol(n + 1, NULL, 0); 378 | } else { 379 | /* Unix ctime() format. Does not conform to HTTP spec. */ 380 | /* Day MMM DD HH:MM:SS YYYY */ 381 | month = n + 1; 382 | n = strchr(month, ' '); 383 | while (isspace(*n)) 384 | n++; 385 | time.tm_mday = strtol(n, &n, 0); 386 | time.tm_hour = strtol(n + 1, &n, 0); 387 | time.tm_min = strtol(n + 1, &n, 0); 388 | time.tm_sec = strtol(n + 1, &n, 0); 389 | time.tm_year = strtol(n + 1, NULL, 0); 390 | } 391 | if (time.tm_year > 100) 392 | time.tm_year -= ysub; 393 | 394 | for (i = 0; i < 12; i++) 395 | if (!strncasecmp(month, monthtab[i], 3)) { 396 | time.tm_mon = i; 397 | break; 398 | } 399 | time.tm_isdst = 0; /* daylight saving is never in effect in GMT */ 400 | 401 | /* this is normally the value of extern int timezone, but some 402 | * braindead C libraries don't provide it. 403 | */ 404 | if (!tzchecked) { 405 | struct tm *tc; 406 | time_t then = JAN02_1980; 407 | tc = localtime(&then); 408 | tzoff = (12 - tc->tm_hour) * 3600 + tc->tm_min * 60 + tc->tm_sec; 409 | tzchecked = 1; 410 | } 411 | res = mktime(&time); 412 | /* Unfortunately, mktime() assumes the input is in local time, 413 | * not GMT, so we have to correct it here. 414 | */ 415 | if (res != -1) 416 | res += tzoff; 417 | return res; 418 | } 419 | 420 | /* Convert a Unix time to a network time string 421 | * Weekday, DD-MMM-YYYY HH:MM:SS GMT 422 | */ 423 | void PILI_strtime(time_t *t, char *s) { 424 | struct tm *tm; 425 | 426 | tm = gmtime((time_t *)t); 427 | sprintf(s, "%s, %02d %s %d %02d:%02d:%02d GMT", 428 | days[tm->tm_wday], tm->tm_mday, monthtab[tm->tm_mon], 429 | tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec); 430 | } 431 | 432 | #define HEX2BIN(a) (((a)&0x40) ? ((a)&0xf) + 9 : ((a)&0xf)) 433 | 434 | int PILI_RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, 435 | int age) { 436 | FILE *f = NULL; 437 | char *path, date[64], cctim[64]; 438 | long pos = 0; 439 | time_t ctim = -1, cnow; 440 | int i, got = 0, ret = 0; 441 | unsigned int hlen; 442 | struct info in = {0}; 443 | struct HTTP_ctx http = {0}; 444 | HTTPResult httpres; 445 | z_stream zs = {0}; 446 | PILI_AVal home, hpre; 447 | 448 | date[0] = '\0'; 449 | #ifdef _WIN32 450 | #ifdef _XBOX 451 | hpre.av_val = "Q:"; 452 | hpre.av_len = 2; 453 | home.av_val = "\\UserData"; 454 | #else 455 | hpre.av_val = getenv("HOMEDRIVE"); 456 | hpre.av_len = strlen(hpre.av_val); 457 | home.av_val = getenv("HOMEPATH"); 458 | #endif 459 | #define DIRSEP "\\" 460 | 461 | #else /* !_WIN32 */ 462 | hpre.av_val = ""; 463 | hpre.av_len = 0; 464 | home.av_val = getenv("HOME"); 465 | #define DIRSEP "/" 466 | #endif 467 | if (!home.av_val) 468 | home.av_val = "."; 469 | home.av_len = strlen(home.av_val); 470 | 471 | /* SWF hash info is cached in a fixed-format file. 472 | * url: 473 | * ctim: HTTP datestamp of when we last checked it. 474 | * date: HTTP datestamp of the SWF's last modification. 475 | * size: SWF size in hex 476 | * hash: SWF hash in hex 477 | * 478 | * These fields must be present in this order. All fields 479 | * besides URL are fixed size. 480 | */ 481 | path = malloc(hpre.av_len + home.av_len + sizeof(DIRSEP ".swfinfo")); 482 | sprintf(path, "%s%s" DIRSEP ".swfinfo", hpre.av_val, home.av_val); 483 | 484 | f = fopen(path, "r+"); 485 | while (f) { 486 | char buf[4096], *file, *p; 487 | 488 | file = strchr(url, '/'); 489 | if (!file) 490 | break; 491 | file += 2; 492 | file = strchr(file, '/'); 493 | if (!file) 494 | break; 495 | file++; 496 | hlen = file - url; 497 | p = strrchr(file, '/'); 498 | if (p) 499 | file = p; 500 | else 501 | file--; 502 | 503 | while (fgets(buf, sizeof(buf), f)) { 504 | char *r1; 505 | 506 | got = 0; 507 | 508 | if (strncmp(buf, "url: ", 5)) 509 | continue; 510 | if (strncmp(buf + 5, url, hlen)) 511 | continue; 512 | r1 = strrchr(buf, '/'); 513 | i = strlen(r1); 514 | r1[--i] = '\0'; 515 | if (strncmp(r1, file, i)) 516 | continue; 517 | pos = ftell(f); 518 | while (got < 4 && fgets(buf, sizeof(buf), f)) { 519 | if (!strncmp(buf, "size: ", 6)) { 520 | *size = strtol(buf + 6, NULL, 16); 521 | got++; 522 | } else if (!strncmp(buf, "hash: ", 6)) { 523 | unsigned char *ptr = hash, *in = (unsigned char *)buf + 6; 524 | int l = strlen((char *)in) - 1; 525 | for (i = 0; i < l; i += 2) 526 | *ptr++ = (HEX2BIN(in[i]) << 4) | HEX2BIN(in[i + 1]); 527 | got++; 528 | } else if (!strncmp(buf, "date: ", 6)) { 529 | buf[strlen(buf) - 1] = '\0'; 530 | strncpy(date, buf + 6, sizeof(date)); 531 | got++; 532 | } else if (!strncmp(buf, "ctim: ", 6)) { 533 | buf[strlen(buf) - 1] = '\0'; 534 | ctim = PILI_make_unix_time(buf + 6); 535 | got++; 536 | } else if (!strncmp(buf, "url: ", 5)) 537 | break; 538 | } 539 | break; 540 | } 541 | break; 542 | } 543 | 544 | cnow = time(NULL); 545 | /* If we got a cache time, see if it's young enough to use directly */ 546 | if (age && ctim > 0) { 547 | ctim = cnow - ctim; 548 | ctim /= 3600 * 24; /* seconds to days */ 549 | if (ctim < age) /* ok, it's new enough */ 550 | goto out; 551 | } 552 | 553 | in.first = 1; 554 | HMAC_setup(in.ctx, "Genuine Adobe Flash Player 001", 30); 555 | inflateInit(&zs); 556 | in.zs = &zs; 557 | 558 | http.date = date; 559 | http.data = ∈ 560 | 561 | httpres = PILI_HTTP_get(&http, url, PILI_swfcrunch); 562 | 563 | inflateEnd(&zs); 564 | 565 | if (httpres != HTTPRES_OK && httpres != HTTPRES_OK_NOT_MODIFIED) { 566 | ret = -1; 567 | if (httpres == HTTPRES_LOST_CONNECTION) 568 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "%s: connection lost while downloading swfurl %s", 569 | __FUNCTION__, url); 570 | else if (httpres == HTTPRES_NOT_FOUND) 571 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "%s: swfurl %s not found", __FUNCTION__, url); 572 | else 573 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "%s: couldn't contact swfurl %s (HTTP error %d)", 574 | __FUNCTION__, url, http.status); 575 | } else { 576 | if (got && pos) 577 | fseek(f, pos, SEEK_SET); 578 | else { 579 | char *q; 580 | if (!f) 581 | f = fopen(path, "w"); 582 | if (!f) { 583 | int err = errno; 584 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, 585 | "%s: couldn't open %s for writing, errno %d (%s)", 586 | __FUNCTION__, path, err, strerror(err)); 587 | ret = -1; 588 | goto out; 589 | } 590 | fseek(f, 0, SEEK_END); 591 | q = strchr(url, '?'); 592 | if (q) 593 | i = q - url; 594 | else 595 | i = strlen(url); 596 | 597 | fprintf(f, "url: %.*s\n", i, url); 598 | } 599 | PILI_strtime(&cnow, cctim); 600 | fprintf(f, "ctim: %s\n", cctim); 601 | 602 | if (!in.first) { 603 | HMAC_finish(in.ctx, hash, hlen); 604 | *size = in.size; 605 | 606 | fprintf(f, "date: %s\n", date); 607 | fprintf(f, "size: %08x\n", in.size); 608 | fprintf(f, "hash: "); 609 | for (i = 0; i < SHA256_DIGEST_LENGTH; i++) 610 | fprintf(f, "%02x", hash[i]); 611 | fprintf(f, "\n"); 612 | } 613 | } 614 | HMAC_close(in.ctx); 615 | out: 616 | free(path); 617 | if (f) 618 | fclose(f); 619 | return ret; 620 | } 621 | #else 622 | int PILI_RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, 623 | int age) { 624 | return -1; 625 | } 626 | #endif 627 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/http.h: -------------------------------------------------------------------------------- 1 | #ifndef __RTMP_HTTP_H__ 2 | #define __RTMP_HTTP_H__ 3 | /* 4 | * Copyright (C) 2010 Howard Chu 5 | * Copyright (C) 2010 Antti Ajanki 6 | * 7 | * This file is part of librtmp. 8 | * 9 | * librtmp is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU Lesser General Public License as 11 | * published by the Free Software Foundation; either version 2.1, 12 | * or (at your option) any later version. 13 | * 14 | * librtmp is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public License 20 | * along with librtmp see the file COPYING. If not, write to 21 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 | * Boston, MA 02110-1301, USA. 23 | * http://www.gnu.org/copyleft/lgpl.html 24 | */ 25 | 26 | typedef enum { 27 | HTTPRES_OK, /* result OK */ 28 | HTTPRES_OK_NOT_MODIFIED, /* not modified since last request */ 29 | HTTPRES_NOT_FOUND, /* not found */ 30 | HTTPRES_BAD_REQUEST, /* client error */ 31 | HTTPRES_SERVER_ERROR, /* server reported an error */ 32 | HTTPRES_REDIRECTED, /* resource has been moved */ 33 | HTTPRES_LOST_CONNECTION /* connection lost while waiting for data */ 34 | } HTTPResult; 35 | 36 | struct HTTP_ctx { 37 | char *date; 38 | int size; 39 | int status; 40 | void *data; 41 | }; 42 | 43 | typedef size_t(PILI_HTTP_read_callback)(void *ptr, size_t size, size_t nmemb, 44 | void *stream); 45 | 46 | HTTPResult PILI_HTTP_get(struct HTTP_ctx *http, const char *url, 47 | PILI_HTTP_read_callback *cb); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2009 Andrej Stepanchuk 3 | * Copyright (C) 2009-2010 Howard Chu 4 | * 5 | * This file is part of librtmp. 6 | * 7 | * librtmp is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1, 10 | * or (at your option) any later version. 11 | * 12 | * librtmp is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with librtmp see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | * Boston, MA 02110-1301, USA. 21 | * http://www.gnu.org/copyleft/lgpl.html 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "log.h" 31 | #include "rtmp_sys.h" 32 | 33 | #define MAX_PRINT_LEN 2048 34 | 35 | PILI_RTMP_LogLevel PILI_RTMP_debuglevel = PILI_RTMP_LOGERROR; 36 | 37 | static int neednl; 38 | 39 | static FILE *fmsg; 40 | 41 | static PILI_RTMP_LogCallback PILI_rtmp_log_default, *cb = PILI_rtmp_log_default; 42 | 43 | static const char *levels[] = { 44 | "CRIT", "ERROR", "WARNING", "INFO", 45 | "DEBUG", "DEBUG2"}; 46 | 47 | static void PILI_rtmp_log_default(int level, const char *format, va_list vl) { 48 | char str[MAX_PRINT_LEN] = ""; 49 | 50 | vsnprintf(str, MAX_PRINT_LEN - 1, format, vl); 51 | 52 | /* Filter out 'no-name' */ 53 | if (PILI_RTMP_debuglevel < PILI_RTMP_LOGALL && strstr(str, "no-name") != NULL) 54 | return; 55 | 56 | if (!fmsg) fmsg = stderr; 57 | 58 | if (level <= PILI_RTMP_debuglevel) { 59 | if (neednl) { 60 | putc('\n', fmsg); 61 | neednl = 0; 62 | } 63 | fprintf(fmsg, "%s: %s\n", levels[level], str); 64 | #ifdef _DEBUG 65 | fflush(fmsg); 66 | #endif 67 | } 68 | } 69 | 70 | void PILI_RTMP_LogSetOutput(FILE *file) { 71 | fmsg = file; 72 | } 73 | 74 | void PILI_RTMP_LogSetLevel(PILI_RTMP_LogLevel level) { 75 | PILI_RTMP_debuglevel = level; 76 | } 77 | 78 | void PILI_RTMP_LogSetCallback(PILI_RTMP_LogCallback *cbp) { 79 | cb = cbp; 80 | } 81 | 82 | PILI_RTMP_LogLevel PILI_RTMP_LogGetLevel() { 83 | return PILI_RTMP_debuglevel; 84 | } 85 | 86 | void PILI_RTMP_Log(int level, const char *format, ...) { 87 | va_list args; 88 | va_start(args, format); 89 | cb(level, format, args); 90 | va_end(args); 91 | } 92 | 93 | static const char hexdig[] = "0123456789abcdef"; 94 | 95 | void PILI_RTMP_LogHex(int level, const uint8_t *data, unsigned long len) { 96 | unsigned long i; 97 | char line[50], *ptr; 98 | 99 | if (level > PILI_RTMP_debuglevel) 100 | return; 101 | 102 | ptr = line; 103 | 104 | for (i = 0; i < len; i++) { 105 | *ptr++ = hexdig[0x0f & (data[i] >> 4)]; 106 | *ptr++ = hexdig[0x0f & data[i]]; 107 | if ((i & 0x0f) == 0x0f) { 108 | *ptr = '\0'; 109 | ptr = line; 110 | PILI_RTMP_Log(level, "%s", line); 111 | } else { 112 | *ptr++ = ' '; 113 | } 114 | } 115 | if (i & 0x0f) { 116 | *ptr = '\0'; 117 | PILI_RTMP_Log(level, "%s", line); 118 | } 119 | } 120 | 121 | void PILI_RTMP_LogHexString(int level, const uint8_t *data, unsigned long len) { 122 | #define BP_OFFSET 9 123 | #define BP_GRAPH 60 124 | #define BP_LEN 80 125 | char line[BP_LEN]; 126 | unsigned long i; 127 | 128 | if (!data || level > PILI_RTMP_debuglevel) 129 | return; 130 | 131 | /* in case len is zero */ 132 | line[0] = '\0'; 133 | 134 | for (i = 0; i < len; i++) { 135 | int n = i % 16; 136 | unsigned off; 137 | 138 | if (!n) { 139 | if (i) PILI_RTMP_Log(level, "%s", line); 140 | memset(line, ' ', sizeof(line) - 2); 141 | line[sizeof(line) - 2] = '\0'; 142 | 143 | off = i % 0x0ffffU; 144 | 145 | line[2] = hexdig[0x0f & (off >> 12)]; 146 | line[3] = hexdig[0x0f & (off >> 8)]; 147 | line[4] = hexdig[0x0f & (off >> 4)]; 148 | line[5] = hexdig[0x0f & off]; 149 | line[6] = ':'; 150 | } 151 | 152 | off = BP_OFFSET + n * 3 + ((n >= 8) ? 1 : 0); 153 | line[off] = hexdig[0x0f & (data[i] >> 4)]; 154 | line[off + 1] = hexdig[0x0f & data[i]]; 155 | 156 | off = BP_GRAPH + n + ((n >= 8) ? 1 : 0); 157 | 158 | if (isprint(data[i])) { 159 | line[BP_GRAPH + n] = data[i]; 160 | } else { 161 | line[BP_GRAPH + n] = '.'; 162 | } 163 | } 164 | 165 | PILI_RTMP_Log(level, "%s", line); 166 | } 167 | 168 | /* These should only be used by apps, never by the library itself */ 169 | void PILI_RTMP_LogPrintf(const char *format, ...) { 170 | char str[MAX_PRINT_LEN] = ""; 171 | int len; 172 | va_list args; 173 | va_start(args, format); 174 | len = vsnprintf(str, MAX_PRINT_LEN - 1, format, args); 175 | va_end(args); 176 | 177 | if (PILI_RTMP_debuglevel == PILI_RTMP_LOGCRIT) 178 | return; 179 | 180 | if (!fmsg) fmsg = stderr; 181 | 182 | if (neednl) { 183 | putc('\n', fmsg); 184 | neednl = 0; 185 | } 186 | 187 | if (len > MAX_PRINT_LEN - 1) 188 | len = MAX_PRINT_LEN - 1; 189 | fprintf(fmsg, "%s", str); 190 | if (str[len - 1] == '\n') 191 | fflush(fmsg); 192 | } 193 | 194 | void PILI_RTMP_LogStatus(const char *format, ...) { 195 | char str[MAX_PRINT_LEN] = ""; 196 | va_list args; 197 | va_start(args, format); 198 | vsnprintf(str, MAX_PRINT_LEN - 1, format, args); 199 | va_end(args); 200 | 201 | if (PILI_RTMP_debuglevel == PILI_RTMP_LOGCRIT) 202 | return; 203 | 204 | if (!fmsg) fmsg = stderr; 205 | 206 | fprintf(fmsg, "%s", str); 207 | fflush(fmsg); 208 | neednl = 1; 209 | } 210 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008-2009 Andrej Stepanchuk 3 | * Copyright (C) 2009-2010 Howard Chu 4 | * 5 | * This file is part of librtmp. 6 | * 7 | * librtmp is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1, 10 | * or (at your option) any later version. 11 | * 12 | * librtmp is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with librtmp see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | * Boston, MA 02110-1301, USA. 21 | * http://www.gnu.org/copyleft/lgpl.html 22 | */ 23 | 24 | #ifndef __RTMP_LOG_H__ 25 | #define __RTMP_LOG_H__ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | /* Enable this to get full debugging output */ 35 | /* #define _DEBUG */ 36 | 37 | #ifdef _DEBUG 38 | #undef NODEBUG 39 | #endif 40 | 41 | typedef enum { 42 | PILI_RTMP_LOGCRIT = 0, 43 | PILI_RTMP_LOGERROR, 44 | PILI_RTMP_LOGWARNING, 45 | PILI_RTMP_LOGINFO, 46 | PILI_RTMP_LOGDEBUG, 47 | PILI_RTMP_LOGDEBUG2, 48 | PILI_RTMP_LOGALL 49 | } PILI_RTMP_LogLevel; 50 | 51 | extern PILI_RTMP_LogLevel PILI_RTMP_debuglevel; 52 | 53 | typedef void(PILI_RTMP_LogCallback)(int level, const char *fmt, va_list); 54 | void PILI_RTMP_LogSetCallback(PILI_RTMP_LogCallback *cb); 55 | void PILI_RTMP_LogSetOutput(FILE *file); 56 | void PILI_RTMP_LogPrintf(const char *format, ...); 57 | void PILI_RTMP_LogStatus(const char *format, ...); 58 | void PILI_RTMP_Log(int level, const char *format, ...); 59 | void PILI_RTMP_LogHex(int level, const uint8_t *data, unsigned long len); 60 | void PILI_RTMP_LogHexString(int level, const uint8_t *data, unsigned long len); 61 | void PILI_RTMP_LogSetLevel(PILI_RTMP_LogLevel lvl); 62 | PILI_RTMP_LogLevel PILI_RTMP_LogGetLevel(void); 63 | 64 | #ifdef __cplusplus 65 | } 66 | #endif 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/parseurl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 Andrej Stepanchuk 3 | * Copyright (C) 2009-2010 Howard Chu 4 | * 5 | * This file is part of librtmp. 6 | * 7 | * librtmp is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1, 10 | * or (at your option) any later version. 11 | * 12 | * librtmp is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with librtmp see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | * Boston, MA 02110-1301, USA. 21 | * http://www.gnu.org/copyleft/lgpl.html 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "log.h" 31 | #include "rtmp_sys.h" 32 | 33 | int PILI_RTMP_ParseURL2(const char *url, int *protocol, PILI_AVal *host, unsigned int *port, 34 | PILI_AVal *playpath, PILI_AVal *app, PILI_AVal *domainName) { 35 | char *p, *end, *col, *ques, *slash; 36 | 37 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Parsing..."); 38 | 39 | *protocol = RTMP_PROTOCOL_RTMP; 40 | *port = 0; 41 | playpath->av_len = 0; 42 | playpath->av_val = NULL; 43 | app->av_len = 0; 44 | app->av_val = NULL; 45 | 46 | /* Old School Parsing */ 47 | 48 | /* look for usual :// pattern */ 49 | p = strstr(url, "://"); 50 | if (!p) { 51 | PILI_RTMP_Log(PILI_RTMP_LOGERROR, "RTMP URL: No :// in url!"); 52 | return FALSE; 53 | } 54 | { 55 | int len = (int)(p - url); 56 | 57 | if (len == 4 && strncasecmp(url, "rtmp", 4) == 0) 58 | *protocol = RTMP_PROTOCOL_RTMP; 59 | else if (len == 5 && strncasecmp(url, "rtmpt", 5) == 0) 60 | *protocol = RTMP_PROTOCOL_RTMPT; 61 | else if (len == 5 && strncasecmp(url, "rtmps", 5) == 0) 62 | *protocol = RTMP_PROTOCOL_RTMPS; 63 | else if (len == 5 && strncasecmp(url, "rtmpe", 5) == 0) 64 | *protocol = RTMP_PROTOCOL_RTMPE; 65 | else if (len == 5 && strncasecmp(url, "rtmfp", 5) == 0) 66 | *protocol = RTMP_PROTOCOL_RTMFP; 67 | else if (len == 6 && strncasecmp(url, "rtmpte", 6) == 0) 68 | *protocol = RTMP_PROTOCOL_RTMPTE; 69 | else if (len == 6 && strncasecmp(url, "rtmpts", 6) == 0) 70 | *protocol = RTMP_PROTOCOL_RTMPTS; 71 | else { 72 | PILI_RTMP_Log(PILI_RTMP_LOGWARNING, "Unknown protocol!\n"); 73 | goto parsehost; 74 | } 75 | } 76 | 77 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Parsed protocol: %d", *protocol); 78 | 79 | parsehost: 80 | /* let's get the hostname */ 81 | p += 3; 82 | 83 | /* check for sudden death */ 84 | if (*p == 0) { 85 | PILI_RTMP_Log(PILI_RTMP_LOGWARNING, "No hostname in URL!"); 86 | return FALSE; 87 | } 88 | 89 | end = p + strlen(p); 90 | col = strchr(p, ':'); 91 | ques = strchr(p, '?'); 92 | slash = strchr(p, '/'); 93 | 94 | { 95 | int hostlen; 96 | if (slash) 97 | hostlen = slash - p; 98 | else 99 | hostlen = end - p; 100 | if (col && col - p < hostlen) 101 | hostlen = col - p; 102 | 103 | if (hostlen < 256) { 104 | host->av_val = p; 105 | host->av_len = hostlen; 106 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Parsed host : %.*s", hostlen, host->av_val); 107 | } else { 108 | PILI_RTMP_Log(PILI_RTMP_LOGWARNING, "Hostname exceeds 255 characters!"); 109 | } 110 | 111 | p += hostlen; 112 | } 113 | 114 | /* get the port number if available */ 115 | if (*p == ':') { 116 | unsigned int p2; 117 | p++; 118 | p2 = atoi(p); 119 | if (p2 > 65535) { 120 | PILI_RTMP_Log(PILI_RTMP_LOGWARNING, "Invalid port number!"); 121 | } else { 122 | *port = p2; 123 | } 124 | } 125 | 126 | if (!slash) { 127 | PILI_RTMP_Log(PILI_RTMP_LOGWARNING, "No application or playpath in URL!"); 128 | return TRUE; 129 | } 130 | p = slash + 1; 131 | 132 | /** parse domain 133 | + * rtmp://host:[port]/app/...?domain=a.com 134 | + * use domain to replace host 135 | + */ 136 | 137 | if (domainName != NULL && ques != NULL) { 138 | char *domain = strstr(ques, "domain="); 139 | if (domain) { 140 | end = domain - 1; 141 | domain += 7; //skip "domain=" 142 | char *domain_end = strchr(domain, '&'); 143 | int host_len = 0; 144 | if (domain_end) { 145 | host_len = domain_end - domain; 146 | } else { 147 | host_len = strlen(domain); 148 | } 149 | if (host_len < 256) { 150 | domainName->av_val = domain; 151 | domainName->av_len = host_len; 152 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Parsed host and domain : %.*s", host_len, host->av_val); 153 | } 154 | } 155 | } 156 | 157 | { 158 | /* parse application 159 | * 160 | * rtmp://host[:port]/app[/appinstance][/...] 161 | * application = app[/appinstance] 162 | */ 163 | 164 | char *slash2, *slash3 = NULL; 165 | int applen, appnamelen; 166 | 167 | slash2 = strchr(p, '/'); 168 | if (slash2) 169 | slash3 = strchr(slash2 + 1, '/'); 170 | 171 | applen = end - p; /* ondemand, pass all parameters as app */ 172 | appnamelen = applen; /* ondemand length */ 173 | 174 | if (ques && strstr(p, "slist=")) { /* whatever it is, the '?' and slist= means we need to use everything as app and parse plapath from slist= */ 175 | appnamelen = ques - p; 176 | } else if (strncmp(p, "ondemand/", 9) == 0) { 177 | /* app = ondemand/foobar, only pass app=ondemand */ 178 | applen = 8; 179 | appnamelen = 8; 180 | } else { /* app!=ondemand, so app is app[/appinstance] */ 181 | if (slash3) 182 | appnamelen = slash3 - p; 183 | else if (slash2) 184 | appnamelen = slash2 - p; 185 | 186 | applen = appnamelen; 187 | } 188 | 189 | app->av_val = p; 190 | app->av_len = applen; 191 | PILI_RTMP_Log(PILI_RTMP_LOGDEBUG, "Parsed app : %.*s", applen, p); 192 | 193 | p += appnamelen; 194 | } 195 | 196 | if (*p == '/') 197 | p++; 198 | 199 | if (end - p) { 200 | PILI_AVal av = {p, end - p}; 201 | PILI_RTMP_ParsePlaypath(&av, playpath); 202 | } 203 | 204 | return TRUE; 205 | } 206 | 207 | /* 208 | * Extracts playpath from RTMP URL. playpath is the file part of the 209 | * URL, i.e. the part that comes after rtmp://host:port/app/ 210 | * 211 | * Returns the stream name in a format understood by FMS. The name is 212 | * the playpath part of the URL with formatting depending on the stream 213 | * type: 214 | * 215 | * mp4 streams: prepend "mp4:", remove extension 216 | * mp3 streams: prepend "mp3:", remove extension 217 | * flv streams: remove extension 218 | */ 219 | void PILI_RTMP_ParsePlaypath(PILI_AVal *in, PILI_AVal *out) { 220 | int addMP4 = 0; 221 | int addMP3 = 0; 222 | int subExt = 0; 223 | const char *playpath = in->av_val; 224 | const char *temp, *q, *ext = NULL; 225 | const char *ppstart = playpath; 226 | char *streamname, *destptr, *p; 227 | 228 | int pplen = in->av_len; 229 | 230 | out->av_val = NULL; 231 | out->av_len = 0; 232 | 233 | if ((*ppstart == '?') && 234 | (temp = strstr(ppstart, "slist=")) != 0) { 235 | ppstart = temp + 6; 236 | pplen = strlen(ppstart); 237 | 238 | temp = strchr(ppstart, '&'); 239 | if (temp) { 240 | pplen = temp - ppstart; 241 | } 242 | } 243 | 244 | q = strchr(ppstart, '?'); 245 | if (pplen >= 4) { 246 | if (q) 247 | ext = q - 4; 248 | else 249 | ext = &ppstart[pplen - 4]; 250 | if ((strncmp(ext, ".f4v", 4) == 0) || 251 | (strncmp(ext, ".mp4", 4) == 0)) { 252 | addMP4 = 1; 253 | subExt = 1; 254 | /* Only remove .flv from rtmp URL, not slist params */ 255 | } else if ((ppstart == playpath) && 256 | (strncmp(ext, ".flv", 4) == 0)) { 257 | subExt = 1; 258 | } else if (strncmp(ext, ".mp3", 4) == 0) { 259 | addMP3 = 1; 260 | subExt = 1; 261 | } 262 | } 263 | 264 | streamname = (char *)malloc((pplen + 4 + 1) * sizeof(char)); 265 | if (!streamname) 266 | return; 267 | 268 | destptr = streamname; 269 | if (addMP4) { 270 | if (strncmp(ppstart, "mp4:", 4)) { 271 | strcpy(destptr, "mp4:"); 272 | destptr += 4; 273 | } else { 274 | subExt = 0; 275 | } 276 | } else if (addMP3) { 277 | if (strncmp(ppstart, "mp3:", 4)) { 278 | strcpy(destptr, "mp3:"); 279 | destptr += 4; 280 | } else { 281 | subExt = 0; 282 | } 283 | } 284 | 285 | for (p = (char *)ppstart; pplen > 0;) { 286 | /* skip extension */ 287 | if (subExt && p == ext) { 288 | p += 4; 289 | pplen -= 4; 290 | continue; 291 | } 292 | if (*p == '%') { 293 | unsigned int c; 294 | sscanf(p + 1, "%02x", &c); 295 | *destptr++ = c; 296 | pplen -= 3; 297 | p += 3; 298 | } else { 299 | *destptr++ = *p++; 300 | pplen--; 301 | } 302 | } 303 | *destptr = '\0'; 304 | 305 | out->av_val = streamname; 306 | out->av_len = destptr - streamname; 307 | } 308 | 309 | int PILI_RTMP_ParseURL(const char *url, int *protocol, PILI_AVal *host, 310 | unsigned int *port, PILI_AVal *playpath, PILI_AVal *app) { 311 | return PILI_RTMP_ParseURL2(url, protocol, host, port, playpath, app, NULL); 312 | } 313 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/rtmp.h: -------------------------------------------------------------------------------- 1 | #ifndef __RTMP_H__ 2 | #define __RTMP_H__ 3 | /* 4 | * Copyright (C) 2005-2008 Team XBMC 5 | * http://www.xbmc.org 6 | * Copyright (C) 2008-2009 Andrej Stepanchuk 7 | * Copyright (C) 2009-2010 Howard Chu 8 | * 9 | * This file is part of librtmp. 10 | * 11 | * librtmp is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU Lesser General Public License as 13 | * published by the Free Software Foundation; either version 2.1, 14 | * or (at your option) any later version. 15 | * 16 | * librtmp is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Lesser General Public License 22 | * along with librtmp see the file COPYING. If not, write to 23 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 24 | * Boston, MA 02110-1301, USA. 25 | * http://www.gnu.org/copyleft/lgpl.html 26 | */ 27 | 28 | #define NO_CRYPTO 29 | 30 | #if !defined(NO_CRYPTO) && !defined(CRYPTO) 31 | #define CRYPTO 32 | #endif 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #include "amf.h" 39 | #include "error.h" 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | #define RTMP_LIB_VERSION 0x020300 /* 2.3 */ 46 | 47 | #define RTMP_FEATURE_HTTP 0x01 48 | #define RTMP_FEATURE_ENC 0x02 49 | #define RTMP_FEATURE_SSL 0x04 50 | #define RTMP_FEATURE_MFP 0x08 /* not yet supported */ 51 | #define RTMP_FEATURE_WRITE 0x10 /* publish, not play */ 52 | #define RTMP_FEATURE_HTTP2 0x20 /* server-side rtmpt */ 53 | //#define RTMP_FEATURE_NONBLOCK 0x40 /* non block socket */ 54 | 55 | #define RTMP_PROTOCOL_UNDEFINED -1 56 | #define RTMP_PROTOCOL_RTMP 0 57 | #define RTMP_PROTOCOL_RTMPE RTMP_FEATURE_ENC 58 | #define RTMP_PROTOCOL_RTMPT RTMP_FEATURE_HTTP 59 | #define RTMP_PROTOCOL_RTMPS RTMP_FEATURE_SSL 60 | #define RTMP_PROTOCOL_RTMPTE (RTMP_FEATURE_HTTP | RTMP_FEATURE_ENC) 61 | #define RTMP_PROTOCOL_RTMPTS (RTMP_FEATURE_HTTP | RTMP_FEATURE_SSL) 62 | #define RTMP_PROTOCOL_RTMFP RTMP_FEATURE_MFP 63 | 64 | #define RTMP_DEFAULT_CHUNKSIZE 128 65 | 66 | /* needs to fit largest number of bytes recv() may return */ 67 | #define RTMP_BUFFER_CACHE_SIZE (16 * 1024) 68 | 69 | #define RTMP_CHANNELS 65600 70 | 71 | extern const char PILI_RTMPProtocolStringsLower[][7]; 72 | extern const PILI_AVal PILI_RTMP_DefaultFlashVer; 73 | extern int PILI_RTMP_ctrlC; 74 | 75 | uint32_t PILI_RTMP_GetTime(void); 76 | 77 | #define RTMP_PACKET_TYPE_AUDIO 0x08 78 | #define RTMP_PACKET_TYPE_VIDEO 0x09 79 | #define RTMP_PACKET_TYPE_INFO 0x12 80 | 81 | #define RTMP_MAX_HEADER_SIZE 18 82 | 83 | #define RTMP_PACKET_SIZE_LARGE 0 84 | #define RTMP_PACKET_SIZE_MEDIUM 1 85 | #define RTMP_PACKET_SIZE_SMALL 2 86 | #define RTMP_PACKET_SIZE_MINIMUM 3 87 | 88 | typedef struct PILI_RTMPChunk { 89 | int c_headerSize; 90 | int c_chunkSize; 91 | char *c_chunk; 92 | char c_header[RTMP_MAX_HEADER_SIZE]; 93 | } PILI_RTMPChunk; 94 | 95 | typedef struct PILI_RTMPPacket { 96 | uint8_t m_headerType; 97 | uint8_t m_packetType; 98 | uint8_t m_hasAbsTimestamp; /* timestamp absolute or relative? */ 99 | int m_nChannel; 100 | uint32_t m_nTimeStamp; /* timestamp */ 101 | int32_t m_nInfoField2; /* last 4 bytes in a long header */ 102 | uint32_t m_nBodySize; 103 | uint32_t m_nBytesRead; 104 | PILI_RTMPChunk *m_chunk; 105 | char *m_body; 106 | int m_useExtTimestamp; 107 | } PILI_RTMPPacket; 108 | 109 | typedef struct PILI_RTMPSockBuf { 110 | int sb_socket; 111 | int sb_size; /* number of unprocessed bytes in buffer */ 112 | char *sb_start; /* pointer into sb_pBuffer of next byte to process */ 113 | char sb_buf[RTMP_BUFFER_CACHE_SIZE]; /* data read from socket */ 114 | int sb_timedout; 115 | void *sb_ssl; 116 | } PILI_RTMPSockBuf; 117 | 118 | void PILI_RTMPPacket_Reset(PILI_RTMPPacket *p); 119 | void PILI_RTMPPacket_Dump(PILI_RTMPPacket *p); 120 | int PILI_RTMPPacket_Alloc(PILI_RTMPPacket *p, int nSize); 121 | void PILI_RTMPPacket_Free(PILI_RTMPPacket *p); 122 | 123 | #define RTMPPacket_IsReady(a) ((a)->m_nBytesRead == (a)->m_nBodySize) 124 | 125 | typedef struct PILI_RTMP_LNK { 126 | PILI_AVal hostname; 127 | PILI_AVal domain; 128 | PILI_AVal sockshost; 129 | 130 | PILI_AVal playpath0; /* parsed from URL */ 131 | PILI_AVal playpath; /* passed in explicitly */ 132 | PILI_AVal tcUrl; 133 | PILI_AVal swfUrl; 134 | PILI_AVal pageUrl; 135 | PILI_AVal app; 136 | PILI_AVal auth; 137 | PILI_AVal flashVer; 138 | PILI_AVal subscribepath; 139 | PILI_AVal token; 140 | PILI_AMFObject extras; 141 | int edepth; 142 | 143 | int seekTime; 144 | int stopTime; 145 | 146 | #define RTMP_LF_AUTH 0x0001 /* using auth param */ 147 | #define RTMP_LF_LIVE 0x0002 /* stream is live */ 148 | #define RTMP_LF_SWFV 0x0004 /* do SWF verification */ 149 | #define RTMP_LF_PLST 0x0008 /* send playlist before play */ 150 | #define RTMP_LF_BUFX 0x0010 /* toggle stream on BufferEmpty msg */ 151 | #define RTMP_LF_FTCU 0x0020 /* free tcUrl on close */ 152 | int lFlags; 153 | 154 | int swfAge; 155 | 156 | int protocol; 157 | int timeout; /* connection timeout in seconds */ 158 | int send_timeout; /* send data timeout */ 159 | 160 | unsigned short socksport; 161 | unsigned short port; 162 | 163 | #ifdef CRYPTO 164 | #define RTMP_SWF_HASHLEN 32 165 | void *dh; /* for encryption */ 166 | void *rc4keyIn; 167 | void *rc4keyOut; 168 | 169 | uint32_t SWFSize; 170 | uint8_t SWFHash[RTMP_SWF_HASHLEN]; 171 | char SWFVerificationResponse[RTMP_SWF_HASHLEN + 10]; 172 | #endif 173 | } PILI_RTMP_LNK; 174 | 175 | /* state for read() wrapper */ 176 | typedef struct PILI_RTMP_READ { 177 | char *buf; 178 | char *bufpos; 179 | unsigned int buflen; 180 | uint32_t timestamp; 181 | uint8_t dataType; 182 | uint8_t flags; 183 | #define RTMP_READ_HEADER 0x01 184 | #define RTMP_READ_RESUME 0x02 185 | #define RTMP_READ_NO_IGNORE 0x04 186 | #define RTMP_READ_GOTKF 0x08 187 | #define RTMP_READ_GOTFLVK 0x10 188 | #define RTMP_READ_SEEKING 0x20 189 | int8_t status; 190 | #define RTMP_READ_COMPLETE -3 191 | #define RTMP_READ_ERROR -2 192 | #define RTMP_READ_EOF -1 193 | #define RTMP_READ_IGNORE 0 194 | 195 | /* if bResume == TRUE */ 196 | uint8_t initialFrameType; 197 | uint32_t nResumeTS; 198 | char *metaHeader; 199 | char *initialFrame; 200 | uint32_t nMetaHeaderSize; 201 | uint32_t nInitialFrameSize; 202 | uint32_t nIgnoredFrameCounter; 203 | uint32_t nIgnoredFlvFrameCounter; 204 | } PILI_RTMP_READ; 205 | 206 | typedef struct PILI_RTMP_METHOD { 207 | PILI_AVal name; 208 | int num; 209 | } PILI_RTMP_METHOD; 210 | 211 | typedef void (*PILI_RTMPErrorCallback)(RTMPError *error, void *userData); 212 | 213 | typedef struct PILI_CONNECTION_TIME { 214 | uint32_t connect_time; 215 | uint32_t handshake_time; 216 | } PILI_CONNECTION_TIME; 217 | 218 | typedef void (*PILI_RTMP_ConnectionTimeCallback)( 219 | PILI_CONNECTION_TIME *conn_time, void *userData); 220 | 221 | typedef struct PILI_RTMP { 222 | int m_inChunkSize; 223 | int m_outChunkSize; 224 | int m_nBWCheckCounter; 225 | int m_nBytesIn; 226 | int m_nBytesInSent; 227 | int m_nBufferMS; 228 | int m_stream_id; /* returned in _result from createStream */ 229 | int m_mediaChannel; 230 | uint32_t m_mediaStamp; 231 | uint32_t m_pauseStamp; 232 | int m_pausing; 233 | int m_nServerBW; 234 | int m_nClientBW; 235 | uint8_t m_nClientBW2; 236 | uint8_t m_bPlaying; 237 | uint8_t m_bSendEncoding; 238 | uint8_t m_bSendCounter; 239 | 240 | int m_numInvokes; 241 | int m_numCalls; 242 | PILI_RTMP_METHOD *m_methodCalls; /* remote method calls queue */ 243 | 244 | PILI_RTMPPacket *m_vecChannelsIn[RTMP_CHANNELS]; 245 | PILI_RTMPPacket *m_vecChannelsOut[RTMP_CHANNELS]; 246 | int m_channelTimestamp[RTMP_CHANNELS]; /* abs timestamp of last packet */ 247 | 248 | double m_fAudioCodecs; /* audioCodecs for the connect packet */ 249 | double m_fVideoCodecs; /* videoCodecs for the connect packet */ 250 | double m_fEncoding; /* AMF0 or AMF3 */ 251 | 252 | double m_fDuration; /* duration of stream in seconds */ 253 | 254 | int m_msgCounter; /* RTMPT stuff */ 255 | int m_polling; 256 | int m_resplen; 257 | int m_unackd; 258 | PILI_AVal m_clientID; 259 | 260 | PILI_RTMP_READ m_read; 261 | PILI_RTMPPacket m_write; 262 | PILI_RTMPSockBuf m_sb; 263 | PILI_RTMP_LNK Link; 264 | 265 | PILI_RTMPErrorCallback m_errorCallback; 266 | PILI_RTMP_ConnectionTimeCallback m_connCallback; 267 | RTMPError *m_error; 268 | void *m_userData; 269 | int m_is_closing; 270 | int m_tcp_nodelay; 271 | uint32_t ip; 272 | } PILI_RTMP; 273 | 274 | int PILI_RTMP_ParseURL(const char *url, int *protocol, PILI_AVal *host, 275 | unsigned int *port, PILI_AVal *playpath, PILI_AVal *app); 276 | 277 | int PILI_RTMP_ParseURL2(const char *url, int *protocol, PILI_AVal *host, 278 | unsigned int *port, PILI_AVal *playpath, PILI_AVal *app, PILI_AVal *domain); 279 | 280 | void PILI_RTMP_ParsePlaypath(PILI_AVal *in, PILI_AVal *out); 281 | void PILI_RTMP_SetBufferMS(PILI_RTMP *r, int size); 282 | void PILI_RTMP_UpdateBufferMS(PILI_RTMP *r, RTMPError *error); 283 | 284 | int PILI_RTMP_SetOpt(PILI_RTMP *r, const PILI_AVal *opt, PILI_AVal *arg, 285 | RTMPError *error); 286 | int PILI_RTMP_SetupURL(PILI_RTMP *r, const char *url, RTMPError *error); 287 | void PILI_RTMP_SetupStream(PILI_RTMP *r, int protocol, PILI_AVal *hostname, 288 | unsigned int port, PILI_AVal *sockshost, PILI_AVal *playpath, 289 | PILI_AVal *tcUrl, PILI_AVal *swfUrl, PILI_AVal *pageUrl, PILI_AVal *app, 290 | PILI_AVal *auth, PILI_AVal *swfSHA256Hash, uint32_t swfSize, 291 | PILI_AVal *flashVer, PILI_AVal *subscribepath, int dStart, 292 | int dStop, int bLiveStream, long int timeout); 293 | 294 | int PILI_RTMP_Connect(PILI_RTMP *r, PILI_RTMPPacket *cp, RTMPError *error); 295 | struct sockaddr; 296 | int PILI_RTMP_Connect0(PILI_RTMP *r, struct addrinfo *ai, unsigned short port, 297 | RTMPError *error); 298 | int PILI_RTMP_Connect1(PILI_RTMP *r, PILI_RTMPPacket *cp, RTMPError *error); 299 | int PILI_RTMP_Serve(PILI_RTMP *r, RTMPError *error); 300 | 301 | int PILI_RTMP_ReadPacket(PILI_RTMP *r, PILI_RTMPPacket *packet); 302 | int PILI_RTMP_SendPacket(PILI_RTMP *r, PILI_RTMPPacket *packet, int queue, 303 | RTMPError *error); 304 | int PILI_RTMP_SendChunk(PILI_RTMP *r, PILI_RTMPChunk *chunk, RTMPError *error); 305 | int PILI_RTMP_IsConnected(PILI_RTMP *r); 306 | int PILI_RTMP_Socket(PILI_RTMP *r); 307 | int PILI_RTMP_IsTimedout(PILI_RTMP *r); 308 | double PILI_RTMP_GetDuration(PILI_RTMP *r); 309 | int PILI_RTMP_ToggleStream(PILI_RTMP *r, RTMPError *error); 310 | 311 | int PILI_RTMP_ConnectStream(PILI_RTMP *r, int seekTime, RTMPError *error); 312 | int PILI_RTMP_ReconnectStream(PILI_RTMP *r, int seekTime, RTMPError *error); 313 | void PILI_RTMP_DeleteStream(PILI_RTMP *r, RTMPError *error); 314 | int PILI_RTMP_GetNextMediaPacket(PILI_RTMP *r, PILI_RTMPPacket *packet); 315 | int PILI_RTMP_ClientPacket(PILI_RTMP *r, PILI_RTMPPacket *packet); 316 | 317 | void PILI_RTMP_Init(PILI_RTMP *r); 318 | void PILI_RTMP_Close(PILI_RTMP *r, RTMPError *error); 319 | PILI_RTMP *PILI_RTMP_Alloc(void); 320 | void PILI_RTMP_Free(PILI_RTMP *r); 321 | void PILI_RTMP_EnableWrite(PILI_RTMP *r); 322 | 323 | int PILI_RTMP_LibVersion(void); 324 | void PILI_RTMP_UserInterrupt(void); /* user typed Ctrl-C */ 325 | 326 | int PILI_RTMP_SendCtrl(PILI_RTMP *r, short nType, unsigned int nObject, 327 | unsigned int nTime, RTMPError *error); 328 | 329 | /* caller probably doesn't know current timestamp, should 330 | * just use RTMP_Pause instead 331 | */ 332 | int PILI_RTMP_SendPause(PILI_RTMP *r, int DoPause, int dTime, RTMPError *error); 333 | int PILI_RTMP_Pause(PILI_RTMP *r, int DoPause, RTMPError *error); 334 | 335 | int PILI_RTMP_FindFirstMatchingProperty(PILI_AMFObject *obj, const PILI_AVal *name, 336 | PILI_AMFObjectProperty *p); 337 | 338 | int PILI_RTMPSockBuf_Fill(PILI_RTMPSockBuf *sb, int timeout); 339 | int PILI_RTMPSockBuf_Send(PILI_RTMPSockBuf *sb, const char *buf, int len); 340 | int PILI_RTMPSockBuf_Close(PILI_RTMPSockBuf *sb); 341 | 342 | int PILI_RTMP_SendCreateStream(PILI_RTMP *r, RTMPError *error); 343 | int PILI_RTMP_SendSeek(PILI_RTMP *r, int dTime, RTMPError *error); 344 | int PILI_RTMP_SendServerBW(PILI_RTMP *r, RTMPError *error); 345 | int PILI_RTMP_SendClientBW(PILI_RTMP *r, RTMPError *error); 346 | void PILI_RTMP_DropRequest(PILI_RTMP *r, int i, int freeit); 347 | int PILI_RTMP_Read(PILI_RTMP *r, char *buf, int size); 348 | int PILI_RTMP_Write(PILI_RTMP *r, const char *buf, int size, RTMPError *error); 349 | 350 | #define MAJOR 1 351 | #define MINOR 0 352 | #define PATCH 4 353 | 354 | int PILI_RTMP_Version(); 355 | 356 | const char * PILI_RTMP_GetReqId(); 357 | 358 | const char * PILI_RTMP_GetRemoteIp(); 359 | 360 | 361 | /* hashswf.c */ 362 | int PILI_RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, 363 | int age); 364 | 365 | #ifdef __cplusplus 366 | }; 367 | #endif 368 | 369 | #endif 370 | -------------------------------------------------------------------------------- /Pod/Classes/pili-librtmp/rtmp_sys.h: -------------------------------------------------------------------------------- 1 | #ifndef __RTMP_SYS_H__ 2 | #define __RTMP_SYS_H__ 3 | /* 4 | * Copyright (C) 2010 Howard Chu 5 | * 6 | * This file is part of librtmp. 7 | * 8 | * librtmp is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU Lesser General Public License as 10 | * published by the Free Software Foundation; either version 2.1, 11 | * or (at your option) any later version. 12 | * 13 | * librtmp is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with librtmp see the file COPYING. If not, write to 20 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 | * Boston, MA 02110-1301, USA. 22 | * http://www.gnu.org/copyleft/lgpl.html 23 | */ 24 | 25 | #ifdef _WIN32 26 | 27 | #ifdef _XBOX 28 | #include 29 | #include 30 | #define snprintf _snprintf 31 | #define strcasecmp stricmp 32 | #define strncasecmp strnicmp 33 | #define vsnprintf _vsnprintf 34 | 35 | #else /* !_XBOX */ 36 | #include 37 | #include 38 | #endif 39 | 40 | #define GetSockError() WSAGetLastError() 41 | #define SetSockError(e) WSASetLastError(e) 42 | #define setsockopt(a, b, c, d, e) (setsockopt)(a, b, c, (const char *)d, (int)e) 43 | #define EWOULDBLOCK \ 44 | WSAETIMEDOUT /* we don't use nonblocking, but we do use timeouts */ 45 | #define sleep(n) Sleep(n * 1000) 46 | #define msleep(n) Sleep(n) 47 | #define SET_RCVTIMEO(tv, s) int tv = s * 1000 48 | #else /* !_WIN32 */ 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #define GetSockError() errno 58 | #define SetSockError(e) errno = e 59 | #undef closesocket 60 | #define closesocket(s) close(s) 61 | #define msleep(n) usleep(n * 1000) 62 | #define SET_RCVTIMEO(tv, s) struct timeval tv = {s, 0} 63 | #endif 64 | 65 | #include "rtmp.h" 66 | 67 | #ifdef USE_POLARSSL 68 | #include 69 | #include 70 | #include 71 | typedef struct tls_ctx { 72 | havege_state hs; 73 | ssl_session ssn; 74 | } tls_ctx; 75 | #define TLS_CTX tls_ctx * 76 | #define TLS_client(ctx, s) \ 77 | s = malloc(sizeof(ssl_context)); \ 78 | ssl_init(s); \ 79 | ssl_set_endpoint(s, SSL_IS_CLIENT); \ 80 | ssl_set_authmode(s, SSL_VERIFY_NONE); \ 81 | ssl_set_rng(s, havege_rand, &ctx->hs); \ 82 | ssl_set_ciphers(s, ssl_default_ciphers); \ 83 | ssl_set_session(s, 1, 600, &ctx->ssn) 84 | #define TLS_setfd(s, fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd) 85 | #define TLS_connect(s) ssl_handshake(s) 86 | #define TLS_read(s, b, l) ssl_read(s, (unsigned char *)b, l) 87 | #define TLS_write(s, b, l) ssl_write(s, (unsigned char *)b, l) 88 | #define TLS_shutdown(s) ssl_close_notify(s) 89 | #define TLS_close(s) \ 90 | ssl_free(s); \ 91 | free(s) 92 | 93 | #elif defined(USE_GNUTLS) 94 | #include 95 | typedef struct tls_ctx { 96 | gnutls_certificate_credentials_t cred; 97 | gnutls_priority_t prios; 98 | } tls_ctx; 99 | #define TLS_CTX tls_ctx * 100 | #define TLS_client(ctx, s) \ 101 | gnutls_init((gnutls_session_t *)(&s), GNUTLS_CLIENT); \ 102 | gnutls_priority_set(s, ctx->prios); \ 103 | gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx->cred) 104 | #define TLS_setfd(s, fd) \ 105 | gnutls_transport_set_ptr(s, (gnutls_transport_ptr_t)(long)fd) 106 | #define TLS_connect(s) gnutls_handshake(s) 107 | #define TLS_read(s, b, l) gnutls_record_recv(s, b, l) 108 | #define TLS_write(s, b, l) gnutls_record_send(s, b, l) 109 | #define TLS_shutdown(s) gnutls_bye(s, GNUTLS_SHUT_RDWR) 110 | #define TLS_close(s) gnutls_deinit(s) 111 | 112 | #else /* USE_OPENSSL */ 113 | #define TLS_CTX SSL_CTX * 114 | #define TLS_client(ctx, s) s = SSL_new(ctx) 115 | #define TLS_setfd(s, fd) SSL_set_fd(s, fd) 116 | #define TLS_connect(s) SSL_connect(s) 117 | #define TLS_read(s, b, l) SSL_read(s, b, l) 118 | #define TLS_write(s, b, l) SSL_write(s, b, l) 119 | #define TLS_shutdown(s) SSL_shutdown(s) 120 | #define TLS_close(s) SSL_free(s) 121 | 122 | #endif 123 | #endif 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # librtmp 2 | -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Change this if your clang-format executable is somewhere else 3 | CLANG_FORMAT="$HOME/Library/Application Support/Alcatraz/Plug-ins/ClangFormat/bin/clang-format" 4 | 5 | find . \( -name '*.h' -or -name '*.c' -or -name '*.mm' \) -print0 | xargs -0 "$CLANG_FORMAT" -i 6 | -------------------------------------------------------------------------------- /librtmp.3: -------------------------------------------------------------------------------- 1 | .TH LIBRTMP 3 "2010-05-29" "RTMPDump v2.2e" 2 | .\" Copyright 2010 Howard Chu. 3 | .\" Copying permitted according to the GNU General Public License V2. 4 | .SH NAME 5 | librtmp \- RTMPDump Real-Time Messaging Protocol API 6 | .SH LIBRARY 7 | RTMPDump RTMP (librtmp, -lrtmp) 8 | .SH SYNOPSIS 9 | .B #include 10 | .SH DESCRIPTION 11 | The Real-Time Messaging Protocol (RTMP) is used for streaming 12 | multimedia content across a TCP/IP network. This API provides most client 13 | functions and a few server functions needed to support RTMP, RTMP tunneled 14 | in HTTP (RTMPT), encrypted RTMP (RTMPE), RTMP over SSL/TLS (RTMPS) and 15 | tunneled variants of these encrypted types (RTMPTE, RTMPTS). The basic 16 | RTMP specification has been published by Adobe but this API was 17 | reverse-engineered without use of the Adobe specification. As such, it may 18 | deviate from any published specifications but it usually duplicates the 19 | actual behavior of the original Adobe clients. 20 | 21 | The RTMPDump software package includes a basic client utility program 22 | in 23 | .BR rtmpdump (1), 24 | some sample servers, and a library used to provide programmatic access 25 | to the RTMP protocol. This man page gives an overview of the RTMP 26 | library routines. These routines are found in the -lrtmp library. Many 27 | other routines are also available, but they are not documented yet. 28 | 29 | The basic interaction is as follows. A session handle is created using 30 | .BR RTMP_Alloc () 31 | and initialized using 32 | .BR RTMP_Init (). 33 | All session parameters are provided using 34 | .BR RTMP_SetupURL (). 35 | The network connection is established using 36 | .BR RTMP_Connect (), 37 | and then the RTMP session is established using 38 | .BR RTMP_ConnectStream (). 39 | The stream is read using 40 | .BR RTMP_Read (). 41 | A client can publish a stream by calling 42 | .BR RTMP_EnableWrite () 43 | before the 44 | .BR RTMP_Connect () 45 | call, and then using 46 | .BR RTMP_Write () 47 | after the session is established. 48 | While a stream is playing it may be paused and unpaused using 49 | .BR RTMP_Pause (). 50 | The stream playback position can be moved using 51 | .BR RTMP_Seek (). 52 | When 53 | .BR RTMP_Read () 54 | returns 0 bytes, the stream is complete and may be closed using 55 | .BR RTMP_Close (). 56 | The session handle is freed using 57 | .BR RTMP_Free (). 58 | 59 | All data is transferred using FLV format. The basic session requires 60 | an RTMP URL. Additional options may be specified by appending 61 | space-separated key=value pairs to the URL. The RTMP URL format 62 | is of the form 63 | .nf 64 | rtmp[t][e|s]://hostname[:port][/app[/playpath]] 65 | .fi 66 | 67 | Plain rtmp, as well as tunneled and encrypted sessions are supported. 68 | .SH OPTIONS 69 | .SS "Network Parameters" 70 | These options define how to connect to the media server. 71 | .TP 72 | .BI socks= host:port 73 | Use the specified SOCKS4 proxy. 74 | .SS "Connection Parameters" 75 | These options define the content of the RTMP Connect request packet. 76 | If correct values are not provided, the media server will reject the 77 | connection attempt. 78 | .TP 79 | .BI app= name 80 | Name of application to connect to on the RTMP server. Overrides 81 | the app in the RTMP URL. Sometimes the librtmp URL parser cannot 82 | determine the app name automatically, so it must be given explicitly 83 | using this option. 84 | .TP 85 | .BI tcUrl= url 86 | URL of the target stream. Defaults to rtmp[t][e|s]://host[:port]/app. 87 | .TP 88 | .BI pageUrl= url 89 | URL of the web page in which the media was embedded. By default no 90 | value will be sent. 91 | .TP 92 | .BI swfUrl= url 93 | URL of the SWF player for the media. By default no value will be sent. 94 | .TP 95 | .BI flashVer= version 96 | Version of the Flash plugin used to run the SWF player. The 97 | default is "LNX 10,0,32,18". 98 | .TP 99 | .BI conn= type:data 100 | Append arbitrary AMF data to the Connect message. The type 101 | must be B for Boolean, N for number, S for string, O for object, or Z 102 | for null. For Booleans the data must be either 0 or 1 for FALSE or TRUE, 103 | respectively. Likewise for Objects the data must be 0 or 1 to end or 104 | begin an object, respectively. Data items in subobjects may be named, by 105 | prefixing the type with 'N' and specifying the name before the value, e.g. 106 | NB:myFlag:1. This option may be used multiple times to construct arbitrary 107 | AMF sequences. E.g. 108 | .nf 109 | conn=B:1 conn=S:authMe conn=O:1 conn=NN:code:1.23 conn=NS:flag:ok conn=O:0 110 | .fi 111 | .SS "Session Parameters" 112 | These options take effect after the Connect request has succeeded. 113 | .TP 114 | .BI playpath= path 115 | Overrides the playpath parsed from the RTMP URL. Sometimes the 116 | rtmpdump URL parser cannot determine the correct playpath 117 | automatically, so it must be given explicitly using this option. 118 | .TP 119 | .BI playlist= 0|1 120 | If the value is 1 or TRUE, issue a set_playlist command before sending the 121 | play command. The playlist will just contain the current playpath. If the 122 | value is 0 or FALSE, the set_playlist command will not be sent. The 123 | default is FALSE. 124 | .TP 125 | .BI live= 0|1 126 | Specify that the media is a live stream. No resuming or seeking in 127 | live streams is possible. 128 | .TP 129 | .BI subscribe= path 130 | Name of live stream to subscribe to. Defaults to 131 | .IR playpath . 132 | .TP 133 | .BI start= num 134 | Start at 135 | .I num 136 | seconds into the stream. Not valid for live streams. 137 | .TP 138 | .BI stop= num 139 | Stop at 140 | .I num 141 | seconds into the stream. 142 | .TP 143 | .BI buffer= num 144 | Set buffer time to 145 | .I num 146 | milliseconds. The default is 30000. 147 | .TP 148 | .BI timeout= num 149 | Timeout the session after 150 | .I num 151 | seconds without receiving any data from the server. The default is 120. 152 | .SS "Security Parameters" 153 | These options handle additional authentication requests from the server. 154 | .TP 155 | .BI token= key 156 | Key for SecureToken response, used if the server requires SecureToken 157 | authentication. 158 | .TP 159 | .BI swfVfy= 0|1 160 | If the value is 1 or TRUE, the SWF player is retrieved from the 161 | specified 162 | .I swfUrl 163 | for performing SWF Verification. The SWF hash and size (used in the 164 | verification step) are computed automatically. Also the SWF information is 165 | cached in a 166 | .I .swfinfo 167 | file in the user's home directory, so that it doesn't need to be retrieved 168 | and recalculated every time. The .swfinfo file records 169 | the SWF URL, the time it was fetched, the modification timestamp of the SWF 170 | file, its size, and its hash. By default, the cached info will be used 171 | for 30 days before re-checking. 172 | .TP 173 | .BI swfAge= days 174 | Specify how many days to use the cached SWF info before re-checking. Use 175 | 0 to always check the SWF URL. Note that if the check shows that the 176 | SWF file has the same modification timestamp as before, it will not be 177 | retrieved again. 178 | .SH EXAMPLES 179 | An example character string suitable for use with 180 | .BR RTMP_SetupURL (): 181 | .nf 182 | "rtmp://flashserver:1935/ondemand/thefile swfUrl=http://flashserver/player.swf swfVfy=1" 183 | .fi 184 | .SH ENVIRONMENT 185 | .TP 186 | .B HOME 187 | The value of 188 | .RB $ HOME 189 | is used as the location for the 190 | .I .swfinfo 191 | file. 192 | .SH FILES 193 | .TP 194 | .I $HOME/.swfinfo 195 | Cache of SWF Verification information 196 | .SH "SEE ALSO" 197 | .BR rtmpdump (1), 198 | .BR rtmpgw (8) 199 | .SH AUTHORS 200 | Andrej Stepanchuk, Howard Chu, The Flvstreamer Team 201 | .br 202 | 203 | -------------------------------------------------------------------------------- /librtmp.3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | LIBRTMP(3): 4 | 5 | 6 | 8 | 9 | 11 |
LIBRTMP(3)LIBRTMP(3) 7 |
RTMPDump v2.2e2010-05-29LIBRTMP(3) 10 |


    12 | 14 |
15 | 16 |

NAME

    17 | librtmp − RTMPDump Real-Time Messaging Protocol API 18 |
19 | 20 |

LIBRARY

    21 | RTMPDump RTMP (librtmp, -lrtmp) 22 |
23 | 24 |

SYNOPSIS

    25 | #include <librtmp/rtmp.h> 26 |
27 | 28 |

DESCRIPTION

    29 | The Real-Time Messaging Protocol (RTMP) is used for streaming 30 | multimedia content across a TCP/IP network. This API provides most client 31 | functions and a few server functions needed to support RTMP, RTMP tunneled 32 | in HTTP (RTMPT), encrypted RTMP (RTMPE), RTMP over SSL/TLS (RTMPS) and 33 | tunneled variants of these encrypted types (RTMPTE, RTMPTS). The basic 34 | RTMP specification has been published by Adobe but this API was 35 | reverse-engineered without use of the Adobe specification. As such, it may 36 | deviate from any published specifications but it usually duplicates the 37 | actual behavior of the original Adobe clients. 38 |

    39 | The RTMPDump software package includes a basic client utility program 40 | in 41 | rtmpdump(1), 42 | some sample servers, and a library used to provide programmatic access 43 | to the RTMP protocol. This man page gives an overview of the RTMP 44 | library routines. These routines are found in the -lrtmp library. Many 45 | other routines are also available, but they are not documented yet. 46 |

    47 | The basic interaction is as follows. A session handle is created using 48 | RTMP_Alloc() 49 | and initialized using 50 | RTMP_Init(). 51 | All session parameters are provided using 52 | RTMP_SetupURL(). 53 | The network connection is established using 54 | RTMP_Connect(), 55 | and then the RTMP session is established using 56 | RTMP_ConnectStream(). 57 | The stream is read using 58 | RTMP_Read(). 59 | A client can publish a stream by calling 60 | RTMP_EnableWrite() 61 | before the 62 | RTMP_Connect() 63 | call, and then using 64 | RTMP_Write() 65 | after the session is established. 66 | While a stream is playing it may be paused and unpaused using 67 | RTMP_Pause(). 68 | The stream playback position can be moved using 69 | RTMP_Seek(). 70 | When 71 | RTMP_Read() 72 | returns 0 bytes, the stream is complete and may be closed using 73 | RTMP_Close(). 74 | The session handle is freed using 75 | RTMP_Free(). 76 |

    77 | All data is transferred using FLV format. The basic session requires 78 | an RTMP URL. Additional options may be specified by appending 79 | space-separated key=value pairs to the URL. The RTMP URL format 80 | is of the form 81 |

     82 |   rtmp[t][e|s]://hostname[:port][/app[/playpath]]
     83 | 
    84 |

    85 | Plain rtmp, as well as tunneled and encrypted sessions are supported. 86 |

87 | 88 |

OPTIONS

    89 |
90 | 91 |

Network Parameters

    92 | These options define how to connect to the media server. 93 |

    94 |

    95 | socks=host:port 96 |
    97 | Use the specified SOCKS4 proxy. 98 |
    99 |
100 | 101 |

Connection Parameters

    102 | These options define the content of the RTMP Connect request packet. 103 | If correct values are not provided, the media server will reject the 104 | connection attempt. 105 |

    106 |

    107 | app=name 108 |
    109 | Name of application to connect to on the RTMP server. Overrides 110 | the app in the RTMP URL. Sometimes the librtmp URL parser cannot 111 | determine the app name automatically, so it must be given explicitly 112 | using this option. 113 |
    114 |

    115 |

    116 | tcUrl=url 117 |
    118 | URL of the target stream. Defaults to rtmp[t][e|s]://host[:port]/app. 119 |
    120 |

    121 |

    122 | pageUrl=url 123 |
    124 | URL of the web page in which the media was embedded. By default no 125 | value will be sent. 126 |
    127 |

    128 |

    129 | swfUrl=url 130 |
    131 | URL of the SWF player for the media. By default no value will be sent. 132 |
    133 |

    134 |

    135 | flashVer=version 136 |
    137 | Version of the Flash plugin used to run the SWF player. The 138 | default is "LNX 10,0,32,18". 139 |
    140 |

    141 |

    142 | conn=type:data 143 |
    144 | Append arbitrary AMF data to the Connect message. The type 145 | must be B for Boolean, N for number, S for string, O for object, or Z 146 | for null. For Booleans the data must be either 0 or 1 for FALSE or TRUE, 147 | respectively. Likewise for Objects the data must be 0 or 1 to end or 148 | begin an object, respectively. Data items in subobjects may be named, by 149 | prefixing the type with 'N' and specifying the name before the value, e.g. 150 | NB:myFlag:1. This option may be used multiple times to construct arbitrary 151 | AMF sequences. E.g. 152 |
    153 |   conn=B:1 conn=S:authMe conn=O:1 conn=NN:code:1.23 conn=NS:flag:ok conn=O:0
    154 | 
    155 |
    156 |
157 | 158 |

Session Parameters

    159 | These options take effect after the Connect request has succeeded. 160 |

    161 |

    162 | playpath=path 163 |
    164 | Overrides the playpath parsed from the RTMP URL. Sometimes the 165 | rtmpdump URL parser cannot determine the correct playpath 166 | automatically, so it must be given explicitly using this option. 167 |
    168 |

    169 |

    170 | playlist=0|1 171 |
    172 | If the value is 1 or TRUE, issue a set_playlist command before sending the 173 | play command. The playlist will just contain the current playpath. If the 174 | value is 0 or FALSE, the set_playlist command will not be sent. The 175 | default is FALSE. 176 |
    177 |

    178 |

    179 | live=0|1 180 |
    181 | Specify that the media is a live stream. No resuming or seeking in 182 | live streams is possible. 183 |
    184 |

    185 |

    186 | subscribe=path 187 |
    188 | Name of live stream to subscribe to. Defaults to 189 | playpath. 190 |
    191 |

    192 |

    193 | start=num 194 |
    195 | Start at 196 | num 197 | seconds into the stream. Not valid for live streams. 198 |
    199 |

    200 |

    201 | stop=num 202 |
    203 | Stop at 204 | num 205 | seconds into the stream. 206 |
    207 |

    208 |

    209 | buffer=num 210 |
    211 | Set buffer time to 212 | num 213 | milliseconds. The default is 30000. 214 |
    215 |

    216 |

    217 | timeout=num 218 |
    219 | Timeout the session after 220 | num 221 | seconds without receiving any data from the server. The default is 120. 222 |
    223 |
224 | 225 |

Security Parameters

    226 | These options handle additional authentication requests from the server. 227 |

    228 |

    229 | token=key 230 |
    231 | Key for SecureToken response, used if the server requires SecureToken 232 | authentication. 233 |
    234 |

    235 |

    236 | swfVfy=0|1 237 |
    238 | If the value is 1 or TRUE, the SWF player is retrieved from the 239 | specified 240 | swfUrl 241 | for performing SWF Verification. The SWF hash and size (used in the 242 | verification step) are computed automatically. Also the SWF information is 243 | cached in a 244 | .swfinfo 245 | file in the user's home directory, so that it doesn't need to be retrieved 246 | and recalculated every time. The .swfinfo file records 247 | the SWF URL, the time it was fetched, the modification timestamp of the SWF 248 | file, its size, and its hash. By default, the cached info will be used 249 | for 30 days before re-checking. 250 |
    251 |

    252 |

    253 | swfAge=days 254 |
    255 | Specify how many days to use the cached SWF info before re-checking. Use 256 | 0 to always check the SWF URL. Note that if the check shows that the 257 | SWF file has the same modification timestamp as before, it will not be 258 | retrieved again. 259 |
    260 |
261 | 262 |

EXAMPLES

    263 | An example character string suitable for use with 264 | RTMP_SetupURL(): 265 |
    266 |   "rtmp://flashserver:1935/ondemand/thefile swfUrl=http://flashserver/player.swf swfVfy=1"
    267 | 
    268 |
269 | 270 |

ENVIRONMENT

    271 |

    272 |

    273 | HOME 274 |
    275 | The value of 276 | $HOME 277 | is used as the location for the 278 | .swfinfo 279 | file. 280 |
    281 |
282 | 283 |

FILES

    284 |

    285 |

    286 | $HOME/.swfinfo 287 |
    288 | Cache of SWF Verification information 289 |
    290 |
291 | 292 |

SEE ALSO

296 | 297 |

AUTHORS

302 | -------------------------------------------------------------------------------- /librtmp.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | incdir=${prefix}/include 5 | 6 | Name: librtmp 7 | Description: RTMP implementation 8 | Version: @VERSION@ 9 | Requires: @CRYPTO_REQ@ 10 | URL: http://rtmpdump.mplayerhq.hu 11 | Libs: -L${libdir} -lrtmp -lz 12 | Cflags: -I${incdir} 13 | -------------------------------------------------------------------------------- /pili-librtmp.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint pili-librtmp.podspec' to ensure this is a 3 | # valid spec and remove all comments before submitting the spec. 4 | # 5 | # Any lines starting with a # are optional, but encouraged 6 | # 7 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 8 | # 9 | 10 | Pod::Spec.new do |s| 11 | s.name = "pili-librtmp" 12 | s.version = "1.0.7" 13 | s.summary = "pili-librtmp is a RTMP client library." 14 | s.homepage = "https://github.com/pili-engineering/pili-librtmp" 15 | s.license = 'LGPL' 16 | s.author = { "pili" => "pili@qiniu.com" } 17 | s.source = { :git => "https://github.com/pili-engineering/pili-librtmp.git", :tag => "v#{s.version}" } 18 | 19 | s.platform = :ios, '7.0' 20 | s.requires_arc = true 21 | s.source_files = "Pod/Classes/pili-librtmp/*.{h,c}" 22 | s.exclude_files = "Pod/Classes/pili-librtmp/dh.h", "Pod/Classes/pili-librtmp/handshake.h" 23 | end 24 | -------------------------------------------------------------------------------- /pili-librtmp/pili-librtmp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B6BBAE901CDC41F100F358B8 /* amf.c in Sources */ = {isa = PBXBuildFile; fileRef = B6BBAE801CDC41F100F358B8 /* amf.c */; }; 11 | B6BBAE911CDC41F100F358B8 /* error.c in Sources */ = {isa = PBXBuildFile; fileRef = B6BBAE851CDC41F100F358B8 /* error.c */; }; 12 | B6BBAE921CDC41F100F358B8 /* hashswf.c in Sources */ = {isa = PBXBuildFile; fileRef = B6BBAE881CDC41F100F358B8 /* hashswf.c */; }; 13 | B6BBAE931CDC41F100F358B8 /* log.c in Sources */ = {isa = PBXBuildFile; fileRef = B6BBAE8A1CDC41F100F358B8 /* log.c */; }; 14 | B6BBAE941CDC41F100F358B8 /* parseurl.c in Sources */ = {isa = PBXBuildFile; fileRef = B6BBAE8C1CDC41F100F358B8 /* parseurl.c */; }; 15 | B6BBAE951CDC41F100F358B8 /* rtmp.c in Sources */ = {isa = PBXBuildFile; fileRef = B6BBAE8D1CDC41F100F358B8 /* rtmp.c */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | B6BBAE2B1CDC3E2700F358B8 /* CopyFiles */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = "include/$(PRODUCT_NAME)"; 23 | dstSubfolderSpec = 16; 24 | files = ( 25 | ); 26 | runOnlyForDeploymentPostprocessing = 0; 27 | }; 28 | /* End PBXCopyFilesBuildPhase section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | B6BBAE2D1CDC3E2700F358B8 /* libpili-librtmp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libpili-librtmp.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | B6BBAE801CDC41F100F358B8 /* amf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amf.c; sourceTree = ""; }; 33 | B6BBAE811CDC41F100F358B8 /* amf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = amf.h; sourceTree = ""; }; 34 | B6BBAE821CDC41F100F358B8 /* bytes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bytes.h; sourceTree = ""; }; 35 | B6BBAE831CDC41F100F358B8 /* dh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dh.h; sourceTree = ""; }; 36 | B6BBAE841CDC41F100F358B8 /* dhgroups.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dhgroups.h; sourceTree = ""; }; 37 | B6BBAE851CDC41F100F358B8 /* error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = error.c; sourceTree = ""; }; 38 | B6BBAE861CDC41F100F358B8 /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error.h; sourceTree = ""; }; 39 | B6BBAE871CDC41F100F358B8 /* handshake.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = handshake.h; sourceTree = ""; }; 40 | B6BBAE881CDC41F100F358B8 /* hashswf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hashswf.c; sourceTree = ""; }; 41 | B6BBAE891CDC41F100F358B8 /* http.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http.h; sourceTree = ""; }; 42 | B6BBAE8A1CDC41F100F358B8 /* log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = log.c; sourceTree = ""; }; 43 | B6BBAE8B1CDC41F100F358B8 /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = ""; }; 44 | B6BBAE8C1CDC41F100F358B8 /* parseurl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parseurl.c; sourceTree = ""; }; 45 | B6BBAE8D1CDC41F100F358B8 /* rtmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rtmp.c; sourceTree = ""; }; 46 | B6BBAE8E1CDC41F100F358B8 /* rtmp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rtmp.h; sourceTree = ""; }; 47 | B6BBAE8F1CDC41F100F358B8 /* rtmp_sys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rtmp_sys.h; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | B6BBAE2A1CDC3E2700F358B8 /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXFrameworksBuildPhase section */ 59 | 60 | /* Begin PBXGroup section */ 61 | B6BBAE241CDC3E2700F358B8 = { 62 | isa = PBXGroup; 63 | children = ( 64 | B6BBAE7F1CDC41F100F358B8 /* pili-librtmp */, 65 | B6BBAE2E1CDC3E2700F358B8 /* Products */, 66 | ); 67 | sourceTree = ""; 68 | }; 69 | B6BBAE2E1CDC3E2700F358B8 /* Products */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | B6BBAE2D1CDC3E2700F358B8 /* libpili-librtmp.a */, 73 | ); 74 | name = Products; 75 | sourceTree = ""; 76 | }; 77 | B6BBAE7F1CDC41F100F358B8 /* pili-librtmp */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | B6BBAE801CDC41F100F358B8 /* amf.c */, 81 | B6BBAE811CDC41F100F358B8 /* amf.h */, 82 | B6BBAE821CDC41F100F358B8 /* bytes.h */, 83 | B6BBAE831CDC41F100F358B8 /* dh.h */, 84 | B6BBAE841CDC41F100F358B8 /* dhgroups.h */, 85 | B6BBAE851CDC41F100F358B8 /* error.c */, 86 | B6BBAE861CDC41F100F358B8 /* error.h */, 87 | B6BBAE871CDC41F100F358B8 /* handshake.h */, 88 | B6BBAE881CDC41F100F358B8 /* hashswf.c */, 89 | B6BBAE891CDC41F100F358B8 /* http.h */, 90 | B6BBAE8A1CDC41F100F358B8 /* log.c */, 91 | B6BBAE8B1CDC41F100F358B8 /* log.h */, 92 | B6BBAE8C1CDC41F100F358B8 /* parseurl.c */, 93 | B6BBAE8D1CDC41F100F358B8 /* rtmp.c */, 94 | B6BBAE8E1CDC41F100F358B8 /* rtmp.h */, 95 | B6BBAE8F1CDC41F100F358B8 /* rtmp_sys.h */, 96 | ); 97 | name = "pili-librtmp"; 98 | path = "../Pod/Classes/pili-librtmp"; 99 | sourceTree = ""; 100 | }; 101 | /* End PBXGroup section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | B6BBAE2C1CDC3E2700F358B8 /* pili-librtmp */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = B6BBAE361CDC3E2700F358B8 /* Build configuration list for PBXNativeTarget "pili-librtmp" */; 107 | buildPhases = ( 108 | B6BBAE291CDC3E2700F358B8 /* Sources */, 109 | B6BBAE2A1CDC3E2700F358B8 /* Frameworks */, 110 | B6BBAE2B1CDC3E2700F358B8 /* CopyFiles */, 111 | ); 112 | buildRules = ( 113 | ); 114 | dependencies = ( 115 | ); 116 | name = "pili-librtmp"; 117 | productName = "pili-librtmp"; 118 | productReference = B6BBAE2D1CDC3E2700F358B8 /* libpili-librtmp.a */; 119 | productType = "com.apple.product-type.library.static"; 120 | }; 121 | /* End PBXNativeTarget section */ 122 | 123 | /* Begin PBXProject section */ 124 | B6BBAE251CDC3E2700F358B8 /* Project object */ = { 125 | isa = PBXProject; 126 | attributes = { 127 | LastUpgradeCheck = 0720; 128 | ORGANIZATIONNAME = "Pili Engineering, Qiniu Inc."; 129 | TargetAttributes = { 130 | B6BBAE2C1CDC3E2700F358B8 = { 131 | CreatedOnToolsVersion = 7.2.1; 132 | }; 133 | }; 134 | }; 135 | buildConfigurationList = B6BBAE281CDC3E2700F358B8 /* Build configuration list for PBXProject "pili-librtmp" */; 136 | compatibilityVersion = "Xcode 3.2"; 137 | developmentRegion = English; 138 | hasScannedForEncodings = 0; 139 | knownRegions = ( 140 | en, 141 | ); 142 | mainGroup = B6BBAE241CDC3E2700F358B8; 143 | productRefGroup = B6BBAE2E1CDC3E2700F358B8 /* Products */; 144 | projectDirPath = ""; 145 | projectRoot = ""; 146 | targets = ( 147 | B6BBAE2C1CDC3E2700F358B8 /* pili-librtmp */, 148 | ); 149 | }; 150 | /* End PBXProject section */ 151 | 152 | /* Begin PBXSourcesBuildPhase section */ 153 | B6BBAE291CDC3E2700F358B8 /* Sources */ = { 154 | isa = PBXSourcesBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | B6BBAE941CDC41F100F358B8 /* parseurl.c in Sources */, 158 | B6BBAE931CDC41F100F358B8 /* log.c in Sources */, 159 | B6BBAE951CDC41F100F358B8 /* rtmp.c in Sources */, 160 | B6BBAE911CDC41F100F358B8 /* error.c in Sources */, 161 | B6BBAE901CDC41F100F358B8 /* amf.c in Sources */, 162 | B6BBAE921CDC41F100F358B8 /* hashswf.c in Sources */, 163 | ); 164 | runOnlyForDeploymentPostprocessing = 0; 165 | }; 166 | /* End PBXSourcesBuildPhase section */ 167 | 168 | /* Begin XCBuildConfiguration section */ 169 | B6BBAE341CDC3E2700F358B8 /* Debug */ = { 170 | isa = XCBuildConfiguration; 171 | buildSettings = { 172 | ALWAYS_SEARCH_USER_PATHS = NO; 173 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 174 | CLANG_CXX_LIBRARY = "libc++"; 175 | CLANG_ENABLE_MODULES = YES; 176 | CLANG_ENABLE_OBJC_ARC = YES; 177 | CLANG_WARN_BOOL_CONVERSION = YES; 178 | CLANG_WARN_CONSTANT_CONVERSION = YES; 179 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 180 | CLANG_WARN_EMPTY_BODY = YES; 181 | CLANG_WARN_ENUM_CONVERSION = YES; 182 | CLANG_WARN_INT_CONVERSION = YES; 183 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 184 | CLANG_WARN_UNREACHABLE_CODE = YES; 185 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 186 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 187 | COPY_PHASE_STRIP = NO; 188 | DEBUG_INFORMATION_FORMAT = dwarf; 189 | ENABLE_STRICT_OBJC_MSGSEND = YES; 190 | ENABLE_TESTABILITY = YES; 191 | GCC_C_LANGUAGE_STANDARD = gnu99; 192 | GCC_DYNAMIC_NO_PIC = NO; 193 | GCC_NO_COMMON_BLOCKS = YES; 194 | GCC_OPTIMIZATION_LEVEL = 0; 195 | GCC_PREPROCESSOR_DEFINITIONS = ( 196 | "DEBUG=1", 197 | "$(inherited)", 198 | ); 199 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 200 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 201 | GCC_WARN_UNDECLARED_SELECTOR = YES; 202 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 203 | GCC_WARN_UNUSED_FUNCTION = YES; 204 | GCC_WARN_UNUSED_VARIABLE = YES; 205 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 206 | MTL_ENABLE_DEBUG_INFO = YES; 207 | ONLY_ACTIVE_ARCH = YES; 208 | SDKROOT = iphoneos; 209 | }; 210 | name = Debug; 211 | }; 212 | B6BBAE351CDC3E2700F358B8 /* Release */ = { 213 | isa = XCBuildConfiguration; 214 | buildSettings = { 215 | ALWAYS_SEARCH_USER_PATHS = NO; 216 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 217 | CLANG_CXX_LIBRARY = "libc++"; 218 | CLANG_ENABLE_MODULES = YES; 219 | CLANG_ENABLE_OBJC_ARC = YES; 220 | CLANG_WARN_BOOL_CONVERSION = YES; 221 | CLANG_WARN_CONSTANT_CONVERSION = YES; 222 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 223 | CLANG_WARN_EMPTY_BODY = YES; 224 | CLANG_WARN_ENUM_CONVERSION = YES; 225 | CLANG_WARN_INT_CONVERSION = YES; 226 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 227 | CLANG_WARN_UNREACHABLE_CODE = YES; 228 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 229 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 230 | COPY_PHASE_STRIP = NO; 231 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 232 | ENABLE_NS_ASSERTIONS = NO; 233 | ENABLE_STRICT_OBJC_MSGSEND = YES; 234 | GCC_C_LANGUAGE_STANDARD = gnu99; 235 | GCC_NO_COMMON_BLOCKS = YES; 236 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 237 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 238 | GCC_WARN_UNDECLARED_SELECTOR = YES; 239 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 240 | GCC_WARN_UNUSED_FUNCTION = YES; 241 | GCC_WARN_UNUSED_VARIABLE = YES; 242 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 243 | MTL_ENABLE_DEBUG_INFO = NO; 244 | SDKROOT = iphoneos; 245 | VALIDATE_PRODUCT = YES; 246 | }; 247 | name = Release; 248 | }; 249 | B6BBAE371CDC3E2700F358B8 /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | OTHER_LDFLAGS = "-ObjC"; 253 | PRODUCT_NAME = "$(TARGET_NAME)"; 254 | SKIP_INSTALL = YES; 255 | }; 256 | name = Debug; 257 | }; 258 | B6BBAE381CDC3E2700F358B8 /* Release */ = { 259 | isa = XCBuildConfiguration; 260 | buildSettings = { 261 | OTHER_LDFLAGS = "-ObjC"; 262 | PRODUCT_NAME = "$(TARGET_NAME)"; 263 | SKIP_INSTALL = YES; 264 | }; 265 | name = Release; 266 | }; 267 | /* End XCBuildConfiguration section */ 268 | 269 | /* Begin XCConfigurationList section */ 270 | B6BBAE281CDC3E2700F358B8 /* Build configuration list for PBXProject "pili-librtmp" */ = { 271 | isa = XCConfigurationList; 272 | buildConfigurations = ( 273 | B6BBAE341CDC3E2700F358B8 /* Debug */, 274 | B6BBAE351CDC3E2700F358B8 /* Release */, 275 | ); 276 | defaultConfigurationIsVisible = 0; 277 | defaultConfigurationName = Release; 278 | }; 279 | B6BBAE361CDC3E2700F358B8 /* Build configuration list for PBXNativeTarget "pili-librtmp" */ = { 280 | isa = XCConfigurationList; 281 | buildConfigurations = ( 282 | B6BBAE371CDC3E2700F358B8 /* Debug */, 283 | B6BBAE381CDC3E2700F358B8 /* Release */, 284 | ); 285 | defaultConfigurationIsVisible = 0; 286 | defaultConfigurationName = Release; 287 | }; 288 | /* End XCConfigurationList section */ 289 | }; 290 | rootObject = B6BBAE251CDC3E2700F358B8 /* Project object */; 291 | } 292 | -------------------------------------------------------------------------------- /pili-librtmp/pili-librtmp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /pili-librtmp/pili-librtmp.xcodeproj/project.xcworkspace/xcshareddata/pili-librtmp.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "E95434706541E4F53523D4F8C1057CE8237AC944", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "1572C2605581CAFA6E620B982A8CF730602185E5" : 0, 8 | "E95434706541E4F53523D4F8C1057CE8237AC944" : 0 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "50A19D2C-8EF8-4062-88EE-08450BDD9806", 11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 12 | "1572C2605581CAFA6E620B982A8CF730602185E5" : "..\/..", 13 | "E95434706541E4F53523D4F8C1057CE8237AC944" : "pili-librtmp\/" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "pili-librtmp", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "pili-librtmp\/pili-librtmp.xcodeproj", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/www.github.com\/hzwangsiyu\/pili-player-ios-kit.git", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "1572C2605581CAFA6E620B982A8CF730602185E5" 23 | }, 24 | { 25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:hzwangsiyu\/pili-librtmp.git", 26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "E95434706541E4F53523D4F8C1057CE8237AC944" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /pili-librtmp/pili-librtmp.xcodeproj/project.xcworkspace/xcuserdata/wangsiyu.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pili-engineering/pili-librtmp/e814f73f122f626f15e21d6dc8ade72f65bcb96f/pili-librtmp/pili-librtmp.xcodeproj/project.xcworkspace/xcuserdata/wangsiyu.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /pili-librtmp/pili-librtmp.xcodeproj/xcuserdata/wangsiyu.xcuserdatad/xcschemes/pili-librtmp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /pili-librtmp/pili-librtmp.xcodeproj/xcuserdata/wangsiyu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | pili-librtmp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | B6BBAE2C1CDC3E2700F358B8 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | --------------------------------------------------------------------------------