├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── TcpServer.js ├── TcpSocket.js ├── TcpSockets.js ├── TcpSockets.podspec ├── android ├── .classpath ├── .project ├── .settings │ └── org.eclipse.buildship.core.prefs ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── peel │ └── react │ ├── TcpSocketListener.java │ ├── TcpSocketManager.java │ ├── TcpSockets.java │ └── TcpSocketsModule.java ├── base64-str.js ├── examples └── rctsockets │ ├── .babelrc │ ├── .buckconfig │ ├── .flowconfig │ ├── .gitattributes │ ├── .gitignore │ ├── .watchmanconfig │ ├── __tests__ │ ├── index.android.js │ └── index.ios.js │ ├── android │ ├── app │ │ ├── BUCK │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── rctsockets │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── keystores │ │ ├── BUCK │ │ └── debug.keystore.properties │ └── settings.gradle │ ├── index.android.js │ ├── index.ios.js │ ├── ios │ ├── rctsockets.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── rctsockets.xcscheme │ ├── rctsockets │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── rctsocketsTests │ │ ├── Info.plist │ │ └── rctsocketsTests.m │ ├── package.json │ └── shim.js ├── interfaces └── interface.js ├── ios ├── TcpSocketClient.h ├── TcpSocketClient.m ├── TcpSockets.h ├── TcpSockets.m └── TcpSockets.xcodeproj │ └── project.pbxproj ├── package-lock.json └── package.json /.eslintignore: -------------------------------------------------------------------------------- 1 | interfaces 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | 4 | "ecmaFeatures": { 5 | "jsx": true 6 | }, 7 | 8 | "env": { 9 | "es6": true, 10 | "jasmine": true, 11 | }, 12 | 13 | "plugins": [ 14 | "react" 15 | ], 16 | 17 | // Map from global var to bool specifying if it can be redefined 18 | "globals": { 19 | "__DEV__": true, 20 | "__dirname": false, 21 | "__fbBatchedBridgeConfig": false, 22 | "cancelAnimationFrame": false, 23 | "clearImmediate": true, 24 | "clearInterval": false, 25 | "clearTimeout": false, 26 | "console": false, 27 | "document": false, 28 | "escape": false, 29 | "exports": false, 30 | "fetch": false, 31 | "global": false, 32 | "jest": false, 33 | "Map": true, 34 | "module": false, 35 | "navigator": false, 36 | "process": false, 37 | "Promise": true, 38 | "requestAnimationFrame": true, 39 | "require": false, 40 | "Set": true, 41 | "setImmediate": true, 42 | "setInterval": false, 43 | "setTimeout": false, 44 | "window": false, 45 | "XMLHttpRequest": false, 46 | "pit": false 47 | }, 48 | 49 | "rules": { 50 | "comma-dangle": 0, // disallow trailing commas in object literals 51 | "no-cond-assign": 1, // disallow assignment in conditional expressions 52 | "no-console": 0, // disallow use of console (off by default in the node environment) 53 | "no-constant-condition": 0, // disallow use of constant expressions in conditions 54 | "no-control-regex": 1, // disallow control characters in regular expressions 55 | "no-debugger": 1, // disallow use of debugger 56 | "no-dupe-keys": 1, // disallow duplicate keys when creating object literals 57 | "no-empty": 0, // disallow empty statements 58 | "no-ex-assign": 1, // disallow assigning to the exception in a catch block 59 | "no-extra-boolean-cast": 1, // disallow double-negation boolean casts in a boolean context 60 | "no-extra-parens": 0, // disallow unnecessary parentheses (off by default) 61 | "no-extra-semi": 1, // disallow unnecessary semicolons 62 | "no-func-assign": 1, // disallow overwriting functions written as function declarations 63 | "no-inner-declarations": 0, // disallow function or variable declarations in nested blocks 64 | "no-invalid-regexp": 1, // disallow invalid regular expression strings in the RegExp constructor 65 | "no-negated-in-lhs": 1, // disallow negation of the left operand of an in expression 66 | "no-obj-calls": 1, // disallow the use of object properties of the global object (Math and JSON) as functions 67 | "no-regex-spaces": 1, // disallow multiple spaces in a regular expression literal 68 | "no-reserved-keys": 0, // disallow reserved words being used as object literal keys (off by default) 69 | "no-sparse-arrays": 1, // disallow sparse arrays 70 | "no-unreachable": 1, // disallow unreachable statements after a return, throw, continue, or break statement 71 | "use-isnan": 1, // disallow comparisons with the value NaN 72 | "valid-jsdoc": 0, // Ensure JSDoc comments are valid (off by default) 73 | "valid-typeof": 1, // Ensure that the results of typeof are compared against a valid string 74 | 75 | // Best Practices 76 | // These are rules designed to prevent you from making mistakes. They either prescribe a better way of doing something or help you avoid footguns. 77 | 78 | "block-scoped-var": 0, // treat var statements as if they were block scoped (off by default) 79 | "complexity": 0, // specify the maximum cyclomatic complexity allowed in a program (off by default) 80 | "consistent-return": 0, // require return statements to either always or never specify values 81 | "curly": 1, // specify curly brace conventions for all control statements 82 | "default-case": 0, // require default case in switch statements (off by default) 83 | "dot-notation": 1, // encourages use of dot notation whenever possible 84 | "eqeqeq": 1, // require the use of === and !== 85 | "guard-for-in": 0, // make sure for-in loops have an if statement (off by default) 86 | "no-alert": 1, // disallow the use of alert, confirm, and prompt 87 | "no-caller": 1, // disallow use of arguments.caller or arguments.callee 88 | "no-div-regex": 1, // disallow division operators explicitly at beginning of regular expression (off by default) 89 | "no-else-return": 0, // disallow else after a return in an if (off by default) 90 | "no-empty-label": 1, // disallow use of labels for anything other then loops and switches 91 | "no-eq-null": 0, // disallow comparisons to null without a type-checking operator (off by default) 92 | "no-eval": 1, // disallow use of eval() 93 | "no-extend-native": 1, // disallow adding to native types 94 | "no-extra-bind": 1, // disallow unnecessary function binding 95 | "no-fallthrough": 1, // disallow fallthrough of case statements 96 | "no-floating-decimal": 1, // disallow the use of leading or trailing decimal points in numeric literals (off by default) 97 | "no-implied-eval": 1, // disallow use of eval()-like methods 98 | "no-labels": 1, // disallow use of labeled statements 99 | "no-iterator": 1, // disallow usage of __iterator__ property 100 | "no-lone-blocks": 1, // disallow unnecessary nested blocks 101 | "no-loop-func": 0, // disallow creation of functions within loops 102 | "no-multi-str": 0, // disallow use of multiline strings 103 | "no-native-reassign": 0, // disallow reassignments of native objects 104 | "no-new": 1, // disallow use of new operator when not part of the assignment or comparison 105 | "no-new-func": 1, // disallow use of new operator for Function object 106 | "no-new-wrappers": 1, // disallows creating new instances of String,Number, and Boolean 107 | "no-octal": 1, // disallow use of octal literals 108 | "no-octal-escape": 1, // disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251"; 109 | "no-proto": 1, // disallow usage of __proto__ property 110 | "no-redeclare": 0, // disallow declaring the same variable more then once 111 | "no-return-assign": 1, // disallow use of assignment in return statement 112 | "no-script-url": 1, // disallow use of javascript: urls. 113 | "no-self-compare": 1, // disallow comparisons where both sides are exactly the same (off by default) 114 | "no-sequences": 1, // disallow use of comma operator 115 | "no-unused-expressions": 0, // disallow usage of expressions in statement position 116 | "no-void": 1, // disallow use of void operator (off by default) 117 | "no-warning-comments": 0, // disallow usage of configurable warning terms in comments": 1, // e.g. TODO or FIXME (off by default) 118 | "no-with": 1, // disallow use of the with statement 119 | "radix": 1, // require use of the second argument for parseInt() (off by default) 120 | "semi-spacing": 1, // require a space after a semi-colon 121 | "vars-on-top": 0, // requires to declare all vars on top of their containing scope (off by default) 122 | "wrap-iife": 0, // require immediate function invocation to be wrapped in parentheses (off by default) 123 | "yoda": 1, // require or disallow Yoda conditions 124 | 125 | // Strict Mode 126 | // These rules relate to using strict mode. 127 | 128 | "strict": [2, "global"], // require or disallow the "use strict" pragma in the global scope (off by default in the node environment) 129 | 130 | // Variables 131 | // These rules have to do with variable declarations. 132 | 133 | "no-catch-shadow": 1, // disallow the catch clause parameter name being the same as a variable in the outer scope (off by default in the node environment) 134 | "no-delete-var": 1, // disallow deletion of variables 135 | "no-label-var": 1, // disallow labels that share a name with a variable 136 | "no-shadow": 1, // disallow declaration of variables already declared in the outer scope 137 | "no-shadow-restricted-names": 1, // disallow shadowing of names such as arguments 138 | "no-undef": 2, // disallow use of undeclared variables unless mentioned in a /*global */ block 139 | "no-undefined": 0, // disallow use of undefined variable (off by default) 140 | "no-undef-init": 1, // disallow use of undefined when initializing variables 141 | "no-unused-vars": [1, {"vars": "all", "args": "none"}], // disallow declaration of variables that are not used in the code 142 | "no-use-before-define": 0, // disallow use of variables before they are defined 143 | 144 | // Node.js 145 | // These rules are specific to JavaScript running on Node.js. 146 | 147 | "handle-callback-err": 1, // enforces error handling in callbacks (off by default) (on by default in the node environment) 148 | "no-mixed-requires": 1, // disallow mixing regular variable and require declarations (off by default) (on by default in the node environment) 149 | "no-new-require": 1, // disallow use of new operator with the require function (off by default) (on by default in the node environment) 150 | "no-path-concat": 1, // disallow string concatenation with __dirname and __filename (off by default) (on by default in the node environment) 151 | "no-process-exit": 0, // disallow process.exit() (on by default in the node environment) 152 | "no-restricted-modules": 1, // restrict usage of specified node modules (off by default) 153 | "no-sync": 0, // disallow use of synchronous methods (off by default) 154 | 155 | // Stylistic Issues 156 | // These rules are purely matters of style and are quite subjective. 157 | 158 | "key-spacing": 0, 159 | "comma-spacing": 0, 160 | "no-multi-spaces": 0, 161 | "brace-style": 0, // enforce one true brace style (off by default) 162 | "camelcase": 0, // require camel case names 163 | "consistent-this": [1, "self"], // enforces consistent naming when capturing the current execution context (off by default) 164 | "eol-last": 1, // enforce newline at the end of file, with no multiple empty lines 165 | "func-names": 0, // require function expressions to have a name (off by default) 166 | "func-style": 0, // enforces use of function declarations or expressions (off by default) 167 | "new-cap": 0, // require a capital letter for constructors 168 | "new-parens": 1, // disallow the omission of parentheses when invoking a constructor with no arguments 169 | "no-nested-ternary": 0, // disallow nested ternary expressions (off by default) 170 | "no-array-constructor": 1, // disallow use of the Array constructor 171 | "no-lonely-if": 0, // disallow if as the only statement in an else block (off by default) 172 | "no-new-object": 1, // disallow use of the Object constructor 173 | "no-spaced-func": 1, // disallow space between function identifier and application 174 | "no-ternary": 0, // disallow the use of ternary operators (off by default) 175 | "no-trailing-spaces": 1, // disallow trailing whitespace at the end of lines 176 | "no-underscore-dangle": 0, // disallow dangling underscores in identifiers 177 | "no-mixed-spaces-and-tabs": 1, // disallow mixed spaces and tabs for indentation 178 | "quotes": [1, "single", "avoid-escape"], // specify whether double or single quotes should be used 179 | "quote-props": 0, // require quotes around object literal property names (off by default) 180 | "semi": 1, // require or disallow use of semicolons instead of ASI 181 | "sort-vars": 0, // sort variables within the same declaration block (off by default) 182 | "space-after-keywords": 1, // require a space after certain keywords (off by default) 183 | "space-in-brackets": 0, // require or disallow spaces inside brackets (off by default) 184 | "space-in-parens": 0, // require or disallow spaces inside parentheses (off by default) 185 | "space-infix-ops": 1, // require spaces around operators 186 | "space-return-throw-case": 1, // require a space after return, throw, and case 187 | "space-unary-ops": [1, { "words": true, "nonwords": false }], // require or disallow spaces before/after unary operators (words on by default, nonwords off by default) 188 | "max-nested-callbacks": 0, // specify the maximum depth callbacks can be nested (off by default) 189 | "one-var": 0, // allow just one var statement per function (off by default) 190 | "wrap-regex": 0, // require regex literals to be wrapped in parentheses (off by default) 191 | 192 | // Legacy 193 | // The following rules are included for compatibility with JSHint and JSLint. While the names of the rules may not match up with the JSHint/JSLint counterpart, the functionality is the same. 194 | 195 | "max-depth": 0, // specify the maximum depth that blocks can be nested (off by default) 196 | "max-len": 0, // specify the maximum length of a line in your program (off by default) 197 | "max-params": 0, // limits the number of parameters that can be used in the function declaration. (off by default) 198 | "max-statements": 0, // specify the maximum number of statement allowed in a function (off by default) 199 | "no-bitwise": 0, // disallow use of bitwise operators (off by default) 200 | "no-plusplus": 0, // disallow use of unary operators, ++ and -- (off by default) 201 | 202 | "react/display-name": 0, 203 | "react/jsx-boolean-value": 0, 204 | "jsx-quotes": [2, "prefer-single"], 205 | "react/jsx-no-undef": 1, 206 | "react/jsx-sort-props": 0, 207 | "react/jsx-uses-react": 0, 208 | "react/jsx-uses-vars": 1, 209 | "react/no-did-mount-set-state": [1, "allow-in-func"], 210 | "react/no-did-update-set-state": [1, "allow-in-func"], 211 | "react/no-multi-comp": 0, 212 | "react/no-unknown-property": 0, 213 | "react/prop-types": 0, 214 | "react/react-in-jsx-scope": 0, 215 | "react/self-closing-comp": 1, 216 | "react/wrap-multilines": 0 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | # We fork some components by platform. 4 | .*/*.web.js 5 | .*/*.android.js 6 | 7 | # Some modules have their own node_modules with overlap 8 | .*/node_modules/node-haste/.* 9 | 10 | # Ugh 11 | .*/node_modules/babel.* 12 | .*/node_modules/babylon.* 13 | .*/node_modules/invariant.* 14 | 15 | # Ignore react and fbjs where there are overlaps, but don't ignore 16 | # anything that react-native relies on 17 | .*/node_modules/fbjs/lib/Map.js 18 | .*/node_modules/fbjs/lib/ErrorUtils.js 19 | 20 | # Flow has a built-in definition for the 'react' module which we prefer to use 21 | # over the currently-untyped source 22 | .*/node_modules/react/react.js 23 | .*/node_modules/react/lib/React.js 24 | .*/node_modules/react/lib/ReactDOM.js 25 | 26 | .*/__mocks__/.* 27 | .*/__tests__/.* 28 | 29 | .*/commoner/test/source/widget/share.js 30 | 31 | # Ignore commoner tests 32 | .*/node_modules/commoner/test/.* 33 | 34 | # See https://github.com/facebook/flow/issues/442 35 | .*/react-tools/node_modules/commoner/lib/reader.js 36 | 37 | # Ignore jest 38 | .*/node_modules/jest-cli/.* 39 | 40 | # Ignore Website 41 | .*/website/.* 42 | 43 | # Ignore generators 44 | .*/local-cli/generator.* 45 | 46 | # Ignore BUCK generated folders 47 | .*\.buckd/ 48 | 49 | # Ignore RNPM 50 | .*/local-cli/rnpm/.* 51 | 52 | .*/node_modules/is-my-json-valid/test/.*\.json 53 | .*/node_modules/iconv-lite/encodings/tables/.*\.json 54 | .*/node_modules/y18n/test/.*\.json 55 | .*/node_modules/spdx-license-ids/spdx-license-ids.json 56 | .*/node_modules/spdx-exceptions/index.json 57 | .*/node_modules/resolve/test/subdirs/node_modules/a/b/c/x.json 58 | .*/node_modules/resolve/lib/core.json 59 | .*/node_modules/jsonparse/samplejson/.*\.json 60 | .*/node_modules/json5/test/.*\.json 61 | .*/node_modules/ua-parser-js/test/.*\.json 62 | .*/node_modules/builtin-modules/builtin-modules.json 63 | .*/node_modules/binary-extensions/binary-extensions.json 64 | .*/node_modules/url-regex/tlds.json 65 | .*/node_modules/joi/.*\.json 66 | .*/node_modules/isemail/.*\.json 67 | .*/node_modules/tr46/.*\.json 68 | 69 | 70 | [include] 71 | 72 | [libs] 73 | node_modules/react-native/Libraries/react-native/react-native-interface.js 74 | node_modules/react-native/flow 75 | flow/ 76 | 77 | [options] 78 | module.system=haste 79 | 80 | esproposal.class_static_fields=enable 81 | esproposal.class_instance_fields=enable 82 | 83 | munge_underscores=true 84 | 85 | module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' 86 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' 87 | 88 | suppress_type=$FlowIssue 89 | suppress_type=$FlowFixMe 90 | suppress_type=$FixMe 91 | 92 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-5]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 93 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-5]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 94 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 95 | 96 | [version] 97 | ^0.25.0 98 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IJ 26 | # 27 | *.iml 28 | .idea 29 | .gradle 30 | local.properties 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | examples -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Peel Technologies, Inc 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TCP in React Native 2 | 3 | node's [net](https://nodejs.org/api/net.html) API in React Native 4 | 5 | This module is used by [Peel](http://www.peel.com/) 6 | 7 | ## Install 8 | 9 | * Create a new react-native project. [Check react-native getting started](http://facebook.github.io/react-native/docs/getting-started.html#content) 10 | 11 | * In your project dir: 12 | 13 | ``` 14 | npm install react-native-tcp --save 15 | ``` 16 | 17 | __Note for iOS:__ If your react-native version < 0.40 install with this tag instead: 18 | ``` 19 | npm install react-native-tcp@3.1.0 --save 20 | ``` 21 | ## if using Cocoapods 22 | 23 | Update the following line with your path to `node_modules/` and add it to your 24 | podfile: 25 | 26 | ```ruby 27 | pod 'TcpSockets', :path => '../node_modules/react-native-tcp' 28 | ``` 29 | 30 | ## Link in the native dependency 31 | 32 | ``` 33 | react-native link react-native-tcp 34 | ``` 35 | 36 | ## Additional dependencies 37 | 38 | ### Due to limitations in the react-native packager, streams need to be hacked in with [rn-nodeify](https://www.npmjs.com/package/rn-nodeify) 39 | 40 | 1. install rn-nodeify as a dev-dependency 41 | ``` npm install --save-dev rn-nodeify ``` 42 | 2. run rn-nodeify manually 43 | ``` rn-nodeify --install stream,process,util --hack ``` 44 | 3. optionally you can add this as a postinstall script 45 | ``` "postinstall": "rn-nodeify --install stream,process,util --hack" ``` 46 | 47 | ## Usage 48 | 49 | ### package.json 50 | 51 | _only if you want to write require('net') in your javascript_ 52 | 53 | ```json 54 | { 55 | "browser": { 56 | "net": "react-native-tcp" 57 | } 58 | } 59 | ``` 60 | 61 | ### JS 62 | 63 | _see/run [index.ios.js/index.android.js](examples/rctsockets) for a complete example, but basically it's just like net_ 64 | 65 | ```js 66 | var net = require('net'); 67 | // OR, if not shimming via package.json "browser" field: 68 | // var net = require('react-native-tcp') 69 | 70 | var server = net.createServer(function(socket) { 71 | socket.write('excellent!'); 72 | }).listen(12345); 73 | 74 | var client = net.createConnection(12345); 75 | 76 | client.on('error', function(error) { 77 | console.log(error) 78 | }); 79 | 80 | client.on('data', function(data) { 81 | console.log('message was received', data) 82 | }); 83 | ``` 84 | 85 | ### TODO 86 | 87 | add select tests from node's tests for net 88 | 89 | PR's welcome! 90 | 91 | 92 | 93 | _originally forked from [react-native-udp](https://github.com/tradle/react-native-udp)_ 94 | -------------------------------------------------------------------------------- /TcpServer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Peel Technologies, Inc. 3 | * All rights reserved. 4 | * 5 | * @providesModule TcpServer 6 | * @flow 7 | */ 8 | 9 | var util = require('util'); 10 | var EventEmitter = require('events').EventEmitter; 11 | var { NativeModules } = require('react-native'); 12 | var Sockets = NativeModules.TcpSockets; 13 | 14 | var Socket = require('./TcpSocket'); 15 | 16 | function TcpServer(connectionListener: (socket: Socket) => void) { 17 | if (!(this instanceof TcpServer)) { 18 | return new TcpServer(connectionListener); 19 | } 20 | 21 | if (EventEmitter instanceof Function) { 22 | EventEmitter.call(this); 23 | } 24 | 25 | var self = this; 26 | 27 | this._socket = new Socket(); 28 | 29 | // $FlowFixMe: suppressing this error flow doesn't like EventEmitter 30 | this._socket.on('connect', function () { 31 | self.emit('listening'); 32 | }); 33 | // $FlowFixMe: suppressing this error flow doesn't like EventEmitter 34 | this._socket.on('connection', function (socket) { 35 | self._connections++; 36 | self.emit('connection', socket); 37 | }); 38 | // $FlowFixMe: suppressing this error flow doesn't like EventEmitter 39 | this._socket.on('error', function (error) { 40 | self.emit('error', error); 41 | }); 42 | 43 | if (typeof connectionListener === 'function') { 44 | self.on('connection', connectionListener); 45 | } 46 | 47 | this._connections = 0; 48 | } 49 | 50 | util.inherits(TcpServer, EventEmitter); 51 | 52 | TcpServer.prototype._debug = function () { 53 | if (__DEV__) { 54 | var args = [].slice.call(arguments); 55 | console.log.apply(console, args); 56 | } 57 | }; 58 | 59 | // TODO : determine how to properly overload this with flow 60 | TcpServer.prototype.listen = function (): TcpServer { 61 | var args = this._socket._normalizeConnectArgs(arguments); 62 | var options = args[0]; 63 | var callback = args[1]; 64 | 65 | var port = options.port; 66 | var host = options.host || '0.0.0.0'; 67 | 68 | if (callback) { 69 | this.once('listening', callback); 70 | } 71 | 72 | this._socket._registerEvents(); 73 | Sockets.listen(this._socket._id, host, port); 74 | 75 | return this; 76 | }; 77 | 78 | TcpServer.prototype.getConnections = function ( 79 | callback: (err: ?any, count: number) => void, 80 | ) { 81 | if (typeof callback === 'function') { 82 | callback.invoke(null, this._connections); 83 | } 84 | }; 85 | 86 | TcpServer.prototype.address = function (): { 87 | port: number, 88 | address: string, 89 | family: string, 90 | } { 91 | return this._socket ? this._socket.address() : {}; 92 | }; 93 | 94 | TcpServer.prototype.close = function (callback: ?() => void) { 95 | if (typeof callback === 'function') { 96 | if (!this._socket) { 97 | this.once('close', function close() { 98 | callback(new Error('Not running')); 99 | }); 100 | } else { 101 | this.once('close', callback); 102 | } 103 | } 104 | 105 | if (this._socket) { 106 | this._socket.end(); 107 | } 108 | 109 | var self = this; 110 | setImmediate(function () { 111 | self.emit('close'); 112 | }); 113 | }; 114 | 115 | // unimplemented net.Server apis 116 | TcpServer.prototype.ref = TcpServer.prototype.unref = function () { 117 | /* nop */ 118 | }; 119 | 120 | module.exports = TcpServer; 121 | -------------------------------------------------------------------------------- /TcpSocket.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Peel Technologies, Inc. 3 | * All rights reserved. 4 | * 5 | * @providesModule TcpSocket 6 | * @flow 7 | */ 8 | 9 | if (!(global.process && global.process.nextTick)) { 10 | global.process = require('process'); // needed to make stream-browserify happy 11 | } 12 | 13 | var Buffer = (global.Buffer = global.Buffer || require('buffer').Buffer); 14 | 15 | var util = require('util'); 16 | var stream = require('stream-browserify'); 17 | // var EventEmitter = require('events').EventEmitter; 18 | var ipRegex = require('ip-regex'); 19 | var { NativeEventEmitter, NativeModules } = require('react-native'); 20 | var Sockets = NativeModules.TcpSockets; 21 | var base64 = require('base64-js'); 22 | var Base64Str = require('./base64-str'); 23 | var noop = function () { }; 24 | var instances = 0; 25 | var STATE = { 26 | DISCONNECTED: 0, 27 | CONNECTING: 1, 28 | CONNECTED: 2, 29 | }; 30 | 31 | function TcpSocket(options: ?{ id: ?number }) { 32 | if (!(this instanceof TcpSocket)) { 33 | return new TcpSocket(options); 34 | } 35 | 36 | if (options && options.id) { 37 | // e.g. incoming server connections 38 | this._id = Number(options.id); 39 | 40 | if (this._id <= instances) { 41 | throw new Error('Socket id ' + this._id + 'already in use'); 42 | } 43 | } else { 44 | // javascript generated sockets range from 1-1000 45 | this._id = instances++; 46 | } 47 | 48 | this._eventEmitter = new NativeEventEmitter(Sockets); 49 | stream.Duplex.call(this, {}); 50 | 51 | // ensure compatibility with node's EventEmitter 52 | if (!this.on) { 53 | this.on = this.addListener.bind(this); 54 | } 55 | 56 | // these will be set once there is a connection 57 | this.writable = this.readable = false; 58 | 59 | this._state = STATE.DISCONNECTED; 60 | 61 | this.read(0); 62 | } 63 | 64 | util.inherits(TcpSocket, stream.Duplex); 65 | 66 | TcpSocket.prototype._debug = function () { 67 | if (__DEV__) { 68 | var args = [].slice.call(arguments); 69 | args.unshift('socket-' + this._id); 70 | console.log.apply(console, args); 71 | } 72 | }; 73 | 74 | // TODO : determine how to properly overload this with flow 75 | TcpSocket.prototype.connect = function (options, callback): TcpSocket { 76 | this._registerEvents(); 77 | 78 | if (options === null || typeof options !== 'object') { 79 | // Old API: 80 | // connect(port, [host], [cb]) 81 | var args = this._normalizeConnectArgs(arguments); 82 | return TcpSocket.prototype.connect.apply(this, args); 83 | } 84 | 85 | if (typeof callback === 'function') { 86 | this.once('connect', callback); 87 | } 88 | 89 | var host = options.host || 'localhost'; 90 | var port = options.port || 0; 91 | var localAddress = options.localAddress; 92 | var localPort = options.localPort; 93 | 94 | if (localAddress && !ipRegex({ exact: true }).test(localAddress)) { 95 | throw new TypeError( 96 | '"localAddress" option must be a valid IP: ' + localAddress, 97 | ); 98 | } 99 | 100 | if (localPort && typeof localPort !== 'number') { 101 | throw new TypeError('"localPort" option should be a number: ' + localPort); 102 | } 103 | 104 | if (typeof port !== 'undefined') { 105 | if (typeof port !== 'number' && typeof port !== 'string') { 106 | throw new TypeError( 107 | '"port" option should be a number or string: ' + port, 108 | ); 109 | } 110 | 111 | port = +port; 112 | 113 | if (!isLegalPort(port)) { 114 | throw new RangeError('"port" option should be >= 0 and < 65536: ' + port); 115 | } 116 | } 117 | 118 | if (options.timeout) { 119 | this.setTimeout(options.timeout); 120 | } else if (this._timeout) { 121 | this._activeTimer(this._timeout.msecs); 122 | } 123 | 124 | this._state = STATE.CONNECTING; 125 | this._debug('connecting, host:', host, 'port:', port); 126 | 127 | this._destroyed = false; 128 | Sockets.connect(this._id, host, Number(port), options); 129 | 130 | return this; 131 | }; 132 | 133 | // Check that the port number is not NaN when coerced to a number, 134 | // is an integer and that it falls within the legal range of port numbers. 135 | function isLegalPort(port: number): boolean { 136 | if (typeof port === 'string' && port.trim() === '') { 137 | return false; 138 | } 139 | return +port === port >>> 0 && port >= 0 && port <= 0xffff; 140 | } 141 | 142 | TcpSocket.prototype.read = function (n) { 143 | if (n === 0) { 144 | return stream.Readable.prototype.read.call(this, n); 145 | } 146 | 147 | this.read = stream.Readable.prototype.read; 148 | this._consuming = true; 149 | return this.read(n); 150 | }; 151 | 152 | // Just call handle.readStart until we have enough in the buffer 153 | TcpSocket.prototype._read = function (n) { 154 | this._debug('_read'); 155 | 156 | if (this._state === STATE.CONNECTING) { 157 | this._debug('_read wait for connection'); 158 | this.once('connect', () => this._read(n)); 159 | } else if (!this._reading) { 160 | // not already reading, start the flow 161 | this._debug('Socket._read resume'); 162 | this._reading = true; 163 | this.resume(); 164 | } 165 | }; 166 | 167 | TcpSocket.prototype._activeTimer = function (msecs, wrapper) { 168 | if (this._timeout && this._timeout.handle) { 169 | clearTimeout(this._timeout.handle); 170 | } 171 | 172 | if (!wrapper) { 173 | var self = this; 174 | wrapper = function () { 175 | self._timeout = null; 176 | self.emit('timeout'); 177 | }; 178 | } 179 | 180 | this._timeout = { 181 | handle: setTimeout(wrapper, msecs), 182 | wrapper: wrapper, 183 | msecs: msecs, 184 | }; 185 | }; 186 | 187 | TcpSocket.prototype._clearTimeout = function () { 188 | if (this._timeout) { 189 | clearTimeout(this._timeout.handle); 190 | this._timeout = null; 191 | } 192 | }; 193 | 194 | TcpSocket.prototype.setTimeout = function (msecs: number, callback: () => void) { 195 | if (msecs === 0) { 196 | this._clearTimeout(); 197 | if (callback) { 198 | this.removeListener('timeout', callback); 199 | } 200 | } else { 201 | if (callback) { 202 | this.once('timeout', callback); 203 | } 204 | 205 | this._activeTimer(msecs); 206 | } 207 | 208 | return this; 209 | }; 210 | 211 | TcpSocket.prototype.address = function (): { 212 | port: number, 213 | address: string, 214 | family: string, 215 | } { 216 | return this._address; 217 | }; 218 | 219 | TcpSocket.prototype.end = function (data, encoding) { 220 | stream.Duplex.prototype.end.call(this, data, encoding); 221 | this.writable = false; 222 | 223 | if (this._destroyed) { 224 | return; 225 | } 226 | 227 | if (data) { 228 | this.write(data, encoding); 229 | } 230 | 231 | if (this.readable) { 232 | this.read(0); 233 | this.readable = false; 234 | } 235 | 236 | this._destroyed = true; 237 | this._debug('ending'); 238 | 239 | Sockets.end(this._id); 240 | }; 241 | 242 | TcpSocket.prototype.destroy = function () { 243 | if (!this._destroyed) { 244 | this._destroyed = true; 245 | this._debug('destroying'); 246 | this._clearTimeout(); 247 | 248 | Sockets.destroy(this._id); 249 | } 250 | }; 251 | 252 | TcpSocket.prototype._registerEvents = function (): void { 253 | if (this._subs && this._subs.length > 0) { 254 | return; 255 | } 256 | 257 | this._subs = [ 258 | this._eventEmitter.addListener('connect', ev => { 259 | if (this._id !== ev.id) { 260 | return; 261 | } 262 | this._onConnect(ev.address); 263 | }), 264 | this._eventEmitter.addListener('connection', ev => { 265 | if (this._id !== ev.id) { 266 | return; 267 | } 268 | this._onConnection(ev.info); 269 | }), 270 | this._eventEmitter.addListener('data', ev => { 271 | if (this._id !== ev.id) { 272 | return; 273 | } 274 | this._onData(ev.data); 275 | }), 276 | this._eventEmitter.addListener('close', ev => { 277 | if (this._id !== ev.id) { 278 | return; 279 | } 280 | this._onClose(ev.hadError); 281 | }), 282 | this._eventEmitter.addListener('error', ev => { 283 | if (this._id !== ev.id) { 284 | return; 285 | } 286 | this._onError(ev.error); 287 | }), 288 | ]; 289 | }; 290 | 291 | TcpSocket.prototype._unregisterEvents = function (): void { 292 | this._subs.forEach(e => e.remove()); 293 | this._subs = []; 294 | }; 295 | 296 | TcpSocket.prototype._onConnect = function (address: { 297 | port: number, 298 | address: string, 299 | family: string, 300 | }): void { 301 | this._debug('received', 'connect'); 302 | 303 | setConnected(this, address); 304 | this.emit('connect'); 305 | 306 | this.read(0); 307 | }; 308 | 309 | TcpSocket.prototype._onConnection = function (info: { 310 | id: number, 311 | address: { port: number, address: string, family: string }, 312 | }): void { 313 | this._debug('received', 'connection'); 314 | 315 | var socket = new TcpSocket({ id: info.id }); 316 | 317 | socket._registerEvents(); 318 | setConnected(socket, info.address); 319 | this.emit('connection', socket); 320 | }; 321 | 322 | TcpSocket.prototype._onData = function (data: string): void { 323 | this._debug('received', 'data'); 324 | 325 | if (this._timeout) { 326 | this._activeTimer(this._timeout.msecs); 327 | } 328 | 329 | if (data && data.length > 0) { 330 | // debug('got data'); 331 | 332 | // read success. 333 | // In theory (and in practice) calling readStop right now 334 | // will prevent this from being called again until _read() gets 335 | // called again. 336 | 337 | var ret = this.push(new Buffer(data, 'base64')); 338 | if (this._reading && !ret) { 339 | this._reading = false; 340 | this.pause(); 341 | } 342 | 343 | return; 344 | } 345 | }; 346 | 347 | TcpSocket.prototype._onClose = function (hadError: boolean): void { 348 | this._debug('received', 'close'); 349 | 350 | setDisconnected(this, hadError); 351 | }; 352 | 353 | TcpSocket.prototype._onError = function (error: string): void { 354 | this._debug('received', 'error'); 355 | 356 | this.emit('error', normalizeError(error)); 357 | this.destroy(); 358 | }; 359 | 360 | TcpSocket.prototype.write = function (chunk, encoding, cb) { 361 | if (typeof chunk !== 'string' && !Buffer.isBuffer(chunk)) { 362 | throw new TypeError( 363 | 'Invalid data, chunk must be a string or buffer, not ' + typeof chunk, 364 | ); 365 | } 366 | 367 | return stream.Duplex.prototype.write.apply(this, arguments); 368 | }; 369 | 370 | TcpSocket.prototype._write = function ( 371 | buffer: any, 372 | encoding: ?String, 373 | callback: ?(err: ?Error) => void, 374 | ): boolean { 375 | var self = this; 376 | 377 | if (this._state === STATE.DISCONNECTED) { 378 | throw new Error('Socket is not connected.'); 379 | } else if (this._state === STATE.CONNECTING) { 380 | // we're ok, GCDAsyncSocket handles queueing internally 381 | } 382 | 383 | callback = callback || noop; 384 | var str; 385 | if (typeof buffer === 'string') { 386 | self._debug('socket.WRITE(): encoding as base64'); 387 | str = Base64Str.encode(buffer); 388 | } else if (Buffer.isBuffer(buffer)) { 389 | str = buffer.toString('base64'); 390 | } else { 391 | throw new TypeError( 392 | 'Invalid data, chunk must be a string or buffer, not ' + typeof buffer, 393 | ); 394 | } 395 | 396 | Sockets.write(this._id, str, function (err) { 397 | if (self._timeout) { 398 | self._activeTimer(self._timeout.msecs); 399 | } 400 | 401 | err = normalizeError(err); 402 | if (err) { 403 | self._debug('write failed', err); 404 | return callback(err); 405 | } 406 | 407 | callback(); 408 | }); 409 | 410 | return true; 411 | }; 412 | 413 | function setConnected( 414 | socket: TcpSocket, 415 | address: { port: number, address: string, family: string }, 416 | ) { 417 | socket.writable = socket.readable = true; 418 | socket._state = STATE.CONNECTED; 419 | socket._address = address; 420 | } 421 | 422 | function setDisconnected(socket: TcpSocket, hadError: boolean): void { 423 | if (socket._state === STATE.DISCONNECTED) { 424 | return; 425 | } 426 | 427 | socket._unregisterEvents(); 428 | socket._state = STATE.DISCONNECTED; 429 | socket.emit('close', hadError); 430 | } 431 | 432 | function normalizeError(err) { 433 | if (err) { 434 | if (typeof err === 'string') { 435 | err = new Error(err); 436 | } 437 | 438 | return err; 439 | } 440 | } 441 | 442 | // Returns an array [options] or [options, cb] 443 | // It is the same as the argument of Socket.prototype.connect(). 444 | TcpSocket.prototype._normalizeConnectArgs = function (args) { 445 | var options = {}; 446 | 447 | if (args[0] !== null && typeof args[0] === 'object') { 448 | // connect(options, [cb]) 449 | options = args[0]; 450 | } else { 451 | // connect(port, [host], [cb]) 452 | options.port = args[0]; 453 | if (typeof args[1] === 'string') { 454 | options.host = args[1]; 455 | } 456 | } 457 | 458 | var cb = args[args.length - 1]; 459 | return typeof cb === 'function' ? [options, cb] : [options]; 460 | }; 461 | 462 | // unimplemented net.Socket apis 463 | TcpSocket.prototype.ref = TcpSocket.prototype.unref = TcpSocket.prototype.setNoDelay = TcpSocket.prototype.setKeepAlive = TcpSocket.prototype.setEncoding = function () { 464 | /* nop */ 465 | }; 466 | 467 | module.exports = TcpSocket; 468 | -------------------------------------------------------------------------------- /TcpSockets.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Peel Technologies, Inc. 3 | * All rights reserved. 4 | * 5 | * @providesModule TcpSockets 6 | * @flow 7 | */ 8 | 9 | var ipRegex = require('ip-regex'); 10 | 11 | var Socket = require('./TcpSocket'); 12 | var Server = require('./TcpServer'); 13 | 14 | exports.createServer = function ( 15 | connectionListener: (socket: Socket) => void, 16 | ): Server { 17 | return new Server(connectionListener); 18 | }; 19 | 20 | // TODO : determine how to properly overload this with flow 21 | exports.connect = exports.createConnection = function (): Socket { 22 | var tcpSocket = new Socket(); 23 | return Socket.prototype.connect.apply( 24 | tcpSocket, 25 | tcpSocket._normalizeConnectArgs(arguments), 26 | ); 27 | }; 28 | 29 | exports.isIP = function (input: string): number { 30 | var result = 0; 31 | if (ipRegex.v4({ exact: true }).test(input)) { 32 | result = 4; 33 | } else if (ipRegex.v6({ exact: true }).test(input)) { 34 | result = 6; 35 | } 36 | return result; 37 | }; 38 | 39 | exports.isIPv4 = function (input: string): boolean { 40 | return exports.isIP(input) === 4; 41 | }; 42 | 43 | exports.isIPv6 = function (input: string): boolean { 44 | return exports.isIP(input) === 6; 45 | }; 46 | 47 | exports.Socket = Socket; 48 | exports.Server = Server; 49 | -------------------------------------------------------------------------------- /TcpSockets.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) 4 | 5 | Pod::Spec.new do |s| 6 | 7 | s.name = 'TcpSockets' 8 | s.version = package['version'] 9 | s.summary = package['description'] 10 | s.homepage = package['repository']['url'] 11 | s.license = package['license'] 12 | s.author = package['author'] 13 | s.source = { :git => s.homepage, :tag => 'v#{s.version}' } 14 | 15 | s.requires_arc = true 16 | s.ios.deployment_target = '8.0' 17 | s.tvos.deployment_target = '9.0' 18 | 19 | s.preserve_paths = 'README.md', 'package.json', '**/*.js' 20 | s.source_files = 'ios/**/*.{h,m}' 21 | s.dependency 'React' 22 | 23 | end 24 | -------------------------------------------------------------------------------- /android/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | react-native-tcp 4 | Project react-native-tcp created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /android/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir=../../../android 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | def safeExtGet(prop, fallback) { 2 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 3 | } 4 | 5 | buildscript { 6 | repositories { 7 | google() 8 | jcenter() 9 | } 10 | 11 | dependencies { 12 | classpath("com.android.tools.build:gradle:3.5.1") 13 | } 14 | } 15 | 16 | apply plugin: 'com.android.library' 17 | 18 | android { 19 | 20 | compileSdkVersion safeExtGet('compileSdkVersion', 29) 21 | buildToolsVersion safeExtGet('buildToolsVersion', '29.0.2') 22 | 23 | defaultConfig { 24 | minSdkVersion safeExtGet('minSdkVersion', 21) 25 | targetSdkVersion safeExtGet('targetSdkVersion', 29) 26 | versionCode 1 27 | versionName "0.2.0" 28 | } 29 | 30 | 31 | buildTypes { 32 | release { 33 | minifyEnabled false 34 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 35 | } 36 | } 37 | 38 | // needed for https://github.com/square/okio/issues/58 39 | lintOptions { 40 | abortOnError false 41 | warning 'InvalidPackage' 42 | } 43 | } 44 | 45 | repositories { 46 | google() 47 | jcenter() 48 | } 49 | 50 | dependencies { 51 | implementation 'com.facebook.react:react-native:+' 52 | implementation 'com.koushikdutta.async:androidasync:2.1.6' 53 | } 54 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | android.enableJetifier=true -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aprock/react-native-tcp/be5f656ffd3aa4559270e8472ee24a1c36029cf1/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=`expr $i + 1` 158 | done 159 | case $i in 160 | 0) set -- ;; 161 | 1) set -- "$args0" ;; 162 | 2) set -- "$args0" "$args1" ;; 163 | 3) set -- "$args0" "$args1" "$args2" ;; 164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=`save "$@"` 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | exec "$JAVACMD" "$@" 184 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/src/main/java/com/peel/react/TcpSocketListener.java: -------------------------------------------------------------------------------- 1 | package com.peel.react; 2 | 3 | import java.net.InetSocketAddress; 4 | 5 | /** 6 | * Created by aprock on 12/28/15. 7 | */ 8 | public interface TcpSocketListener { 9 | // server 10 | void onConnection(Integer serverId, Integer clientId, InetSocketAddress socketAddress); 11 | 12 | // client and server 13 | void onConnect(Integer id, InetSocketAddress socketAddress); 14 | void onData(Integer id, byte[] data); 15 | void onClose(Integer id, String error); 16 | void onError(Integer id, String error); 17 | } 18 | -------------------------------------------------------------------------------- /android/src/main/java/com/peel/react/TcpSocketManager.java: -------------------------------------------------------------------------------- 1 | package com.peel.react; 2 | 3 | import androidx.annotation.Nullable; 4 | import android.util.SparseArray; 5 | 6 | import com.koushikdutta.async.AsyncNetworkSocket; 7 | import com.koushikdutta.async.AsyncServer; 8 | import com.koushikdutta.async.AsyncServerSocket; 9 | import com.koushikdutta.async.AsyncSocket; 10 | import com.koushikdutta.async.ByteBufferList; 11 | import com.koushikdutta.async.DataEmitter; 12 | import com.koushikdutta.async.Util; 13 | import com.koushikdutta.async.callback.CompletedCallback; 14 | import com.koushikdutta.async.callback.ConnectCallback; 15 | import com.koushikdutta.async.callback.DataCallback; 16 | import com.koushikdutta.async.callback.ListenCallback; 17 | 18 | import java.io.IOException; 19 | import java.lang.ref.WeakReference; 20 | import java.net.InetAddress; 21 | import java.net.InetSocketAddress; 22 | import java.net.UnknownHostException; 23 | 24 | /** 25 | * Created by aprock on 12/29/15. 26 | */ 27 | public final class TcpSocketManager { 28 | private SparseArray mClients = new SparseArray(); 29 | 30 | private WeakReference mListener; 31 | private AsyncServer mServer = AsyncServer.getDefault(); 32 | 33 | private int mInstances = 5000; 34 | 35 | public TcpSocketManager(TcpSocketListener listener) throws IOException { 36 | mListener = new WeakReference(listener); 37 | } 38 | 39 | private void setSocketCallbacks(final Integer cId, final AsyncSocket socket) { 40 | socket.setClosedCallback(new CompletedCallback() { 41 | @Override 42 | public void onCompleted(Exception ex) { 43 | TcpSocketListener listener = mListener.get(); 44 | if (listener != null) { 45 | listener.onClose(cId, ex==null?null:ex.getMessage()); 46 | } 47 | } 48 | }); 49 | 50 | socket.setDataCallback(new DataCallback() { 51 | @Override 52 | public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) { 53 | TcpSocketListener listener = mListener.get(); 54 | if (listener != null) { 55 | listener.onData(cId, bb.getAllByteArray()); 56 | } 57 | } 58 | }); 59 | 60 | socket.setEndCallback(new CompletedCallback() { 61 | @Override 62 | public void onCompleted(Exception ex) { 63 | if (ex != null) { 64 | TcpSocketListener listener = mListener.get(); 65 | if (listener != null) { 66 | listener.onError(cId, ex.getMessage()); 67 | } 68 | } 69 | socket.close(); 70 | } 71 | }); 72 | } 73 | 74 | public void listen(final Integer cId, final String host, final Integer port) throws UnknownHostException, IOException { 75 | // resolve the address 76 | final InetSocketAddress socketAddress; 77 | if (host != null) { 78 | socketAddress = new InetSocketAddress(InetAddress.getByName(host), port); 79 | } else { 80 | socketAddress = new InetSocketAddress(port); 81 | } 82 | 83 | mServer.listen(InetAddress.getByName(host), port, new ListenCallback() { 84 | InetSocketAddress localAddress = socketAddress; 85 | 86 | @Override 87 | public void onListening(AsyncServerSocket socket) { 88 | mClients.put(cId, socket); 89 | 90 | if(socketAddress.getPort() != socket.getLocalPort()) { 91 | localAddress = new InetSocketAddress(socketAddress.getAddress(), socket.getLocalPort()); 92 | } 93 | 94 | TcpSocketListener listener = mListener.get(); 95 | if (listener != null) { 96 | listener.onConnect(cId, localAddress); 97 | } 98 | } 99 | 100 | @Override 101 | public void onAccepted(AsyncSocket socket) { 102 | setSocketCallbacks(mInstances, socket); 103 | mClients.put(mInstances, socket); 104 | 105 | AsyncNetworkSocket socketConverted = Util.getWrappedSocket(socket, AsyncNetworkSocket.class); 106 | InetSocketAddress remoteAddress = socketConverted != null ? socketConverted.getRemoteAddress() : localAddress; 107 | 108 | TcpSocketListener listener = mListener.get(); 109 | if (listener != null) { 110 | listener.onConnection(cId, mInstances, remoteAddress); 111 | } 112 | 113 | mInstances++; 114 | } 115 | 116 | @Override 117 | public void onCompleted(Exception ex) { 118 | mClients.delete(cId); 119 | 120 | TcpSocketListener listener = mListener.get(); 121 | if (listener != null) { 122 | listener.onClose(cId, ex != null ? ex.getMessage() : null); 123 | } 124 | } 125 | }); 126 | } 127 | 128 | public void connect(final Integer cId, final @Nullable String host, final Integer port) throws UnknownHostException, IOException { 129 | // resolve the address 130 | final InetSocketAddress socketAddress; 131 | if (host != null) { 132 | socketAddress = new InetSocketAddress(InetAddress.getByName(host), port); 133 | } else { 134 | socketAddress = new InetSocketAddress(port); 135 | } 136 | 137 | mServer.connectSocket(socketAddress, new ConnectCallback() { 138 | @Override 139 | public void onConnectCompleted(Exception ex, AsyncSocket socket) { 140 | TcpSocketListener listener = mListener.get(); 141 | if (ex == null) { 142 | mClients.put(cId, socket); 143 | setSocketCallbacks(cId, socket); 144 | 145 | if (listener != null) { 146 | listener.onConnect(cId, socketAddress); 147 | } 148 | } else if (listener != null) { 149 | listener.onError(cId, ex.getMessage()); 150 | } 151 | } 152 | }); 153 | } 154 | 155 | public void write(final Integer cId, final byte[] data) { 156 | Object socket = mClients.get(cId); 157 | if (socket != null && socket instanceof AsyncSocket) { 158 | ((AsyncSocket) socket).write(new ByteBufferList(data)); 159 | } 160 | } 161 | 162 | public void close(final Integer cId) { 163 | Object socket = mClients.get(cId); 164 | if (socket != null) { 165 | if (socket instanceof AsyncSocket) { 166 | ((AsyncSocket) socket).close(); 167 | } else if (socket instanceof AsyncServerSocket) { 168 | ((AsyncServerSocket) socket).stop(); 169 | } 170 | } else { 171 | TcpSocketListener listener = mListener.get(); 172 | if (listener != null) { 173 | listener.onError(cId, "unable to find socket"); 174 | } 175 | } 176 | } 177 | 178 | public void closeAllSockets() { 179 | for (int i = 0; i < mClients.size(); i++) { 180 | close(mClients.keyAt(i)); 181 | } 182 | mClients.clear(); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /android/src/main/java/com/peel/react/TcpSockets.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Peel Technologies, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | package com.peel.react; 7 | 8 | import androidx.annotation.Nullable; 9 | import android.util.Base64; 10 | 11 | import com.facebook.common.logging.FLog; 12 | import com.facebook.react.bridge.Arguments; 13 | import com.facebook.react.bridge.Callback; 14 | import com.facebook.react.bridge.GuardedAsyncTask; 15 | import com.facebook.react.bridge.ReactApplicationContext; 16 | import com.facebook.react.bridge.ReactContext; 17 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 18 | import com.facebook.react.bridge.ReactMethod; 19 | import com.facebook.react.bridge.ReadableMap; 20 | import com.facebook.react.bridge.WritableMap; 21 | import com.facebook.react.modules.core.DeviceEventManagerModule; 22 | 23 | import java.io.IOException; 24 | import java.net.InetAddress; 25 | import java.net.Inet6Address; 26 | import java.net.InetSocketAddress; 27 | import java.net.UnknownHostException; 28 | import java.util.concurrent.ExecutionException; 29 | 30 | /** 31 | * The NativeModule acting as an api layer for {@link TcpSocketManager} 32 | */ 33 | public final class TcpSockets extends ReactContextBaseJavaModule implements TcpSocketListener { 34 | private static final String TAG = "TcpSockets"; 35 | 36 | private boolean mShuttingDown = false; 37 | private TcpSocketManager socketManager; 38 | 39 | private ReactContext mReactContext; 40 | 41 | public TcpSockets(ReactApplicationContext reactContext) { 42 | super(reactContext); 43 | mReactContext = reactContext; 44 | 45 | try { 46 | socketManager = new TcpSocketManager(this); 47 | } catch (IOException e) { 48 | e.printStackTrace(); 49 | } 50 | } 51 | 52 | @Override 53 | public String getName() { 54 | return TAG; 55 | } 56 | 57 | @Override 58 | public void initialize() { 59 | mShuttingDown = false; 60 | } 61 | 62 | @Override 63 | public void onCatalystInstanceDestroy() { 64 | mShuttingDown = true; 65 | 66 | try { 67 | new GuardedAsyncTask(getReactApplicationContext()) { 68 | @Override 69 | protected void doInBackgroundGuarded(Void... params) { 70 | socketManager.closeAllSockets(); 71 | } 72 | }.execute().get(); 73 | } catch (InterruptedException ioe) { 74 | FLog.e(TAG, "onCatalystInstanceDestroy", ioe); 75 | } catch (ExecutionException ee) { 76 | FLog.e(TAG, "onCatalystInstanceDestroy", ee); 77 | } 78 | } 79 | 80 | private void sendEvent(String eventName, WritableMap params) { 81 | mReactContext 82 | .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) 83 | .emit(eventName, params); 84 | } 85 | 86 | @ReactMethod 87 | public void listen(final Integer cId, final String host, final Integer port) { 88 | new GuardedAsyncTask(getReactApplicationContext()) { 89 | @Override 90 | protected void doInBackgroundGuarded(Void... params) { 91 | try { 92 | socketManager.listen(cId, host, port); 93 | } catch (UnknownHostException uhe) { 94 | FLog.e(TAG, "listen", uhe); 95 | onError(cId, uhe.getMessage()); 96 | } catch (IOException ioe) { 97 | FLog.e(TAG, "listen", ioe); 98 | onError(cId, ioe.getMessage()); 99 | } 100 | } 101 | }.execute(); 102 | } 103 | 104 | @ReactMethod 105 | public void connect(final Integer cId, final @Nullable String host, final Integer port, final ReadableMap options) { 106 | new GuardedAsyncTask(getReactApplicationContext()) { 107 | @Override 108 | protected void doInBackgroundGuarded(Void... params) { 109 | // NOTE : ignoring options for now, just use the available interface. 110 | try { 111 | socketManager.connect(cId, host, port); 112 | } catch (UnknownHostException uhe) { 113 | FLog.e(TAG, "connect", uhe); 114 | onError(cId, uhe.getMessage()); 115 | } catch (IOException ioe) { 116 | FLog.e(TAG, "connect", ioe); 117 | onError(cId, ioe.getMessage()); 118 | } 119 | } 120 | }.execute(); 121 | } 122 | 123 | @ReactMethod 124 | public void write(final Integer cId, final String base64String, final Callback callback) { 125 | new GuardedAsyncTask(getReactApplicationContext()) { 126 | @Override 127 | protected void doInBackgroundGuarded(Void... params) { 128 | socketManager.write(cId, Base64.decode(base64String, Base64.NO_WRAP)); 129 | if (callback != null) { 130 | callback.invoke(); 131 | } 132 | } 133 | }.execute(); 134 | } 135 | 136 | @ReactMethod 137 | public void end(final Integer cId) { 138 | new GuardedAsyncTask(getReactApplicationContext()) { 139 | @Override 140 | protected void doInBackgroundGuarded(Void... params) { 141 | socketManager.close(cId); 142 | } 143 | }.execute(); 144 | } 145 | 146 | @ReactMethod 147 | public void destroy(final Integer cId) { 148 | end(cId); 149 | } 150 | 151 | /** TcpSocketListener */ 152 | 153 | @Override 154 | public void onConnection(Integer serverId, Integer clientId, InetSocketAddress socketAddress) { 155 | if (mShuttingDown) { 156 | return; 157 | } 158 | WritableMap eventParams = Arguments.createMap(); 159 | eventParams.putInt("id", serverId); 160 | 161 | WritableMap infoParams = Arguments.createMap(); 162 | infoParams.putInt("id", clientId); 163 | 164 | final InetAddress address = socketAddress.getAddress(); 165 | 166 | WritableMap addressParams = Arguments.createMap(); 167 | addressParams.putString("address", address.getHostAddress()); 168 | addressParams.putInt("port", socketAddress.getPort()); 169 | addressParams.putString("family", address instanceof Inet6Address ? "IPv6" : "IPv4"); 170 | 171 | infoParams.putMap("address", addressParams); 172 | eventParams.putMap("info", infoParams); 173 | 174 | sendEvent("connection", eventParams); 175 | } 176 | 177 | @Override 178 | public void onConnect(Integer id, InetSocketAddress socketAddress) { 179 | if (mShuttingDown) { 180 | return; 181 | } 182 | WritableMap eventParams = Arguments.createMap(); 183 | eventParams.putInt("id", id); 184 | 185 | final InetAddress address = socketAddress.getAddress(); 186 | 187 | WritableMap addressParams = Arguments.createMap(); 188 | addressParams.putString("address", address.getHostAddress()); 189 | addressParams.putInt("port", socketAddress.getPort()); 190 | addressParams.putString("family", address instanceof Inet6Address ? "IPv6" : "IPv4"); 191 | 192 | eventParams.putMap("address", addressParams); 193 | 194 | sendEvent("connect", eventParams); 195 | } 196 | 197 | @Override 198 | public void onData(Integer id, byte[] data) { 199 | if (mShuttingDown) { 200 | return; 201 | } 202 | WritableMap eventParams = Arguments.createMap(); 203 | eventParams.putInt("id", id); 204 | eventParams.putString("data", Base64.encodeToString(data, Base64.NO_WRAP)); 205 | 206 | sendEvent("data", eventParams); 207 | } 208 | 209 | @Override 210 | public void onClose(Integer id, String error) { 211 | if (mShuttingDown) { 212 | return; 213 | } 214 | if (error != null) { 215 | onError(id, error); 216 | } 217 | 218 | WritableMap eventParams = Arguments.createMap(); 219 | eventParams.putInt("id", id); 220 | eventParams.putBoolean("hadError", error != null); 221 | 222 | sendEvent("close", eventParams); 223 | } 224 | 225 | @Override 226 | public void onError(Integer id, String error) { 227 | if (mShuttingDown) { 228 | return; 229 | } 230 | 231 | WritableMap eventParams = Arguments.createMap(); 232 | eventParams.putInt("id", id); 233 | eventParams.putString("error", error); 234 | 235 | sendEvent("error", eventParams); 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /android/src/main/java/com/peel/react/TcpSocketsModule.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Peel Technologies, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | package com.peel.react; 7 | 8 | import com.facebook.react.ReactPackage; 9 | import com.facebook.react.bridge.JavaScriptModule; 10 | import com.facebook.react.bridge.NativeModule; 11 | import com.facebook.react.bridge.ReactApplicationContext; 12 | import com.facebook.react.uimanager.ViewManager; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Collections; 16 | import java.util.List; 17 | 18 | public final class TcpSocketsModule implements ReactPackage { 19 | 20 | @Override 21 | public List createNativeModules(ReactApplicationContext reactContext) { 22 | List modules = new ArrayList(); 23 | 24 | modules.add(new TcpSockets(reactContext)); 25 | 26 | return modules; 27 | } 28 | 29 | // Deprecated RN 0.47 30 | public List> createJSModules() { 31 | return Collections.emptyList(); 32 | } 33 | 34 | @Override 35 | public List createViewManagers(ReactApplicationContext reactContext) { 36 | return Collections.emptyList(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /base64-str.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @providesModule base64-js 3 | * @noflow 4 | * 5 | * Original Source: https://gist.github.com/ncerminara/11257943 6 | */ 7 | 8 | (function () { 9 | var Base64Str = { 10 | _keyStr: 11 | 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', 12 | encode: function (e: string) { 13 | var t = ''; 14 | var n, r, i, s, o, u, a; 15 | var f = 0; 16 | e = Base64Str._utf8_encode(e); 17 | while (f < e.length) { 18 | n = e.charCodeAt(f++); 19 | r = e.charCodeAt(f++); 20 | i = e.charCodeAt(f++); 21 | s = n >> 2; 22 | o = ((n & 3) << 4) | (r >> 4); 23 | u = ((r & 15) << 2) | (i >> 6); 24 | a = i & 63; 25 | if (isNaN(r)) { 26 | u = a = 64; 27 | } else if (isNaN(i)) { 28 | a = 64; 29 | } 30 | t = 31 | t + 32 | this._keyStr.charAt(s) + 33 | this._keyStr.charAt(o) + 34 | this._keyStr.charAt(u) + 35 | this._keyStr.charAt(a); 36 | } 37 | return t; 38 | }, 39 | decode: function (e: string) { 40 | var t = ''; 41 | var n, r, i; 42 | var s, o, u, a; 43 | var f = 0; 44 | e = e.replace(/[^A-Za-z0-9\+\/\=]/g, ''); 45 | while (f < e.length) { 46 | s = this._keyStr.indexOf(e.charAt(f++)); 47 | o = this._keyStr.indexOf(e.charAt(f++)); 48 | u = this._keyStr.indexOf(e.charAt(f++)); 49 | a = this._keyStr.indexOf(e.charAt(f++)); 50 | n = (s << 2) | (o >> 4); 51 | r = ((o & 15) << 4) | (u >> 2); 52 | i = ((u & 3) << 6) | a; 53 | t = t + String.fromCharCode(n); 54 | if (u !== 64) { 55 | t = t + String.fromCharCode(r); 56 | } 57 | if (a !== 64) { 58 | t = t + String.fromCharCode(i); 59 | } 60 | } 61 | t = Base64Str._utf8_decode(t); 62 | return t; 63 | }, 64 | _utf8_encode: function (e) { 65 | e = e.replace(/\r\n/g, '\n'); 66 | var t = ''; 67 | for (var n = 0; n < e.length; n++) { 68 | var r = e.charCodeAt(n); 69 | if (r < 128) { 70 | t += String.fromCharCode(r); 71 | } else if (r > 127 && r < 2048) { 72 | t += String.fromCharCode((r >> 6) | 192); 73 | t += String.fromCharCode((r & 63) | 128); 74 | } else { 75 | t += String.fromCharCode((r >> 12) | 224); 76 | t += String.fromCharCode(((r >> 6) & 63) | 128); 77 | t += String.fromCharCode((r & 63) | 128); 78 | } 79 | } 80 | return t; 81 | }, 82 | _utf8_decode: function (e) { 83 | var t = ''; 84 | var n = 0; 85 | var r = 0, 86 | /*c1 = 0, */ c2 = 0; 87 | while (n < e.length) { 88 | r = e.charCodeAt(n); 89 | if (r < 128) { 90 | t += String.fromCharCode(r); 91 | n++; 92 | } else if (r > 191 && r < 224) { 93 | c2 = e.charCodeAt(n + 1); 94 | t += String.fromCharCode(((r & 31) << 6) | (c2 & 63)); 95 | n += 2; 96 | } else { 97 | c2 = e.charCodeAt(n + 1); 98 | var c3 = e.charCodeAt(n + 2); 99 | t += String.fromCharCode( 100 | ((r & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63), 101 | ); 102 | n += 3; 103 | } 104 | } 105 | return t; 106 | }, 107 | }; 108 | 109 | module.exports = Base64Str; 110 | })(); 111 | -------------------------------------------------------------------------------- /examples/rctsockets/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react-native"] 3 | } -------------------------------------------------------------------------------- /examples/rctsockets/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /examples/rctsockets/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore unexpected extra "@providesModule" 9 | .*/node_modules/.*/node_modules/fbjs/.* 10 | 11 | ; Ignore duplicate module providers 12 | ; For RN Apps installed via npm, "Libraries" folder is inside 13 | ; "node_modules/react-native" but in the source repo it is in the root 14 | .*/Libraries/react-native/React.js 15 | .*/Libraries/react-native/ReactNative.js 16 | 17 | [include] 18 | 19 | [libs] 20 | node_modules/react-native/Libraries/react-native/react-native-interface.js 21 | node_modules/react-native/flow 22 | flow/ 23 | 24 | [options] 25 | module.system=haste 26 | 27 | experimental.strict_type_args=true 28 | 29 | munge_underscores=true 30 | 31 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' 32 | 33 | suppress_type=$FlowIssue 34 | suppress_type=$FlowFixMe 35 | suppress_type=$FixMe 36 | 37 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-6]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 38 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-6]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 39 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 40 | 41 | unsafe.enable_getters_and_setters=true 42 | 43 | [version] 44 | ^0.36.0 45 | -------------------------------------------------------------------------------- /examples/rctsockets/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /examples/rctsockets/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | 33 | # node.js 34 | # 35 | node_modules/ 36 | npm-debug.log 37 | 38 | # BUCK 39 | buck-out/ 40 | \.buckd/ 41 | android/app/libs 42 | *.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 50 | 51 | fastlane/report.xml 52 | fastlane/Preview.html 53 | fastlane/screenshots 54 | -------------------------------------------------------------------------------- /examples/rctsockets/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /examples/rctsockets/__tests__/index.android.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import Index from '../index.android.js'; 4 | 5 | // Note: test renderer must be required after react-native. 6 | import renderer from 'react-test-renderer'; 7 | 8 | it('renders correctly', () => { 9 | const tree = renderer.create( 10 | 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /examples/rctsockets/__tests__/index.ios.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import Index from '../index.ios.js'; 4 | 5 | // Note: test renderer must be required after react-native. 6 | import renderer from 'react-test-renderer'; 7 | 8 | it('renders correctly', () => { 9 | const tree = renderer.create( 10 | 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /examples/rctsockets/android/app/BUCK: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | # To learn about Buck see [Docs](https://buckbuild.com/). 4 | # To run your application with Buck: 5 | # - install Buck 6 | # - `npm start` - to start the packager 7 | # - `cd android` 8 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 9 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 10 | # - `buck install -r android/app` - compile, install and run application 11 | # 12 | 13 | lib_deps = [] 14 | for jarfile in glob(['libs/*.jar']): 15 | name = 'jars__' + re.sub(r'^.*/([^/]+)\.jar$', r'\1', jarfile) 16 | lib_deps.append(':' + name) 17 | prebuilt_jar( 18 | name = name, 19 | binary_jar = jarfile, 20 | ) 21 | 22 | for aarfile in glob(['libs/*.aar']): 23 | name = 'aars__' + re.sub(r'^.*/([^/]+)\.aar$', r'\1', aarfile) 24 | lib_deps.append(':' + name) 25 | android_prebuilt_aar( 26 | name = name, 27 | aar = aarfile, 28 | ) 29 | 30 | android_library( 31 | name = 'all-libs', 32 | exported_deps = lib_deps 33 | ) 34 | 35 | android_library( 36 | name = 'app-code', 37 | srcs = glob([ 38 | 'src/main/java/**/*.java', 39 | ]), 40 | deps = [ 41 | ':all-libs', 42 | ':build_config', 43 | ':res', 44 | ], 45 | ) 46 | 47 | android_build_config( 48 | name = 'build_config', 49 | package = 'com.rctsockets', 50 | ) 51 | 52 | android_resource( 53 | name = 'res', 54 | res = 'src/main/res', 55 | package = 'com.rctsockets', 56 | ) 57 | 58 | android_binary( 59 | name = 'app', 60 | package_type = 'debug', 61 | manifest = 'src/main/AndroidManifest.xml', 62 | keystore = '//android/keystores:debug', 63 | deps = [ 64 | ':app-code', 65 | ], 66 | ) 67 | -------------------------------------------------------------------------------- /examples/rctsockets/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | 3 | import com.android.build.OutputFile 4 | 5 | /** 6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets 7 | * and bundleReleaseJsAndAssets). 8 | * These basically call `react-native bundle` with the correct arguments during the Android build 9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the 10 | * bundle directly from the development server. Below you can see all the possible configurations 11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the 12 | * `apply from: "../../node_modules/react-native/react.gradle"` line. 13 | * 14 | * project.ext.react = [ 15 | * // the name of the generated asset file containing your JS bundle 16 | * bundleAssetName: "index.android.bundle", 17 | * 18 | * // the entry file for bundle generation 19 | * entryFile: "index.android.js", 20 | * 21 | * // whether to bundle JS and assets in debug mode 22 | * bundleInDebug: false, 23 | * 24 | * // whether to bundle JS and assets in release mode 25 | * bundleInRelease: true, 26 | * 27 | * // whether to bundle JS and assets in another build variant (if configured). 28 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 29 | * // The configuration property can be in the following formats 30 | * // 'bundleIn${productFlavor}${buildType}' 31 | * // 'bundleIn${buildType}' 32 | * // bundleInFreeDebug: true, 33 | * // bundleInPaidRelease: true, 34 | * // bundleInBeta: true, 35 | * 36 | * // the root of your project, i.e. where "package.json" lives 37 | * root: "../../", 38 | * 39 | * // where to put the JS bundle asset in debug mode 40 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 41 | * 42 | * // where to put the JS bundle asset in release mode 43 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 44 | * 45 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 46 | * // require('./image.png')), in debug mode 47 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 48 | * 49 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 50 | * // require('./image.png')), in release mode 51 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 52 | * 53 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 54 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 55 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 56 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 57 | * // for example, you might want to remove it from here. 58 | * inputExcludes: ["android/**", "ios/**"], 59 | * 60 | * // override which node gets called and with what additional arguments 61 | * nodeExecutableAndArgs: ["node"] 62 | * 63 | * // supply additional arguments to the packager 64 | * extraPackagerArgs: [] 65 | * ] 66 | */ 67 | 68 | apply from: "../../node_modules/react-native/react.gradle" 69 | 70 | /** 71 | * Set this to true to create two separate APKs instead of one: 72 | * - An APK that only works on ARM devices 73 | * - An APK that only works on x86 devices 74 | * The advantage is the size of the APK is reduced by about 4MB. 75 | * Upload all the APKs to the Play Store and people will download 76 | * the correct one based on the CPU architecture of their device. 77 | */ 78 | def enableSeparateBuildPerCPUArchitecture = false 79 | 80 | /** 81 | * Run Proguard to shrink the Java bytecode in release builds. 82 | */ 83 | def enableProguardInReleaseBuilds = false 84 | 85 | android { 86 | compileSdkVersion 23 87 | buildToolsVersion "23.0.1" 88 | 89 | defaultConfig { 90 | applicationId "com.rctsockets" 91 | minSdkVersion 16 92 | targetSdkVersion 22 93 | versionCode 1 94 | versionName "1.0" 95 | ndk { 96 | abiFilters "armeabi-v7a", "x86" 97 | } 98 | } 99 | splits { 100 | abi { 101 | reset() 102 | enable enableSeparateBuildPerCPUArchitecture 103 | universalApk false // If true, also generate a universal APK 104 | include "armeabi-v7a", "x86" 105 | } 106 | } 107 | buildTypes { 108 | release { 109 | minifyEnabled enableProguardInReleaseBuilds 110 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 111 | } 112 | } 113 | // applicationVariants are e.g. debug, release 114 | applicationVariants.all { variant -> 115 | variant.outputs.each { output -> 116 | // For each separate APK per architecture, set a unique version code as described here: 117 | // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits 118 | def versionCodes = ["armeabi-v7a":1, "x86":2] 119 | def abi = output.getFilter(OutputFile.ABI) 120 | if (abi != null) { // null for the universal-debug, universal-release variants 121 | output.versionCodeOverride = 122 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 123 | } 124 | } 125 | } 126 | } 127 | 128 | dependencies { 129 | compile project(':react-native-tcp') 130 | compile fileTree(dir: "libs", include: ["*.jar"]) 131 | compile "com.android.support:appcompat-v7:23.0.1" 132 | compile "com.facebook.react:react-native:+" // From node_modules 133 | } 134 | 135 | // Run this once to be able to run the application with BUCK 136 | // puts all compile dependencies into folder libs for BUCK to use 137 | task copyDownloadableDepsToLibs(type: Copy) { 138 | from configurations.compile 139 | into 'libs' 140 | } 141 | -------------------------------------------------------------------------------- /examples/rctsockets/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Disabling obfuscation is useful if you collect stack traces from production crashes 20 | # (unless you are using a system that supports de-obfuscate the stack traces). 21 | -dontobfuscate 22 | 23 | # React Native 24 | 25 | # Keep our interfaces so they can be used by other ProGuard rules. 26 | # See http://sourceforge.net/p/proguard/bugs/466/ 27 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip 28 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters 29 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip 30 | 31 | # Do not strip any method/class that is annotated with @DoNotStrip 32 | -keep @com.facebook.proguard.annotations.DoNotStrip class * 33 | -keep @com.facebook.common.internal.DoNotStrip class * 34 | -keepclassmembers class * { 35 | @com.facebook.proguard.annotations.DoNotStrip *; 36 | @com.facebook.common.internal.DoNotStrip *; 37 | } 38 | 39 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { 40 | void set*(***); 41 | *** get*(); 42 | } 43 | 44 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } 45 | -keep class * extends com.facebook.react.bridge.NativeModule { *; } 46 | -keepclassmembers,includedescriptorclasses class * { native ; } 47 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; } 48 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; } 49 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; } 50 | 51 | -dontwarn com.facebook.react.** 52 | 53 | # okhttp 54 | 55 | -keepattributes Signature 56 | -keepattributes *Annotation* 57 | -keep class okhttp3.** { *; } 58 | -keep interface okhttp3.** { *; } 59 | -dontwarn okhttp3.** 60 | 61 | # okio 62 | 63 | -keep class sun.misc.Unsafe { *; } 64 | -dontwarn java.nio.file.* 65 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement 66 | -dontwarn okio.** 67 | -------------------------------------------------------------------------------- /examples/rctsockets/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /examples/rctsockets/android/app/src/main/java/com/rctsockets/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.rctsockets; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. 9 | * This is used to schedule rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "rctsockets"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/rctsockets/android/app/src/main/java/com/rctsockets/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.rctsockets; 2 | 3 | import android.app.Application; 4 | import android.util.Log; 5 | 6 | import com.facebook.react.ReactApplication; 7 | import com.peel.react.TcpSocketsModule; 8 | import com.facebook.react.ReactInstanceManager; 9 | import com.facebook.react.ReactNativeHost; 10 | import com.facebook.react.ReactPackage; 11 | import com.facebook.react.shell.MainReactPackage; 12 | import com.facebook.soloader.SoLoader; 13 | 14 | import java.util.Arrays; 15 | import java.util.List; 16 | 17 | public class MainApplication extends Application implements ReactApplication { 18 | 19 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 20 | @Override 21 | protected boolean getUseDeveloperSupport() { 22 | return BuildConfig.DEBUG; 23 | } 24 | 25 | @Override 26 | protected List getPackages() { 27 | return Arrays.asList( 28 | new MainReactPackage(), 29 | new TcpSocketsModule() 30 | ); 31 | } 32 | }; 33 | 34 | @Override 35 | public ReactNativeHost getReactNativeHost() { 36 | return mReactNativeHost; 37 | } 38 | 39 | @Override 40 | public void onCreate() { 41 | super.onCreate(); 42 | SoLoader.init(this, /* native exopackage */ false); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/rctsockets/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aprock/react-native-tcp/be5f656ffd3aa4559270e8472ee24a1c36029cf1/examples/rctsockets/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/rctsockets/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aprock/react-native-tcp/be5f656ffd3aa4559270e8472ee24a1c36029cf1/examples/rctsockets/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/rctsockets/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aprock/react-native-tcp/be5f656ffd3aa4559270e8472ee24a1c36029cf1/examples/rctsockets/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/rctsockets/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aprock/react-native-tcp/be5f656ffd3aa4559270e8472ee24a1c36029cf1/examples/rctsockets/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/rctsockets/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | rctsockets 3 | 4 | -------------------------------------------------------------------------------- /examples/rctsockets/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/rctsockets/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.3.1' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | mavenLocal() 18 | jcenter() 19 | maven { 20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 21 | url "$rootDir/../node_modules/react-native/android" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/rctsockets/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useDeprecatedNdk=true 21 | -------------------------------------------------------------------------------- /examples/rctsockets/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aprock/react-native-tcp/be5f656ffd3aa4559270e8472ee24a1c36029cf1/examples/rctsockets/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/rctsockets/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 6 | -------------------------------------------------------------------------------- /examples/rctsockets/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /examples/rctsockets/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /examples/rctsockets/android/keystores/BUCK: -------------------------------------------------------------------------------- 1 | keystore( 2 | name = 'debug', 3 | store = 'debug.keystore', 4 | properties = 'debug.keystore.properties', 5 | visibility = [ 6 | 'PUBLIC', 7 | ], 8 | ) 9 | -------------------------------------------------------------------------------- /examples/rctsockets/android/keystores/debug.keystore.properties: -------------------------------------------------------------------------------- 1 | key.store=debug.keystore 2 | key.alias=androiddebugkey 3 | key.store.password=android 4 | key.alias.password=android 5 | -------------------------------------------------------------------------------- /examples/rctsockets/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'rctsockets' 2 | include ':react-native-tcp' 3 | project(':react-native-tcp').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-tcp/android') 4 | 5 | include ':app' 6 | -------------------------------------------------------------------------------- /examples/rctsockets/index.android.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * @flow 5 | */ 6 | import './shim'; 7 | 8 | import React, { Component } from 'react'; 9 | import { 10 | AppRegistry, 11 | ScrollView, 12 | StyleSheet, 13 | Text, 14 | View 15 | } from 'react-native'; 16 | 17 | var net = require('net'); 18 | 19 | function randomPort() { 20 | return Math.random() * 60536 | 0 + 5000; // 60536-65536 21 | } 22 | 23 | var serverPort = randomPort(); 24 | 25 | class RctSockets extends Component { 26 | constructor(props) { 27 | super(props); 28 | 29 | this.updateChatter = this.updateChatter.bind(this); 30 | this.state = { chatter: [] }; 31 | } 32 | 33 | updateChatter(msg) { 34 | this.setState({ 35 | chatter: this.state.chatter.concat([msg]) 36 | }); 37 | } 38 | 39 | componentDidMount() { 40 | let server = net.createServer((socket) => { 41 | this.updateChatter('server connected on ' + JSON.stringify(socket.address())); 42 | 43 | socket.on('data', (data) => { 44 | this.updateChatter('Server Received: ' + data); 45 | socket.write('Echo server\r\n'); 46 | }); 47 | 48 | socket.on('error', (error) => { 49 | this.updateChatter('error ' + error); 50 | }); 51 | 52 | socket.on('close', (error) => { 53 | this.updateChatter('server client closed ' + (error ? error : '')); 54 | }); 55 | }).listen(serverPort, () => { 56 | this.updateChatter('opened server on ' + JSON.stringify(server.address())); 57 | }); 58 | 59 | server.on('error', (error) => { 60 | this.updateChatter('error ' + error); 61 | }); 62 | 63 | server.on('close', () => { 64 | this.updateChatter('server close'); 65 | }); 66 | 67 | let client = net.createConnection(serverPort, () => { 68 | this.updateChatter('opened client on ' + JSON.stringify(client.address())); 69 | client.write('Hello, server! Love, Client.'); 70 | }); 71 | 72 | client.on('data', (data) => { 73 | this.updateChatter('Client Received: ' + data); 74 | 75 | this.client.destroy(); // kill client after server's response 76 | this.server.close(); 77 | }); 78 | 79 | client.on('error', (error) => { 80 | this.updateChatter('client error ' + error); 81 | }); 82 | 83 | client.on('close', () => { 84 | this.updateChatter('client close'); 85 | }); 86 | 87 | this.server = server; 88 | this.client = client; 89 | } 90 | 91 | componentWillUnmount() { 92 | this.server = null; 93 | this.client = null; 94 | } 95 | 96 | render() { 97 | return ( 98 | 99 | 100 | {this.state.chatter.map((msg, index) => { 101 | return ( 102 | 103 | {msg} 104 | 105 | ); 106 | })} 107 | 108 | 109 | ); 110 | } 111 | } 112 | 113 | const styles = StyleSheet.create({ 114 | container: { 115 | flex: 1, 116 | justifyContent: 'center', 117 | alignItems: 'center', 118 | backgroundColor: '#F5FCFF', 119 | }, 120 | welcome: { 121 | fontSize: 20, 122 | textAlign: 'center', 123 | margin: 10, 124 | }, 125 | instructions: { 126 | textAlign: 'center', 127 | color: '#333333', 128 | marginBottom: 5, 129 | }, 130 | }); 131 | 132 | AppRegistry.registerComponent('rctsockets', () => RctSockets); 133 | -------------------------------------------------------------------------------- /examples/rctsockets/index.ios.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * @flow 5 | */ 6 | import './shim'; 7 | 8 | import React, { Component } from 'react'; 9 | import { 10 | AppRegistry, 11 | ScrollView, 12 | StyleSheet, 13 | Text, 14 | View 15 | } from 'react-native'; 16 | 17 | var net = require('net'); 18 | 19 | function randomPort() { 20 | return Math.random() * 60536 | 0 + 5000; // 60536-65536 21 | } 22 | 23 | var serverPort = randomPort(); 24 | 25 | class RctSockets extends Component { 26 | constructor(props) { 27 | super(props); 28 | 29 | this.updateChatter = this.updateChatter.bind(this); 30 | this.state = { chatter: [] }; 31 | } 32 | 33 | updateChatter(msg) { 34 | this.setState({ 35 | chatter: this.state.chatter.concat([msg]) 36 | }); 37 | } 38 | 39 | componentDidMount() { 40 | let server = net.createServer((socket) => { 41 | this.updateChatter('server connected on ' + JSON.stringify(socket.address())); 42 | 43 | socket.on('data', (data) => { 44 | this.updateChatter('Server Received: ' + data); 45 | socket.write('Echo server\r\n'); 46 | }); 47 | 48 | socket.on('error', (error) => { 49 | this.updateChatter('error ' + error); 50 | }); 51 | 52 | socket.on('close', (error) => { 53 | this.updateChatter('server client closed ' + (error ? error : '')); 54 | }); 55 | }).listen(serverPort, () => { 56 | this.updateChatter('opened server on ' + JSON.stringify(server.address())); 57 | }); 58 | 59 | server.on('error', (error) => { 60 | this.updateChatter('error ' + error); 61 | }); 62 | 63 | server.on('close', () => { 64 | this.updateChatter('server close'); 65 | }); 66 | 67 | let client = net.createConnection(serverPort, () => { 68 | this.updateChatter('opened client on ' + JSON.stringify(client.address())); 69 | client.write('Hello, server! Love, Client.'); 70 | }); 71 | 72 | client.on('data', (data) => { 73 | this.updateChatter('Client Received: ' + data); 74 | 75 | this.client.destroy(); // kill client after server's response 76 | this.server.close(); 77 | }); 78 | 79 | client.on('error', (error) => { 80 | this.updateChatter('client error ' + error); 81 | }); 82 | 83 | client.on('close', () => { 84 | this.updateChatter('client close'); 85 | }); 86 | 87 | this.server = server; 88 | this.client = client; 89 | } 90 | 91 | componentWillUnmount() { 92 | this.server = null; 93 | this.client = null; 94 | } 95 | 96 | render() { 97 | return ( 98 | 99 | 100 | {this.state.chatter.map((msg, index) => { 101 | return ( 102 | 103 | {msg} 104 | 105 | ); 106 | })} 107 | 108 | 109 | ); 110 | } 111 | } 112 | 113 | const styles = StyleSheet.create({ 114 | container: { 115 | flex: 1, 116 | justifyContent: 'center', 117 | alignItems: 'center', 118 | backgroundColor: '#F5FCFF', 119 | }, 120 | welcome: { 121 | fontSize: 20, 122 | textAlign: 'center', 123 | margin: 10, 124 | }, 125 | instructions: { 126 | textAlign: 'center', 127 | color: '#333333', 128 | marginBottom: 5, 129 | }, 130 | }); 131 | 132 | AppRegistry.registerComponent('rctsockets', () => RctSockets); 133 | -------------------------------------------------------------------------------- /examples/rctsockets/ios/rctsockets.xcodeproj/xcshareddata/xcschemes/rctsockets.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /examples/rctsockets/ios/rctsockets/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (nonatomic, strong) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /examples/rctsockets/ios/rctsockets/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "AppDelegate.h" 11 | 12 | #import 13 | #import 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 18 | { 19 | NSURL *jsCodeLocation; 20 | 21 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; 22 | 23 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 24 | moduleName:@"rctsockets" 25 | initialProperties:nil 26 | launchOptions:launchOptions]; 27 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 28 | 29 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 30 | UIViewController *rootViewController = [UIViewController new]; 31 | rootViewController.view = rootView; 32 | self.window.rootViewController = rootViewController; 33 | [self.window makeKeyAndVisible]; 34 | return YES; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /examples/rctsockets/ios/rctsockets/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/rctsockets/ios/rctsockets/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /examples/rctsockets/ios/rctsockets/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UIViewControllerBasedStatusBarAppearance 38 | 39 | NSLocationWhenInUseUsageDescription 40 | 41 | NSAppTransportSecurity 42 | 43 | 44 | NSExceptionDomains 45 | 46 | localhost 47 | 48 | NSExceptionAllowsInsecureHTTPLoads 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /examples/rctsockets/ios/rctsockets/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/rctsockets/ios/rctsocketsTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/rctsockets/ios/rctsocketsTests/rctsocketsTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import 12 | 13 | #import 14 | #import 15 | 16 | #define TIMEOUT_SECONDS 600 17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!" 18 | 19 | @interface rctsocketsTests : XCTestCase 20 | 21 | @end 22 | 23 | @implementation rctsocketsTests 24 | 25 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 26 | { 27 | if (test(view)) { 28 | return YES; 29 | } 30 | for (UIView *subview in [view subviews]) { 31 | if ([self findSubviewInView:subview matching:test]) { 32 | return YES; 33 | } 34 | } 35 | return NO; 36 | } 37 | 38 | - (void)testRendersWelcomeScreen 39 | { 40 | UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; 41 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 42 | BOOL foundElement = NO; 43 | 44 | __block NSString *redboxError = nil; 45 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 46 | if (level >= RCTLogLevelError) { 47 | redboxError = message; 48 | } 49 | }); 50 | 51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 54 | 55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 57 | return YES; 58 | } 59 | return NO; 60 | }]; 61 | } 62 | 63 | RCTSetLogFunction(RCTDefaultLogFunction); 64 | 65 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 66 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /examples/rctsockets/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rctsockets", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node node_modules/react-native/local-cli/cli.js start", 7 | "test": "jest", 8 | "postinstall": "rn-nodeify --install stream,process,util --hack" 9 | }, 10 | "browser": { 11 | "net": "react-native-tcp", 12 | "_stream_transform": "readable-stream/transform", 13 | "_stream_readable": "readable-stream/readable", 14 | "_stream_writable": "readable-stream/writable", 15 | "_stream_duplex": "readable-stream/duplex", 16 | "_stream_passthrough": "readable-stream/passthrough", 17 | "stream": "stream-browserify" 18 | }, 19 | "dependencies": { 20 | "process": "^0.11.9", 21 | "react": "15.4.2", 22 | "react-native": "^0.40.0", 23 | "react-native-tcp": "../../", 24 | "readable-stream": "^1.0.33", 25 | "stream-browserify": "^1.0.0" 26 | }, 27 | "devDependencies": { 28 | "babel-jest": "18.0.0", 29 | "babel-preset-react-native": "1.9.1", 30 | "jest": "18.1.0", 31 | "react-test-renderer": "15.4.2", 32 | "rn-nodeify": "^7.0.1" 33 | }, 34 | "jest": { 35 | "preset": "react-native" 36 | }, 37 | "react-native": { 38 | "net": "react-native-tcp", 39 | "_stream_transform": "readable-stream/transform", 40 | "_stream_readable": "readable-stream/readable", 41 | "_stream_writable": "readable-stream/writable", 42 | "_stream_duplex": "readable-stream/duplex", 43 | "_stream_passthrough": "readable-stream/passthrough", 44 | "stream": "stream-browserify" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/rctsockets/shim.js: -------------------------------------------------------------------------------- 1 | if (typeof __dirname === 'undefined') global.__dirname = '/' 2 | if (typeof __filename === 'undefined') global.__filename = '' 3 | if (typeof process === 'undefined') { 4 | global.process = require('process') 5 | } else { 6 | var bProcess = require('process') 7 | for (var p in bProcess) { 8 | if (!(p in process)) { 9 | process[p] = bProcess[p] 10 | } 11 | } 12 | } 13 | 14 | process.browser = false 15 | if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer 16 | 17 | // global.location = global.location || { port: 80 } 18 | var isDev = typeof __DEV__ === 'boolean' && __DEV__ 19 | process.env['NODE_ENV'] = isDev ? 'development' : 'production' 20 | if (typeof localStorage !== 'undefined') { 21 | localStorage.debug = isDev ? '*' : '' 22 | } 23 | -------------------------------------------------------------------------------- /interfaces/interface.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Peel Technologies, Inc. 3 | * All rights reserved. 4 | * 5 | * @flow 6 | */ 7 | 8 | declare var __DEV__: boolean; 9 | 10 | declare module 'react-native' { 11 | declare var NativeModules: any; 12 | declare var DeviceEventEmitter: any; 13 | } 14 | -------------------------------------------------------------------------------- /ios/TcpSocketClient.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Peel Technologies, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import "CocoaAsyncSocket/GCDAsyncSocket.h" 8 | 9 | extern NSString *const RCTTCPErrorDomain; 10 | 11 | enum RCTTCPError 12 | { 13 | RCTTCPNoError = 0, // Never used 14 | RCTTCPInvalidInvocationError,// Invalid method invocation 15 | RCTTCPBadConfigError, // Invalid configuration 16 | RCTTCPBadParamError, // Invalid parameter was passed 17 | RCTTCPSendTimeoutError, // A send operation timed out 18 | RCTTCPSendFailedError, // A send operation failed 19 | RCTTCPClosedError, // The socket was closed 20 | RCTTCPOtherError, // Description provided in userInfo 21 | }; 22 | 23 | typedef enum RCTTCPError RCTTCPError; 24 | 25 | @class TcpSocketClient; 26 | 27 | @protocol SocketClientDelegate 28 | 29 | - (void)onConnect:(TcpSocketClient*)client; 30 | - (void)onConnection:(TcpSocketClient*)client toClient:(NSNumber *)clientID; 31 | - (void)onData:(NSNumber *)clientID data:(NSData *)data; 32 | - (void)onClose:(TcpSocketClient*)client withError:(NSError *)err; 33 | - (void)onError:(TcpSocketClient*)client withError:(NSError *)err; 34 | - (NSNumber*)getNextTag; 35 | - (void)setPendingSend:(RCTResponseSenderBlock)callback forKey:(NSNumber *)key; 36 | - (RCTResponseSenderBlock)getPendingSend:(NSNumber *)key; 37 | - (void)dropPendingSend:(NSNumber *)key; 38 | - (NSNumber*)getNextId; 39 | 40 | @end 41 | 42 | @interface TcpSocketClient : NSObject 43 | 44 | @property (nonatomic, retain) NSNumber * id; 45 | @property (nonatomic, weak) id clientDelegate; 46 | 47 | ///--------------------------------------------------------------------------------------- 48 | /// @name Class Methods 49 | ///--------------------------------------------------------------------------------------- 50 | /** 51 | * Initializes a new RCTTCPClient 52 | * 53 | * @param delegate The object holding the callbacks, usually 'self'. 54 | * 55 | * @return New RCTTCPClient 56 | */ 57 | 58 | + (id)socketClientWithId:(NSNumber *)clientID andConfig:(id) delegate; 59 | 60 | ///--------------------------------------------------------------------------------------- 61 | /// @name Instance Methods 62 | ///--------------------------------------------------------------------------------------- 63 | /** 64 | * Connects to a host and port 65 | * 66 | * @param port 67 | * @param host ip address 68 | * @param options NSDictionary which can have @"localAddress" and @"localPort" to specify the local interface 69 | * @return true if connected, false if there was an error 70 | */ 71 | - (BOOL)connect:(NSString *)host port:(int)port withOptions:(NSDictionary *)options error:(NSError **)error; 72 | 73 | /** 74 | * Starts listening on a local host and port 75 | * 76 | * @param local ip address 77 | * @param local port 78 | * @return true if connected, false if there was an error 79 | */ 80 | - (BOOL)listen:(NSString *)host port:(int)port error:(NSError **)error; 81 | 82 | /** 83 | * Returns the address information 84 | * 85 | * @return NSDictionary with @"address" host, @"port" port, @"family" IPv4/IPv6 86 | */ 87 | - (NSDictionary *)getAddress; 88 | 89 | /** 90 | * write data 91 | * 92 | */ 93 | - (void)writeData:(NSData*) data callback:(RCTResponseSenderBlock) callback; 94 | 95 | /** 96 | * end client 97 | */ 98 | - (void)end; 99 | 100 | /** 101 | * destroy client 102 | */ 103 | - (void)destroy; 104 | 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /ios/TcpSocketClient.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Peel Technologies, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import 8 | #import "TcpSocketClient.h" 9 | 10 | #import 11 | 12 | NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain"; 13 | 14 | @interface TcpSocketClient() 15 | { 16 | @private 17 | GCDAsyncSocket *_tcpSocket; 18 | } 19 | 20 | - (id)initWithClientId:(NSNumber *)clientID andConfig:(id)aDelegate; 21 | - (id)initWithClientId:(NSNumber *)clientID andConfig:(id)aDelegate andSocket:(GCDAsyncSocket*)tcpSocket; 22 | 23 | @end 24 | 25 | @implementation TcpSocketClient 26 | 27 | + (id)socketClientWithId:(nonnull NSNumber *)clientID andConfig:(id)delegate 28 | { 29 | return [[[self class] alloc] initWithClientId:clientID andConfig:delegate andSocket:nil]; 30 | } 31 | 32 | - (id)initWithClientId:(NSNumber *)clientID andConfig:(id)aDelegate 33 | { 34 | return [self initWithClientId:clientID andConfig:aDelegate andSocket:nil]; 35 | } 36 | 37 | - (id)initWithClientId:(NSNumber *)clientID andConfig:(id)aDelegate andSocket:(GCDAsyncSocket*)tcpSocket; 38 | { 39 | self = [super init]; 40 | if (self) { 41 | _id = clientID; 42 | _clientDelegate = aDelegate; 43 | _tcpSocket = tcpSocket; 44 | [_tcpSocket setUserData: clientID]; 45 | } 46 | 47 | return self; 48 | } 49 | 50 | - (BOOL)connect:(NSString *)host port:(int)port withOptions:(NSDictionary *)options error:(NSError **)error 51 | { 52 | if (_tcpSocket) { 53 | if (error) { 54 | *error = [self badInvocationError:@"this client's socket is already connected"]; 55 | } 56 | 57 | return false; 58 | } 59 | 60 | _tcpSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:[self methodQueue]]; 61 | [_tcpSocket setUserData: _id]; 62 | 63 | BOOL result = false; 64 | 65 | NSString *localAddress = (options?options[@"localAddress"]:nil); 66 | NSNumber *localPort = (options?options[@"localPort"]:nil); 67 | 68 | if (!localAddress && !localPort) { 69 | result = [_tcpSocket connectToHost:host onPort:port error:error]; 70 | } else { 71 | NSMutableArray *interface = [NSMutableArray arrayWithCapacity:2]; 72 | [interface addObject: localAddress?localAddress:@""]; 73 | if (localPort) { 74 | [interface addObject:[localPort stringValue]]; 75 | } 76 | result = [_tcpSocket connectToHost:host 77 | onPort:port 78 | viaInterface:[interface componentsJoinedByString:@":"] 79 | withTimeout:-1 80 | error:error]; 81 | } 82 | 83 | return result; 84 | } 85 | 86 | - (NSDictionary *)getAddress 87 | { 88 | if (_tcpSocket) 89 | { 90 | if (_tcpSocket.isConnected) { 91 | return @{ @"port": @(_tcpSocket.connectedPort), 92 | @"address": _tcpSocket.connectedHost ?: @"unknown", 93 | @"family": _tcpSocket.isIPv6?@"IPv6":@"IPv4" }; 94 | } else { 95 | return @{ @"port": @(_tcpSocket.localPort), 96 | @"address": _tcpSocket.localHost ?: @"unknown", 97 | @"family": _tcpSocket.isIPv6?@"IPv6":@"IPv4" }; 98 | } 99 | } 100 | 101 | return @{ @"port": @(0), 102 | @"address": @"unknown", 103 | @"family": @"unkown" }; 104 | } 105 | 106 | - (BOOL)listen:(NSString *)host port:(int)port error:(NSError **)error 107 | { 108 | if (_tcpSocket) { 109 | if (error) { 110 | *error = [self badInvocationError:@"this client's socket is already connected"]; 111 | } 112 | 113 | return false; 114 | } 115 | 116 | _tcpSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:[self methodQueue]]; 117 | [_tcpSocket setUserData: _id]; 118 | 119 | // GCDAsyncSocket doesn't recognize 0.0.0.0 120 | if ([@"0.0.0.0" isEqualToString: host]) { 121 | host = nil; 122 | } 123 | BOOL isListening = [_tcpSocket acceptOnInterface:host port:port error:error]; 124 | if (isListening == YES) { 125 | [_clientDelegate onConnect: self]; 126 | [_tcpSocket readDataWithTimeout:-1 tag:_id.longValue]; 127 | } 128 | 129 | return isListening; 130 | } 131 | 132 | - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)msgTag 133 | { 134 | NSNumber* tagNum = [NSNumber numberWithLong:msgTag]; 135 | RCTResponseSenderBlock callback = [_clientDelegate getPendingSend:tagNum]; 136 | if (callback) { 137 | callback(@[]); 138 | [_clientDelegate dropPendingSend:tagNum]; 139 | } 140 | } 141 | 142 | - (void) writeData:(NSData *)data 143 | callback:(RCTResponseSenderBlock)callback 144 | { 145 | NSNumber *sendTag = [_clientDelegate getNextTag]; 146 | if (callback) { 147 | [_clientDelegate setPendingSend:callback forKey:sendTag]; 148 | } 149 | [_tcpSocket writeData:data withTimeout:-1 tag:sendTag.longValue]; 150 | 151 | [_tcpSocket readDataWithTimeout:-1 tag:_id.longValue]; 152 | } 153 | 154 | - (void)end 155 | { 156 | [_tcpSocket disconnectAfterWriting]; 157 | } 158 | 159 | - (void)destroy 160 | { 161 | [_tcpSocket disconnect]; 162 | } 163 | 164 | - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { 165 | if (!_clientDelegate) { 166 | RCTLogWarn(@"didReadData with nil clientDelegate for %@", [sock userData]); 167 | return; 168 | } 169 | 170 | [_clientDelegate onData:@(tag) data:data]; 171 | 172 | [sock readDataWithTimeout:-1 tag:tag]; 173 | } 174 | 175 | - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket 176 | { 177 | TcpSocketClient *inComing = [[TcpSocketClient alloc] initWithClientId:[_clientDelegate getNextId] 178 | andConfig:_clientDelegate 179 | andSocket:newSocket]; 180 | [_clientDelegate onConnection: inComing 181 | toClient: _id]; 182 | [newSocket readDataWithTimeout:-1 tag:inComing.id.longValue]; 183 | } 184 | 185 | - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port 186 | { 187 | if (!_clientDelegate) { 188 | RCTLogWarn(@"didConnectToHost with nil clientDelegate for %@", [sock userData]); 189 | return; 190 | } 191 | 192 | [_clientDelegate onConnect:self]; 193 | 194 | [sock readDataWithTimeout:-1 tag:_id.longValue]; 195 | } 196 | 197 | - (void)socketDidCloseReadStream:(GCDAsyncSocket *)sock 198 | { 199 | // TODO : investigate for half-closed sockets 200 | // for now close the stream completely 201 | [sock disconnect]; 202 | } 203 | 204 | - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err 205 | { 206 | if (!_clientDelegate) { 207 | RCTLogWarn(@"socketDidDisconnect with nil clientDelegate for %@", [sock userData]); 208 | return; 209 | } 210 | 211 | [_clientDelegate onClose:[sock userData] withError:(!err || err.code == GCDAsyncSocketClosedError ? nil : err)]; 212 | } 213 | 214 | - (NSError *)badInvocationError:(NSString *)errMsg 215 | { 216 | NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; 217 | 218 | return [NSError errorWithDomain:RCTTCPErrorDomain 219 | code:RCTTCPInvalidInvocationError 220 | userInfo:userInfo]; 221 | } 222 | 223 | - (dispatch_queue_t)methodQueue 224 | { 225 | return dispatch_get_main_queue(); 226 | } 227 | 228 | @end 229 | -------------------------------------------------------------------------------- /ios/TcpSockets.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Peel Technologies, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import "TcpSocketClient.h" 7 | 8 | #import 9 | #import "CocoaAsyncSocket/GCDAsyncSocket.h" 10 | 11 | @interface TcpSockets : RCTEventEmitter 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ios/TcpSockets.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Peel Technologies, Inc. 3 | * All rights reserved. 4 | */ 5 | 6 | #import 7 | #import 8 | #import 9 | #import 10 | 11 | #import "TcpSockets.h" 12 | #import "TcpSocketClient.h" 13 | 14 | // offset native ids by 5000 15 | #define COUNTER_OFFSET 5000 16 | 17 | @interface TcpSockets() { 18 | 19 | @private 20 | NSMutableDictionary *_pendingSends; 21 | NSLock *_lock; 22 | long _tag; 23 | } 24 | @end 25 | 26 | @implementation TcpSockets 27 | { 28 | NSMutableDictionary *_clients; 29 | int _counter; 30 | } 31 | 32 | RCT_EXPORT_MODULE() 33 | 34 | - (id)init { 35 | self = [super init]; 36 | if (self) { 37 | _pendingSends = [NSMutableDictionary dictionary]; 38 | _lock = [[NSLock alloc] init]; 39 | } 40 | return self; 41 | } 42 | 43 | - (NSNumber*)getNextTag { 44 | return [NSNumber numberWithLong:_tag++]; 45 | } 46 | 47 | - (NSArray *)supportedEvents 48 | { 49 | return @[@"connect", 50 | @"connection", 51 | @"data", 52 | @"close", 53 | @"error"]; 54 | } 55 | 56 | - (void)startObserving { 57 | // Does nothing 58 | } 59 | 60 | - (void)stopObserving { 61 | // Does nothing 62 | } 63 | 64 | -(void)dealloc 65 | { 66 | for (NSNumber *cId in _clients.allKeys) { 67 | [self destroyClient:cId]; 68 | } 69 | } 70 | 71 | - (TcpSocketClient *)createSocket:(nonnull NSNumber*)cId 72 | { 73 | if (!cId) { 74 | RCTLogWarn(@"%@.createSocket called with nil id parameter.", [self class]); 75 | return nil; 76 | } 77 | 78 | if (!_clients) { 79 | _clients = [NSMutableDictionary new]; 80 | } 81 | 82 | if (_clients[cId]) { 83 | RCTLogWarn(@"%@.createSocket called twice with the same id.", [self class]); 84 | return nil; 85 | } 86 | 87 | _clients[cId] = [TcpSocketClient socketClientWithId:cId andConfig:self]; 88 | 89 | return _clients[cId]; 90 | } 91 | 92 | RCT_EXPORT_METHOD(connect:(nonnull NSNumber*)cId 93 | host:(NSString *)host 94 | port:(int)port 95 | withOptions:(NSDictionary *)options) 96 | { 97 | TcpSocketClient *client = _clients[cId]; 98 | if (!client) { 99 | client = [self createSocket:cId]; 100 | } 101 | 102 | NSError *error = nil; 103 | if (![client connect:host port:port withOptions:options error:&error]) 104 | { 105 | [self onError:client withError:error]; 106 | return; 107 | } 108 | } 109 | 110 | RCT_EXPORT_METHOD(write:(nonnull NSNumber*)cId 111 | string:(NSString *)base64String 112 | callback:(RCTResponseSenderBlock)callback) { 113 | TcpSocketClient* client = [self findClient:cId]; 114 | if (!client) return; 115 | 116 | // iOS7+ 117 | // TODO: use https://github.com/nicklockwood/Base64 for compatibility with earlier iOS versions 118 | NSData *data = [[NSData alloc] initWithBase64EncodedString:base64String options:0]; 119 | [client writeData:data callback:callback]; 120 | } 121 | 122 | RCT_EXPORT_METHOD(end:(nonnull NSNumber*)cId) { 123 | [self endClient:cId]; 124 | } 125 | 126 | RCT_EXPORT_METHOD(destroy:(nonnull NSNumber*)cId) { 127 | [self destroyClient:cId]; 128 | } 129 | 130 | RCT_EXPORT_METHOD(listen:(nonnull NSNumber*)cId 131 | host:(NSString *)host 132 | port:(int)port) 133 | { 134 | TcpSocketClient* client = _clients[cId]; 135 | if (!client) { 136 | client = [self createSocket:cId]; 137 | } 138 | 139 | NSError *error = nil; 140 | if (![client listen:host port:port error:&error]) 141 | { 142 | [self onError:client withError:error]; 143 | return; 144 | } 145 | } 146 | 147 | - (void)onConnect:(TcpSocketClient*) client 148 | { 149 | [self sendEventWithName:@"connect" 150 | body:@{ @"id": client.id, @"address" : [client getAddress] }]; 151 | } 152 | 153 | -(void)onConnection:(TcpSocketClient *)client toClient:(NSNumber *)clientID { 154 | _clients[client.id] = client; 155 | 156 | [self sendEventWithName:@"connection" 157 | body:@{ @"id": clientID, @"info": @{ @"id": client.id, @"address" : [client getAddress] } }]; 158 | } 159 | 160 | - (void)onData:(NSNumber *)clientID data:(NSData *)data 161 | { 162 | NSString *base64String = [data base64EncodedStringWithOptions:0]; 163 | [self sendEventWithName:@"data" 164 | body:@{ @"id": clientID, @"data" : base64String }]; 165 | } 166 | 167 | - (void)onClose:(NSNumber*) clientID withError:(NSError *)err 168 | { 169 | TcpSocketClient* client = [self findClient:clientID]; 170 | if (!client) { 171 | RCTLogWarn(@"onClose: unrecognized client id %@", clientID); 172 | } 173 | 174 | if (err) { 175 | [self onError:client withError:err]; 176 | } 177 | 178 | [self sendEventWithName:@"close" 179 | body:@{ @"id": clientID, @"hadError": err == nil ? @NO : @YES }]; 180 | 181 | [_clients removeObjectForKey:clientID]; 182 | } 183 | 184 | - (void)onError:(TcpSocketClient*) client withError:(NSError *)err { 185 | NSString *msg = err.localizedFailureReason ?: err.localizedDescription; 186 | [self sendEventWithName:@"error" 187 | body:@{ @"id": client.id, @"error": msg }]; 188 | 189 | } 190 | 191 | -(TcpSocketClient*)findClient:(nonnull NSNumber*)cId 192 | { 193 | TcpSocketClient *client = _clients[cId]; 194 | if (!client) { 195 | NSString *msg = [NSString stringWithFormat:@"no client found with id %@", cId]; 196 | [self sendEventWithName:@"error" 197 | body:@{ @"id": cId, @"error": msg }]; 198 | 199 | return nil; 200 | } 201 | 202 | return client; 203 | } 204 | 205 | -(void)endClient:(nonnull NSNumber*)cId 206 | { 207 | TcpSocketClient* client = [self findClient:cId]; 208 | if (!client) return; 209 | 210 | [client end]; 211 | } 212 | 213 | -(void)destroyClient:(nonnull NSNumber*)cId 214 | { 215 | TcpSocketClient* client = [self findClient:cId]; 216 | if (!client) return; 217 | 218 | [client destroy]; 219 | } 220 | 221 | -(NSNumber*)getNextId { 222 | return @(_counter++ + COUNTER_OFFSET); 223 | } 224 | 225 | - (void)setPendingSend:(RCTResponseSenderBlock)callback forKey:(NSNumber *)key 226 | { 227 | [_lock lock]; 228 | @try { 229 | [_pendingSends setObject:callback forKey:key]; 230 | } 231 | @finally { 232 | [_lock unlock]; 233 | } 234 | } 235 | 236 | - (RCTResponseSenderBlock)getPendingSend:(NSNumber *)key 237 | { 238 | [_lock lock]; 239 | @try { 240 | return [_pendingSends objectForKey:key]; 241 | } 242 | @finally { 243 | [_lock unlock]; 244 | } 245 | } 246 | 247 | - (void)dropPendingSend:(NSNumber *)key 248 | { 249 | [_lock lock]; 250 | @try { 251 | [_pendingSends removeObjectForKey:key]; 252 | } 253 | @finally { 254 | [_lock unlock]; 255 | } 256 | } 257 | 258 | @end 259 | -------------------------------------------------------------------------------- /ios/TcpSockets.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 13BE3DEE1AC21097009241FE /* TcpSockets.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* TcpSockets.m */; }; 11 | 7350006B1AFF9AB600ED3C82 /* TcpSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 7350006A1AFF9AB600ED3C82 /* TcpSocketClient.m */; }; 12 | 73D9377D1AFF9EBE00450142 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73D9377C1AFF9EBE00450142 /* CFNetwork.framework */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXCopyFilesBuildPhase section */ 16 | 58B511D91A9E6C8500147676 /* CopyFiles */ = { 17 | isa = PBXCopyFilesBuildPhase; 18 | buildActionMask = 2147483647; 19 | dstPath = "include/$(PRODUCT_NAME)"; 20 | dstSubfolderSpec = 16; 21 | files = ( 22 | ); 23 | runOnlyForDeploymentPostprocessing = 0; 24 | }; 25 | /* End PBXCopyFilesBuildPhase section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 134814201AA4EA6300B7C361 /* libTcpSockets.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTcpSockets.a; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | 13BE3DEC1AC21097009241FE /* TcpSockets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TcpSockets.h; sourceTree = ""; }; 30 | 13BE3DED1AC21097009241FE /* TcpSockets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TcpSockets.m; sourceTree = ""; }; 31 | 735000691AFF9AB600ED3C82 /* TcpSocketClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TcpSocketClient.h; sourceTree = ""; }; 32 | 7350006A1AFF9AB600ED3C82 /* TcpSocketClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TcpSocketClient.m; sourceTree = ""; }; 33 | 73D9377C1AFF9EBE00450142 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 58B511D81A9E6C8500147676 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | 73D9377D1AFF9EBE00450142 /* CFNetwork.framework in Frameworks */, 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | 134814211AA4EA7D00B7C361 /* Products */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | 134814201AA4EA6300B7C361 /* libTcpSockets.a */, 52 | ); 53 | name = Products; 54 | sourceTree = ""; 55 | }; 56 | 58B511D21A9E6C8500147676 = { 57 | isa = PBXGroup; 58 | children = ( 59 | 73D9377C1AFF9EBE00450142 /* CFNetwork.framework */, 60 | 735000691AFF9AB600ED3C82 /* TcpSocketClient.h */, 61 | 7350006A1AFF9AB600ED3C82 /* TcpSocketClient.m */, 62 | 13BE3DEC1AC21097009241FE /* TcpSockets.h */, 63 | 13BE3DED1AC21097009241FE /* TcpSockets.m */, 64 | 96EDB0A91C10C33B00D41E94 /* CocoaAsyncSocket */, 65 | 134814211AA4EA7D00B7C361 /* Products */, 66 | ); 67 | sourceTree = ""; 68 | }; 69 | 96EDB0A91C10C33B00D41E94 /* CocoaAsyncSocket */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 96EDB0AA1C10C33B00D41E94 /* GCDAsyncSocket.h */, 73 | 96EDB0AB1C10C33B00D41E94 /* GCDAsyncSocket.m */, 74 | ); 75 | path = CocoaAsyncSocket; 76 | sourceTree = ""; 77 | }; 78 | /* End PBXGroup section */ 79 | 80 | /* Begin PBXNativeTarget section */ 81 | 58B511DA1A9E6C8500147676 /* TcpSockets */ = { 82 | isa = PBXNativeTarget; 83 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "TcpSockets" */; 84 | buildPhases = ( 85 | 58B511D71A9E6C8500147676 /* Sources */, 86 | 58B511D81A9E6C8500147676 /* Frameworks */, 87 | 58B511D91A9E6C8500147676 /* CopyFiles */, 88 | ); 89 | buildRules = ( 90 | ); 91 | dependencies = ( 92 | ); 93 | name = TcpSockets; 94 | productName = RCTDataManager; 95 | productReference = 134814201AA4EA6300B7C361 /* libTcpSockets.a */; 96 | productType = "com.apple.product-type.library.static"; 97 | }; 98 | /* End PBXNativeTarget section */ 99 | 100 | /* Begin PBXProject section */ 101 | 58B511D31A9E6C8500147676 /* Project object */ = { 102 | isa = PBXProject; 103 | attributes = { 104 | LastUpgradeCheck = 0720; 105 | ORGANIZATIONNAME = "Peel, Inc."; 106 | TargetAttributes = { 107 | 58B511DA1A9E6C8500147676 = { 108 | CreatedOnToolsVersion = 6.1.1; 109 | }; 110 | }; 111 | }; 112 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "TcpSockets" */; 113 | compatibilityVersion = "Xcode 3.2"; 114 | developmentRegion = English; 115 | hasScannedForEncodings = 0; 116 | knownRegions = ( 117 | en, 118 | ); 119 | mainGroup = 58B511D21A9E6C8500147676; 120 | productRefGroup = 58B511D21A9E6C8500147676; 121 | projectDirPath = ""; 122 | projectRoot = ""; 123 | targets = ( 124 | 58B511DA1A9E6C8500147676 /* TcpSockets */, 125 | ); 126 | }; 127 | /* End PBXProject section */ 128 | 129 | /* Begin PBXSourcesBuildPhase section */ 130 | 58B511D71A9E6C8500147676 /* Sources */ = { 131 | isa = PBXSourcesBuildPhase; 132 | buildActionMask = 2147483647; 133 | files = ( 134 | 7350006B1AFF9AB600ED3C82 /* TcpSocketClient.m in Sources */, 135 | 13BE3DEE1AC21097009241FE /* TcpSockets.m in Sources */, 136 | ); 137 | runOnlyForDeploymentPostprocessing = 0; 138 | }; 139 | /* End PBXSourcesBuildPhase section */ 140 | 141 | /* Begin XCBuildConfiguration section */ 142 | 58B511ED1A9E6C8500147676 /* Debug */ = { 143 | isa = XCBuildConfiguration; 144 | buildSettings = { 145 | ALWAYS_SEARCH_USER_PATHS = NO; 146 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 147 | CLANG_CXX_LIBRARY = "libc++"; 148 | CLANG_ENABLE_MODULES = YES; 149 | CLANG_ENABLE_OBJC_ARC = YES; 150 | CLANG_WARN_BOOL_CONVERSION = YES; 151 | CLANG_WARN_CONSTANT_CONVERSION = YES; 152 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 153 | CLANG_WARN_EMPTY_BODY = YES; 154 | CLANG_WARN_ENUM_CONVERSION = YES; 155 | CLANG_WARN_INT_CONVERSION = YES; 156 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 157 | CLANG_WARN_UNREACHABLE_CODE = YES; 158 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 159 | COPY_PHASE_STRIP = NO; 160 | ENABLE_STRICT_OBJC_MSGSEND = YES; 161 | ENABLE_TESTABILITY = YES; 162 | GCC_C_LANGUAGE_STANDARD = gnu99; 163 | GCC_DYNAMIC_NO_PIC = NO; 164 | GCC_OPTIMIZATION_LEVEL = 0; 165 | GCC_PREPROCESSOR_DEFINITIONS = ( 166 | "DEBUG=1", 167 | "$(inherited)", 168 | ); 169 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 170 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 171 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 172 | GCC_WARN_UNDECLARED_SELECTOR = YES; 173 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 174 | GCC_WARN_UNUSED_FUNCTION = YES; 175 | GCC_WARN_UNUSED_VARIABLE = YES; 176 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 177 | MTL_ENABLE_DEBUG_INFO = YES; 178 | ONLY_ACTIVE_ARCH = YES; 179 | SDKROOT = iphoneos; 180 | }; 181 | name = Debug; 182 | }; 183 | 58B511EE1A9E6C8500147676 /* Release */ = { 184 | isa = XCBuildConfiguration; 185 | buildSettings = { 186 | ALWAYS_SEARCH_USER_PATHS = NO; 187 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 188 | CLANG_CXX_LIBRARY = "libc++"; 189 | CLANG_ENABLE_MODULES = YES; 190 | CLANG_ENABLE_OBJC_ARC = YES; 191 | CLANG_WARN_BOOL_CONVERSION = YES; 192 | CLANG_WARN_CONSTANT_CONVERSION = YES; 193 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 194 | CLANG_WARN_EMPTY_BODY = YES; 195 | CLANG_WARN_ENUM_CONVERSION = YES; 196 | CLANG_WARN_INT_CONVERSION = YES; 197 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 198 | CLANG_WARN_UNREACHABLE_CODE = YES; 199 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 200 | COPY_PHASE_STRIP = YES; 201 | ENABLE_NS_ASSERTIONS = NO; 202 | ENABLE_STRICT_OBJC_MSGSEND = YES; 203 | GCC_C_LANGUAGE_STANDARD = gnu99; 204 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 205 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 206 | GCC_WARN_UNDECLARED_SELECTOR = YES; 207 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 208 | GCC_WARN_UNUSED_FUNCTION = YES; 209 | GCC_WARN_UNUSED_VARIABLE = YES; 210 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 211 | MTL_ENABLE_DEBUG_INFO = NO; 212 | SDKROOT = iphoneos; 213 | VALIDATE_PRODUCT = YES; 214 | }; 215 | name = Release; 216 | }; 217 | 58B511F01A9E6C8500147676 /* Debug */ = { 218 | isa = XCBuildConfiguration; 219 | buildSettings = { 220 | HEADER_SEARCH_PATHS = ( 221 | "$(inherited)", 222 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 223 | "$(SRCROOT)/../../react-native/React/**", 224 | ); 225 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 226 | OTHER_LDFLAGS = "-ObjC"; 227 | PRODUCT_NAME = TcpSockets; 228 | SKIP_INSTALL = YES; 229 | USER_HEADER_SEARCH_PATHS = ""; 230 | }; 231 | name = Debug; 232 | }; 233 | 58B511F11A9E6C8500147676 /* Release */ = { 234 | isa = XCBuildConfiguration; 235 | buildSettings = { 236 | HEADER_SEARCH_PATHS = ( 237 | "$(inherited)", 238 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 239 | "$(SRCROOT)/../../react-native/React/**", 240 | ); 241 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 242 | OTHER_LDFLAGS = "-ObjC"; 243 | PRODUCT_NAME = TcpSockets; 244 | SKIP_INSTALL = YES; 245 | USER_HEADER_SEARCH_PATHS = ""; 246 | }; 247 | name = Release; 248 | }; 249 | /* End XCBuildConfiguration section */ 250 | 251 | /* Begin XCConfigurationList section */ 252 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "TcpSockets" */ = { 253 | isa = XCConfigurationList; 254 | buildConfigurations = ( 255 | 58B511ED1A9E6C8500147676 /* Debug */, 256 | 58B511EE1A9E6C8500147676 /* Release */, 257 | ); 258 | defaultConfigurationIsVisible = 0; 259 | defaultConfigurationName = Release; 260 | }; 261 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "TcpSockets" */ = { 262 | isa = XCConfigurationList; 263 | buildConfigurations = ( 264 | 58B511F01A9E6C8500147676 /* Debug */, 265 | 58B511F11A9E6C8500147676 /* Release */, 266 | ); 267 | defaultConfigurationIsVisible = 0; 268 | defaultConfigurationName = Release; 269 | }; 270 | /* End XCConfigurationList section */ 271 | }; 272 | rootObject = 58B511D31A9E6C8500147676 /* Project object */; 273 | } 274 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-tcp", 3 | "version": "3.3.2", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.5.5", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", 10 | "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.0.0" 14 | } 15 | }, 16 | "@babel/generator": { 17 | "version": "7.7.4", 18 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", 19 | "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", 20 | "dev": true, 21 | "requires": { 22 | "@babel/types": "^7.7.4", 23 | "jsesc": "^2.5.1", 24 | "lodash": "^4.17.13", 25 | "source-map": "^0.5.0" 26 | } 27 | }, 28 | "@babel/helper-function-name": { 29 | "version": "7.7.4", 30 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", 31 | "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", 32 | "dev": true, 33 | "requires": { 34 | "@babel/helper-get-function-arity": "^7.7.4", 35 | "@babel/template": "^7.7.4", 36 | "@babel/types": "^7.7.4" 37 | } 38 | }, 39 | "@babel/helper-get-function-arity": { 40 | "version": "7.7.4", 41 | "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", 42 | "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", 43 | "dev": true, 44 | "requires": { 45 | "@babel/types": "^7.7.4" 46 | } 47 | }, 48 | "@babel/helper-split-export-declaration": { 49 | "version": "7.7.4", 50 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", 51 | "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", 52 | "dev": true, 53 | "requires": { 54 | "@babel/types": "^7.7.4" 55 | } 56 | }, 57 | "@babel/highlight": { 58 | "version": "7.5.0", 59 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", 60 | "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", 61 | "dev": true, 62 | "requires": { 63 | "chalk": "^2.0.0", 64 | "esutils": "^2.0.2", 65 | "js-tokens": "^4.0.0" 66 | } 67 | }, 68 | "@babel/parser": { 69 | "version": "7.7.4", 70 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.4.tgz", 71 | "integrity": "sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==", 72 | "dev": true 73 | }, 74 | "@babel/template": { 75 | "version": "7.7.4", 76 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", 77 | "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", 78 | "dev": true, 79 | "requires": { 80 | "@babel/code-frame": "^7.0.0", 81 | "@babel/parser": "^7.7.4", 82 | "@babel/types": "^7.7.4" 83 | } 84 | }, 85 | "@babel/traverse": { 86 | "version": "7.7.4", 87 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", 88 | "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", 89 | "dev": true, 90 | "requires": { 91 | "@babel/code-frame": "^7.5.5", 92 | "@babel/generator": "^7.7.4", 93 | "@babel/helper-function-name": "^7.7.4", 94 | "@babel/helper-split-export-declaration": "^7.7.4", 95 | "@babel/parser": "^7.7.4", 96 | "@babel/types": "^7.7.4", 97 | "debug": "^4.1.0", 98 | "globals": "^11.1.0", 99 | "lodash": "^4.17.13" 100 | } 101 | }, 102 | "@babel/types": { 103 | "version": "7.7.4", 104 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", 105 | "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", 106 | "dev": true, 107 | "requires": { 108 | "esutils": "^2.0.2", 109 | "lodash": "^4.17.13", 110 | "to-fast-properties": "^2.0.0" 111 | } 112 | }, 113 | "ansi-styles": { 114 | "version": "3.2.1", 115 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 116 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 117 | "dev": true, 118 | "requires": { 119 | "color-convert": "^1.9.0" 120 | } 121 | }, 122 | "array-includes": { 123 | "version": "3.0.3", 124 | "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", 125 | "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", 126 | "dev": true, 127 | "requires": { 128 | "define-properties": "^1.1.2", 129 | "es-abstract": "^1.7.0" 130 | } 131 | }, 132 | "babel-eslint": { 133 | "version": "10.0.3", 134 | "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz", 135 | "integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==", 136 | "dev": true, 137 | "requires": { 138 | "@babel/code-frame": "^7.0.0", 139 | "@babel/parser": "^7.0.0", 140 | "@babel/traverse": "^7.0.0", 141 | "@babel/types": "^7.0.0", 142 | "eslint-visitor-keys": "^1.0.0", 143 | "resolve": "^1.12.0" 144 | } 145 | }, 146 | "base64-js": { 147 | "version": "1.3.1", 148 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", 149 | "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" 150 | }, 151 | "buffer": { 152 | "version": "5.4.3", 153 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", 154 | "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", 155 | "requires": { 156 | "base64-js": "^1.0.2", 157 | "ieee754": "^1.1.4" 158 | } 159 | }, 160 | "chalk": { 161 | "version": "2.4.2", 162 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 163 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 164 | "dev": true, 165 | "requires": { 166 | "ansi-styles": "^3.2.1", 167 | "escape-string-regexp": "^1.0.5", 168 | "supports-color": "^5.3.0" 169 | } 170 | }, 171 | "color-convert": { 172 | "version": "1.9.3", 173 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 174 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 175 | "dev": true, 176 | "requires": { 177 | "color-name": "1.1.3" 178 | } 179 | }, 180 | "color-name": { 181 | "version": "1.1.3", 182 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 183 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 184 | "dev": true 185 | }, 186 | "debug": { 187 | "version": "4.1.1", 188 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 189 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 190 | "dev": true, 191 | "requires": { 192 | "ms": "^2.1.1" 193 | } 194 | }, 195 | "define-properties": { 196 | "version": "1.1.3", 197 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 198 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 199 | "requires": { 200 | "object-keys": "^1.0.12" 201 | } 202 | }, 203 | "doctrine": { 204 | "version": "2.1.0", 205 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 206 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 207 | "dev": true, 208 | "requires": { 209 | "esutils": "^2.0.2" 210 | } 211 | }, 212 | "es-abstract": { 213 | "version": "1.16.3", 214 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.3.tgz", 215 | "integrity": "sha512-WtY7Fx5LiOnSYgF5eg/1T+GONaGmpvpPdCpSnYij+U2gDTL0UPfWrhDw7b2IYb+9NQJsYpCA0wOQvZfsd6YwRw==", 216 | "requires": { 217 | "es-to-primitive": "^1.2.1", 218 | "function-bind": "^1.1.1", 219 | "has": "^1.0.3", 220 | "has-symbols": "^1.0.1", 221 | "is-callable": "^1.1.4", 222 | "is-regex": "^1.0.4", 223 | "object-inspect": "^1.7.0", 224 | "object-keys": "^1.1.1", 225 | "string.prototype.trimleft": "^2.1.0", 226 | "string.prototype.trimright": "^2.1.0" 227 | } 228 | }, 229 | "es-to-primitive": { 230 | "version": "1.2.1", 231 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 232 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 233 | "requires": { 234 | "is-callable": "^1.1.4", 235 | "is-date-object": "^1.0.1", 236 | "is-symbol": "^1.0.2" 237 | } 238 | }, 239 | "escape-string-regexp": { 240 | "version": "1.0.5", 241 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 242 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 243 | "dev": true 244 | }, 245 | "eslint-plugin-eslint-plugin": { 246 | "version": "2.1.0", 247 | "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-2.1.0.tgz", 248 | "integrity": "sha512-kT3A/ZJftt28gbl/Cv04qezb/NQ1dwYIbi8lyf806XMxkus7DvOVCLIfTXMrorp322Pnoez7+zabXH29tADIDg==", 249 | "dev": true 250 | }, 251 | "eslint-plugin-react": { 252 | "version": "7.17.0", 253 | "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.17.0.tgz", 254 | "integrity": "sha512-ODB7yg6lxhBVMeiH1c7E95FLD4E/TwmFjltiU+ethv7KPdCwgiFuOZg9zNRHyufStTDLl/dEFqI2Q1VPmCd78A==", 255 | "dev": true, 256 | "requires": { 257 | "array-includes": "^3.0.3", 258 | "doctrine": "^2.1.0", 259 | "eslint-plugin-eslint-plugin": "^2.1.0", 260 | "has": "^1.0.3", 261 | "jsx-ast-utils": "^2.2.3", 262 | "object.entries": "^1.1.0", 263 | "object.fromentries": "^2.0.1", 264 | "object.values": "^1.1.0", 265 | "prop-types": "^15.7.2", 266 | "resolve": "^1.13.1" 267 | } 268 | }, 269 | "eslint-visitor-keys": { 270 | "version": "1.1.0", 271 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", 272 | "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", 273 | "dev": true 274 | }, 275 | "esutils": { 276 | "version": "2.0.3", 277 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 278 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 279 | "dev": true 280 | }, 281 | "events": { 282 | "version": "3.0.0", 283 | "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", 284 | "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==" 285 | }, 286 | "function-bind": { 287 | "version": "1.1.1", 288 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 289 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 290 | }, 291 | "globals": { 292 | "version": "11.12.0", 293 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 294 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 295 | "dev": true 296 | }, 297 | "has": { 298 | "version": "1.0.3", 299 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 300 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 301 | "requires": { 302 | "function-bind": "^1.1.1" 303 | } 304 | }, 305 | "has-flag": { 306 | "version": "3.0.0", 307 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 308 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 309 | "dev": true 310 | }, 311 | "has-symbols": { 312 | "version": "1.0.1", 313 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", 314 | "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" 315 | }, 316 | "ieee754": { 317 | "version": "1.1.13", 318 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 319 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 320 | }, 321 | "inherits": { 322 | "version": "2.0.4", 323 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 324 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 325 | }, 326 | "ip-regex": { 327 | "version": "4.1.0", 328 | "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.1.0.tgz", 329 | "integrity": "sha512-pKnZpbgCTfH/1NLIlOduP/V+WRXzC2MOz3Qo8xmxk8C5GudJLgK5QyLVXOSWy3ParAH7Eemurl3xjv/WXYFvMA==" 330 | }, 331 | "is-arguments": { 332 | "version": "1.0.4", 333 | "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", 334 | "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" 335 | }, 336 | "is-callable": { 337 | "version": "1.1.4", 338 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", 339 | "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" 340 | }, 341 | "is-date-object": { 342 | "version": "1.0.1", 343 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", 344 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" 345 | }, 346 | "is-generator-function": { 347 | "version": "1.0.7", 348 | "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", 349 | "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==" 350 | }, 351 | "is-regex": { 352 | "version": "1.0.4", 353 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 354 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 355 | "requires": { 356 | "has": "^1.0.1" 357 | } 358 | }, 359 | "is-symbol": { 360 | "version": "1.0.3", 361 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", 362 | "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", 363 | "requires": { 364 | "has-symbols": "^1.0.1" 365 | } 366 | }, 367 | "js-tokens": { 368 | "version": "4.0.0", 369 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 370 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 371 | "dev": true 372 | }, 373 | "jsesc": { 374 | "version": "2.5.2", 375 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 376 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", 377 | "dev": true 378 | }, 379 | "jsx-ast-utils": { 380 | "version": "2.2.3", 381 | "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz", 382 | "integrity": "sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==", 383 | "dev": true, 384 | "requires": { 385 | "array-includes": "^3.0.3", 386 | "object.assign": "^4.1.0" 387 | } 388 | }, 389 | "lodash": { 390 | "version": "4.17.15", 391 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 392 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 393 | "dev": true 394 | }, 395 | "loose-envify": { 396 | "version": "1.4.0", 397 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 398 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 399 | "dev": true, 400 | "requires": { 401 | "js-tokens": "^3.0.0 || ^4.0.0" 402 | } 403 | }, 404 | "ms": { 405 | "version": "2.1.2", 406 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 407 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 408 | "dev": true 409 | }, 410 | "object-assign": { 411 | "version": "4.1.1", 412 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 413 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 414 | "dev": true 415 | }, 416 | "object-inspect": { 417 | "version": "1.7.0", 418 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", 419 | "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" 420 | }, 421 | "object-keys": { 422 | "version": "1.1.1", 423 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 424 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" 425 | }, 426 | "object.assign": { 427 | "version": "4.1.0", 428 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", 429 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", 430 | "dev": true, 431 | "requires": { 432 | "define-properties": "^1.1.2", 433 | "function-bind": "^1.1.1", 434 | "has-symbols": "^1.0.0", 435 | "object-keys": "^1.0.11" 436 | } 437 | }, 438 | "object.entries": { 439 | "version": "1.1.0", 440 | "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", 441 | "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", 442 | "requires": { 443 | "define-properties": "^1.1.3", 444 | "es-abstract": "^1.12.0", 445 | "function-bind": "^1.1.1", 446 | "has": "^1.0.3" 447 | } 448 | }, 449 | "object.fromentries": { 450 | "version": "2.0.1", 451 | "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.1.tgz", 452 | "integrity": "sha512-PUQv8Hbg3j2QX0IQYv3iAGCbGcu4yY4KQ92/dhA4sFSixBmSmp13UpDLs6jGK8rBtbmhNNIK99LD2k293jpiGA==", 453 | "dev": true, 454 | "requires": { 455 | "define-properties": "^1.1.3", 456 | "es-abstract": "^1.15.0", 457 | "function-bind": "^1.1.1", 458 | "has": "^1.0.3" 459 | } 460 | }, 461 | "object.values": { 462 | "version": "1.1.0", 463 | "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", 464 | "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", 465 | "dev": true, 466 | "requires": { 467 | "define-properties": "^1.1.3", 468 | "es-abstract": "^1.12.0", 469 | "function-bind": "^1.1.1", 470 | "has": "^1.0.3" 471 | } 472 | }, 473 | "path-parse": { 474 | "version": "1.0.6", 475 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 476 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 477 | "dev": true 478 | }, 479 | "process": { 480 | "version": "0.11.10", 481 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 482 | "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" 483 | }, 484 | "prop-types": { 485 | "version": "15.7.2", 486 | "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", 487 | "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", 488 | "dev": true, 489 | "requires": { 490 | "loose-envify": "^1.4.0", 491 | "object-assign": "^4.1.1", 492 | "react-is": "^16.8.1" 493 | } 494 | }, 495 | "react-is": { 496 | "version": "16.12.0", 497 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", 498 | "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==", 499 | "dev": true 500 | }, 501 | "resolve": { 502 | "version": "1.13.1", 503 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", 504 | "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", 505 | "dev": true, 506 | "requires": { 507 | "path-parse": "^1.0.6" 508 | } 509 | }, 510 | "safe-buffer": { 511 | "version": "5.2.0", 512 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 513 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" 514 | }, 515 | "source-map": { 516 | "version": "0.5.7", 517 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 518 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 519 | "dev": true 520 | }, 521 | "string.prototype.trimleft": { 522 | "version": "2.1.0", 523 | "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", 524 | "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", 525 | "requires": { 526 | "define-properties": "^1.1.3", 527 | "function-bind": "^1.1.1" 528 | } 529 | }, 530 | "string.prototype.trimright": { 531 | "version": "2.1.0", 532 | "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", 533 | "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", 534 | "requires": { 535 | "define-properties": "^1.1.3", 536 | "function-bind": "^1.1.1" 537 | } 538 | }, 539 | "supports-color": { 540 | "version": "5.5.0", 541 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 542 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 543 | "dev": true, 544 | "requires": { 545 | "has-flag": "^3.0.0" 546 | } 547 | }, 548 | "to-fast-properties": { 549 | "version": "2.0.0", 550 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 551 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", 552 | "dev": true 553 | }, 554 | "util": { 555 | "version": "0.12.1", 556 | "resolved": "https://registry.npmjs.org/util/-/util-0.12.1.tgz", 557 | "integrity": "sha512-MREAtYOp+GTt9/+kwf00IYoHZyjM8VU4aVrkzUlejyqaIjd2GztVl5V9hGXKlvBKE3gENn/FMfHE5v6hElXGcQ==", 558 | "requires": { 559 | "inherits": "^2.0.3", 560 | "is-arguments": "^1.0.4", 561 | "is-generator-function": "^1.0.7", 562 | "object.entries": "^1.1.0", 563 | "safe-buffer": "^5.1.2" 564 | } 565 | } 566 | } 567 | } 568 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-tcp", 3 | "version": "4.0.0", 4 | "description": "node's net API for react-native", 5 | "main": "TcpSockets.js", 6 | "scripts": { 7 | "start": "exit 1" 8 | }, 9 | "browser": { 10 | "net": "./TcpSockets.js" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/aprock/react-native-tcp" 15 | }, 16 | "keywords": [ 17 | "react-component", 18 | "reactnative", 19 | "react-native", 20 | "net", 21 | "tcp", 22 | "sockets", 23 | "ios", 24 | "android" 25 | ], 26 | "author": { 27 | "name": "Andy Prock", 28 | "email": "aprock@protonmail.com" 29 | }, 30 | "license": "MIT", 31 | "bugs": { 32 | "url": "https://github.com/aprock/react-native-tcp/issues" 33 | }, 34 | "homepage": "https://github.com/aprock/react-native-tcp", 35 | "peerDependencies": { 36 | "react-native": ">=0.60.0" 37 | }, 38 | "dependencies": { 39 | "base64-js": "1.3.1", 40 | "buffer": "^5.4.3", 41 | "events": "^3.0.0", 42 | "ip-regex": "^4.1.0", 43 | "process": "^0.11.9", 44 | "util": "^0.12.1" 45 | }, 46 | "devDependencies": { 47 | "babel-eslint": "^10.0.3", 48 | "eslint-plugin-react": "^7.17.0" 49 | } 50 | } 51 | --------------------------------------------------------------------------------