Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connection error never emitted on iOS #53

Closed
mi-mazouz opened this issue Jun 15, 2020 · 33 comments
Closed

Connection error never emitted on iOS #53

mi-mazouz opened this issue Jun 15, 2020 · 33 comments
Labels
bug Something isn't working iOS

Comments

@mi-mazouz
Copy link

mi-mazouz commented Jun 15, 2020

Description

Hello!!

I'm trying to create a tcp connection to an incorrect host (the ip is unreachable).

Here is my code:


...
private _device = null

private async openConnection(
        host,
        dataListenerCallback,
    ): Promise<void> {
        if (this._device) {
              this._device.destroy();
        }

        return new Promise((resolve, reject) => {
            this._device = net.createConnection({
                port: 53333,
                host,
                timeout: 1000,
            }, (socket) => {
                console.log('connected');
                resolve();
            });

            this._device.on('connect', () => {
                console.log('connect');
            });

            this._device.on('connection', () => {
                console.log('connnection');
            });

            this._device.on('error', (error) => {
                console.log('Error', error);
                reject();
            });

            this._device.on('data', dataListener);

            this._device.on('close', () => {
                console.log('Connection closed!');
            });
        });

Current behavior

this function never rejects or resolves.

Expected behavior

I expected to catch a connection error in the error event listener.

Relevant information

| react-native | 0.61.5 |
| react-native-tcp-socket | 3.7.1 |

@mi-mazouz mi-mazouz added the bug Something isn't working label Jun 15, 2020
@Rapsssito
Copy link
Owner

@mi-mazouz, thanks for the feedback! Currently, there is not official timeout support. I am working on it. There is JS code that acts as a timeout listener/event, but it is not fully tested and might not work in all circumstances. In the meantime, this is a possible workaround:

function connect(options) {
       return new Promise((resolve, reject) => {
            const tcpTimeout = setTimeout(() => {
                     reject('Timeout');
            }, 1000);
            const tcpSocket = net.createConnection(options, () => {
                    clearTimeout(tcpTimeout);
                    resolve();
                }
            );
      });
}

@Rapsssito Rapsssito changed the title Timeout/connection error never emitted Timeout never emitted Jun 15, 2020
@Rapsssito Rapsssito added feature request New feature or request and removed bug Something isn't working labels Jun 15, 2020
@mi-mazouz
Copy link
Author

mi-mazouz commented Jun 15, 2020

ok for the timeout but what about the connection error? What should happen if the connection fails?

@Rapsssito
Copy link
Owner

Rapsssito commented Jun 16, 2020

@mi-mazouz, if you are setting an "incorrect" IP, you should get an 'error' event with a message along the lines of "Host unreachable".

@mi-mazouz
Copy link
Author

mi-mazouz commented Jun 16, 2020

That's what I expected but I don't get this error

@Rapsssito
Copy link
Owner

@mi-mazouz, can you reproduce the bug using the example code?

@mi-mazouz
Copy link
Author

mi-mazouz commented Jun 16, 2020

@Rapsssito Yes you should be able to reproduce it using my code

@Rapsssito
Copy link
Owner

@mi-mazouz, I meant if you could reproduce the issue using the example code provided in the repository. You can comment out all the server references and test the client with your "incorrect" IP.

@mi-mazouz
Copy link
Author

mi-mazouz commented Jun 17, 2020

same with this code, nothing happened:


import React from 'react';
import {
    ScrollView,
    StyleSheet,
    Text,
    View,
} from 'react-native';
import TcpSocket from 'react-native-tcp-socket';

class App extends React.Component {
    constructor(props) {
        super(props);

        this.updateChatter = this.updateChatter.bind(this);
        this.state = { chatter: [] };
    }

    updateChatter(msg) {
        this.setState({
            chatter: this.state.chatter.concat([msg]),
        });
    }

    componentDidMount() {
        const serverPort = 53333;
        const serverHost = '192.1.1.1';
        // let server;
        let client;

        // server = TcpSocket.createServer((socket) => {
        //     this.updateChatter(`server connected on ${JSON.stringify(socket.address())}`);

        //     socket.on('data', (data) => {
        //         this.updateChatter(`Server Received: ${data}`);
        //         socket.write('Echo server\r\n');
        //     });

        //     socket.on('error', (error) => {
        //         this.updateChatter(`server client error ${error}`);
        //     });

        //     socket.on('close', (error) => {
        //         this.updateChatter(`server client closed ${error || ''}`);
        //     });
        // }).listen({ port: serverPort, host: serverHost, reuseAddress: true }, (address) => {
        //     this.updateChatter(`opened server on ${JSON.stringify(address)}`);
        // });

        // server.on('error', (error) => {
        //     this.updateChatter(`Server error ${error}`);
        // });

        // server.on('close', () => {
        //     this.updateChatter('server close');
        // });

        client = TcpSocket.createConnection({
            port: serverPort,
            host: serverHost,
        }, (address) => {
            this.updateChatter(`opened client on ${JSON.stringify(address)}`);
            client.write('Hello, server! Love, Client.');
        });

        client.on('data', (data) => {
            this.updateChatter(`Client Received: ${data}`);
            this.client.destroy(); // kill client after server's response
        });

        client.on('error', (error) => {
            this.updateChatter(`client error ${error}`);
        });

        client.on('close', () => {
            this.updateChatter('client close');
        });

        this.client = client;
    }

    componentWillUnmount() {
        this.client = null;
    }

    render() {
        return (
            <View style={styles.container}>
                <ScrollView>
                    {this.state.chatter.map((msg, index) => (
                        <Text key={index} style={styles.welcome}>
                            {msg}
                        </Text>
                    ))}
                </ScrollView>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

export default App;

anyway, the setTimeout does the job!

@Rapsssito
Copy link
Owner

Rapsssito commented Jun 17, 2020

@mi-mazouz, glad it works with setTimeout()! I am not able to reproduce the issue, the device on your 192.168.1.1 may be accepting the TCP connection and keeping it on hold forever (that's why you don't get any error).

I will be releasing a setTimeout() update soon (#56), it should work in all scenarios.

@Rapsssito Rapsssito added bug Something isn't working and removed feature request New feature or request labels Jun 17, 2020
@mi-mazouz
Copy link
Author

mi-mazouz commented Jun 17, 2020

same when I change the ip and I don't have any device on 192.168.1.1

@Rapsssito
Copy link
Owner

@mi-mazouz, what device are you using?

@mi-mazouz
Copy link
Author

mi-mazouz commented Jun 19, 2020

what do you mean? We use our own device but it does not change anything because the problem persists even if my device is off.

@Rapsssito
Copy link
Owner

@mi-mazouz, I mean what device are you using to test the app: iPhone, Huawei, Pixel...

@mi-mazouz
Copy link
Author

I'm testing with ios simulator

@Rapsssito Rapsssito changed the title Timeout never emitted Timeout never emitted on iOS Jun 19, 2020
@Rapsssito Rapsssito added the iOS label Jun 19, 2020
@Rapsssito
Copy link
Owner

@mi-mazouz, I am able to reproduce the bug on iOS. Working on it.

@mi-mazouz mi-mazouz changed the title Timeout never emitted on iOS Connection error never emitted on iOS Jun 22, 2020
@github-actions github-actions bot added the stale label Jul 29, 2020
@Rapsssito Rapsssito removed the stale label Jul 29, 2020
Repository owner deleted a comment from github-actions bot Jul 29, 2020
@mi-mazouz
Copy link
Author

hey @Rapsssito, do you have any news about this issue?

@Rapsssito
Copy link
Owner

@mi-mazouz, I have not been able to figure it out yet. I have came into the conclusion that it might be related to GCDAsyncSocket inner workings. I am still working on it. If you find anything, please let me know.

@github-actions github-actions bot added the stale label Sep 22, 2020
Repository owner deleted a comment from github-actions bot Sep 22, 2020
@Rapsssito Rapsssito removed the stale label Sep 22, 2020
@ewc003

This comment has been minimized.

@Rapsssito

This comment has been minimized.

@itzsankar
Copy link

itzsankar commented Mar 26, 2021

@Rapsssito I'm facing similar issue, but not in all the devices only iOS 14 with iphone 7,8,XR , In iPhone 11 with iOS 14 working fine.

Issue is occurring at first time ,when you back and do create connection, connection created successfully.

@Rapsssito
Copy link
Owner

@itzsankar I am currently working on a fix.

@Santhosh-kumark
Copy link

@Rapsssito Is there any update on this issue ?

@Rapsssito
Copy link
Owner

@Santhosh-kumark, yes! I found the problem, but I am really busy at the moment. The fix might take a while.

@Rapsssito
Copy link
Owner

@Santhosh-kumark @mi-mazouz, could you check if the issue still persists in the last version? I am testing on the iOS simulator without any timeout and after 1 minutes and 15 seconds I get an error in the error handler.

@itzsankar
Copy link

@Rapsssito I'm facing similar issue, but not in all the devices only iOS 14 with iphone 7,8,XR , In iPhone 11 with iOS 14 working fine.

Issue is occurring at first time ,when you back and do create connection, connection created successfully.

@Rapsssito Have you fixed this in the latest version?

@Santhosh-kumark
Copy link

@Rapsssito Mine was similar issue to #53 (comment) . Seems like this is not fixed in new version as well.

@Rapsssito
Copy link
Owner

@itzsankar @Santhosh-kumark, could you check if you get an error response after 2 minutes?

@mi-mazouz
Copy link
Author

mi-mazouz commented Apr 14, 2021

I updated the package to the latest version and tested this code:

import React from 'react';
import {
    StyleSheet,
    Text,
    View,
} from 'react-native';
import TcpSocket from 'react-native-tcp-socket';

class App extends React.Component {
    constructor(props) {
        super(props);

        this.updateChatter = this.updateChatter.bind(this);
        this.state = { chatter: ['hello'] };
    }

    updateChatter(msg) {
        this.setState({
            chatter: this.state.chatter.concat([msg]),
        });
    }

    componentDidMount() {
        const serverPort = 53333;
        const serverHost = '192.1.1.3';
        let client;

        client = TcpSocket.createConnection({
            port: serverPort,
            host: serverHost,
        }, (address) => {
            this.updateChatter(`opened client on ${JSON.stringify(address)}`);
            client.write('Hello, server! Love, Client.');
        });

        client.on('connect', () => {
            this.updateChatter('Client connect');
            console.log('CONNECT');
        });

        client.on('timeout', () => {
            this.updateChatter('Client timeout');
            console.log('TIMEOUT');
        });

        client.on('data', (data) => {
            console.log('DATA');
            this.updateChatter(`Client Received: ${data}`);
        });

        client.on('error', (error) => {
            console.log('ERROR');
            this.updateChatter(`client error ${error}`);
        });

        client.on('close', () => {
            console.log('CLOSE');
            this.updateChatter('client close');
        });

        this.client = client;
    }

    componentWillUnmount() {
        this.client = null;
    }

    render() {
        return (
            <View style={styles.container}>
                {this.state.chatter.map((msg, index) => (
                    <Text key={index} style={styles.welcome}>
                        {msg}
                    </Text>
                ))}
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'red',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        color: 'black',
        margin: 10,
    },
});

export default App;

and after 1 min and 15secs the error and close events were triggered so that's a good new.

@itzsankar
Copy link

@itzsankar @Santhosh-kumark, could you check if you get an error response after 2 minutes?

@Rapsssito , my problem is only in iPhone version other than 11 ,iOS 14 I'm not getting any response for first time, if I quit the app and connect it again, it is connecting perfectly. But in iPhone 11 with iOS 14 it is connecting for the first time itself without any issues.
Lower iOS versions no problem.

@mi-mazouz
Copy link
Author

mi-mazouz commented Apr 15, 2021

@Rapsssito I think timeout is not working well, with the following code timeout and createConnection callback are triggered:

 this._device = net.createConnection({
                port: TCP_PORT,
                host: deviceIp,
                timeout: 1500,
            }, (address) => {
                console.log('CONNECTED', address);
                resolve();
            });

            this._device.on('error', (error) => {
                console.log('ERROR', error);
            });

            this._device.on('timeout', (error) => {
                console.log('TIMEOUT', error);
            });

            this._device.on('data', dataListener);

if createConnection callback is triggered when the connection was successful timeout should not be triggered right?

@mi-mazouz
Copy link
Author

my bad this_.device.removeListener('timeout') in createConnection callback did the job!

@Rapsssito
Copy link
Owner

@mi-mazouz, I am glad it worked! If you agree, I think we can close this issue now. It has been a difficult problem to tackle.

@itzsankar, this issue has +30 comments right now. Could you please create a new issue with your problem, the devices with issues and a reproducible code?

@itzsankar
Copy link

@Rapsssito sure, I have created a new issue #106 we can track from there , let me know if you need any details

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working iOS
Projects
None yet
Development

No branches or pull requests

5 participants