3

Does anyone know how to do the TURN portion of Ice4j? I've managed to code it so that it works when the phone is on WiFi, but not when its on the mobile network.

I'm sending agent info via TCP and then building the connection manually instead of using a signalling process. The TCP connection already works fine, so I don't think its the TCP issue. Maybe I'm building the agent wrong?

I know that you're supposed to use a TURN server if STUN doesn't work, and I provided a large list of public TURN servers, but I might be missing something. Maybe the packets aren't being sent out properly?

Error: (Mostly Failed to send ALLOCATE-REQUEST(0X3))

Sep 11, 2014 3:36:09 PM org.ice4j.ice.Agent createMediaStream
INFO: Create media stream for data
Sep 11, 2014 3:36:09 PM org.ice4j.ice.Agent createComponent
INFO: Create component data.1
Sep 11, 2014 3:36:09 PM org.ice4j.ice.Agent gatherCandidates
INFO: Gather candidates for component data.1
Sep 11, 2014 3:36:09 PM org.ice4j.ice.harvest.HostCandidateHarvester harvest
INFO: End candidate harvest within 160 ms, for org.ice4j.ice.harvest.HostCandidateHarvester, component: 1
Sep 11, 2014 3:36:09 PM org.ice4j.ice.harvest.StunCandidateHarvest sendRequest
INFO: Failed to send ALLOCATE-REQUEST(0x3)[attrib.count=3 len=32 tranID=0x9909DC6648016A67FDD4B2D8] through /192.168.0.8:5001/udp to stun2.l.google.com:19302:5001/udp
Sep 11, 2014 3:36:12 PM org.ice4j.ice.ConnectivityCheckClient processTimeout
INFO: timeout for pair: /fe80:0:0:0:c8ce:5a17:c339:cc40%4:5001/udp -> /fe80:0:0:0:14e8:f3ff:fef3:6a21:6001/udp (data.1), failing.
Sep 11, 2014 3:36:12 PM org.ice4j.ice.ConnectivityCheckClient processTimeout
INFO: timeout for pair: /fe80:0:0:0:380d:2a4c:b350:eea8%8:5001/udp -> /fe80:0:0:0:14e8:f3ff:fef3:6a21:6001/udp (data.1), failing.
Sep 11, 2014 3:36:12 PM org.ice4j.ice.ConnectivityCheckClient processTimeout
INFO: timeout for pair: /192.168.0.8:5001/udp -> /100.64.74.58:6001/udp (data.1), failing.
Sep 11, 2014 3:36:12 PM org.ice4j.ice.ConnectivityCheckClient processTimeout
INFO: timeout for pair: /192.168.0.8:5001/udp -> /100.64.74.58:6001/udp (data.1), failing.
Sep 11, 2014 3:36:12 PM org.ice4j.ice.ConnectivityCheckClient updateCheckListAndTimerStates
INFO: CheckList will failed in a few seconds if nosucceeded checks come
Sep 11, 2014 3:36:17 PM org.ice4j.ice.ConnectivityCheckClient$1 run
INFO: CheckList for stream data FAILED
Sep 11, 2014 3:36:17 PM org.ice4j.ice.Agent checkListStatesUpdated
INFO: ICE state is FAILED

Script (Both the server and the client sides have similar codes to this one):

