react-native-tcp-windows 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +145 -0
- package/lib/commonjs/ReactNativeTcpWindows.js +9 -0
- package/lib/commonjs/ReactNativeTcpWindows.js.map +1 -0
- package/lib/commonjs/index.js +124 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/module/ReactNativeTcpWindows.js +5 -0
- package/lib/module/ReactNativeTcpWindows.js.map +1 -0
- package/lib/module/index.js +104 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/ReactNativeTcpWindows.d.ts +13 -0
- package/lib/typescript/commonjs/src/ReactNativeTcpWindows.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/__tests__/index.test.d.ts +1 -0
- package/lib/typescript/commonjs/src/__tests__/index.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +80 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/ReactNativeTcpWindows.d.ts +13 -0
- package/lib/typescript/module/src/ReactNativeTcpWindows.d.ts.map +1 -0
- package/lib/typescript/module/src/__tests__/index.test.d.ts +1 -0
- package/lib/typescript/module/src/__tests__/index.test.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +80 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/package.json +204 -0
- package/react-native.config.js +12 -0
- package/src/ReactNativeTcpWindows.ts +14 -0
- package/src/__tests__/index.test.tsx +1 -0
- package/src/index.tsx +124 -0
- package/windows/ExperimentalFeatures.props +33 -0
- package/windows/ReactNativeTcpWindows/ReactNativeTcpWindows.cpp +206 -0
- package/windows/ReactNativeTcpWindows/ReactNativeTcpWindows.def +3 -0
- package/windows/ReactNativeTcpWindows/ReactNativeTcpWindows.h +83 -0
- package/windows/ReactNativeTcpWindows/ReactNativeTcpWindows.rc +0 -0
- package/windows/ReactNativeTcpWindows/ReactNativeTcpWindows.vcxproj +146 -0
- package/windows/ReactNativeTcpWindows/ReactNativeTcpWindows.vcxproj.filters +44 -0
- package/windows/ReactNativeTcpWindows/ReactPackageProvider.cpp +20 -0
- package/windows/ReactNativeTcpWindows/ReactPackageProvider.h +24 -0
- package/windows/ReactNativeTcpWindows/ReactPackageProvider.idl +9 -0
- package/windows/ReactNativeTcpWindows/TcpSocket.cpp +565 -0
- package/windows/ReactNativeTcpWindows/TcpSocket.h +69 -0
- package/windows/ReactNativeTcpWindows/codegen/.clang-format +2 -0
- package/windows/ReactNativeTcpWindows/codegen/NativeReactNativeTcpWindowsSpec.g.h +71 -0
- package/windows/ReactNativeTcpWindows/packages.lock.json +60 -0
- package/windows/ReactNativeTcpWindows/pch.cpp +1 -0
- package/windows/ReactNativeTcpWindows/pch.h +30 -0
- package/windows/ReactNativeTcpWindows/resource.h +5 -0
- package/windows/ReactNativeTcpWindows/targetver.h +8 -0
- package/windows/ReactNativeTcpWindows.sln +43 -0
package/package.json
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
{
|
2
|
+
"name": "react-native-tcp-windows",
|
3
|
+
"version": "0.2.0",
|
4
|
+
"description": "TCP sockets communication for RNW",
|
5
|
+
"source": "./src/index.tsx",
|
6
|
+
"main": "./lib/commonjs/index.js",
|
7
|
+
"module": "./lib/module/index.js",
|
8
|
+
"exports": {
|
9
|
+
".": {
|
10
|
+
"import": {
|
11
|
+
"types": "./lib/typescript/module/src/index.d.ts",
|
12
|
+
"default": "./lib/module/index.js"
|
13
|
+
},
|
14
|
+
"require": {
|
15
|
+
"types": "./lib/typescript/commonjs/src/index.d.ts",
|
16
|
+
"default": "./lib/commonjs/index.js"
|
17
|
+
}
|
18
|
+
},
|
19
|
+
"./package.json": "./package.json"
|
20
|
+
},
|
21
|
+
"files": [
|
22
|
+
"src",
|
23
|
+
"lib",
|
24
|
+
"cpp",
|
25
|
+
"react-native.config.js",
|
26
|
+
"windows"
|
27
|
+
],
|
28
|
+
"scripts": {
|
29
|
+
"example": "yarn workspace react-native-tcp-windows-example",
|
30
|
+
"test": "jest",
|
31
|
+
"typecheck": "tsc",
|
32
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
33
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
34
|
+
"prepare": "bob build",
|
35
|
+
"codegen": "react-native codegen-windows",
|
36
|
+
"release": "release-it"
|
37
|
+
},
|
38
|
+
"keywords": [
|
39
|
+
"react-native",
|
40
|
+
"react-native-windows",
|
41
|
+
"tcp"
|
42
|
+
],
|
43
|
+
"repository": {
|
44
|
+
"type": "git",
|
45
|
+
"url": "git+https://github.com/KGGrande/react-native-tcp-windows.git"
|
46
|
+
},
|
47
|
+
"author": "Kyle Grande <KGGrande@hormel.com> (https://github.com/KGGrande)",
|
48
|
+
"license": "MIT",
|
49
|
+
"bugs": {
|
50
|
+
"url": "https://github.com/KGGrande/react-native-tcp-windows/issues"
|
51
|
+
},
|
52
|
+
"homepage": "https://github.com/KGGrande/react-native-tcp-windows#readme",
|
53
|
+
"publishConfig": {
|
54
|
+
"registry": "https://registry.npmjs.org/"
|
55
|
+
},
|
56
|
+
"devDependencies": {
|
57
|
+
"@commitlint/config-conventional": "^19.6.0",
|
58
|
+
"@evilmartians/lefthook": "^1.5.0",
|
59
|
+
"@react-native-community/cli": "18.0.0",
|
60
|
+
"@react-native/eslint-config": "^0.73.1",
|
61
|
+
"@release-it/conventional-changelog": "^9.0.2",
|
62
|
+
"@types/jest": "^29.5.5",
|
63
|
+
"@types/react": "^19.0.0",
|
64
|
+
"commitlint": "^19.6.1",
|
65
|
+
"del-cli": "^5.1.0",
|
66
|
+
"eslint": "^8.51.0",
|
67
|
+
"eslint-config-prettier": "^9.0.0",
|
68
|
+
"eslint-plugin-prettier": "^5.0.1",
|
69
|
+
"jest": "^29.7.0",
|
70
|
+
"prettier": "^3.0.3",
|
71
|
+
"react": "19.0.0",
|
72
|
+
"react-native": "0.79.0",
|
73
|
+
"react-native-builder-bob": "^0.38.3",
|
74
|
+
"react-native-windows": "0.79.0",
|
75
|
+
"release-it": "^17.10.0",
|
76
|
+
"turbo": "^1.10.7",
|
77
|
+
"typescript": "^5.2.2"
|
78
|
+
},
|
79
|
+
"peerDependencies": {
|
80
|
+
"react": "*",
|
81
|
+
"react-native": "*",
|
82
|
+
"react-native-windows": "*"
|
83
|
+
},
|
84
|
+
"workspaces": [
|
85
|
+
"example"
|
86
|
+
],
|
87
|
+
"packageManager": "yarn@3.6.1",
|
88
|
+
"jest": {
|
89
|
+
"preset": "react-native",
|
90
|
+
"modulePathIgnorePatterns": [
|
91
|
+
"<rootDir>/example/node_modules",
|
92
|
+
"<rootDir>/lib/"
|
93
|
+
]
|
94
|
+
},
|
95
|
+
"commitlint": {
|
96
|
+
"extends": [
|
97
|
+
"@commitlint/config-conventional"
|
98
|
+
]
|
99
|
+
},
|
100
|
+
"release-it": {
|
101
|
+
"git": {
|
102
|
+
"commitMessage": "chore: release ${version}",
|
103
|
+
"tagName": "v${version}"
|
104
|
+
},
|
105
|
+
"npm": {
|
106
|
+
"publish": true
|
107
|
+
},
|
108
|
+
"github": {
|
109
|
+
"release": true
|
110
|
+
},
|
111
|
+
"plugins": {
|
112
|
+
"@release-it/conventional-changelog": {
|
113
|
+
"preset": {
|
114
|
+
"name": "angular"
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|
118
|
+
},
|
119
|
+
"eslintConfig": {
|
120
|
+
"root": true,
|
121
|
+
"extends": [
|
122
|
+
"@react-native",
|
123
|
+
"prettier"
|
124
|
+
],
|
125
|
+
"rules": {
|
126
|
+
"react/react-in-jsx-scope": "off",
|
127
|
+
"prettier/prettier": [
|
128
|
+
"error",
|
129
|
+
{
|
130
|
+
"quoteProps": "consistent",
|
131
|
+
"singleQuote": true,
|
132
|
+
"tabWidth": 2,
|
133
|
+
"trailingComma": "es5",
|
134
|
+
"useTabs": false
|
135
|
+
}
|
136
|
+
]
|
137
|
+
}
|
138
|
+
},
|
139
|
+
"eslintIgnore": [
|
140
|
+
"node_modules/",
|
141
|
+
"lib/"
|
142
|
+
],
|
143
|
+
"prettier": {
|
144
|
+
"quoteProps": "consistent",
|
145
|
+
"singleQuote": true,
|
146
|
+
"tabWidth": 2,
|
147
|
+
"trailingComma": "es5",
|
148
|
+
"useTabs": false
|
149
|
+
},
|
150
|
+
"react-native-builder-bob": {
|
151
|
+
"source": "src",
|
152
|
+
"output": "lib",
|
153
|
+
"targets": [
|
154
|
+
[
|
155
|
+
"module",
|
156
|
+
{
|
157
|
+
"esm": true
|
158
|
+
}
|
159
|
+
],
|
160
|
+
[
|
161
|
+
"commonjs",
|
162
|
+
{
|
163
|
+
"esm": true
|
164
|
+
}
|
165
|
+
],
|
166
|
+
[
|
167
|
+
"typescript",
|
168
|
+
{
|
169
|
+
"project": "tsconfig.build.json"
|
170
|
+
}
|
171
|
+
]
|
172
|
+
]
|
173
|
+
},
|
174
|
+
"codegenConfig": {
|
175
|
+
"name": "ReactNativeTcpWindowsSpec",
|
176
|
+
"type": "modules",
|
177
|
+
"jsSrcsDir": "src",
|
178
|
+
"outputDir": {
|
179
|
+
"ios": "ios/generated",
|
180
|
+
"android": "android/generated"
|
181
|
+
},
|
182
|
+
"android": {
|
183
|
+
"javaPackageName": "com.tcpwindows"
|
184
|
+
},
|
185
|
+
"includesGeneratedCode": true,
|
186
|
+
"windows": {
|
187
|
+
"namespace": "ReactNativeTcpWindowsCodegen",
|
188
|
+
"outputDirectory": "windows/ReactNativeTcpWindows/codegen",
|
189
|
+
"separateDataTypes": false
|
190
|
+
}
|
191
|
+
},
|
192
|
+
"create-react-native-library": {
|
193
|
+
"type": "turbo-module",
|
194
|
+
"languages": "kotlin-objc",
|
195
|
+
"version": "0.48.9"
|
196
|
+
},
|
197
|
+
"react-native-windows": {
|
198
|
+
"init-windows": {
|
199
|
+
"name": "ReactNativeTcpWindows",
|
200
|
+
"namespace": "ReactNativeTcpWindows",
|
201
|
+
"template": "cpp-lib"
|
202
|
+
}
|
203
|
+
}
|
204
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
3
|
+
|
4
|
+
export interface Spec extends TurboModule {
|
5
|
+
connectToServer(address: string, port: number): Promise<string>;
|
6
|
+
startServer(port: number): Promise<string>;
|
7
|
+
closeConnection(): Promise<string>;
|
8
|
+
write(data: Array<number>): Promise<boolean>;
|
9
|
+
getConnectionStatus(): Promise<boolean>;
|
10
|
+
addListener(eventType: string): void;
|
11
|
+
removeListeners(count: number): void;
|
12
|
+
}
|
13
|
+
|
14
|
+
export default TurboModuleRegistry.getEnforcing<Spec>('ReactNativeTcpWindows');
|
@@ -0,0 +1 @@
|
|
1
|
+
it.todo('write a test');
|
package/src/index.tsx
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
import { NativeEventEmitter } from 'react-native';
|
2
|
+
import TcpSocketWindows from './ReactNativeTcpWindows';
|
3
|
+
|
4
|
+
export const eventEmitter = new NativeEventEmitter(TcpSocketWindows);
|
5
|
+
export { TcpSocketWindows };
|
6
|
+
// Event types for better type safety
|
7
|
+
export const TCP_SOCKET_EVENTS = {
|
8
|
+
DATA_RECEIVED: 'TcpSocketDataReceived',
|
9
|
+
CLIENT_CONNECTED: 'TcpSocketClientConnected',
|
10
|
+
CLIENT_DISCONNECTED: 'TcpSocketClientDisconnected',
|
11
|
+
CONNECTION_STATUS_CHANGED: 'TcpSocketConnectionStatusChanged',
|
12
|
+
} as const;
|
13
|
+
|
14
|
+
export type TcpSocketEvent =
|
15
|
+
(typeof TCP_SOCKET_EVENTS)[keyof typeof TCP_SOCKET_EVENTS];
|
16
|
+
|
17
|
+
// Event data interfaces
|
18
|
+
export interface DataReceivedEvent {
|
19
|
+
data: number[];
|
20
|
+
}
|
21
|
+
|
22
|
+
export interface ClientConnectedEvent {
|
23
|
+
clientAddress: string;
|
24
|
+
}
|
25
|
+
|
26
|
+
export interface ClientDisconnectedEvent {
|
27
|
+
clientAddress: string;
|
28
|
+
}
|
29
|
+
|
30
|
+
export interface ConnectionStatusChangedEvent {
|
31
|
+
connected: boolean;
|
32
|
+
message: string;
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
* Connect to a TCP server as a client
|
37
|
+
* @param address Server IP address (e.g., "192.168.1.100")
|
38
|
+
* @param port Server port number
|
39
|
+
* @returns Promise that resolves with success message
|
40
|
+
*/
|
41
|
+
export function connectToServer(
|
42
|
+
address: string,
|
43
|
+
port: number
|
44
|
+
): Promise<string> {
|
45
|
+
return TcpSocketWindows.connectToServer(address, port);
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Start a TCP server to accept client connections
|
50
|
+
* @param port Port number to listen on
|
51
|
+
* @returns Promise that resolves with success message
|
52
|
+
*/
|
53
|
+
export function startServer(port: number): Promise<string> {
|
54
|
+
return TcpSocketWindows.startServer(port);
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Close the current connection (client or server)
|
59
|
+
* @returns Promise that resolves with success message
|
60
|
+
*/
|
61
|
+
export function closeConnection(): Promise<string> {
|
62
|
+
return TcpSocketWindows.closeConnection();
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Write data to the TCP connection
|
67
|
+
* For clients: sends to the connected server
|
68
|
+
* For servers: sends to all connected clients
|
69
|
+
* @param data Array of bytes to send (0-255)
|
70
|
+
* @returns Promise that resolves with success status
|
71
|
+
*/
|
72
|
+
export function write(data: number[]): Promise<boolean> {
|
73
|
+
return TcpSocketWindows.write(data);
|
74
|
+
}
|
75
|
+
|
76
|
+
/**
|
77
|
+
* Get the current connection status
|
78
|
+
* @returns Promise that resolves with connection status object
|
79
|
+
*/
|
80
|
+
export function getConnectionStatus(): Promise<boolean> {
|
81
|
+
return TcpSocketWindows.getConnectionStatus();
|
82
|
+
}
|
83
|
+
|
84
|
+
/**
|
85
|
+
* Write a string as UTF-8 bytes
|
86
|
+
* @param text String to send
|
87
|
+
* @returns Promise that resolves with success status
|
88
|
+
*/
|
89
|
+
export function writeString(text: string): Promise<boolean> {
|
90
|
+
const encoder = new TextEncoder();
|
91
|
+
const bytes = Array.from(encoder.encode(text));
|
92
|
+
return write(bytes);
|
93
|
+
}
|
94
|
+
|
95
|
+
/**
|
96
|
+
* Write JSON data as UTF-8 bytes
|
97
|
+
* @param data Object to serialize and send
|
98
|
+
* @returns Promise that resolves with success status
|
99
|
+
*/
|
100
|
+
export function writeJson(data: any): Promise<boolean> {
|
101
|
+
const jsonString = JSON.stringify(data);
|
102
|
+
return writeString(jsonString);
|
103
|
+
}
|
104
|
+
|
105
|
+
/**
|
106
|
+
* Convenience function to convert received byte array to string
|
107
|
+
* @param data Byte array from DataReceivedEvent
|
108
|
+
* @returns Decoded UTF-8 string
|
109
|
+
*/
|
110
|
+
export function bytesToString(data: number[]): string {
|
111
|
+
const uint8Array = new Uint8Array(data);
|
112
|
+
const decoder = new TextDecoder();
|
113
|
+
return decoder.decode(uint8Array);
|
114
|
+
}
|
115
|
+
|
116
|
+
/**
|
117
|
+
* Convenience function to convert received byte array to JSON
|
118
|
+
* @param data Byte array from DataReceivedEvent
|
119
|
+
* @returns Parsed JSON object
|
120
|
+
*/
|
121
|
+
export function bytesToJson(data: number[]): any {
|
122
|
+
const jsonString = bytesToString(data);
|
123
|
+
return JSON.parse(jsonString);
|
124
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
3
|
+
|
4
|
+
<PropertyGroup Label="Microsoft.ReactNative Experimental Features">
|
5
|
+
<!--
|
6
|
+
Required for building a New Architecture project.
|
7
|
+
|
8
|
+
Library projects can change this value to test against Old and New
|
9
|
+
Architectures when building the library project's local sln file.
|
10
|
+
|
11
|
+
Otherwise this value will be decided by the consuming RNW app.
|
12
|
+
|
13
|
+
See https://microsoft.github.io/react-native-windows/docs/new-architecture
|
14
|
+
-->
|
15
|
+
<RnwNewArch>true</RnwNewArch>
|
16
|
+
|
17
|
+
<!--
|
18
|
+
Changes compilation to assume use of Microsoft.ReactNative NuGet packages
|
19
|
+
instead of building the framework from source. Defaults to true.
|
20
|
+
|
21
|
+
This is set during library project creation and is used when building
|
22
|
+
the library project's local sln file.
|
23
|
+
|
24
|
+
Otherwise this value will be decided by the consuming RNW app.
|
25
|
+
|
26
|
+
See https://microsoft.github.io/react-native-windows/docs/nuget
|
27
|
+
-->
|
28
|
+
<UseExperimentalNuget>true</UseExperimentalNuget>
|
29
|
+
|
30
|
+
<ReactExperimentalFeaturesSet>true</ReactExperimentalFeaturesSet>
|
31
|
+
</PropertyGroup>
|
32
|
+
|
33
|
+
</Project>
|
@@ -0,0 +1,206 @@
|
|
1
|
+
#include "pch.h"
|
2
|
+
#include "ReactNativeTcpWindows.h"
|
3
|
+
#include "TcpSocket.h"
|
4
|
+
namespace winrt::ReactNativeTcpWindows
|
5
|
+
{
|
6
|
+
|
7
|
+
// See https://microsoft.github.io/react-native-windows/docs/native-platform for help writing native modules
|
8
|
+
|
9
|
+
void ReactNativeTcpWindows::Initialize(React::ReactContext const &reactContext) noexcept {
|
10
|
+
m_context = reactContext;
|
11
|
+
OutputDebugStringA("ReactNativeTcpWindows::Initialize called\n");
|
12
|
+
// m_tcpSocket = std::make_unique<TcpSocket>("127.0.0.1", 1234, TcpSocket::ConnectionType::Client);
|
13
|
+
if (m_tcpSocket) {
|
14
|
+
m_tcpSocket->close();
|
15
|
+
m_tcpSocket.reset();
|
16
|
+
OutputDebugStringA("Existing TcpSocket instance closed during Initialize\n");
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
ReactNativeTcpWindows::~ReactNativeTcpWindows() {
|
21
|
+
OutputDebugStringA("ReactNativeTcpWindows destructor called\n");
|
22
|
+
|
23
|
+
if (m_tcpSocket) {
|
24
|
+
m_tcpSocket->close(); // Calls TcpSocket::close
|
25
|
+
m_tcpSocket.reset(); // Triggers TcpSocket destructor
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
// double ReactNativeTcpWindows::multiply(double a, double b) noexcept {
|
30
|
+
// return a * b;
|
31
|
+
// }
|
32
|
+
void ReactNativeTcpWindows::connectToServer(std::string address, double port,
|
33
|
+
React::ReactPromise<std::string> &&promise) noexcept {
|
34
|
+
try {
|
35
|
+
OutputDebugStringA(("Connecting to TCP server:\n"
|
36
|
+
"Address: " + address + "\n"
|
37
|
+
"Port: " + std::to_string(static_cast<int>(port)) + "\n").c_str());
|
38
|
+
|
39
|
+
// Close existing connection if any
|
40
|
+
if (m_tcpSocket) {
|
41
|
+
m_tcpSocket->close();
|
42
|
+
m_tcpSocket.reset();
|
43
|
+
}
|
44
|
+
|
45
|
+
m_tcpSocket = std::make_unique<TcpSocket>(address, static_cast<int>(port), TcpSocket::ConnectionType::Client);
|
46
|
+
|
47
|
+
// Set up callbacks
|
48
|
+
m_tcpSocket->setDataReceivedCallback([this](const std::vector<uint8_t>& data) {
|
49
|
+
OnDataReceived(data);
|
50
|
+
});
|
51
|
+
|
52
|
+
m_tcpSocket->setConnectionStatusCallback([this, promise](bool connected, const std::string& message) {
|
53
|
+
OnConnectionStatusChanged(connected, message);
|
54
|
+
if (connected) {
|
55
|
+
promise.Resolve("Connected to server successfully");
|
56
|
+
} else {
|
57
|
+
promise.Reject(React::ReactError{"Error", message});
|
58
|
+
}
|
59
|
+
});
|
60
|
+
|
61
|
+
// Attempt connection
|
62
|
+
if (!m_tcpSocket->connect()) {
|
63
|
+
promise.Reject(React::ReactError{"Error", "Failed to initiate connection"});
|
64
|
+
}
|
65
|
+
// Note: Promise will be resolved/rejected in the connection status callback
|
66
|
+
|
67
|
+
} catch (const std::exception& e) {
|
68
|
+
promise.Reject(React::ReactError{"Error", e.what()});
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
void ReactNativeTcpWindows::startServer(double port,
|
73
|
+
React::ReactPromise<std::string> &&promise) noexcept {
|
74
|
+
try {
|
75
|
+
OutputDebugStringA(("Starting TCP server on port: " + std::to_string(static_cast<int>(port)) + "\n").c_str());
|
76
|
+
|
77
|
+
// Close existing connection if any
|
78
|
+
if (m_tcpSocket) {
|
79
|
+
m_tcpSocket->close();
|
80
|
+
m_tcpSocket.reset();
|
81
|
+
}
|
82
|
+
|
83
|
+
m_tcpSocket = std::make_unique<TcpSocket>("0.0.0.0", static_cast<int>(port), TcpSocket::ConnectionType::Server);
|
84
|
+
|
85
|
+
// Set up callbacks
|
86
|
+
m_tcpSocket->setDataReceivedCallback([this](const std::vector<uint8_t>& data) {
|
87
|
+
OnDataReceived(data);
|
88
|
+
});
|
89
|
+
|
90
|
+
m_tcpSocket->setClientConnectedCallback([this](const std::string& clientAddress) {
|
91
|
+
OnClientConnected(clientAddress);
|
92
|
+
});
|
93
|
+
|
94
|
+
m_tcpSocket->setClientDisconnectedCallback([this](const std::string& clientAddress) {
|
95
|
+
OnClientDisconnected(clientAddress);
|
96
|
+
});
|
97
|
+
|
98
|
+
m_tcpSocket->setConnectionStatusCallback([this](bool connected, const std::string& message) {
|
99
|
+
OnConnectionStatusChanged(connected, message);
|
100
|
+
});
|
101
|
+
|
102
|
+
if (m_tcpSocket->startServer()) {
|
103
|
+
promise.Resolve("TCP server started successfully on port " + std::to_string(static_cast<int>(port)));
|
104
|
+
} else {
|
105
|
+
promise.Reject(React::ReactError{"Error", "Failed to start TCP server"});
|
106
|
+
}
|
107
|
+
|
108
|
+
} catch (const std::exception& e) {
|
109
|
+
promise.Reject(React::ReactError{"Error", e.what()});
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
void ReactNativeTcpWindows::closeConnection(React::ReactPromise<std::string> &&promise) noexcept {
|
114
|
+
try {
|
115
|
+
OutputDebugStringA("Called Close Connection for TCP socket...\n");
|
116
|
+
if (m_tcpSocket) {
|
117
|
+
OutputDebugStringA("Closing TCP socket...\n");
|
118
|
+
m_tcpSocket->close();
|
119
|
+
m_tcpSocket.reset();
|
120
|
+
promise.Resolve("Connection closed successfully");
|
121
|
+
} else {
|
122
|
+
OutputDebugStringA("No active TCP socket to close.\n");
|
123
|
+
promise.Reject(React::ReactError{ "Error", "No connection open" });
|
124
|
+
}
|
125
|
+
} catch (const std::exception& e) {
|
126
|
+
std::string errorMsg = std::string("Exception in closeConnection: ") + e.what();
|
127
|
+
OutputDebugStringA(errorMsg.c_str());
|
128
|
+
promise.Reject(React::ReactError{"Exception", errorMsg});
|
129
|
+
} catch (...) {
|
130
|
+
OutputDebugStringA("Unknown exception in closeConnection\n");
|
131
|
+
promise.Reject(React::ReactError{"Exception", "Unknown exception in closeConnection"});
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
void ReactNativeTcpWindows::write(std::vector<double> const& data,
|
136
|
+
React::ReactPromise<bool> &&promise) noexcept {
|
137
|
+
if (!m_tcpSocket) {
|
138
|
+
promise.Reject("No connection open");
|
139
|
+
return;
|
140
|
+
}
|
141
|
+
|
142
|
+
std::vector<uint8_t> byteData;
|
143
|
+
byteData.reserve(data.size());
|
144
|
+
for (const auto& value : data) {
|
145
|
+
byteData.push_back(static_cast<uint8_t>(value));
|
146
|
+
}
|
147
|
+
|
148
|
+
promise.Resolve(m_tcpSocket->write(byteData));
|
149
|
+
}
|
150
|
+
|
151
|
+
void ReactNativeTcpWindows::getConnectionStatus(
|
152
|
+
React::ReactPromise<bool> &&promise
|
153
|
+
) noexcept {
|
154
|
+
bool isConnected = m_tcpSocket ? m_tcpSocket->isConnected() : false;
|
155
|
+
promise.Resolve(isConnected);
|
156
|
+
}
|
157
|
+
void ReactNativeTcpWindows::OnDataReceived(const std::vector<uint8_t>& data) {
|
158
|
+
if (m_context) {
|
159
|
+
auto eventData = winrt::Microsoft::ReactNative::JSValueObject();
|
160
|
+
winrt::Microsoft::ReactNative::JSValueArray jsDataArray;
|
161
|
+
for (auto byte : data) {
|
162
|
+
jsDataArray.push_back(static_cast<int>(byte));
|
163
|
+
}
|
164
|
+
|
165
|
+
eventData["data"] = std::move(jsDataArray);
|
166
|
+
|
167
|
+
m_context.EmitJSEvent(L"RCTDeviceEventEmitter", L"TcpSocketDataReceived", eventData);
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
void ReactNativeTcpWindows::OnClientConnected(const std::string& clientAddress) {
|
172
|
+
if (m_context) {
|
173
|
+
auto eventData = winrt::Microsoft::ReactNative::JSValueObject();
|
174
|
+
eventData["clientAddress"] = clientAddress;
|
175
|
+
|
176
|
+
m_context.EmitJSEvent(L"RCTDeviceEventEmitter", L"TcpSocketClientConnected", eventData);
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
void ReactNativeTcpWindows::OnClientDisconnected(const std::string& clientAddress) {
|
181
|
+
if (m_context) {
|
182
|
+
auto eventData = winrt::Microsoft::ReactNative::JSValueObject();
|
183
|
+
eventData["clientAddress"] = clientAddress;
|
184
|
+
|
185
|
+
m_context.EmitJSEvent(L"RCTDeviceEventEmitter", L"TcpSocketClientDisconnected", eventData);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
void ReactNativeTcpWindows::OnConnectionStatusChanged(bool connected, const std::string& message) {
|
190
|
+
if (m_context) {
|
191
|
+
auto eventData = winrt::Microsoft::ReactNative::JSValueObject();
|
192
|
+
eventData["connected"] = connected;
|
193
|
+
eventData["message"] = message;
|
194
|
+
|
195
|
+
m_context.EmitJSEvent(L"RCTDeviceEventEmitter", L"TcpSocketConnectionStatusChanged", eventData);
|
196
|
+
}
|
197
|
+
}
|
198
|
+
|
199
|
+
void ReactNativeTcpWindows::addListener(std::string eventType) noexcept {
|
200
|
+
// Event listener management - can be implemented if needed
|
201
|
+
}
|
202
|
+
|
203
|
+
void ReactNativeTcpWindows::removeListeners(double count) noexcept {
|
204
|
+
// Event listener management - can be implemented if needed
|
205
|
+
}
|
206
|
+
} // namespace winrt::ReactNativeTcpWindows
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "pch.h"
|
4
|
+
#include "resource.h"
|
5
|
+
#include "TcpSocket.h"
|
6
|
+
|
7
|
+
#if __has_include("codegen/NativeReactNativeTcpWindowsDataTypes.g.h")
|
8
|
+
#include "codegen/NativeReactNativeTcpWindowsDataTypes.g.h"
|
9
|
+
#endif
|
10
|
+
#include "codegen/NativeReactNativeTcpWindowsSpec.g.h"
|
11
|
+
|
12
|
+
#include "NativeModules.h"
|
13
|
+
|
14
|
+
|
15
|
+
namespace winrt::ReactNativeTcpWindows
|
16
|
+
{
|
17
|
+
|
18
|
+
// See https://microsoft.github.io/react-native-windows/docs/native-platform for help writing native modules
|
19
|
+
|
20
|
+
REACT_MODULE(ReactNativeTcpWindows)
|
21
|
+
|
22
|
+
struct ReactNativeTcpWindows
|
23
|
+
{
|
24
|
+
using ModuleSpec = ReactNativeTcpWindowsCodegen::ReactNativeTcpWindowsSpec;
|
25
|
+
|
26
|
+
REACT_INIT(Initialize)
|
27
|
+
void Initialize(React::ReactContext const &reactContext) noexcept;
|
28
|
+
|
29
|
+
~ReactNativeTcpWindows(); // Add this to the struct
|
30
|
+
|
31
|
+
// REACT_SYNC_METHOD(multiply)
|
32
|
+
// double multiply(double a, double b) noexcept;
|
33
|
+
|
34
|
+
REACT_METHOD(connectToServer)
|
35
|
+
void connectToServer(std::string address, double port,
|
36
|
+
React::ReactPromise<std::string> &&promise) noexcept;
|
37
|
+
|
38
|
+
REACT_METHOD(startServer)
|
39
|
+
void startServer(double port,
|
40
|
+
React::ReactPromise<std::string> &&promise) noexcept;
|
41
|
+
|
42
|
+
REACT_METHOD(closeConnection)
|
43
|
+
void closeConnection(React::ReactPromise<std::string> &&promise) noexcept;
|
44
|
+
|
45
|
+
REACT_METHOD(write)
|
46
|
+
void write(std::vector<double> const& data, React::ReactPromise<bool> &&promise) noexcept;
|
47
|
+
|
48
|
+
// REACT_METHOD(getConnectionStatus)
|
49
|
+
// void getConnectionStatus(React::ReactPromise<winrt::Microsoft::ReactNative::JSValueObject> &&promise) noexcept;
|
50
|
+
|
51
|
+
|
52
|
+
REACT_METHOD(getConnectionStatus)
|
53
|
+
void getConnectionStatus(React::ReactPromise<bool> &&promise) noexcept;
|
54
|
+
|
55
|
+
REACT_METHOD(addListener)
|
56
|
+
void addListener(std::string eventType) noexcept;
|
57
|
+
|
58
|
+
REACT_METHOD(removeListeners)
|
59
|
+
void removeListeners(double count) noexcept;
|
60
|
+
|
61
|
+
void OnDataReceived(const std::vector<uint8_t>& data);
|
62
|
+
void OnClientConnected(const std::string& clientAddress);
|
63
|
+
void OnClientDisconnected(const std::string& clientAddress);
|
64
|
+
void OnConnectionStatusChanged(bool connected, const std::string& message);
|
65
|
+
|
66
|
+
private:
|
67
|
+
React::ReactContext m_context;
|
68
|
+
std::unique_ptr<TcpSocket> m_tcpSocket;
|
69
|
+
};
|
70
|
+
// {
|
71
|
+
// using ModuleSpec = ReactNativeTcpWindowsCodegen::ReactNativeTcpWindowsSpec;
|
72
|
+
|
73
|
+
// REACT_INIT(Initialize)
|
74
|
+
// void Initialize(React::ReactContext const &reactContext) noexcept;
|
75
|
+
|
76
|
+
// REACT_SYNC_METHOD(multiply)
|
77
|
+
// double multiply(double a, double b) noexcept;
|
78
|
+
|
79
|
+
// private:
|
80
|
+
// React::ReactContext m_context;
|
81
|
+
// };
|
82
|
+
|
83
|
+
} // namespace winrt::ReactNativeTcpWindows
|
Binary file
|