1515
1616#if RCT_DEV // Only supported in dev mode
1717
18+ static const NSTimeInterval RCTReconnectInitialDelay = 2.0 ;
19+ static const NSTimeInterval RCTReconnectMaxDelay = 120.0 ;
20+
1821@interface RCTReconnectingWebSocket () <SRWebSocketDelegate>
1922@end
2023
2124@implementation RCTReconnectingWebSocket {
2225 NSURL *_url;
2326 SRWebSocket *_socket;
2427 BOOL _stopped;
28+ BOOL _reconnectPending;
29+ NSTimeInterval _reconnectDelay;
30+ uint64_t _reconnectToken;
2531}
2632
2733- (instancetype )initWithURL : (NSURL *)url queue : (dispatch_queue_t )queue
2834{
2935 if (self = [super init ]) {
3036 _url = url;
3137 _delegateDispatchQueue = queue;
38+ _reconnectDelay = RCTReconnectInitialDelay;
3239 }
3340 return self;
3441}
@@ -40,69 +47,138 @@ - (instancetype)initWithURL:(NSURL *)url
4047
4148- (void )send : (id )data
4249{
43- [_socket sendData: data error: nil ];
50+ SRWebSocket *socket;
51+ @synchronized (self) {
52+ socket = _socket;
53+ }
54+ [socket sendData: data error: nil ];
4455}
4556
46- - (void )start
57+ - (void )connect
4758{
48- [self stop ];
49- _stopped = NO ;
50- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: _url];
51- [[RCTDevSupportHttpHeaders sharedInstance ] applyHeadersToRequest: request];
52- _socket = [[SRWebSocket alloc ] initWithURLRequest: request];
53- _socket.delegate = self;
54- [_socket setDelegateDispatchQueue: _delegateDispatchQueue];
55- [_socket open ];
59+ SRWebSocket *socketToClose = nil ;
60+ NSMutableURLRequest *request = nil ;
61+ SRWebSocket *socket = nil ;
62+
63+ @synchronized (self) {
64+ if (_stopped) {
65+ return ;
66+ }
67+ _reconnectPending = NO ;
68+
69+ socketToClose = _socket;
70+ _socket.delegate = nil ;
71+ _socket = nil ;
72+
73+ request = [NSMutableURLRequest requestWithURL: _url];
74+ [[RCTDevSupportHttpHeaders sharedInstance ] applyHeadersToRequest: request];
75+ socket = [[SRWebSocket alloc ] initWithURLRequest: request];
76+ socket.delegate = self;
77+ [socket setDelegateDispatchQueue: _delegateDispatchQueue];
78+ _socket = socket;
79+ }
80+
81+ [socketToClose closeWithCode: 1000 reason: @" Invalidated" ];
82+ [socket open ];
5683}
5784
58- - (void )stop
85+ - (void )start
5986{
60- _stopped = YES ;
61- _socket.delegate = nil ;
62- [_socket closeWithCode: 1000 reason: @" Invalidated" ];
63- _socket = nil ;
87+ @synchronized (self) {
88+ _stopped = NO ;
89+ _reconnectPending = NO ;
90+ _reconnectToken++;
91+ _reconnectDelay = RCTReconnectInitialDelay;
92+ }
93+ [self connect ];
6494}
6595
66- - (void )webSocket : (SRWebSocket *) webSocket didReceiveMessage : ( id ) message
96+ - (void )stop
6797{
68- [_delegate reconnectingWebSocket: self didReceiveMessage: message];
98+ SRWebSocket *socketToClose = nil ;
99+ @synchronized (self) {
100+ _stopped = YES ;
101+ _reconnectPending = NO ;
102+ _reconnectToken++;
103+ _reconnectDelay = RCTReconnectInitialDelay;
104+ socketToClose = _socket;
105+ _socket.delegate = nil ;
106+ _socket = nil ;
107+ }
108+ [socketToClose closeWithCode: 1000 reason: @" Invalidated" ];
69109}
70110
71111- (void )reconnect
72112{
73- if (_stopped) {
74- return ;
113+ NSTimeInterval delay;
114+ uint64_t token;
115+ @synchronized (self) {
116+ if (_stopped || _reconnectPending) {
117+ return ;
118+ }
119+ _reconnectPending = YES ;
120+ token = ++_reconnectToken;
121+ delay = _reconnectDelay;
122+ _reconnectDelay = MIN (_reconnectDelay * 2 , RCTReconnectMaxDelay);
75123 }
76124
77- __weak SRWebSocket *socket = _socket;
78125 __weak __typeof (self) weakSelf = self;
79-
80- dispatch_after (dispatch_time (DISPATCH_TIME_NOW , (int64_t )(2 * NSEC_PER_SEC )), dispatch_get_main_queue (), ^{
81- [weakSelf start ];
82- if (!socket) {
83- [weakSelf reconnect ];
126+ dispatch_after (dispatch_time (DISPATCH_TIME_NOW , (int64_t )(delay * NSEC_PER_SEC )), dispatch_get_main_queue (), ^{
127+ __typeof (self) strongSelf = weakSelf;
128+ if (!strongSelf) {
129+ return ;
84130 }
131+ @synchronized (strongSelf) {
132+ if (strongSelf->_stopped || strongSelf->_reconnectToken != token) {
133+ return ;
134+ }
135+ }
136+ [strongSelf connect ];
85137 });
86138}
87139
88140- (void )webSocketDidOpen : (SRWebSocket *)webSocket
89141{
142+ @synchronized (self) {
143+ if (webSocket != _socket) {
144+ return ;
145+ }
146+ _reconnectDelay = RCTReconnectInitialDelay;
147+ }
90148 [_delegate reconnectingWebSocketDidOpen: self ];
91149}
92150
151+ - (void )webSocket : (SRWebSocket *)webSocket didReceiveMessage : (id )message
152+ {
153+ @synchronized (self) {
154+ if (webSocket != _socket) {
155+ return ;
156+ }
157+ }
158+ [_delegate reconnectingWebSocket: self didReceiveMessage: message];
159+ }
160+
93161- (void )webSocket : (SRWebSocket *)webSocket didFailWithError : (NSError *)error
94162{
95- [_delegate reconnectingWebSocketDidClose: self ];
96- if ([error code ] != ECONNREFUSED ) {
97- [self reconnect ];
163+ @synchronized (self) {
164+ if (webSocket != _socket) {
165+ return ;
166+ }
98167 }
168+ [_delegate reconnectingWebSocketDidClose: self ];
169+ [self reconnect ];
99170}
100171
101172- (void )webSocket : (SRWebSocket *)webSocket
102173 didCloseWithCode : (NSInteger )code
103174 reason : (NSString *)reason
104175 wasClean : (BOOL )wasClean
105176{
177+ @synchronized (self) {
178+ if (webSocket != _socket) {
179+ return ;
180+ }
181+ }
106182 [_delegate reconnectingWebSocketDidClose: self ];
107183 [self reconnect ];
108184}
0 commit comments