/** * Creates a listening point from the following address and attempts to * discover how it is mapped so that using inside the application is possible. * @param address the [address]:[port] pair where ther request should be * sent from. * @return a StunAddress object containing the mapped address or null if * discovery failed. * @throws StunException if something fails along the way. */ public virtual StunAddress GetMappingFor(StunAddress address) { NetAccessPointDescriptor apDesc = new NetAccessPointDescriptor(address); stunStack.InstallNetAccessPoint(apDesc); requestSender = new BlockingRequestSender(stunProvider, apDesc); StunMessageEvent evt = null; try { evt = requestSender.SendRequestAndWaitForResponse( MessageFactory.CreateBindingRequest(), serverAddress); } finally { //free the port to allow the application to use it. stunStack.RemoveNetAccessPoint(apDesc); } if (evt != null) { Response res = (Response)evt.GetMessage(); MappedAddressAttribute maAtt = (MappedAddressAttribute) res.GetAttribute(Attribute.MAPPED_ADDRESS); if (maAtt != null) { StunAddress sa = maAtt.GetAddress(); return(sa); } } return(null); }
/** * Called to notify this provider for an incoming message. * @param event the event object that contains the new message. */ public virtual void HandleMessageEvent(StunMessageEvent @event) { Message msg = @event.GetMessage(); //request if (msg is Request) { TransactionID serverTid = TransactionID. CreateTransactionID(msg.GetTransactionID()); serverTransactions.Add(serverTid); if (requestListener != null) { requestListener.requestReceived(@event); } } //response else if (msg is Response) { TransactionID tid = TransactionID. CreateTransactionID(msg.GetTransactionID()); StunClientTransaction tran = (StunClientTransaction)clientTransactions[tid]; clientTransactions.Remove(tid); if (tran != null) { tran.HandleResponse(@event); } else { //do nothing - just drop the phantom response. } } }
/** * Creates a listening point for the specified socket and attempts to * discover how its local address is NAT mapped. * @param socket the socket whose address needs to be resolved. * @return a StunAddress object containing the mapped address or null if * discovery failed. * @throws StunException if something fails along the way. */ public virtual StunAddress GetMappingFor(MyUdpClient socket) { NetAccessPointDescriptor apDesc = stunStack.InstallNetAccessPoint(socket); requestSender = new BlockingRequestSender(stunProvider, apDesc); StunMessageEvent evt = null; try { evt = requestSender.SendRequestAndWaitForResponse( MessageFactory.CreateBindingRequest(), serverAddress); } finally { stunStack.RemoveNetAccessPoint(apDesc); } if (evt != null) { Response res = (Response)evt.GetMessage(); MappedAddressAttribute maAtt = (MappedAddressAttribute) res.GetAttribute(Attribute.MAPPED_ADDRESS); if (maAtt != null) { return(maAtt.GetAddress()); } } return(null); }
/** * Sends a binding request to the specified server address with only change * port flag set to true and change IP flag - to false. * @param serverAddress the address where to send the bindingRequest. * @return The returned message encapsulating event or null if no message * was received. * @throws StunException if an exception occurs while sending the messge */ private StunMessageEvent doTestIII(StunAddress serverAddress) { Request request = MessageFactory.CreateBindingRequest(); ChangeRequestAttribute changeRequest = (ChangeRequestAttribute)request.GetAttribute(Attribute.CHANGE_REQUEST); changeRequest.SetChangeIpFlag(false); changeRequest.SetChangePortFlag(true); StunMessageEvent evt = requestSender.SendRequestAndWaitForResponse(request, serverAddress); #if false if (evt != null) { System.oout.println("Test III res=" + evt.getRemoteAddress().toString() + " - " + evt.getRemoteAddress().getHostName()); } else { Console.WriteLine("NO RESPONSE received to Test III."); } #endif return(evt); }
/** * Called to notify this provider for an incoming message. * @param event the event object that contains the new message. */ public virtual void HandleMessageEvent(StunMessageEvent @event) { Message msg = @event.GetMessage(); //request if(msg is Request) { TransactionID serverTid = TransactionID. CreateTransactionID(msg.GetTransactionID()); serverTransactions.Add(serverTid); if(requestListener != null) requestListener.requestReceived(@event); } //response else if(msg is Response) { TransactionID tid = TransactionID. CreateTransactionID(msg.GetTransactionID()); StunClientTransaction tran = (StunClientTransaction)clientTransactions[tid]; clientTransactions.Remove(tid); if(tran != null) { tran.HandleResponse(@event); } else { //do nothing - just drop the phantom response. } } }
/** * Does the message parsing. */ public virtual void Run() { //add an extra try/catch block that handles uncatched errors and helps avoid //having dead threads in our pools. try { while (isRunning) { RawMessage rawMessage = null; rawMessage = messageQueue.Remove(); // were we asked to stop? if (!IsRunning()) { return; } //anything to parse? if (rawMessage == null) { continue; } Message stunMessage = null; try { stunMessage = Message.Decode(rawMessage.GetBytes(), 0, rawMessage.GetMessageLength()); } catch (StunException ex) { errorHandler.HandleError("Failed to decode a stun mesage!", ex); continue; //let this one go and for better luck next time. } StunAddress sa = new StunAddress( rawMessage.GetRemoteAddress().GetAddress(), rawMessage.GetRemoteAddress().GetPort()); sa.Local = rawMessage.GetLocalAddress(); StunMessageEvent stunMessageEvent = new StunMessageEvent(rawMessage.GetNetAccessPoint(), stunMessage, sa); messageHandler.HandleMessageEvent(stunMessageEvent); } } catch (Exception err) { //notify and bail errorHandler.HandleFatalError(this, "Unexpected Error!", err); } }
/** * Saves the message event and notifies the discoverer thread so that * it may resume. * @param evt the newly arrived message event. */ public virtual void ProcessResponse(StunMessageEvent evt) { Monitor.Enter(this); try { this.responseEvent = evt; Monitor.PulseAll(this); } finally { Monitor.Exit(this); } }
/** * Sends the specified request and blocks until a response has been * received or the request transaction has timed out. * @param request the reuqest to send * @param serverAddress the request destination address * @return the event encapsulating the response or null if no response * has been received. * @throws StunException NETWORK_ERROR or other if we fail to send * the message */ public virtual StunMessageEvent SendRequestAndWaitForResponse( Request request, StunAddress serverAddress) { Monitor.Enter(this); try { stunProvider.SendRequest(request, serverAddress, apDescriptor, this); Monitor.Wait(this); StunMessageEvent res = responseEvent; responseEvent = null; //prepare for next message return(res); } finally { Monitor.Exit(this); } }
/** * Does the message parsing. */ public virtual void Run() { //add an extra try/catch block that handles uncatched errors and helps avoid //having dead threads in our pools. try { while (isRunning) { RawMessage rawMessage = null; rawMessage = messageQueue.Remove(); // were we asked to stop? if (!IsRunning()) return; //anything to parse? if (rawMessage == null) continue; Message stunMessage = null; try { stunMessage = Message.Decode(rawMessage.GetBytes(), 0, rawMessage.GetMessageLength()); } catch (StunException ex) { errorHandler.HandleError("Failed to decode a stun mesage!", ex); continue; //let this one go and for better luck next time. } StunAddress sa = new StunAddress( rawMessage.GetRemoteAddress().GetAddress(), rawMessage.GetRemoteAddress().GetPort() ); sa.Local = rawMessage.GetLocalAddress(); StunMessageEvent stunMessageEvent = new StunMessageEvent(rawMessage.GetNetAccessPoint(), stunMessage, sa); messageHandler.HandleMessageEvent(stunMessageEvent); } } catch(Exception err) { //notify and bail errorHandler.HandleFatalError(this, "Unexpected Error!", err); } }
/** * Dispatches the response then cancels itself and notifies the StunProvider * for its termination. * @param evt the event that contains the newly received message */ public virtual void HandleResponse(StunMessageEvent evt) { this.Cancel(); this.responseCollector.ProcessResponse(evt); }
/** * Sends the specified request and blocks until a response has been * received or the request transaction has timed out. * @param request the reuqest to send * @param serverAddress the request destination address * @return the event encapsulating the response or null if no response * has been received. * @throws StunException NETWORK_ERROR or other if we fail to send * the message */ public virtual StunMessageEvent SendRequestAndWaitForResponse( Request request, StunAddress serverAddress) { Monitor.Enter(this); try { stunProvider.SendRequest(request, serverAddress, apDescriptor, this); Monitor.Wait(this); StunMessageEvent res = responseEvent; responseEvent = null; //prepare for next message return res; } finally { Monitor.Exit(this); } }
/** * Implements the discovery process itself (see class description). * @return a StunDiscoveryReport containing details about the network * configuration of the host where the class is executed. * @throws StunException ILLEGAL_STATE if the discoverer has not been started * NETWORK_ERROR or ILLEGAL_ARGUMENT if a failure occurs while executing * the discovery algorithm */ virtual public StunDiscoveryReport determineAddress() { checkStarted(); StunDiscoveryReport report = new StunDiscoveryReport(); StunMessageEvent evt = doTestI(serverAddress); if (evt == null) { //UDP Blocked report.SetNatType(StunDiscoveryReport.UDP_BLOCKING_FIREWALL); return(report); } else { StunAddress mappedAddress = ((MappedAddressAttribute)evt.GetMessage(). GetAttribute(Attribute.MAPPED_ADDRESS)).GetAddress(); StunAddress backupServerAddress = ((ChangedAddressAttribute)evt.GetMessage(). GetAttribute(Attribute.CHANGED_ADDRESS)).GetAddress(); report.SetPublicAddress(mappedAddress); if (mappedAddress.Equals(apDescriptor.GetAddress())) { evt = doTestII(serverAddress); if (evt == null) { //Sym UDP Firewall report.SetNatType(StunDiscoveryReport.SYMMETRIC_UDP_FIREWALL); return(report); } else { //open internet report.SetNatType(StunDiscoveryReport.OPEN_INTERNET); return(report); } } else { evt = doTestII(serverAddress); if (evt == null) { evt = doTestI(backupServerAddress); if (evt == null) { // System.oout.println("Failed to receive a response from backup stun server!"); return(report); } StunAddress mappedAddress2 = ((MappedAddressAttribute)evt.GetMessage(). GetAttribute(Attribute.MAPPED_ADDRESS)).GetAddress(); if (mappedAddress.Equals(mappedAddress2)) { evt = doTestIII(serverAddress); if (evt == null) { //port restricted cone report.SetNatType(StunDiscoveryReport.PORT_RESTRICTED_CONE_NAT); return(report); } else { //restricted cone report.SetNatType(StunDiscoveryReport.RESTRICTED_CONE_NAT); return(report); } } else { //Symmetric NAT report.SetNatType(StunDiscoveryReport.SYMMETRIC_NAT); return(report); } } else { //full cone report.SetNatType(StunDiscoveryReport.FULL_CONE_NAT); return(report); } } } }