1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | #import "RCTReconnectingWebSocket.h"
|
9 |
|
10 | #import <React/RCTConvert.h>
|
11 | #import <React/RCTDefines.h>
|
12 |
|
13 | #if __has_include(<React/fishhook.h>)
|
14 | #import <React/fishhook.h>
|
15 | #else
|
16 | #import <fishhook/fishhook.h>
|
17 | #endif
|
18 |
|
19 | #if __has_include(<os/log.h>) && defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100300
|
20 | #import <os/log.h>
|
21 | #endif
|
22 |
|
23 | #import "RCTSRWebSocket.h"
|
24 |
|
25 | #if RCT_DEV // Only supported in dev mode
|
26 |
|
27 | #if __has_include(<os/log.h>) && defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100300
|
28 |
|
29 | // From https://github.com/apple/swift/blob/ad40c770bfe372f879b530443a3d94761fe258a6/stdlib/public/SDK/os/os_log.m
|
30 | typedef struct os_log_pack_s {
|
31 | uint64_t olp_continuous_time;
|
32 | struct timespec olp_wall_time;
|
33 | const void *olp_mh;
|
34 | const void *olp_pc;
|
35 | const char *olp_format;
|
36 | uint8_t olp_data[0];
|
37 | } os_log_pack_s, *os_log_pack_t;
|
38 |
|
39 | static void (*orig__nwlog_pack)(os_log_pack_t pack, os_log_type_t logType);
|
40 |
|
41 | static void my__nwlog_pack(os_log_pack_t pack, os_log_type_t logType)
|
42 | {
|
43 | if (logType == OS_LOG_TYPE_ERROR && strstr(pack->olp_format, "Connection has no connected handler") == NULL) {
|
44 | orig__nwlog_pack(pack, logType);
|
45 | }
|
46 | }
|
47 |
|
48 | #endif
|
49 |
|
50 | static void (*orig_nwlog_legacy_v)(int, char*, va_list);
|
51 |
|
52 | static void my_nwlog_legacy_v(int level, char *format, va_list args) {
|
53 | static const uint buffer_size = 256;
|
54 | static char buffer[buffer_size];
|
55 | va_list copy;
|
56 | va_copy(copy, args);
|
57 | vsnprintf(buffer, buffer_size, format, copy);
|
58 | va_end(copy);
|
59 |
|
60 | if (strstr(buffer, "nw_connection_get_connected_socket_block_invoke") == NULL &&
|
61 | strstr(buffer, "Connection has no connected handler") == NULL) {
|
62 | orig_nwlog_legacy_v(level, format, args);
|
63 | }
|
64 | }
|
65 |
|
66 | #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
|
67 |
|
68 | static void (*orig_os_log_error_impl)(void *dso, os_log_t log, os_log_type_t type, const char *format, uint8_t *buf, uint32_t size);
|
69 |
|
70 | static void my_os_log_error_impl(void *dso, os_log_t log, os_log_type_t type, const char *format, uint8_t *buf, uint32_t size)
|
71 | {
|
72 | if (strstr(format, "TCP Conn %p Failed : error %ld:%d") == NULL) {
|
73 | orig_os_log_error_impl(dso, log, type, format, buf, size);
|
74 | }
|
75 | }
|
76 |
|
77 | #endif
|
78 |
|
79 | @interface RCTReconnectingWebSocket () <RCTSRWebSocketDelegate>
|
80 | @end
|
81 |
|
82 | @implementation RCTReconnectingWebSocket {
|
83 | NSURL *_url;
|
84 | RCTSRWebSocket *_socket;
|
85 | }
|
86 |
|
87 | + (void)load
|
88 | {
|
89 | static dispatch_once_t onceToken;
|
90 | dispatch_once(&onceToken, ^{
|
91 | rebind_symbols((struct rebinding[1]){
|
92 | {"nwlog_legacy_v", my_nwlog_legacy_v, (void *)&orig_nwlog_legacy_v}
|
93 | }, 1);
|
94 | #if __has_include(<os/log.h>) && defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100300
|
95 | rebind_symbols((struct rebinding[1]){
|
96 | {"__nwlog_pack", my__nwlog_pack, (void *)&orig__nwlog_pack}
|
97 | }, 1);
|
98 | #endif
|
99 | #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
|
100 | rebind_symbols((struct rebinding[1]){
|
101 | {"_os_log_error_impl", my_os_log_error_impl, (void *)&orig_os_log_error_impl}
|
102 | }, 1);
|
103 | #endif
|
104 | });
|
105 | }
|
106 |
|
107 | - (instancetype)initWithURL:(NSURL *)url queue:(dispatch_queue_t)queue
|
108 | {
|
109 | if (self = [super init]) {
|
110 | _url = url;
|
111 | _delegateDispatchQueue = queue;
|
112 | }
|
113 | return self;
|
114 | }
|
115 |
|
116 | - (instancetype)initWithURL:(NSURL *)url
|
117 | {
|
118 | return [self initWithURL:url queue:dispatch_get_main_queue()];
|
119 | }
|
120 |
|
121 | - (void)send:(id)data
|
122 | {
|
123 | [_socket send:data];
|
124 | }
|
125 |
|
126 | - (void)start
|
127 | {
|
128 | [self stop];
|
129 | _socket = [[RCTSRWebSocket alloc] initWithURL:_url];
|
130 | _socket.delegate = self;
|
131 | [_socket setDelegateDispatchQueue:_delegateDispatchQueue];
|
132 | [_socket open];
|
133 | }
|
134 |
|
135 | - (void)stop
|
136 | {
|
137 | _socket.delegate = nil;
|
138 | [_socket closeWithCode:1000 reason:@"Invalidated"];
|
139 | _socket = nil;
|
140 | }
|
141 |
|
142 | - (void)webSocket:(RCTSRWebSocket *)webSocket didReceiveMessage:(id)message
|
143 | {
|
144 | [_delegate reconnectingWebSocket:self didReceiveMessage:message];
|
145 | }
|
146 |
|
147 | - (void)reconnect
|
148 | {
|
149 | __weak RCTSRWebSocket *socket = _socket;
|
150 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
151 | [self start];
|
152 | if (!socket) {
|
153 | [self reconnect];
|
154 | }
|
155 | });
|
156 | }
|
157 |
|
158 | - (void)webSocketDidOpen:(RCTSRWebSocket *)webSocket
|
159 | {
|
160 | [_delegate reconnectingWebSocketDidOpen:self];
|
161 | }
|
162 |
|
163 | - (void)webSocket:(RCTSRWebSocket *)webSocket didFailWithError:(NSError *)error
|
164 | {
|
165 | [_delegate reconnectingWebSocketDidClose:self];
|
166 | [self reconnect];
|
167 | }
|
168 |
|
169 | - (void)webSocket:(RCTSRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean
|
170 | {
|
171 | [_delegate reconnectingWebSocketDidClose:self];
|
172 | [self reconnect];
|
173 | }
|
174 |
|
175 | @end
|
176 |
|
177 | #endif
|