/* * TurnServer, the OpenSource Java Solution for TURN protocol. Maintained by the * Jitsi community (http://jitsi.org). * * Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jitsi.turnserver.turnClient; import java.io.*; import java.net.*; import org.ice4j.*; import org.ice4j.attribute.*; import org.ice4j.message.*; import org.ice4j.socket.*; import org.ice4j.stack.*; import org.ice4j.stunclient.*; import org.jitsi.turnserver.collectors.AllocationResponseCollector; import org.jitsi.turnserver.listeners.*; import org.jitsi.turnserver.stack.*; /** * Class to run Allocation Client. * * @author Aakash Garg * */ public class TurnAllocationClient { private static BlockingRequestSender requestSender; private static IceUdpSocketWrapper sock; private static TurnStack turnStack; private static TransportAddress localAddress; private static TransportAddress serverAddress; private static boolean started; /** * The instance that should be notified when an incoming UDP message has * been processed and ready for delivery */ private PeerUdpMessageEventHandler peerUdpMessageEventHandler; /** * The instance that should be notified when an incoming ChannelData message * has been processed and ready for delivery */ private ChannelDataEventHandler channelDataEventHandler; /** * @param args * @throws IOException * @throws StunException * @throws InterruptedException */ public static void main(String[] args) throws IOException, StunException, InterruptedException { String[] temp = {InetAddress.getLocalHost().getHostAddress(),"3478"}; // String[] temp = {"176.31.40.85","3478"}; args = temp; Transport protocol = Transport.UDP; // uses args as server name and port localAddress = new TransportAddress(InetAddress.getLocalHost(), 5678, protocol); serverAddress = new TransportAddress(args[0], Integer.valueOf( args[1]).intValue(), protocol); System.out.println("Client adress : "+localAddress); System.out.println("Server adress : "+serverAddress); start(); StunMessageEvent evt = null; evt = sendAllocationRequest(localAddress,serverAddress); evt = sendCreatePermissionRequest(9999); evt = sendCreatePermissionRequest(9999); evt = sendCreatePermissionRequest(11000); TransportAddress peerAddr = new TransportAddress(InetAddress.getLocalHost(), 11000, protocol); evt = sendChannelBindRequest((char) 0x4000,peerAddr); sendChannelDataMessage(); System.out.println("Starting interactive communication."); doInteractiveComm(); /* System.out.println("Thread will now sleep."); Thread.sleep(600*1000); */ shutDown(); } public static StunMessageEvent sendAllocationRequest( TransportAddress localAddr, TransportAddress serverAddress) throws IOException { Request request = MessageFactory.createAllocateRequest(); RequestedTransportAttribute requestedTransportAttribute = AttributeFactory.createRequestedTransportAttribute( RequestedTransportAttribute.UDP); request.putAttribute(requestedTransportAttribute); StunMessageEvent evt = null; try { AllocationResponseCollector allocResCollec = new AllocationResponseCollector(turnStack); /* turnStack.sendRequest(request, serverAddress, localAddress, allocResCollec); */ evt = requestSender.sendRequestAndWaitForResponse( request, serverAddress); allocResCollec.processResponse((StunResponseEvent) evt); } catch (Exception ex) { //this shouldn't happen since we are the ones that created the //request ex.printStackTrace(); System.out.println("Internal Error. Failed to encode a message"); return null; } if(evt != null) System.out.println("Allocation TEST res=" +(int)(evt.getMessage().getMessageType()) +" - "+ evt.getRemoteAddress().getHostAddress()); else System.out.println("NO RESPONSE received to Allocation TEST."); return evt; } public static StunMessageEvent sendCreatePermissionRequest(int peerPort) throws IOException, StunException { System.out.println(); TransportAddress peerAddr = new TransportAddress( serverAddress.getAddress(), peerPort, Transport.UDP); TransactionID tran = TransactionID.createNewTransactionID(); System.out.println("Create request for : "+peerAddr); Request request = MessageFactory.createCreatePermissionRequest( peerAddr, tran.getBytes()); StunMessageEvent evt = null; System.out.println("Permission tran : "+tran); try { evt = requestSender.sendRequestAndWaitForResponse( request, serverAddress,tran); } catch (StunException ex) { //this shouldn't happen since we are the ones that created the //request System.out.println("Internal Error. Failed to encode a message"); return null; } if(evt != null) System.out.println("Permission TEST res=" +(int)(evt.getMessage().getMessageType()) +" - "+ evt.getRemoteAddress().getHostAddress()); else System.out.println("NO RESPONSE received to Permission TEST."); return evt; } public static StunMessageEvent sendChannelBindRequest( char channelNo, TransportAddress peerAddress) throws IOException, StunException { System.out.println(); System.out.println("ChannelBind request for : "+peerAddress +" on "+(int)channelNo); TransactionID tran = TransactionID.createNewTransactionID(); Request request = MessageFactory.createChannelBindRequest( channelNo, peerAddress, tran.getBytes()); char cNo = ((ChannelNumberAttribute) (request .getAttribute(Attribute.CHANNEL_NUMBER))).getChannelNumber(); TransportAddress pAddr = ((XorPeerAddressAttribute) (request .getAttribute(Attribute.XOR_PEER_ADDRESS))).getAddress(); XorMappedAddressAttribute mappedAddr = AttributeFactory.createXorMappedAddressAttribute( localAddress, tran.getBytes()); //mappedAddr.setAddress(mappedAddr.getAddress(), tran.getBytes()); System.out.println(">"+mappedAddr.getAddress()); request.putAttribute(mappedAddr); System.out.println("input mappedAddress : "+mappedAddr.getAddress()); XorMappedAddressAttribute retMapAddr = (XorMappedAddressAttribute) (request .getAttribute(Attribute.XOR_MAPPED_ADDRESS)); TransportAddress mAddr = (retMapAddr).getAddress(); System.out.println("output mappedAddress : "+mAddr.getHostAddress()); System.out.println("Retrived ChannelBind request is : "+pAddr +" on "+(int)cNo); StunMessageEvent evt = null; System.out.println("ChannelBind tran : "+tran); try { evt = requestSender.sendRequestAndWaitForResponse( request, serverAddress,tran); } catch (StunException ex) { //this shouldn't happen since we are the ones that created the //request System.out.println("Internal Error. Failed to encode a message"); return null; } if(evt != null) System.out.println("ChannelBind TEST res=" +evt.getRemoteAddress().toString() +" - "+ evt.getRemoteAddress().getHostAddress()); else System.out.println("NO RESPONSE received to ChannelBind TEST."); return evt; } public static void sendChannelDataMessage() throws StunException, IOException { byte[] message = {0xa,0xb}; ChannelData channelData = new ChannelData(); channelData.setChannelNumber((char)0x4000); channelData.setData(message); turnStack.sendChannelData(channelData, serverAddress, localAddress); System.out.println("ChannelData message sent."); } /** * Puts the discoverer into an operational state. * @throws IOException if we fail to bind. * @throws StunException if the stun4j stack fails start for some reason. */ public static void start() throws IOException, StunException { ClientChannelDataEventHandler channelDataHandler = new ClientChannelDataEventHandler(); turnStack = new TurnStack(null, channelDataHandler); channelDataHandler.setTurnStack(turnStack); sock = new IceUdpSocketWrapper( new SafeCloseDatagramSocket(localAddress)); turnStack.addSocket(sock); DataIndicationListener dataIndListener = new DataIndicationListener(turnStack); dataIndListener.setLocalAddress(localAddress); dataIndListener.start(); requestSender = new BlockingRequestSender(turnStack, localAddress); started = true; } public static void doInteractiveComm() throws IOException, StunException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Started interaction start typing message"); String line = br.readLine(); System.out.println("My first message : "+line); while(line!=null) { byte[] data = line.getBytes(); TransactionID tran = TransactionID.createNewTransactionID(); TransportAddress peerAddress = new TransportAddress( InetAddress.getLocalHost(), 11000, Transport.UDP); Indication ind = MessageFactory.createSendIndication(peerAddress, data, tran.getBytes()); System.out.println("Trying to send message to server"); turnStack.sendIndication(ind, serverAddress, localAddress); System.out.println("message sent"); System.out.println("Type a new message : "); line = br.readLine(); } } /** * Shuts down the underlying stack and prepares the object for garbage * collection. */ public static void shutDown() { turnStack.removeSocket(localAddress); sock.close(); sock = null; localAddress = null; requestSender = null; started = false; } }