Agent agent = new Agent();
        agent.setControlling(false);

        StunCandidateHarvester stunHarv = new StunCandidateHarvester(new TransportAddress("sip-communicator.net", port, Transport.UDP));
        StunCandidateHarvester stun6Harv = new StunCandidateHarvester(new TransportAddress("ipv6.sip-communicator.net", port, Transport.UDP));

        agent.addCandidateHarvester(stunHarv);
        agent.addCandidateHarvester(stun6Harv);
        String[] hostnames = new String[] { "130.79.90.150",
                "2001:660:4701:1001:230:5ff:fe1a:805f",
                "jitsi.org",
                "numb.viagenie.ca",
                "stun01.sipphone.com",
                "stun.ekiga.net",
                "stun.fwdnet.net",
                "stun.ideasip.com",
                "stun.iptel.org",
                "stun.rixtelecom.se",
                "stun.schlund.de",
                "stun.l.google.com:19302",
                "stun1.l.google.com:19302",
                "stun2.l.google.com:19302",
                "stun3.l.google.com:19302",
                "stun4.l.google.com:19302",
                "stunserver.org",
                "stun.softjoys.com",
                "stun.voiparound.com",
                "stun.voipbuster.com",
                "stun.voipstunt.com",
                "stun.voxgratia.org",
                "stun.xten.com",};

        LongTermCredential longTermCredential = new LongTermCredential("guest", "anon");

        for (String hostname : hostnames)
            agent.addCandidateHarvester(new TurnCandidateHarvester(new TransportAddress(hostname, port, Transport.UDP), longTermCredential));

        //Build a stream for agent
        IceMediaStream stream = agent.createMediaStream("data");
        try {
            Component c = agent.createComponent(stream, Transport.UDP, port, port, port+100  );
            String response = "";
            List<LocalCandidate> remoteCandidates = c.getLocalCandidates();
            for(Candidate<?> can : remoteCandidates) {
                response += "||" + can.toString();
            }
            response = "Video||" + agent.getLocalUfrag() + "||" + agent.getLocalPassword() + "||" + c.getDefaultCandidate().toString() + response;
            System.out.println("Server >>> " + response);
            DataOutputStream outStream = new DataOutputStream(client.getOutputStream());
            outStream.write(response.getBytes("UTF-8"));
            outStream.flush();

            List<IceMediaStream> streams = agent.getStreams();
            for(IceMediaStream localStream : streams) {
                List<Component> localComponents = localStream.getComponents();
                for(Component localComponent : localComponents) {
                    for(int i = 3; i < info.length; i++) {
                        String[] detail = info[i].split(" ");   //0: Foundation
                                                                //1: Component ID
                                                                //2: Transport
                                                                //3: Priority #
                                                                //4: Address (Needed with Port # to create Transport Address)
                                                                //5: Port # (Needed with Address to create Transport Address)
                                                                //6: -filler: "Type" is next field-
                                                                //7: Candidate Type

                        String[] foundation = detail[0].split(":"); //Turn "Candidate:#" -> "Candidate" and "#". We use "#"

                        localComponent.addRemoteCandidate(new RemoteCandidate(new TransportAddress(detail[4], Integer.valueOf(detail[5]), Transport.UDP), c, CandidateType.HOST_CANDIDATE, foundation[1], Long.valueOf(detail[3]), null));
                    }
                    String[] defaultDetail = info[3].split(" ");
                    String[] defaultFoundation = defaultDetail[0].split(":");
                    localComponent.setDefaultRemoteCandidate(new RemoteCandidate(new TransportAddress(defaultDetail[4], Integer.valueOf(defaultDetail[5]), Transport.UDP), c, CandidateType.HOST_CANDIDATE, defaultFoundation[1], Long.valueOf(defaultDetail[3]), null));
                }
                localStream.setRemoteUfrag(info[1]);
                localStream.setRemotePassword(info[2]);
            }
            agent.startConnectivityEstablishment();
            System.out.println("ICEServer <><><> Completed");
putty174
  • 305
  • 5
  • 19
  • I'm starting to think that 4G does not allow UDP packets to be sent in either direction, which causes this to fail... – putty174 Apr 02 '15 at 20:06
  • Not sure how the output matches the code because the code shows using TurnCandidateHarvester instead of StunCandidateHarvester for what look like Stun servers. It also looks like the google stun server is port 19302 and not part of the url, not too sure.... – msj121 Apr 12 '15 at 17:51
  • I tried UDP to see if it would work, but I think I was having issues as well, but I haven't looked to deeply into it. You should know that Ice4J has a TCP approach as well. I am curious myself. Let me know if your at all interested. – msj121 Apr 13 '15 at 03:09
  • The TCP portion of the process works and a connection does get established on that path, but UDP doesn't. I'm not sure if the Ice4J test fails if either test fails, but I think that's what happened. What are you suggesting? – putty174 Apr 14 '15 at 00:12
  • Usually ICE uses UDP. Sometimes those are blocked, so you can use TCP to transmit the video/audio which cell networks definitely let through. I have noticed that the TCP protocol seems not to be finished and throws errors.... Are you using a TURN server? Your code is calling TURN servers when I think you want STUN.... – msj121 May 04 '15 at 12:56

1 Answers1

0

I realize now that your list of TURN servers seem to mostly actually be STUN servers (not sure about the first two). They should be added as STUN servers if anything:

 agent.addCandidateHarvester(
   new StunCandidateHarvester(
       new TransportAddress(
           InetAddress.getByName('stun.l.google.com'),
           19302,
           Transport.UDP)));
msj121
  • 2,812
  • 3
  • 28
  • 55