nodechan

decentralized peer-to-peer anonymous messageboard client
git clone git://squid-tech.com/nodechan.git
Log | Files | Refs | README

commit 98da868131065980ea6073d8f2c194912cd0aec0
parent 674a4736cefc8beb0472221fdbe5cad1e0192fd0
Author: joshiemoore <jxm5210@g.rit.edu>
Date:   Tue,  6 Aug 2019 12:34:55 -0400

Add basic build file

Diffstat:
Abuild.sh | 1+
Msrc/NodeChan.java | 2++
Msrc/WaifUPnP/Gateway.java | 2189++++++++-----------------------------------------------------------------------
Msrc/WaifUPnP/GatewayFinder.java | 1801++++++-------------------------------------------------------------------------
Msrc/WaifUPnP/UPnP.java | 1941+++++++------------------------------------------------------------------------
5 files changed, 493 insertions(+), 5441 deletions(-)

diff --git a/build.sh b/build.sh @@ -0,0 +1 @@ +javac -classpath .:/src/WaifUPnP src/NodeChan.java diff --git a/src/NodeChan.java b/src/NodeChan.java @@ -6,6 +6,8 @@ import java.io.InputStreamReader; import java.net.URL; import java.net.InetAddress; +import com.dosse.upnp; + /** * * NodeChan is a peer-to-peer distributed anonymous messageboard client. diff --git a/src/WaifUPnP/Gateway.java b/src/WaifUPnP/Gateway.java @@ -1,1985 +1,204 @@ - - - - - - -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <link rel="dns-prefetch" href="https://github.githubassets.com"> - <link rel="dns-prefetch" href="https://avatars0.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars1.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars2.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars3.githubusercontent.com"> - <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com"> - <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/"> - - - - <link crossorigin="anonymous" media="all" integrity="sha512-kBwTI/PLZvQ8eHdCgA2vpn0uJe4kEM/Ft7Zz5SAkc9BAifCxBxQS4VTaEIDJpVrbrlAhCeRJvf7DQWaA4dEUUQ==" rel="stylesheet" href="https://github.githubassets.com/assets/frameworks-da88be2d386821a8fa8de15789a23d23.css" /> - - <link crossorigin="anonymous" media="all" integrity="sha512-nxbIj3bfB8KtcNqQMnlOaPPMDmP9FiDWwjUpBLQy96vbpF72WO9aDrOU4TSu7T+fHKrBCeBWaRb9+keZgwcQlg==" rel="stylesheet" href="https://github.githubassets.com/assets/github-d7e1e4a3feb3fbdf6b2de5e69a10cb6e.css" /> - - - - - - <meta name="viewport" content="width=device-width"> - - <title>WaifUPnP/Gateway.java at master · adolfintel/WaifUPnP</title> - <meta name="description" content=" UPnP Port Forwarding for Java couldn&#39;t get any easier! - adolfintel/WaifUPnP"> - <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub"> - <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub"> - <meta property="fb:app_id" content="1401488693436528"> - - <meta name="twitter:image:src" content="https://avatars3.githubusercontent.com/u/16307689?s=400&amp;v=4" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary" /><meta name="twitter:title" content="adolfintel/WaifUPnP" /><meta name="twitter:description" content=" UPnP Port Forwarding for Java couldn&#39;t get any easier! - adolfintel/WaifUPnP" /> - <meta property="og:image" content="https://avatars3.githubusercontent.com/u/16307689?s=400&amp;v=4" /><meta property="og:site_name" content="GitHub" /><meta property="og:type" content="object" /><meta property="og:title" content="adolfintel/WaifUPnP" /><meta property="og:url" content="https://github.com/adolfintel/WaifUPnP" /><meta property="og:description" content=" UPnP Port Forwarding for Java couldn&#39;t get any easier! - adolfintel/WaifUPnP" /> - - <link rel="assets" href="https://github.githubassets.com/"> - <link rel="web-socket" href="wss://live.github.com/_sockets/VjI6NDI2ODEwNTUzOjg5NDI5N2JmN2Y3ZDhjZDVhMjNkZGNjZmQyMGEzMzU2YjU5ZjM1OWVjYzNhZDAyNTYzNGYzZDYzM2RmMWNjNGY=--646b8ae59c888585b81cedf035735f8da3a177be"> - <meta name="pjax-timeout" content="1000"> - <link rel="sudo-modal" href="/sessions/sudo_modal"> - <meta name="request-id" content="86A4:43DB:134C3D:219BEB:5D49A98A" data-pjax-transient> - - - - - <meta name="selected-link" value="repo_source" data-pjax-transient> - - <meta name="google-site-verification" content="KT5gs8h0wvaagLKAVWq8bbeNwnZZK1r1XQysX3xurLU"> - <meta name="google-site-verification" content="ZzhVyEFwb7w3e0-uOTltm8Jsck2F5StVihD0exw2fsA"> - <meta name="google-site-verification" content="GXs5KoUUkNCoaAZn7wPN-t01Pywp9M3sEjnt_3_ZWPc"> - - <meta name="octolytics-host" content="collector.githubapp.com" /><meta name="octolytics-app-id" content="github" /><meta name="octolytics-event-url" content="https://collector.githubapp.com/github-external/browser_event" /><meta name="octolytics-dimension-request_id" content="86A4:43DB:134C3D:219BEB:5D49A98A" /><meta name="octolytics-dimension-region_edge" content="iad" /><meta name="octolytics-dimension-region_render" content="iad" /><meta name="octolytics-actor-id" content="36491773" /><meta name="octolytics-actor-login" content="joshiemoore" /><meta name="octolytics-actor-hash" content="9fb9350a5ba47535efbba66a9fcc4ea37914a763e681b8faf401c837136a34a7" /> -<meta name="analytics-location" content="/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show" data-pjax-transient="true" /> - - - - - <meta class="js-ga-set" name="userId" content="70e439b4adcf1202f8343b7daf395cbf"> - -<meta class="js-ga-set" name="dimension1" content="Logged In"> - - - - - - <meta name="hostname" content="github.com"> - <meta name="user-login" content="joshiemoore"> - - <meta name="expected-hostname" content="github.com"> - <meta name="js-proxy-site-detection-payload" content="YWJhY2Q4N2U3YjUzM2RhNjljMjJjOGIxMGU4N2E4MTY0MTc4ZTU1ZTAyODVkOWE0NjljN2Q1ZTUwMGU0NzdhZnx7InJlbW90ZV9hZGRyZXNzIjoiNzEuMTE1LjE1MS4xNCIsInJlcXVlc3RfaWQiOiI4NkE0OjQzREI6MTM0QzNEOjIxOUJFQjo1RDQ5QTk4QSIsInRpbWVzdGFtcCI6MTU2NTEwODYyOCwiaG9zdCI6ImdpdGh1Yi5jb20ifQ=="> - - <meta name="enabled-features" content="MARKETPLACE_FEATURED_BLOG_POSTS,MARKETPLACE_INVOICED_BILLING,MARKETPLACE_SOCIAL_PROOF_CUSTOMERS,MARKETPLACE_TRENDING_SOCIAL_PROOF,MARKETPLACE_RECOMMENDATIONS,MARKETPLACE_PENDING_INSTALLATIONS,NOTIFY_ON_BLOCK,RELATED_ISSUES"> - - <meta name="html-safe-nonce" content="21324b34db3b2bdbb5f491c2f72dc9dfc36873ac"> - - <meta http-equiv="x-pjax-version" content="5a9990041a6b9c1bf57398c337e95d61"> - - - <link href="https://github.com/adolfintel/WaifUPnP/commits/master.atom" rel="alternate" title="Recent Commits to WaifUPnP:master" type="application/atom+xml"> - - <meta name="go-import" content="github.com/adolfintel/WaifUPnP git https://github.com/adolfintel/WaifUPnP.git"> - - <meta name="octolytics-dimension-user_id" content="16307689" /><meta name="octolytics-dimension-user_login" content="adolfintel" /><meta name="octolytics-dimension-repository_id" content="48129574" /><meta name="octolytics-dimension-repository_nwo" content="adolfintel/WaifUPnP" /><meta name="octolytics-dimension-repository_public" content="true" /><meta name="octolytics-dimension-repository_is_fork" content="false" /><meta name="octolytics-dimension-repository_network_root_id" content="48129574" /><meta name="octolytics-dimension-repository_network_root_nwo" content="adolfintel/WaifUPnP" /><meta name="octolytics-dimension-repository_explore_github_marketplace_ci_cta_shown" content="false" /> - - - <link rel="canonical" href="https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/Gateway.java" data-pjax-transient> - - - <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats"> - - <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors"> - - <link rel="mask-icon" href="https://github.githubassets.com/pinned-octocat.svg" color="#000000"> - <link rel="icon" type="image/x-icon" class="js-site-favicon" href="https://github.githubassets.com/favicon.ico"> - -<meta name="theme-color" content="#1e2327"> - - - - - - <link rel="manifest" href="/manifest.json" crossOrigin="use-credentials"> - - </head> - - <body class="logged-in env-production page-responsive page-blob"> - - - <div class="position-relative js-header-wrapper "> - <a href="#start-of-content" tabindex="1" class="p-3 bg-blue text-white show-on-focus js-skip-to-content">Skip to content</a> - <div id="js-pjax-loader-bar" class="pjax-loader-bar"><div class="progress"></div></div> - - - - - - - <header class="Header js-details-container Details flex-wrap flex-lg-nowrap p-responsive" role="banner"> - - <div class="Header-item d-none d-lg-flex"> - <a class="Header-link" href="https://github.com/" data-hotkey="g d" aria-label="Homepage" data-ga-click="Header, go to dashboard, icon:logo"> - <svg class="octicon octicon-mark-github v-align-middle" height="32" viewBox="0 0 16 16" version="1.1" width="32" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg> -</a> - - </div> - - <div class="Header-item d-lg-none"> - <button class="Header-link btn-link js-details-target" type="button" aria-label="Toggle navigation" aria-expanded="false"> - <svg height="24" class="octicon octicon-three-bars" viewBox="0 0 12 16" version="1.1" width="18" aria-hidden="true"><path fill-rule="evenodd" d="M11.41 9H.59C0 9 0 8.59 0 8c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zm0-4H.59C0 5 0 4.59 0 4c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zM.59 11H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1H.59C0 13 0 12.59 0 12c0-.59 0-1 .59-1z"/></svg> - </button> - </div> - - <div class="Header-item Header-item--full flex-column flex-lg-row width-full flex-order-2 flex-lg-order-none mr-0 mr-lg-3 mt-3 mt-lg-0 Details-content--hidden"> - <div class="header-search flex-self-stretch flex-lg-self-auto mr-0 mr-lg-3 mb-3 mb-lg-0 scoped-search site-scoped-search js-site-search position-relative js-jump-to" - role="combobox" - aria-owns="jump-to-results" - aria-label="Search or jump to" - aria-haspopup="listbox" - aria-expanded="false" -> - <div class="position-relative"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="js-site-search-form" role="search" aria-label="Site" data-scope-type="Repository" data-scope-id="48129574" data-scoped-search-url="/adolfintel/WaifUPnP/search" data-unscoped-search-url="/search" action="/adolfintel/WaifUPnP/search" accept-charset="UTF-8" method="get"><input name="utf8" type="hidden" value="&#x2713;" /> - <label class="form-control input-sm header-search-wrapper p-0 header-search-wrapper-jump-to position-relative d-flex flex-justify-between flex-items-center js-chromeless-input-container"> - <input type="text" - class="form-control input-sm header-search-input jump-to-field js-jump-to-field js-site-search-focus js-site-search-field is-clearable" - data-hotkey="s,/" - name="q" - value="" - placeholder="Search or jump to…" - data-unscoped-placeholder="Search or jump to…" - data-scoped-placeholder="Search or jump to…" - autocapitalize="off" - aria-autocomplete="list" - aria-controls="jump-to-results" - aria-label="Search or jump to…" - data-jump-to-suggestions-path="/_graphql/GetSuggestedNavigationDestinations#csrf-token=GCZW+PDc2/6ZvyV8nT3MSxgBSKzlwr4DEpP5SGTlQve0XF9xZWZdET5iUGEZ22Y3YnpUzmLu2C3i5/y3jCwJkA==" - spellcheck="false" - autocomplete="off" - > - <input type="hidden" class="js-site-search-type-field" name="type" > - <img src="https://github.githubassets.com/images/search-key-slash.svg" alt="" class="mr-2 header-search-key-slash"> - - <div class="Box position-absolute overflow-hidden d-none jump-to-suggestions js-jump-to-suggestions-container"> - -<ul class="d-none js-jump-to-suggestions-template-container"> - - -<li class="d-flex flex-justify-start flex-items-center p-0 f5 navigation-item js-navigation-item js-jump-to-suggestion" role="option"> - <a tabindex="-1" class="no-underline d-flex flex-auto flex-items-center jump-to-suggestions-path js-jump-to-suggestion-path js-navigation-open p-2" href=""> - <div class="jump-to-octicon js-jump-to-octicon flex-shrink-0 mr-2 text-center d-none"> - <svg height="16" width="16" class="octicon octicon-repo flex-shrink-0 js-jump-to-octicon-repo d-none" title="Repository" aria-label="Repository" viewBox="0 0 12 16" version="1.1" role="img"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <svg height="16" width="16" class="octicon octicon-project flex-shrink-0 js-jump-to-octicon-project d-none" title="Project" aria-label="Project" viewBox="0 0 15 16" version="1.1" role="img"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - <svg height="16" width="16" class="octicon octicon-search flex-shrink-0 js-jump-to-octicon-search d-none" title="Search" aria-label="Search" viewBox="0 0 16 16" version="1.1" role="img"><path fill-rule="evenodd" d="M15.7 13.3l-3.81-3.83A5.93 5.93 0 0 0 13 6c0-3.31-2.69-6-6-6S1 2.69 1 6s2.69 6 6 6c1.3 0 2.48-.41 3.47-1.11l3.83 3.81c.19.2.45.3.7.3.25 0 .52-.09.7-.3a.996.996 0 0 0 0-1.41v.01zM7 10.7c-2.59 0-4.7-2.11-4.7-4.7 0-2.59 2.11-4.7 4.7-4.7 2.59 0 4.7 2.11 4.7 4.7 0 2.59-2.11 4.7-4.7 4.7z"/></svg> - </div> - - <img class="avatar mr-2 flex-shrink-0 js-jump-to-suggestion-avatar d-none" alt="" aria-label="Team" src="" width="28" height="28"> - - <div class="jump-to-suggestion-name js-jump-to-suggestion-name flex-auto overflow-hidden text-left no-wrap css-truncate css-truncate-target"> - </div> - - <div class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none js-jump-to-badge-search"> - <span class="js-jump-to-badge-search-text-default d-none" aria-label="in this repository"> - In this repository - </span> - <span class="js-jump-to-badge-search-text-global d-none" aria-label="in all of GitHub"> - All GitHub - </span> - <span aria-hidden="true" class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - - <div aria-hidden="true" class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none d-on-nav-focus js-jump-to-badge-jump"> - Jump to - <span class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - </a> -</li> - -</ul> - -<ul class="d-none js-jump-to-no-results-template-container"> - <li class="d-flex flex-justify-center flex-items-center f5 d-none js-jump-to-suggestion p-2"> - <span class="text-gray">No suggested jump to results</span> - </li> -</ul> - -<ul id="jump-to-results" role="listbox" class="p-0 m-0 js-navigation-container jump-to-suggestions-results-container js-jump-to-suggestions-results-container"> - - -<li class="d-flex flex-justify-start flex-items-center p-0 f5 navigation-item js-navigation-item js-jump-to-scoped-search d-none" role="option"> - <a tabindex="-1" class="no-underline d-flex flex-auto flex-items-center jump-to-suggestions-path js-jump-to-suggestion-path js-navigation-open p-2" href=""> - <div class="jump-to-octicon js-jump-to-octicon flex-shrink-0 mr-2 text-center d-none"> - <svg height="16" width="16" class="octicon octicon-repo flex-shrink-0 js-jump-to-octicon-repo d-none" title="Repository" aria-label="Repository" viewBox="0 0 12 16" version="1.1" role="img"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <svg height="16" width="16" class="octicon octicon-project flex-shrink-0 js-jump-to-octicon-project d-none" title="Project" aria-label="Project" viewBox="0 0 15 16" version="1.1" role="img"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - <svg height="16" width="16" class="octicon octicon-search flex-shrink-0 js-jump-to-octicon-search d-none" title="Search" aria-label="Search" viewBox="0 0 16 16" version="1.1" role="img"><path fill-rule="evenodd" d="M15.7 13.3l-3.81-3.83A5.93 5.93 0 0 0 13 6c0-3.31-2.69-6-6-6S1 2.69 1 6s2.69 6 6 6c1.3 0 2.48-.41 3.47-1.11l3.83 3.81c.19.2.45.3.7.3.25 0 .52-.09.7-.3a.996.996 0 0 0 0-1.41v.01zM7 10.7c-2.59 0-4.7-2.11-4.7-4.7 0-2.59 2.11-4.7 4.7-4.7 2.59 0 4.7 2.11 4.7 4.7 0 2.59-2.11 4.7-4.7 4.7z"/></svg> - </div> - - <img class="avatar mr-2 flex-shrink-0 js-jump-to-suggestion-avatar d-none" alt="" aria-label="Team" src="" width="28" height="28"> - - <div class="jump-to-suggestion-name js-jump-to-suggestion-name flex-auto overflow-hidden text-left no-wrap css-truncate css-truncate-target"> - </div> - - <div class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none js-jump-to-badge-search"> - <span class="js-jump-to-badge-search-text-default d-none" aria-label="in this repository"> - In this repository - </span> - <span class="js-jump-to-badge-search-text-global d-none" aria-label="in all of GitHub"> - All GitHub - </span> - <span aria-hidden="true" class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - - <div aria-hidden="true" class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none d-on-nav-focus js-jump-to-badge-jump"> - Jump to - <span class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - </a> -</li> - - - -<li class="d-flex flex-justify-start flex-items-center p-0 f5 navigation-item js-navigation-item js-jump-to-global-search d-none" role="option"> - <a tabindex="-1" class="no-underline d-flex flex-auto flex-items-center jump-to-suggestions-path js-jump-to-suggestion-path js-navigation-open p-2" href=""> - <div class="jump-to-octicon js-jump-to-octicon flex-shrink-0 mr-2 text-center d-none"> - <svg height="16" width="16" class="octicon octicon-repo flex-shrink-0 js-jump-to-octicon-repo d-none" title="Repository" aria-label="Repository" viewBox="0 0 12 16" version="1.1" role="img"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <svg height="16" width="16" class="octicon octicon-project flex-shrink-0 js-jump-to-octicon-project d-none" title="Project" aria-label="Project" viewBox="0 0 15 16" version="1.1" role="img"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - <svg height="16" width="16" class="octicon octicon-search flex-shrink-0 js-jump-to-octicon-search d-none" title="Search" aria-label="Search" viewBox="0 0 16 16" version="1.1" role="img"><path fill-rule="evenodd" d="M15.7 13.3l-3.81-3.83A5.93 5.93 0 0 0 13 6c0-3.31-2.69-6-6-6S1 2.69 1 6s2.69 6 6 6c1.3 0 2.48-.41 3.47-1.11l3.83 3.81c.19.2.45.3.7.3.25 0 .52-.09.7-.3a.996.996 0 0 0 0-1.41v.01zM7 10.7c-2.59 0-4.7-2.11-4.7-4.7 0-2.59 2.11-4.7 4.7-4.7 2.59 0 4.7 2.11 4.7 4.7 0 2.59-2.11 4.7-4.7 4.7z"/></svg> - </div> - - <img class="avatar mr-2 flex-shrink-0 js-jump-to-suggestion-avatar d-none" alt="" aria-label="Team" src="" width="28" height="28"> - - <div class="jump-to-suggestion-name js-jump-to-suggestion-name flex-auto overflow-hidden text-left no-wrap css-truncate css-truncate-target"> - </div> - - <div class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none js-jump-to-badge-search"> - <span class="js-jump-to-badge-search-text-default d-none" aria-label="in this repository"> - In this repository - </span> - <span class="js-jump-to-badge-search-text-global d-none" aria-label="in all of GitHub"> - All GitHub - </span> - <span aria-hidden="true" class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - - <div aria-hidden="true" class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none d-on-nav-focus js-jump-to-badge-jump"> - Jump to - <span class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - </a> -</li> - - - <li class="d-flex flex-justify-center flex-items-center p-0 f5 js-jump-to-suggestion"> - <img src="https://github.githubassets.com/images/spinners/octocat-spinner-128.gif" alt="Octocat Spinner Icon" class="m-2" width="28"> - </li> -</ul> - - </div> - </label> -</form> </div> -</div> - - - <nav class="d-flex flex-column flex-lg-row flex-self-stretch flex-lg-self-auto" aria-label="Global"> - <a class="Header-link d-block d-lg-none py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-ga-click="Header, click, Nav menu - item:dashboard:user" aria-label="Dashboard" href="/dashboard"> - Dashboard -</a> - <a class="js-selected-navigation-item Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-hotkey="g p" data-ga-click="Header, click, Nav menu - item:pulls context:user" aria-label="Pull requests you created" data-selected-links="/pulls /pulls/assigned /pulls/mentioned /pulls" href="/pulls"> - Pull requests -</a> - <a class="js-selected-navigation-item Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-hotkey="g i" data-ga-click="Header, click, Nav menu - item:issues context:user" aria-label="Issues you created" data-selected-links="/issues /issues/assigned /issues/mentioned /issues" href="/issues"> - Issues -</a> - <div class="mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15"> - <a class="js-selected-navigation-item Header-link" data-ga-click="Header, click, Nav menu - item:marketplace context:user" data-octo-click="marketplace_click" data-octo-dimensions="location:nav_bar" data-selected-links=" /marketplace" href="/marketplace"> - Marketplace -</a> - </div> - - <a class="js-selected-navigation-item Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-ga-click="Header, click, Nav menu - item:explore" data-selected-links="/explore /trending /trending/developers /integrations /integrations/feature/code /integrations/feature/collaborate /integrations/feature/ship showcases showcases_search showcases_landing /explore" href="/explore"> - Explore -</a> - - - <a class="Header-link d-block d-lg-none mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" href="https://github.com/joshiemoore"> - <img class="avatar" height="20" width="20" alt="@joshiemoore" src="https://avatars3.githubusercontent.com/u/36491773?s=60&amp;v=4" /> - joshiemoore -</a> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form action="/logout" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="1orWvBX9Db4RY9CFhLi0cVXR14RRvsq5ugNSzxpQdYAnLVWf1L3qguN5PoWufwOJg4SElMueN7HMPAPlhLSJIg==" /> - <button type="submit" class="Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15 d-lg-none btn-link d-block width-full text-left" data-ga-click="Header, sign out, icon:logout" style="padding-left: 2px;"> - <svg class="octicon octicon-sign-out v-align-middle" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 9V7H8V5h4V3l4 3-4 3zm-2 3H6V3L2 1h8v3h1V1c0-.55-.45-1-1-1H1C.45 0 0 .45 0 1v11.38c0 .39.22.73.55.91L6 16.01V13h4c.55 0 1-.45 1-1V8h-1v4z"/></svg> - Sign out - </button> -</form></nav> - - </div> - - <div class="Header-item Header-item--full flex-justify-center d-lg-none position-relative"> - <div class="css-truncate css-truncate-target width-fit position-absolute left-0 right-0 text-center"> - <svg class="octicon octicon-repo" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <a class="Header-link" href="/adolfintel">adolfintel</a> - / - <a class="Header-link" href="/adolfintel/WaifUPnP">WaifUPnP</a> - -</div> - </div> - - <div class="Header-item position-relative d-none d-lg-flex"> - - - </div> - - <div class="Header-item mr-0 mr-lg-3 flex-order-1 flex-lg-order-none"> - - - <a aria-label="You have no unread notifications" class="Header-link notification-indicator position-relative tooltipped tooltipped-s js-socket-channel js-notification-indicator" data-hotkey="g n" data-ga-click="Header, go to notifications, icon:read" data-channel="notification-changed:36491773" href="/notifications"> - <span class="mail-status "></span> - <svg class="octicon octicon-bell" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14 12v1H0v-1l.73-.58c.77-.77.81-2.55 1.19-4.42C2.69 3.23 6 2 6 2c0-.55.45-1 1-1s1 .45 1 1c0 0 3.39 1.23 4.16 5 .38 1.88.42 3.66 1.19 4.42l.66.58H14zm-7 4c1.11 0 2-.89 2-2H5c0 1.11.89 2 2 2z"/></svg> -</a> - </div> - - - <div class="Header-item position-relative d-none d-lg-flex"> - <details class="details-overlay details-reset"> - <summary class="Header-link" - aria-label="Create new…" - data-ga-click="Header, create new, icon:add"> - <svg class="octicon octicon-plus" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 9H7v5H5V9H0V7h5V2h2v5h5v2z"/></svg> <span class="dropdown-caret"></span> - </summary> - <details-menu class="dropdown-menu dropdown-menu-sw"> - -<a role="menuitem" class="dropdown-item" href="/new" data-ga-click="Header, create new repository"> - New repository -</a> - - <a role="menuitem" class="dropdown-item" href="/new/import" data-ga-click="Header, import a repository"> - Import repository - </a> - -<a role="menuitem" class="dropdown-item" href="https://gist.github.com/" data-ga-click="Header, create new gist"> - New gist -</a> - - <a role="menuitem" class="dropdown-item" href="/organizations/new" data-ga-click="Header, create new organization"> - New organization - </a> - - - <div role="none" class="dropdown-divider"></div> - <div class="dropdown-header"> - <span title="adolfintel/WaifUPnP">This repository</span> - </div> - <a role="menuitem" class="dropdown-item" href="/adolfintel/WaifUPnP/issues/new" data-ga-click="Header, create new issue" data-skip-pjax> - New issue - </a> - - - </details-menu> -</details> - - </div> - - <div class="Header-item position-relative mr-0 d-none d-lg-flex"> - -<details class="details-overlay details-reset"> - <summary class="Header-link" - aria-label="View profile and more" - data-ga-click="Header, show menu, icon:avatar"> - <img alt="@joshiemoore" class="avatar" src="https://avatars0.githubusercontent.com/u/36491773?s=40&amp;v=4" height="20" width="20"> - <span class="dropdown-caret"></span> - </summary> - <details-menu class="dropdown-menu dropdown-menu-sw mt-2" style="width: 180px"> - <div class="header-nav-current-user css-truncate"><a role="menuitem" class="no-underline user-profile-link px-3 pt-2 pb-2 mb-n2 mt-n1 d-block" href="/joshiemoore" data-ga-click="Header, go to profile, text:Signed in as">Signed in as <strong class="css-truncate-target">joshiemoore</strong></a></div> - <div role="none" class="dropdown-divider"></div> - - <div class="pl-3 pr-3 f6 user-status-container js-user-status-context pb-1" data-url="/users/status?compact=1&amp;link_mentions=0&amp;truncate=1"> - -<div class="js-user-status-container - user-status-compact rounded-1 px-2 py-1 mt-2 - border - " data-team-hovercards-enabled> - <details class="js-user-status-details details-reset details-overlay details-overlay-dark"> - <summary class="btn-link btn-block link-gray no-underline js-toggle-user-status-edit toggle-user-status-edit " aria-haspopup="dialog" role="menuitem" data-hydro-click="{&quot;event_type&quot;:&quot;user_profile.click&quot;,&quot;payload&quot;:{&quot;profile_user_id&quot;:16307689,&quot;target&quot;:&quot;EDIT_USER_STATUS&quot;,&quot;user_id&quot;:36491773,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134C3D:219BEB:5D49A98A&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/Gateway.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;}}" data-hydro-click-hmac="fc9f93fbf5af52dd083c7782ec8be7d0c6078e898cc9f3a0ac62513bce8b5bc3"> - <div class="d-flex"> - <div class="f6 lh-condensed user-status-header - d-inline-block v-align-middle - user-status-emoji-only-header circle - pr-2 -" - style="max-width: 29px" - > - <div class="user-status-emoji-container flex-shrink-0 mr-1 mt-1 lh-condensed-ultra v-align-bottom" style=""> - <svg class="octicon octicon-smiley" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm4.81 12.81a6.72 6.72 0 0 1-2.17 1.45c-.83.36-1.72.53-2.64.53-.92 0-1.81-.17-2.64-.53-.81-.34-1.55-.83-2.17-1.45a6.773 6.773 0 0 1-1.45-2.17A6.59 6.59 0 0 1 1.21 8c0-.92.17-1.81.53-2.64.34-.81.83-1.55 1.45-2.17.62-.62 1.36-1.11 2.17-1.45A6.59 6.59 0 0 1 8 1.21c.92 0 1.81.17 2.64.53.81.34 1.55.83 2.17 1.45.62.62 1.11 1.36 1.45 2.17.36.83.53 1.72.53 2.64 0 .92-.17 1.81-.53 2.64-.34.81-.83 1.55-1.45 2.17zM4 6.8v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2H5.2C4.53 8 4 7.47 4 6.8zm5 0v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2h-.59C9.53 8 9 7.47 9 6.8zm4 3.2c-.72 1.88-2.91 3-5 3s-4.28-1.13-5-3c-.14-.39.23-1 .66-1h8.59c.41 0 .89.61.75 1z"/></svg> - </div> - </div> - <div class=" - d-inline-block v-align-middle - - - css-truncate css-truncate-target - user-status-message-wrapper f6" - style="line-height: 20px;" > - <div class="d-inline-block text-gray-dark v-align-text-top text-left"> - <span class="text-gray ml-2">Set status</span> - </div> - </div> - </div> -</summary> <details-dialog class="details-dialog rounded-1 anim-fade-in fast Box Box--overlay" role="dialog" tabindex="-1"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="position-relative flex-auto js-user-status-form" action="/users/status?compact=1&amp;link_mentions=0&amp;truncate=1" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="_method" value="put" /><input type="hidden" name="authenticity_token" value="c1TPliSOsl76JtGVJ1icSYZopdGLKUXB0OlnwWs2q/Hwaj1kDltUHy1PO73jbMl6YSpD0h17rHRt7SDeDoxyOQ==" /> - <div class="Box-header bg-gray border-bottom p-3"> - <button class="Box-btn-octicon js-toggle-user-status-edit btn-octicon float-right" type="reset" aria-label="Close dialog" data-close-dialog> - <svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg> - </button> - <h3 class="Box-title f5 text-bold text-gray-dark">Edit status</h3> - </div> - <input type="hidden" name="emoji" class="js-user-status-emoji-field" value=""> - <input type="hidden" name="organization_id" class="js-user-status-org-id-field" value=""> - <div class="px-3 py-2 text-gray-dark"> - <div class="js-characters-remaining-container position-relative mt-2"> - <div class="input-group d-table form-group my-0 js-user-status-form-group"> - <span class="input-group-button d-table-cell v-align-middle" style="width: 1%"> - <button type="button" aria-label="Choose an emoji" class="btn-outline btn js-toggle-user-status-emoji-picker btn-open-emoji-picker p-0"> - <span class="js-user-status-original-emoji" hidden></span> - <span class="js-user-status-custom-emoji"></span> - <span class="js-user-status-no-emoji-icon" > - <svg class="octicon octicon-smiley" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm4.81 12.81a6.72 6.72 0 0 1-2.17 1.45c-.83.36-1.72.53-2.64.53-.92 0-1.81-.17-2.64-.53-.81-.34-1.55-.83-2.17-1.45a6.773 6.773 0 0 1-1.45-2.17A6.59 6.59 0 0 1 1.21 8c0-.92.17-1.81.53-2.64.34-.81.83-1.55 1.45-2.17.62-.62 1.36-1.11 2.17-1.45A6.59 6.59 0 0 1 8 1.21c.92 0 1.81.17 2.64.53.81.34 1.55.83 2.17 1.45.62.62 1.11 1.36 1.45 2.17.36.83.53 1.72.53 2.64 0 .92-.17 1.81-.53 2.64-.34.81-.83 1.55-1.45 2.17zM4 6.8v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2H5.2C4.53 8 4 7.47 4 6.8zm5 0v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2h-.59C9.53 8 9 7.47 9 6.8zm4 3.2c-.72 1.88-2.91 3-5 3s-4.28-1.13-5-3c-.14-.39.23-1 .66-1h8.59c.41 0 .89.61.75 1z"/></svg> - </span> - </button> - </span> - <text-expander keys=": @" data-mention-url="/autocomplete/user-suggestions" data-emoji-url="/autocomplete/emoji"> - <input - type="text" - autocomplete="off" - data-no-org-url="/autocomplete/user-suggestions" - data-org-url="/suggestions?mention_suggester=1" - data-maxlength="80" - class="d-table-cell width-full form-control js-user-status-message-field js-characters-remaining-field" - placeholder="What's happening?" - name="message" - value="" - aria-label="What is your current status?"> - </text-expander> - <div class="error">Could not update your status, please try again.</div> - </div> - <div style="margin-left: 53px" class="my-1 text-small label-characters-remaining js-characters-remaining" data-suffix="remaining" hidden> - 80 remaining - </div> - </div> - <include-fragment class="js-user-status-emoji-picker" data-url="/users/status/emoji"></include-fragment> - <div class="overflow-auto ml-n3 mr-n3 px-3 border-bottom" style="max-height: 33vh"> - <div class="user-status-suggestions js-user-status-suggestions collapsed overflow-hidden"> - <h4 class="f6 text-normal my-3">Suggestions:</h4> - <div class="mx-3 mt-2 clearfix"> - <div class="float-left col-6"> - <button type="button" value=":palm_tree:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="palm_tree" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f334.png">🌴</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - On vacation - </div> - </button> - <button type="button" value=":face_with_thermometer:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="face_with_thermometer" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f912.png">🤒</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - Out sick - </div> - </button> - </div> - <div class="float-left col-6"> - <button type="button" value=":house:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="house" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f3e0.png">🏠</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - Working from home - </div> - </button> - <button type="button" value=":dart:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="dart" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f3af.png">🎯</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - Focusing - </div> - </button> - </div> - </div> - </div> - <div class="user-status-limited-availability-container"> - <div class="form-checkbox my-0"> - <input type="checkbox" name="limited_availability" value="1" class="js-user-status-limited-availability-checkbox" data-default-message="I may be slow to respond." aria-describedby="limited-availability-help-text-truncate-true-compact-true" id="limited-availability-truncate-true-compact-true"> - <label class="d-block f5 text-gray-dark mb-1" for="limited-availability-truncate-true-compact-true"> - Busy - </label> - <p class="note" id="limited-availability-help-text-truncate-true-compact-true"> - When others mention you, assign you, or request your review, - GitHub will let them know that you have limited availability. - </p> - </div> - </div> - </div> - - -<div class="d-inline-block f5 mr-2 pt-3 pb-2" > - <div class="d-inline-block mr-1"> - Clear status - </div> - - <details class="js-user-status-expire-drop-down f6 dropdown details-reset details-overlay d-inline-block mr-2"> - <summary class="f5 btn-link link-gray-dark border px-2 py-1 rounded-1" aria-haspopup="true"> - <div class="js-user-status-expiration-interval-selected d-inline-block v-align-baseline"> - Never - </div> - <div class="dropdown-caret"></div> - </summary> - - <ul class="dropdown-menu dropdown-menu-se pl-0 overflow-auto" style="width: 220px; max-height: 15.5em"> - <li> - <button type="button" class="btn-link dropdown-item js-user-status-expire-button ws-normal" title="Never"> - <span class="d-inline-block text-bold mb-1">Never</span> - <div class="f6 lh-condensed">Keep this status until you clear your status or edit your status.</div> - </button> - </li> - <li class="dropdown-divider" role="none"></li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="in 30 minutes" value="2019-08-06T12:53:48-04:00"> - in 30 minutes - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="in 1 hour" value="2019-08-06T13:23:48-04:00"> - in 1 hour - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="in 4 hours" value="2019-08-06T16:23:48-04:00"> - in 4 hours - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="today" value="2019-08-06T23:59:59-04:00"> - today - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="this week" value="2019-08-11T23:59:59-04:00"> - this week - </button> - </li> - </ul> - </details> - <input class="js-user-status-expiration-date-input" type="hidden" name="expires_at" value=""> -</div> - - <include-fragment class="js-user-status-org-picker" data-url="/users/status/organizations"></include-fragment> - </div> - <div class="d-flex flex-items-center flex-justify-between p-3 border-top"> - <button type="submit" disabled class="width-full btn btn-primary mr-2 js-user-status-submit"> - Set status - </button> - <button type="button" disabled class="width-full js-clear-user-status-button btn ml-2 "> - Clear status - </button> - </div> -</form> </details-dialog> - </details> -</div> - - </div> - <div role="none" class="dropdown-divider"></div> - - - <a role="menuitem" class="dropdown-item" href="/joshiemoore" data-ga-click="Header, go to profile, text:your profile">Your profile</a> - - - <a role="menuitem" class="dropdown-item" href="/joshiemoore?tab=repositories" data-ga-click="Header, go to repositories, text:your repositories">Your repositories</a> - - <a role="menuitem" class="dropdown-item" href="/joshiemoore?tab=projects" data-ga-click="Header, go to projects, text:your projects">Your projects</a> - - <a role="menuitem" class="dropdown-item" href="/joshiemoore?tab=stars" data-ga-click="Header, go to starred repos, text:your stars">Your stars</a> - <a role="menuitem" class="dropdown-item" href="https://gist.github.com/mine" data-ga-click="Header, your gists, text:your gists">Your gists</a> - - - <div role="none" class="dropdown-divider"></div> - <a role="menuitem" class="dropdown-item" href="https://help.github.com" data-ga-click="Header, go to help, text:help">Help</a> - <a role="menuitem" class="dropdown-item" href="/settings/profile" data-ga-click="Header, go to settings, icon:settings">Settings</a> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="logout-form" action="/logout" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="I7ujv+WlO+Fo9tDziAKvv+MvNJTFajebfKxWdgwDTEDSHCCcJOXc3ZrsPvOixRhHNXpnhF9KypMKkwdckuew4g==" /> - - <button type="submit" class="dropdown-item dropdown-signout" data-ga-click="Header, sign out, icon:logout" role="menuitem"> - Sign out - </button> -</form> </details-menu> -</details> - - </div> - - </header> - - - - </div> - - <div id="start-of-content" class="show-on-focus"></div> - - - <div id="js-flash-container"> - -</div> - - - - <div class="application-main " data-commit-hovercards-enabled> - <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class=""> - <main > - - - - - - - - - - - - - <div class="pagehead repohead instapaper_ignore readability-menu experiment-repo-nav pt-0 pt-lg-4 "> - <div class="repohead-details-container clearfix container-lg p-responsive d-none d-lg-block"> - - <ul class="pagehead-actions"> - - - - - <li> - - <!-- '"` --><!-- </textarea></xmp> --></option></form><form data-remote="true" class="clearfix js-social-form js-social-container" action="/notifications/subscribe" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="C2gW/0utI24L2GCPBzE54Lkfx4Gox/MtfQWZDQowlEvO7MmubLWjsMiOu2UrgQyBfdbYGnkQ00c+LAdGIq17yw==" /> <input type="hidden" name="repository_id" value="48129574"> - - <details class="details-reset details-overlay select-menu float-left"> - <summary class="select-menu-button float-left btn btn-sm btn-with-count" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;WATCH_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134C3D:219BEB:5D49A98A&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/Gateway.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="1fc5745a0a40636da03732126c93fccffce22e2f6f820a7c598ac95e813d0c49" data-ga-click="Repository, click Watch settings, action:blob#show"> <span data-menu-button> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Watch - </span> -</summary> <details-menu - class="select-menu-modal position-absolute mt-5" - style="z-index: 99;"> - <div class="select-menu-header"> - <span class="select-menu-title">Notifications</span> - </div> - <div class="select-menu-list"> - <button type="submit" name="do" value="included" class="select-menu-item width-full" aria-checked="true" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Not watching</span> - <span class="description">Be notified only when participating or @mentioned.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Watch - </span> - </div> - </button> - - <button type="submit" name="do" value="release_only" class="select-menu-item width-full" aria-checked="false" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Releases only</span> - <span class="description">Be notified of new releases, and when participating or @mentioned.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Unwatch releases - </span> - </div> - </button> - - <button type="submit" name="do" value="subscribed" class="select-menu-item width-full" aria-checked="false" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Watching</span> - <span class="description">Be notified of all conversations.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Unwatch - </span> - </div> - </button> - - <button type="submit" name="do" value="ignore" class="select-menu-item width-full" aria-checked="false" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Ignoring</span> - <span class="description">Never be notified.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-mute v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 2.81v10.38c0 .67-.81 1-1.28.53L3 10H1c-.55 0-1-.45-1-1V7c0-.55.45-1 1-1h2l3.72-3.72C7.19 1.81 8 2.14 8 2.81zm7.53 3.22l-1.06-1.06-1.97 1.97-1.97-1.97-1.06 1.06L11.44 8 9.47 9.97l1.06 1.06 1.97-1.97 1.97 1.97 1.06-1.06L13.56 8l1.97-1.97z"/></svg> - Stop ignoring - </span> - </div> - </button> - </div> - </details-menu> - </details> - <a class="social-count js-social-count" - href="/adolfintel/WaifUPnP/watchers" - aria-label="4 users are watching this repository"> - 4 - </a> -</form> - </li> - - <li> - <div class="js-toggler-container js-social-container starring-container on"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="starred js-social-form" action="/adolfintel/WaifUPnP/unstar" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="04AufysMu7U1ZAJhIe3zI6nMKtVjmHHPeOw1BPFMOUjL1k5IOJ+OC7JUFFp8f2e2fuDQOGBwQuKRig4DHMdwQA==" /> - <input type="hidden" name="context" value="repository"></input> - <button type="submit" class="btn btn-sm btn-with-count js-toggler-target" aria-label="Unstar this repository" title="Unstar adolfintel/WaifUPnP" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;UNSTAR_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134C3D:219BEB:5D49A98A&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/Gateway.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="91a2569c5d3d44842c4bb6b543c65c10af99aaf0a1e4f699e28bbe2fd26a8ba1" data-ga-click="Repository, click unstar button, action:blob#show; text:Unstar"> <svg class="octicon octicon-star v-align-text-bottom" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74L14 6z"/></svg> - Unstar -</button> <a class="social-count js-social-count" href="/adolfintel/WaifUPnP/stargazers" - aria-label="25 users starred this repository"> - 25 - </a> -</form> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="unstarred js-social-form" action="/adolfintel/WaifUPnP/star" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="pAeqaHLDizAURS73dDJIHJjv+p8A6hhoCADmTkbVv182Hh5mzvfXP4K9iTKz62VtcVwGnlu5YD9DdL/49s6AYg==" /> - <input type="hidden" name="context" value="repository"></input> - <button type="submit" class="btn btn-sm btn-with-count js-toggler-target" aria-label="Unstar this repository" title="Star adolfintel/WaifUPnP" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;STAR_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134C3D:219BEB:5D49A98A&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/Gateway.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="7534fdc3f2e7ebcc541c62d08b24c0ddc7455e411190542375a57b96b7316477" data-ga-click="Repository, click star button, action:blob#show; text:Star"> <svg class="octicon octicon-star v-align-text-bottom" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74L14 6z"/></svg> - Star -</button> <a class="social-count js-social-count" href="/adolfintel/WaifUPnP/stargazers" - aria-label="25 users starred this repository"> - 25 - </a> -</form> </div> - - </li> - - <li> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="btn-with-count" action="/adolfintel/WaifUPnP/fork" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="Z+wcHC9NJ4MzlY38kUlfwfsug++okUvzzRg/M3AjfAnVEsL/EbJKD5Pf/nOyyecnSQN5ZCL2MxiwB3epLIQ5ow==" /> - <button class="btn btn-sm btn-with-count" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;FORK_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134C3D:219BEB:5D49A98A&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/Gateway.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="cd254a86ffc529da690c3ff09435c0c2178f43343fef83bb5ebf17ef470e7a00" data-ga-click="Repository, show fork modal, action:blob#show; text:Fork" type="submit" title="Fork your own copy of adolfintel/WaifUPnP to your account" aria-label="Fork your own copy of adolfintel/WaifUPnP to your account"> <svg class="octicon octicon-repo-forked v-align-text-bottom" viewBox="0 0 10 16" version="1.1" width="10" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 1a1.993 1.993 0 0 0-1 3.72V6L5 8 3 6V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V6.5l3 3v1.78A1.993 1.993 0 0 0 5 15a1.993 1.993 0 0 0 1-3.72V9.5l3-3V4.72A1.993 1.993 0 0 0 8 1zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3 10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3-10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg> - Fork -</button></form> - <a href="/adolfintel/WaifUPnP/network/members" class="social-count" - aria-label="6 users forked this repository"> - 6 - </a> - </li> -</ul> - - <h1 class="public "> - <svg class="octicon octicon-repo" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <span class="author" itemprop="author"><a class="url fn" rel="author" data-hovercard-type="user" data-hovercard-url="/hovercards?user_id=16307689" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/adolfintel">adolfintel</a></span><!-- ---><span class="path-divider">/</span><!-- ---><strong itemprop="name"><a data-pjax="#js-repo-pjax-container" href="/adolfintel/WaifUPnP">WaifUPnP</a></strong> - - -</h1> - - </div> - -<nav class="hx_reponav reponav js-repo-nav js-sidenav-container-pjax container-lg p-responsive d-none d-lg-block" - itemscope - itemtype="http://schema.org/BreadcrumbList" - aria-label="Repository" - data-pjax="#js-repo-pjax-container"> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a class="js-selected-navigation-item selected reponav-item" itemprop="url" data-hotkey="g c" aria-current="page" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches repo_packages /adolfintel/WaifUPnP" href="/adolfintel/WaifUPnP"> - <svg class="octicon octicon-code" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M9.5 3L8 4.5 11.5 8 8 11.5 9.5 13 14 8 9.5 3zm-5 0L0 8l4.5 5L6 11.5 2.5 8 6 4.5 4.5 3z"/></svg> - <span itemprop="name">Code</span> - <meta itemprop="position" content="1"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" data-hotkey="g i" class="js-selected-navigation-item reponav-item" data-selected-links="repo_issues repo_labels repo_milestones /adolfintel/WaifUPnP/issues" href="/adolfintel/WaifUPnP/issues"> - <svg class="octicon octicon-issue-opened" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"/></svg> - <span itemprop="name">Issues</span> - <span class="Counter">2</span> - <meta itemprop="position" content="2"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a data-hotkey="g p" itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_pulls checks /adolfintel/WaifUPnP/pulls" href="/adolfintel/WaifUPnP/pulls"> - <svg class="octicon octicon-git-pull-request" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg> - <span itemprop="name">Pull requests</span> - <span class="Counter">2</span> - <meta itemprop="position" content="3"> -</a> </span> - - - <a data-hotkey="g b" class="js-selected-navigation-item reponav-item" data-selected-links="repo_projects new_repo_project repo_project /adolfintel/WaifUPnP/projects" href="/adolfintel/WaifUPnP/projects"> - <svg class="octicon octicon-project" viewBox="0 0 15 16" version="1.1" width="15" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - Projects - <span class="Counter" >0</span> -</a> - - <a class="js-selected-navigation-item reponav-item" data-hotkey="g w" data-selected-links="repo_wiki /adolfintel/WaifUPnP/wiki" href="/adolfintel/WaifUPnP/wiki"> - <svg class="octicon octicon-book" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M3 5h4v1H3V5zm0 3h4V7H3v1zm0 2h4V9H3v1zm11-5h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm2-6v9c0 .55-.45 1-1 1H9.5l-1 1-1-1H2c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h5.5l1 1 1-1H15c.55 0 1 .45 1 1zm-8 .5L7.5 3H2v9h6V3.5zm7-.5H9.5l-.5.5V12h6V3z"/></svg> - Wiki -</a> - <a data-skip-pjax="true" class="js-selected-navigation-item reponav-item" data-selected-links="security alerts policy /adolfintel/WaifUPnP/security/advisories" href="/adolfintel/WaifUPnP/security/advisories"> - <svg class="octicon octicon-shield" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M0 2l7-2 7 2v6.02C14 12.69 8.69 16 7 16c-1.69 0-7-3.31-7-7.98V2zm1 .75L7 1l6 1.75v5.268C13 12.104 8.449 15 7 15c-1.449 0-6-2.896-6-6.982V2.75zm1 .75L7 2v12c-1.207 0-5-2.482-5-5.985V3.5z"/></svg> - Security -</a> - <a class="js-selected-navigation-item reponav-item" data-selected-links="repo_graphs repo_contributors dependency_graph pulse people /adolfintel/WaifUPnP/pulse" href="/adolfintel/WaifUPnP/pulse"> - <svg class="octicon octicon-graph" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z"/></svg> - Insights -</a> - -</nav> - - <div class="reponav-wrapper reponav-small d-lg-none"> - <nav class="reponav js-reponav text-center no-wrap" - itemscope - itemtype="http://schema.org/BreadcrumbList"> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a class="js-selected-navigation-item selected reponav-item" itemprop="url" aria-current="page" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches repo_packages /adolfintel/WaifUPnP" href="/adolfintel/WaifUPnP"> - <span itemprop="name">Code</span> - <meta itemprop="position" content="1"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_issues repo_labels repo_milestones /adolfintel/WaifUPnP/issues" href="/adolfintel/WaifUPnP/issues"> - <span itemprop="name">Issues</span> - <span class="Counter">2</span> - <meta itemprop="position" content="2"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_pulls checks /adolfintel/WaifUPnP/pulls" href="/adolfintel/WaifUPnP/pulls"> - <span itemprop="name">Pull requests</span> - <span class="Counter">2</span> - <meta itemprop="position" content="3"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_projects new_repo_project repo_project /adolfintel/WaifUPnP/projects" href="/adolfintel/WaifUPnP/projects"> - <span itemprop="name">Projects</span> - <span class="Counter">0</span> - <meta itemprop="position" content="4"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_wiki /adolfintel/WaifUPnP/wiki" href="/adolfintel/WaifUPnP/wiki"> - <span itemprop="name">Wiki</span> - <meta itemprop="position" content="5"> -</a> </span> - - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="security alerts policy /adolfintel/WaifUPnP/security/advisories" href="/adolfintel/WaifUPnP/security/advisories"> - <span itemprop="name">Security</span> - <meta itemprop="position" content="6"> -</a> - <a class="js-selected-navigation-item reponav-item" data-selected-links="pulse /adolfintel/WaifUPnP/pulse" href="/adolfintel/WaifUPnP/pulse"> - Pulse -</a> - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="community /adolfintel/WaifUPnP/community" href="/adolfintel/WaifUPnP/community"> - Community -</a> </span> - - </nav> -</div> - - - </div> -<div class="container-lg clearfix new-discussion-timeline experiment-repo-nav p-responsive"> - <div class="repository-content "> - - - - - - - - - <a class="d-none js-permalink-shortcut" data-hotkey="y" href="/adolfintel/WaifUPnP/blob/d6381a8c6f24c7d0f5879ba037abd018ba428561/src/com/dosse/upnp/Gateway.java">Permalink</a> - - <!-- blob contrib key: blob_contributors:v21:bbeee0ff919fedbbc2a26da194cefb0e --> - - - <div class="d-flex flex-items-start flex-shrink-0 pb-3 flex-column flex-md-row"> - <span class="d-flex flex-justify-between width-full width-md-auto"> - -<details class="details-reset details-overlay select-menu branch-select-menu hx_rsm" id="branch-select-menu"> - <summary class="btn btn-sm select-menu-button css-truncate" - data-hotkey="w" - - title="Switch branches or tags"> - <i>Branch:</i> - <span class="css-truncate-target">master</span> - </summary> - - <details-menu class="select-menu-modal hx_rsm-modal position-absolute" style="z-index: 99;" src="/adolfintel/WaifUPnP/ref-list/master/src/com/dosse/upnp/Gateway.java?source_action=show&amp;source_controller=blob" preload> - <include-fragment class="select-menu-loading-overlay anim-pulse"> - <svg height="32" class="octicon octicon-octoface" viewBox="0 0 16 16" version="1.1" width="32" aria-hidden="true"><path fill-rule="evenodd" d="M14.7 5.34c.13-.32.55-1.59-.13-3.31 0 0-1.05-.33-3.44 1.3-1-.28-2.07-.32-3.13-.32s-2.13.04-3.13.32c-2.39-1.64-3.44-1.3-3.44-1.3-.68 1.72-.26 2.99-.13 3.31C.49 6.21 0 7.33 0 8.69 0 13.84 3.33 15 7.98 15S16 13.84 16 8.69c0-1.36-.49-2.48-1.3-3.35zM8 14.02c-3.3 0-5.98-.15-5.98-3.35 0-.76.38-1.48 1.02-2.07 1.07-.98 2.9-.46 4.96-.46 2.07 0 3.88-.52 4.96.46.65.59 1.02 1.3 1.02 2.07 0 3.19-2.68 3.35-5.98 3.35zM5.49 9.01c-.66 0-1.2.8-1.2 1.78s.54 1.79 1.2 1.79c.66 0 1.2-.8 1.2-1.79s-.54-1.78-1.2-1.78zm5.02 0c-.66 0-1.2.79-1.2 1.78s.54 1.79 1.2 1.79c.66 0 1.2-.8 1.2-1.79s-.53-1.78-1.2-1.78z"/></svg> - </include-fragment> - </details-menu> -</details> - - <div class="BtnGroup flex-shrink-0 d-md-none"> - <a href="/adolfintel/WaifUPnP/find/master" - class="js-pjax-capture-input btn btn-sm BtnGroup-item" - data-pjax - data-hotkey="t"> - Find file - </a> - <clipboard-copy value="src/com/dosse/upnp/Gateway.java" class="btn btn-sm BtnGroup-item"> - Copy path - </clipboard-copy> - </div> - </span> - <h2 id="blob-path" class="breadcrumb flex-auto min-width-0 text-normal flex-md-self-center ml-md-2 mr-md-3 my-2 my-md-0"> - <span class="js-repo-root text-bold"><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP"><span>WaifUPnP</span></a></span></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src"><span>src</span></a></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src/com"><span>com</span></a></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src/com/dosse"><span>dosse</span></a></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp"><span>upnp</span></a></span><span class="separator">/</span><strong class="final-path">Gateway.java</strong> - </h2> - - <div class="BtnGroup flex-shrink-0 d-none d-md-inline-block"> - <a href="/adolfintel/WaifUPnP/find/master" - class="js-pjax-capture-input btn btn-sm BtnGroup-item" - data-pjax - data-hotkey="t"> - Find file - </a> - <clipboard-copy value="src/com/dosse/upnp/Gateway.java" class="btn btn-sm BtnGroup-item"> - Copy path - </clipboard-copy> - </div> - </div> - - - - - <div class="Box Box--condensed d-flex flex-column flex-shrink-0"> - <div class="Box-body d-flex flex-justify-between bg-blue-light flex-column flex-md-row flex-items-start flex-md-items-center"> - <span class="pr-md-4 f6"> - <a rel="author" data-skip-pjax="true" data-hovercard-type="user" data-hovercard-url="/hovercards?user_id=16307689" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/adolfintel"><img class="avatar" src="https://avatars0.githubusercontent.com/u/16307689?s=40&amp;v=4" width="20" height="20" alt="@adolfintel" /></a> - <a class="text-bold link-gray-dark lh-default v-align-middle" rel="author" data-hovercard-type="user" data-hovercard-url="/hovercards?user_id=16307689" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/adolfintel">adolfintel</a> - <span class="lh-default v-align-middle"> - <a data-pjax="true" title="Uploaded to GitHub" class="link-gray" href="/adolfintel/WaifUPnP/commit/93a3b9774dfc1a323cc935877c68d03623086a95">Uploaded to GitHub</a> - </span> - </span> - <span class="d-inline-block flex-shrink-0 v-align-bottom f6 mt-2 mt-md-0"> - <a class="pr-2 text-mono link-gray" href="/adolfintel/WaifUPnP/commit/93a3b9774dfc1a323cc935877c68d03623086a95" data-pjax>93a3b97</a> - <relative-time datetime="2015-12-16T19:09:35Z">Dec 16, 2015</relative-time> - </span> - </div> - - <div class="Box-body d-flex flex-items-center flex-auto f6 border-bottom-0 flex-wrap" > - <details class="details-reset details-overlay details-overlay-dark lh-default text-gray-dark float-left mr-2" id="blob_contributors_box"> - <summary class="btn-link" aria-haspopup="dialog"> - <span><strong>1</strong> contributor</span> - </summary> - <details-dialog - class="Box Box--overlay d-flex flex-column anim-fade-in fast" - aria-label="Users who have contributed to this file" - src="/adolfintel/WaifUPnP/contributors/master/src/com/dosse/upnp/Gateway.java/list" preload> - <div class="Box-header"> - <button class="Box-btn-octicon btn-octicon float-right" type="button" aria-label="Close dialog" data-close-dialog> - <svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg> - </button> - <h3 class="Box-title"> - Users who have contributed to this file - </h3> - </div> - <include-fragment class="octocat-spinner my-3" aria-label="Loading..."></include-fragment> - </details-dialog> - </details> - </div> - </div> - - - - - - <div class="Box mt-3 position-relative"> - -<div class="Box-header py-2 d-flex flex-column flex-shrink-0 flex-md-row flex-md-items-center"> - - <div class="text-mono f6 flex-auto pr-3 flex-order-2 flex-md-order-1 mt-2 mt-md-0"> - 205 lines (191 sloc) - <span class="file-info-divider"></span> - 7.95 KB - </div> - - <div class="d-flex py-1 py-md-0 flex-auto flex-order-1 flex-md-order-2 flex-sm-grow-0 flex-justify-between"> - - <div class="BtnGroup"> - <a id="raw-url" class="btn btn-sm BtnGroup-item" href="/adolfintel/WaifUPnP/raw/master/src/com/dosse/upnp/Gateway.java">Raw</a> - <a class="btn btn-sm js-update-url-with-hash BtnGroup-item" data-hotkey="b" href="/adolfintel/WaifUPnP/blame/master/src/com/dosse/upnp/Gateway.java">Blame</a> - <a rel="nofollow" class="btn btn-sm BtnGroup-item" href="/adolfintel/WaifUPnP/commits/master/src/com/dosse/upnp/Gateway.java">History</a> - </div> - - - <div> - - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="inline-form js-update-url-with-hash" action="/adolfintel/WaifUPnP/edit/master/src/com/dosse/upnp/Gateway.java" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="l4SvPlLw4up/qG5XCe3PUGeauJwE99tv1oqYIPzZ/xezQ0vjjZHxYC9P/AkGU9KodCysD7zOgst5k6Hfifo6Pw==" /> - <button class="btn-octicon tooltipped tooltipped-nw" type="submit" - aria-label="Fork this project and edit the file" data-hotkey="e" data-disable-with> - <svg class="octicon octicon-pencil" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M0 12v3h3l8-8-3-3-8 8zm3 2H1v-2h1v1h1v1zm10.3-9.3L12 6 9 3l1.3-1.3a.996.996 0 0 1 1.41 0l1.59 1.59c.39.39.39 1.02 0 1.41z"/></svg> - </button> -</form> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="inline-form" action="/adolfintel/WaifUPnP/delete/master/src/com/dosse/upnp/Gateway.java" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="2PGTDF5/eTatDsfZQxNrCjLd1alBcGoPm3Fy7MHVSCSopeGBFxSiiBgbZF5IuKZL3wv5Vb62X9PWB+ShlabSqQ==" /> - <button class="btn-octicon btn-octicon-danger tooltipped tooltipped-nw" type="submit" - aria-label="Fork this project and delete the file" data-disable-with> - <svg class="octicon octicon-trashcan" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M11 2H9c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1H2c-.55 0-1 .45-1 1v1c0 .55.45 1 1 1v9c0 .55.45 1 1 1h7c.55 0 1-.45 1-1V5c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 12H3V5h1v8h1V5h1v8h1V5h1v8h1V5h1v9zm1-10H2V3h9v1z"/></svg> - </button> -</form> </div> - </div> -</div> - - - - - - - <div itemprop="text" class="Box-body p-0 blob-wrapper data type-java "> - -<table class="highlight tab-size js-file-line-container" data-tab-size="8"> - <tr> - <td id="L1" class="blob-num js-line-number" data-line-number="1"></td> - <td id="LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">/*</span></span></td> - </tr> - <tr> - <td id="L2" class="blob-num js-line-number" data-line-number="2"></td> - <td id="LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Copyright (C) 2015 Federico Dossena (adolfintel.com).</span></td> - </tr> - <tr> - <td id="L3" class="blob-num js-line-number" data-line-number="3"></td> - <td id="LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> *</span></td> - </tr> - <tr> - <td id="L4" class="blob-num js-line-number" data-line-number="4"></td> - <td id="LC4" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * This library is free software; you can redistribute it and/or</span></td> - </tr> - <tr> - <td id="L5" class="blob-num js-line-number" data-line-number="5"></td> - <td id="LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * modify it under the terms of the GNU Lesser General Public</span></td> - </tr> - <tr> - <td id="L6" class="blob-num js-line-number" data-line-number="6"></td> - <td id="LC6" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * License as published by the Free Software Foundation; either</span></td> - </tr> - <tr> - <td id="L7" class="blob-num js-line-number" data-line-number="7"></td> - <td id="LC7" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * version 2.1 of the License, or (at your option) any later version.</span></td> - </tr> - <tr> - <td id="L8" class="blob-num js-line-number" data-line-number="8"></td> - <td id="LC8" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> *</span></td> - </tr> - <tr> - <td id="L9" class="blob-num js-line-number" data-line-number="9"></td> - <td id="LC9" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * This library is distributed in the hope that it will be useful,</span></td> - </tr> - <tr> - <td id="L10" class="blob-num js-line-number" data-line-number="10"></td> - <td id="LC10" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</span></td> - </tr> - <tr> - <td id="L11" class="blob-num js-line-number" data-line-number="11"></td> - <td id="LC11" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</span></td> - </tr> - <tr> - <td id="L12" class="blob-num js-line-number" data-line-number="12"></td> - <td id="LC12" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Lesser General Public License for more details.</span></td> - </tr> - <tr> - <td id="L13" class="blob-num js-line-number" data-line-number="13"></td> - <td id="LC13" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> *</span></td> - </tr> - <tr> - <td id="L14" class="blob-num js-line-number" data-line-number="14"></td> - <td id="LC14" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * You should have received a copy of the GNU Lesser General Public</span></td> - </tr> - <tr> - <td id="L15" class="blob-num js-line-number" data-line-number="15"></td> - <td id="LC15" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * License along with this library; if not, write to the Free Software</span></td> - </tr> - <tr> - <td id="L16" class="blob-num js-line-number" data-line-number="16"></td> - <td id="LC16" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,</span></td> - </tr> - <tr> - <td id="L17" class="blob-num js-line-number" data-line-number="17"></td> - <td id="LC17" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * MA 02110-1301 USA</span></td> - </tr> - <tr> - <td id="L18" class="blob-num js-line-number" data-line-number="18"></td> - <td id="LC18" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L19" class="blob-num js-line-number" data-line-number="19"></td> - <td id="LC19" class="blob-code blob-code-inner js-file-line"><span class="pl-k">package</span> <span class="pl-smi">com.dosse.upnp</span>;</td> - </tr> - <tr> - <td id="L20" class="blob-num js-line-number" data-line-number="20"></td> - <td id="LC20" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L21" class="blob-num js-line-number" data-line-number="21"></td> - <td id="LC21" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.net.HttpURLConnection</span>;</td> - </tr> - <tr> - <td id="L22" class="blob-num js-line-number" data-line-number="22"></td> - <td id="LC22" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.net.Inet4Address</span>;</td> - </tr> - <tr> - <td id="L23" class="blob-num js-line-number" data-line-number="23"></td> - <td id="LC23" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.net.URL</span>;</td> - </tr> - <tr> - <td id="L24" class="blob-num js-line-number" data-line-number="24"></td> - <td id="LC24" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.util.HashMap</span>;</td> - </tr> - <tr> - <td id="L25" class="blob-num js-line-number" data-line-number="25"></td> - <td id="LC25" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.util.Map</span>;</td> - </tr> - <tr> - <td id="L26" class="blob-num js-line-number" data-line-number="26"></td> - <td id="LC26" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.util.StringTokenizer</span>;</td> - </tr> - <tr> - <td id="L27" class="blob-num js-line-number" data-line-number="27"></td> - <td id="LC27" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">javax.xml.parsers.DocumentBuilderFactory</span>;</td> - </tr> - <tr> - <td id="L28" class="blob-num js-line-number" data-line-number="28"></td> - <td id="LC28" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">org.w3c.dom.Document</span>;</td> - </tr> - <tr> - <td id="L29" class="blob-num js-line-number" data-line-number="29"></td> - <td id="LC29" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">org.w3c.dom.Node</span>;</td> - </tr> - <tr> - <td id="L30" class="blob-num js-line-number" data-line-number="30"></td> - <td id="LC30" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">org.w3c.dom.NodeList</span>;</td> - </tr> - <tr> - <td id="L31" class="blob-num js-line-number" data-line-number="31"></td> - <td id="LC31" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">org.w3c.dom.traversal.DocumentTraversal</span>;</td> - </tr> - <tr> - <td id="L32" class="blob-num js-line-number" data-line-number="32"></td> - <td id="LC32" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">org.w3c.dom.traversal.NodeFilter</span>;</td> - </tr> - <tr> - <td id="L33" class="blob-num js-line-number" data-line-number="33"></td> - <td id="LC33" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">org.w3c.dom.traversal.NodeIterator</span>;</td> - </tr> - <tr> - <td id="L34" class="blob-num js-line-number" data-line-number="34"></td> - <td id="LC34" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L35" class="blob-num js-line-number" data-line-number="35"></td> - <td id="LC35" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L36" class="blob-num js-line-number" data-line-number="36"></td> - <td id="LC36" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * </span></td> - </tr> - <tr> - <td id="L37" class="blob-num js-line-number" data-line-number="37"></td> - <td id="LC37" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@author</span> Federico</span></td> - </tr> - <tr> - <td id="L38" class="blob-num js-line-number" data-line-number="38"></td> - <td id="LC38" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L39" class="blob-num js-line-number" data-line-number="39"></td> - <td id="LC39" class="blob-code blob-code-inner js-file-line"><span class="pl-k">class</span> <span class="pl-en">Gateway</span> {</td> - </tr> - <tr> - <td id="L40" class="blob-num js-line-number" data-line-number="40"></td> - <td id="LC40" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L41" class="blob-num js-line-number" data-line-number="41"></td> - <td id="LC41" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-smi">Inet4Address</span> iface;</td> - </tr> - <tr> - <td id="L42" class="blob-num js-line-number" data-line-number="42"></td> - <td id="LC42" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L43" class="blob-num js-line-number" data-line-number="43"></td> - <td id="LC43" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-smi">String</span> serviceType <span class="pl-k">=</span> <span class="pl-c1">null</span>, controlURL <span class="pl-k">=</span> <span class="pl-c1">null</span>;</td> - </tr> - <tr> - <td id="L44" class="blob-num js-line-number" data-line-number="44"></td> - <td id="LC44" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L45" class="blob-num js-line-number" data-line-number="45"></td> - <td id="LC45" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-en">Gateway</span>(<span class="pl-k">byte</span>[] <span class="pl-v">data</span>, <span class="pl-smi">Inet4Address</span> <span class="pl-v">ip</span>) <span class="pl-k">throws</span> <span class="pl-smi">Exception</span> {</td> - </tr> - <tr> - <td id="L46" class="blob-num js-line-number" data-line-number="46"></td> - <td id="LC46" class="blob-code blob-code-inner js-file-line"> iface <span class="pl-k">=</span> ip;</td> - </tr> - <tr> - <td id="L47" class="blob-num js-line-number" data-line-number="47"></td> - <td id="LC47" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">String</span> location <span class="pl-k">=</span> <span class="pl-c1">null</span>;</td> - </tr> - <tr> - <td id="L48" class="blob-num js-line-number" data-line-number="48"></td> - <td id="LC48" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">StringTokenizer</span> st <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-smi">StringTokenizer</span>(<span class="pl-k">new</span> <span class="pl-smi">String</span>(data), <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-cce">\n</span><span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L49" class="blob-num js-line-number" data-line-number="49"></td> - <td id="LC49" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">while</span> (st<span class="pl-k">.</span>hasMoreTokens()) {</td> - </tr> - <tr> - <td id="L50" class="blob-num js-line-number" data-line-number="50"></td> - <td id="LC50" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">String</span> s <span class="pl-k">=</span> st<span class="pl-k">.</span>nextToken()<span class="pl-k">.</span>trim();</td> - </tr> - <tr> - <td id="L51" class="blob-num js-line-number" data-line-number="51"></td> - <td id="LC51" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (s<span class="pl-k">.</span>isEmpty() <span class="pl-k">||</span> s<span class="pl-k">.</span>startsWith(<span class="pl-s"><span class="pl-pds">&quot;</span>HTTP/1.<span class="pl-pds">&quot;</span></span>) <span class="pl-k">||</span> s<span class="pl-k">.</span>startsWith(<span class="pl-s"><span class="pl-pds">&quot;</span>NOTIFY *<span class="pl-pds">&quot;</span></span>)) {</td> - </tr> - <tr> - <td id="L52" class="blob-num js-line-number" data-line-number="52"></td> - <td id="LC52" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">continue</span>;</td> - </tr> - <tr> - <td id="L53" class="blob-num js-line-number" data-line-number="53"></td> - <td id="LC53" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L54" class="blob-num js-line-number" data-line-number="54"></td> - <td id="LC54" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">String</span> name <span class="pl-k">=</span> s<span class="pl-k">.</span>substring(<span class="pl-c1">0</span>, s<span class="pl-k">.</span>indexOf(<span class="pl-s"><span class="pl-pds">&#39;</span>:<span class="pl-pds">&#39;</span></span>)), val <span class="pl-k">=</span> s<span class="pl-k">.</span>length() <span class="pl-k">&gt;=</span> name<span class="pl-k">.</span>length() <span class="pl-k">?</span> s<span class="pl-k">.</span>substring(name<span class="pl-k">.</span>length() <span class="pl-k">+</span> <span class="pl-c1">1</span>)<span class="pl-k">.</span>trim() <span class="pl-k">:</span> <span class="pl-c1">null</span>;</td> - </tr> - <tr> - <td id="L55" class="blob-num js-line-number" data-line-number="55"></td> - <td id="LC55" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (name<span class="pl-k">.</span>equalsIgnoreCase(<span class="pl-s"><span class="pl-pds">&quot;</span>location<span class="pl-pds">&quot;</span></span>)) {</td> - </tr> - <tr> - <td id="L56" class="blob-num js-line-number" data-line-number="56"></td> - <td id="LC56" class="blob-code blob-code-inner js-file-line"> location <span class="pl-k">=</span> val;</td> - </tr> - <tr> - <td id="L57" class="blob-num js-line-number" data-line-number="57"></td> - <td id="LC57" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L58" class="blob-num js-line-number" data-line-number="58"></td> - <td id="LC58" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L59" class="blob-num js-line-number" data-line-number="59"></td> - <td id="LC59" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (location <span class="pl-k">==</span> <span class="pl-c1">null</span>) {</td> - </tr> - <tr> - <td id="L60" class="blob-num js-line-number" data-line-number="60"></td> - <td id="LC60" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">Exception</span>(<span class="pl-s"><span class="pl-pds">&quot;</span>Unsupported Gateway<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L61" class="blob-num js-line-number" data-line-number="61"></td> - <td id="LC61" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L62" class="blob-num js-line-number" data-line-number="62"></td> - <td id="LC62" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Document</span> d;</td> - </tr> - <tr> - <td id="L63" class="blob-num js-line-number" data-line-number="63"></td> - <td id="LC63" class="blob-code blob-code-inner js-file-line"> d <span class="pl-k">=</span> <span class="pl-smi">DocumentBuilderFactory</span><span class="pl-k">.</span>newInstance()<span class="pl-k">.</span>newDocumentBuilder()<span class="pl-k">.</span>parse(location);</td> - </tr> - <tr> - <td id="L64" class="blob-num js-line-number" data-line-number="64"></td> - <td id="LC64" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">NodeList</span> services <span class="pl-k">=</span> d<span class="pl-k">.</span>getElementsByTagName(<span class="pl-s"><span class="pl-pds">&quot;</span>service<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L65" class="blob-num js-line-number" data-line-number="65"></td> - <td id="LC65" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">for</span> (<span class="pl-k">int</span> i <span class="pl-k">=</span> <span class="pl-c1">0</span>; i <span class="pl-k">&lt;</span> services<span class="pl-k">.</span>getLength(); i<span class="pl-k">++</span>) {</td> - </tr> - <tr> - <td id="L66" class="blob-num js-line-number" data-line-number="66"></td> - <td id="LC66" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Node</span> service <span class="pl-k">=</span> services<span class="pl-k">.</span>item(i);</td> - </tr> - <tr> - <td id="L67" class="blob-num js-line-number" data-line-number="67"></td> - <td id="LC67" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">NodeList</span> n <span class="pl-k">=</span> service<span class="pl-k">.</span>getChildNodes();</td> - </tr> - <tr> - <td id="L68" class="blob-num js-line-number" data-line-number="68"></td> - <td id="LC68" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">String</span> serviceType <span class="pl-k">=</span> <span class="pl-c1">null</span>, controlURL <span class="pl-k">=</span> <span class="pl-c1">null</span>;</td> - </tr> - <tr> - <td id="L69" class="blob-num js-line-number" data-line-number="69"></td> - <td id="LC69" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">for</span> (<span class="pl-k">int</span> j <span class="pl-k">=</span> <span class="pl-c1">0</span>; j <span class="pl-k">&lt;</span> n<span class="pl-k">.</span>getLength(); j<span class="pl-k">++</span>) {</td> - </tr> - <tr> - <td id="L70" class="blob-num js-line-number" data-line-number="70"></td> - <td id="LC70" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Node</span> x <span class="pl-k">=</span> n<span class="pl-k">.</span>item(j);</td> - </tr> - <tr> - <td id="L71" class="blob-num js-line-number" data-line-number="71"></td> - <td id="LC71" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (x<span class="pl-k">.</span>getNodeName()<span class="pl-k">.</span>trim()<span class="pl-k">.</span>equalsIgnoreCase(<span class="pl-s"><span class="pl-pds">&quot;</span>serviceType<span class="pl-pds">&quot;</span></span>)) {</td> - </tr> - <tr> - <td id="L72" class="blob-num js-line-number" data-line-number="72"></td> - <td id="LC72" class="blob-code blob-code-inner js-file-line"> serviceType <span class="pl-k">=</span> x<span class="pl-k">.</span>getFirstChild()<span class="pl-k">.</span>getNodeValue();</td> - </tr> - <tr> - <td id="L73" class="blob-num js-line-number" data-line-number="73"></td> - <td id="LC73" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">else</span> <span class="pl-k">if</span> (x<span class="pl-k">.</span>getNodeName()<span class="pl-k">.</span>trim()<span class="pl-k">.</span>equalsIgnoreCase(<span class="pl-s"><span class="pl-pds">&quot;</span>controlURL<span class="pl-pds">&quot;</span></span>)) {</td> - </tr> - <tr> - <td id="L74" class="blob-num js-line-number" data-line-number="74"></td> - <td id="LC74" class="blob-code blob-code-inner js-file-line"> controlURL <span class="pl-k">=</span> x<span class="pl-k">.</span>getFirstChild()<span class="pl-k">.</span>getNodeValue();</td> - </tr> - <tr> - <td id="L75" class="blob-num js-line-number" data-line-number="75"></td> - <td id="LC75" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L76" class="blob-num js-line-number" data-line-number="76"></td> - <td id="LC76" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L77" class="blob-num js-line-number" data-line-number="77"></td> - <td id="LC77" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (serviceType <span class="pl-k">==</span> <span class="pl-c1">null</span> <span class="pl-k">||</span> controlURL <span class="pl-k">==</span> <span class="pl-c1">null</span>) {</td> - </tr> - <tr> - <td id="L78" class="blob-num js-line-number" data-line-number="78"></td> - <td id="LC78" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">continue</span>;</td> - </tr> - <tr> - <td id="L79" class="blob-num js-line-number" data-line-number="79"></td> - <td id="LC79" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L80" class="blob-num js-line-number" data-line-number="80"></td> - <td id="LC80" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (serviceType<span class="pl-k">.</span>trim()<span class="pl-k">.</span>toLowerCase()<span class="pl-k">.</span>contains(<span class="pl-s"><span class="pl-pds">&quot;</span>:wanipconnection:<span class="pl-pds">&quot;</span></span>) <span class="pl-k">||</span> serviceType<span class="pl-k">.</span>trim()<span class="pl-k">.</span>toLowerCase()<span class="pl-k">.</span>contains(<span class="pl-s"><span class="pl-pds">&quot;</span>:wanpppconnection:<span class="pl-pds">&quot;</span></span>)) {</td> - </tr> - <tr> - <td id="L81" class="blob-num js-line-number" data-line-number="81"></td> - <td id="LC81" class="blob-code blob-code-inner js-file-line"> <span class="pl-c1">this</span><span class="pl-k">.</span>serviceType <span class="pl-k">=</span> serviceType<span class="pl-k">.</span>trim();</td> - </tr> - <tr> - <td id="L82" class="blob-num js-line-number" data-line-number="82"></td> - <td id="LC82" class="blob-code blob-code-inner js-file-line"> <span class="pl-c1">this</span><span class="pl-k">.</span>controlURL <span class="pl-k">=</span> controlURL<span class="pl-k">.</span>trim();</td> - </tr> - <tr> - <td id="L83" class="blob-num js-line-number" data-line-number="83"></td> - <td id="LC83" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L84" class="blob-num js-line-number" data-line-number="84"></td> - <td id="LC84" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L85" class="blob-num js-line-number" data-line-number="85"></td> - <td id="LC85" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (controlURL <span class="pl-k">==</span> <span class="pl-c1">null</span>) {</td> - </tr> - <tr> - <td id="L86" class="blob-num js-line-number" data-line-number="86"></td> - <td id="LC86" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">Exception</span>(<span class="pl-s"><span class="pl-pds">&quot;</span>Unsupported Gateway<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L87" class="blob-num js-line-number" data-line-number="87"></td> - <td id="LC87" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L88" class="blob-num js-line-number" data-line-number="88"></td> - <td id="LC88" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">int</span> slash <span class="pl-k">=</span> location<span class="pl-k">.</span>indexOf(<span class="pl-s"><span class="pl-pds">&quot;</span>/<span class="pl-pds">&quot;</span></span>, <span class="pl-c1">7</span>); <span class="pl-c"><span class="pl-c">//</span>finds first slash after http://</span></td> - </tr> - <tr> - <td id="L89" class="blob-num js-line-number" data-line-number="89"></td> - <td id="LC89" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (slash <span class="pl-k">==</span> <span class="pl-k">-</span><span class="pl-c1">1</span>) {</td> - </tr> - <tr> - <td id="L90" class="blob-num js-line-number" data-line-number="90"></td> - <td id="LC90" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">Exception</span>(<span class="pl-s"><span class="pl-pds">&quot;</span>Unsupported Gateway<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L91" class="blob-num js-line-number" data-line-number="91"></td> - <td id="LC91" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L92" class="blob-num js-line-number" data-line-number="92"></td> - <td id="LC92" class="blob-code blob-code-inner js-file-line"> location <span class="pl-k">=</span> location<span class="pl-k">.</span>substring(<span class="pl-c1">0</span>, slash);</td> - </tr> - <tr> - <td id="L93" class="blob-num js-line-number" data-line-number="93"></td> - <td id="LC93" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (<span class="pl-k">!</span>controlURL<span class="pl-k">.</span>startsWith(<span class="pl-s"><span class="pl-pds">&quot;</span>/<span class="pl-pds">&quot;</span></span>)) {</td> - </tr> - <tr> - <td id="L94" class="blob-num js-line-number" data-line-number="94"></td> - <td id="LC94" class="blob-code blob-code-inner js-file-line"> controlURL <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">&quot;</span>/<span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> controlURL;</td> - </tr> - <tr> - <td id="L95" class="blob-num js-line-number" data-line-number="95"></td> - <td id="LC95" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L96" class="blob-num js-line-number" data-line-number="96"></td> - <td id="LC96" class="blob-code blob-code-inner js-file-line"> controlURL <span class="pl-k">=</span> location <span class="pl-k">+</span> controlURL;</td> - </tr> - <tr> - <td id="L97" class="blob-num js-line-number" data-line-number="97"></td> - <td id="LC97" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L98" class="blob-num js-line-number" data-line-number="98"></td> - <td id="LC98" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L99" class="blob-num js-line-number" data-line-number="99"></td> - <td id="LC99" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-k">Map&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span> <span class="pl-en">command</span>(<span class="pl-smi">String</span> <span class="pl-v">action</span>, <span class="pl-k">Map&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span> <span class="pl-v">params</span>) <span class="pl-k">throws</span> <span class="pl-smi">Exception</span> {</td> - </tr> - <tr> - <td id="L100" class="blob-num js-line-number" data-line-number="100"></td> - <td id="LC100" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Map&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span> ret <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-k">HashMap&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span>();</td> - </tr> - <tr> - <td id="L101" class="blob-num js-line-number" data-line-number="101"></td> - <td id="LC101" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">String</span> soap <span class="pl-k">=</span> <span class="pl-s"><span class="pl-pds">&quot;</span>&lt;?xml version=<span class="pl-cce">\&quot;</span>1.0<span class="pl-cce">\&quot;</span>?&gt;<span class="pl-cce">\r\n</span><span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span>&lt;SOAP-ENV:Envelope xmlns:SOAP-ENV=<span class="pl-cce">\&quot;</span>http://schemas.xmlsoap.org/soap/envelope/<span class="pl-cce">\&quot;</span> SOAP-ENV:encodingStyle=<span class="pl-cce">\&quot;</span>http://schemas.xmlsoap.org/soap/encoding/<span class="pl-cce">\&quot;</span>&gt;<span class="pl-pds">&quot;</span></span></td> - </tr> - <tr> - <td id="L102" class="blob-num js-line-number" data-line-number="102"></td> - <td id="LC102" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span>&lt;SOAP-ENV:Body&gt;<span class="pl-pds">&quot;</span></span></td> - </tr> - <tr> - <td id="L103" class="blob-num js-line-number" data-line-number="103"></td> - <td id="LC103" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span>&lt;m:<span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> action <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span> xmlns:m=<span class="pl-cce">\&quot;</span><span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> serviceType <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-cce">\&quot;</span>&gt;<span class="pl-pds">&quot;</span></span>;</td> - </tr> - <tr> - <td id="L104" class="blob-num js-line-number" data-line-number="104"></td> - <td id="LC104" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (params <span class="pl-k">!=</span> <span class="pl-c1">null</span>) {</td> - </tr> - <tr> - <td id="L105" class="blob-num js-line-number" data-line-number="105"></td> - <td id="LC105" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">for</span> (<span class="pl-smi">Map</span><span class="pl-k">.</span><span class="pl-k">Entry&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span> entry <span class="pl-k">:</span> params<span class="pl-k">.</span>entrySet()) {</td> - </tr> - <tr> - <td id="L106" class="blob-num js-line-number" data-line-number="106"></td> - <td id="LC106" class="blob-code blob-code-inner js-file-line"> soap <span class="pl-k">+=</span> <span class="pl-s"><span class="pl-pds">&quot;</span>&lt;<span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> entry<span class="pl-k">.</span>getKey() <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span>&gt;<span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> entry<span class="pl-k">.</span>getValue() <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span>&lt;/<span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> entry<span class="pl-k">.</span>getKey() <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span>&gt;<span class="pl-pds">&quot;</span></span>;</td> - </tr> - <tr> - <td id="L107" class="blob-num js-line-number" data-line-number="107"></td> - <td id="LC107" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L108" class="blob-num js-line-number" data-line-number="108"></td> - <td id="LC108" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L109" class="blob-num js-line-number" data-line-number="109"></td> - <td id="LC109" class="blob-code blob-code-inner js-file-line"> soap <span class="pl-k">+=</span> <span class="pl-s"><span class="pl-pds">&quot;</span>&lt;/m:<span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> action <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span>&gt;&lt;/SOAP-ENV:Body&gt;&lt;/SOAP-ENV:Envelope&gt;<span class="pl-pds">&quot;</span></span>;</td> - </tr> - <tr> - <td id="L110" class="blob-num js-line-number" data-line-number="110"></td> - <td id="LC110" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">byte</span>[] req <span class="pl-k">=</span> soap<span class="pl-k">.</span>getBytes();</td> - </tr> - <tr> - <td id="L111" class="blob-num js-line-number" data-line-number="111"></td> - <td id="LC111" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">HttpURLConnection</span> conn <span class="pl-k">=</span> (<span class="pl-smi">HttpURLConnection</span>) <span class="pl-k">new</span> <span class="pl-smi">URL</span>(controlURL)<span class="pl-k">.</span>openConnection();</td> - </tr> - <tr> - <td id="L112" class="blob-num js-line-number" data-line-number="112"></td> - <td id="LC112" class="blob-code blob-code-inner js-file-line"> conn<span class="pl-k">.</span>setRequestMethod(<span class="pl-s"><span class="pl-pds">&quot;</span>POST<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L113" class="blob-num js-line-number" data-line-number="113"></td> - <td id="LC113" class="blob-code blob-code-inner js-file-line"> conn<span class="pl-k">.</span>setDoOutput(<span class="pl-c1">true</span>);</td> - </tr> - <tr> - <td id="L114" class="blob-num js-line-number" data-line-number="114"></td> - <td id="LC114" class="blob-code blob-code-inner js-file-line"> conn<span class="pl-k">.</span>setRequestProperty(<span class="pl-s"><span class="pl-pds">&quot;</span>Content-Type<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span>text/xml<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L115" class="blob-num js-line-number" data-line-number="115"></td> - <td id="LC115" class="blob-code blob-code-inner js-file-line"> conn<span class="pl-k">.</span>setRequestProperty(<span class="pl-s"><span class="pl-pds">&quot;</span>SOAPAction<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-cce">\&quot;</span><span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> serviceType <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span>#<span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> action <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-cce">\&quot;</span><span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L116" class="blob-num js-line-number" data-line-number="116"></td> - <td id="LC116" class="blob-code blob-code-inner js-file-line"> conn<span class="pl-k">.</span>setRequestProperty(<span class="pl-s"><span class="pl-pds">&quot;</span>Connection<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span>Close<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L117" class="blob-num js-line-number" data-line-number="117"></td> - <td id="LC117" class="blob-code blob-code-inner js-file-line"> conn<span class="pl-k">.</span>setRequestProperty(<span class="pl-s"><span class="pl-pds">&quot;</span>Content-Length<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> req<span class="pl-k">.</span>length);</td> - </tr> - <tr> - <td id="L118" class="blob-num js-line-number" data-line-number="118"></td> - <td id="LC118" class="blob-code blob-code-inner js-file-line"> conn<span class="pl-k">.</span>getOutputStream()<span class="pl-k">.</span>write(req);</td> - </tr> - <tr> - <td id="L119" class="blob-num js-line-number" data-line-number="119"></td> - <td id="LC119" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Document</span> d <span class="pl-k">=</span> <span class="pl-smi">DocumentBuilderFactory</span><span class="pl-k">.</span>newInstance()<span class="pl-k">.</span>newDocumentBuilder()<span class="pl-k">.</span>parse(conn<span class="pl-k">.</span>getInputStream());</td> - </tr> - <tr> - <td id="L120" class="blob-num js-line-number" data-line-number="120"></td> - <td id="LC120" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">NodeIterator</span> iter <span class="pl-k">=</span> ((<span class="pl-smi">DocumentTraversal</span>) d)<span class="pl-k">.</span>createNodeIterator(d<span class="pl-k">.</span>getDocumentElement(), <span class="pl-smi">NodeFilter</span><span class="pl-c1"><span class="pl-k">.</span>SHOW_ELEMENT</span>, <span class="pl-c1">null</span>, <span class="pl-c1">true</span>);</td> - </tr> - <tr> - <td id="L121" class="blob-num js-line-number" data-line-number="121"></td> - <td id="LC121" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Node</span> n;</td> - </tr> - <tr> - <td id="L122" class="blob-num js-line-number" data-line-number="122"></td> - <td id="LC122" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">while</span> ((n <span class="pl-k">=</span> iter<span class="pl-k">.</span>nextNode()) <span class="pl-k">!=</span> <span class="pl-c1">null</span>) {</td> - </tr> - <tr> - <td id="L123" class="blob-num js-line-number" data-line-number="123"></td> - <td id="LC123" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> {</td> - </tr> - <tr> - <td id="L124" class="blob-num js-line-number" data-line-number="124"></td> - <td id="LC124" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (n<span class="pl-k">.</span>getFirstChild()<span class="pl-k">.</span>getNodeType() <span class="pl-k">==</span> <span class="pl-smi">Node</span><span class="pl-c1"><span class="pl-k">.</span>TEXT_NODE</span>) {</td> - </tr> - <tr> - <td id="L125" class="blob-num js-line-number" data-line-number="125"></td> - <td id="LC125" class="blob-code blob-code-inner js-file-line"> ret<span class="pl-k">.</span>put(n<span class="pl-k">.</span>getNodeName(), n<span class="pl-k">.</span>getTextContent());</td> - </tr> - <tr> - <td id="L126" class="blob-num js-line-number" data-line-number="126"></td> - <td id="LC126" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L127" class="blob-num js-line-number" data-line-number="127"></td> - <td id="LC127" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Throwable</span> t) {</td> - </tr> - <tr> - <td id="L128" class="blob-num js-line-number" data-line-number="128"></td> - <td id="LC128" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L129" class="blob-num js-line-number" data-line-number="129"></td> - <td id="LC129" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L130" class="blob-num js-line-number" data-line-number="130"></td> - <td id="LC130" class="blob-code blob-code-inner js-file-line"> conn<span class="pl-k">.</span>disconnect();</td> - </tr> - <tr> - <td id="L131" class="blob-num js-line-number" data-line-number="131"></td> - <td id="LC131" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> ret;</td> - </tr> - <tr> - <td id="L132" class="blob-num js-line-number" data-line-number="132"></td> - <td id="LC132" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L133" class="blob-num js-line-number" data-line-number="133"></td> - <td id="LC133" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L134" class="blob-num js-line-number" data-line-number="134"></td> - <td id="LC134" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-smi">String</span> <span class="pl-en">getLocalIP</span>() {</td> - </tr> - <tr> - <td id="L135" class="blob-num js-line-number" data-line-number="135"></td> - <td id="LC135" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> iface<span class="pl-k">.</span>getHostAddress();</td> - </tr> - <tr> - <td id="L136" class="blob-num js-line-number" data-line-number="136"></td> - <td id="LC136" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L137" class="blob-num js-line-number" data-line-number="137"></td> - <td id="LC137" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L138" class="blob-num js-line-number" data-line-number="138"></td> - <td id="LC138" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-smi">String</span> <span class="pl-en">getExternalIP</span>() {</td> - </tr> - <tr> - <td id="L139" class="blob-num js-line-number" data-line-number="139"></td> - <td id="LC139" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> {</td> - </tr> - <tr> - <td id="L140" class="blob-num js-line-number" data-line-number="140"></td> - <td id="LC140" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Map&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span> r <span class="pl-k">=</span> command(<span class="pl-s"><span class="pl-pds">&quot;</span>GetExternalIPAddress<span class="pl-pds">&quot;</span></span>, <span class="pl-c1">null</span>);</td> - </tr> - <tr> - <td id="L141" class="blob-num js-line-number" data-line-number="141"></td> - <td id="LC141" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> r<span class="pl-k">.</span>get(<span class="pl-s"><span class="pl-pds">&quot;</span>NewExternalIPAddress<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L142" class="blob-num js-line-number" data-line-number="142"></td> - <td id="LC142" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Throwable</span> t) {</td> - </tr> - <tr> - <td id="L143" class="blob-num js-line-number" data-line-number="143"></td> - <td id="LC143" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> <span class="pl-c1">null</span>;</td> - </tr> - <tr> - <td id="L144" class="blob-num js-line-number" data-line-number="144"></td> - <td id="LC144" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L145" class="blob-num js-line-number" data-line-number="145"></td> - <td id="LC145" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L146" class="blob-num js-line-number" data-line-number="146"></td> - <td id="LC146" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L147" class="blob-num js-line-number" data-line-number="147"></td> - <td id="LC147" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">boolean</span> <span class="pl-en">openPort</span>(<span class="pl-k">int</span> <span class="pl-v">port</span>, <span class="pl-k">boolean</span> <span class="pl-v">udp</span>) {</td> - </tr> - <tr> - <td id="L148" class="blob-num js-line-number" data-line-number="148"></td> - <td id="LC148" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (port <span class="pl-k">&lt;</span> <span class="pl-c1">0</span> <span class="pl-k">||</span> port <span class="pl-k">&gt;</span> <span class="pl-c1">65535</span>) {</td> - </tr> - <tr> - <td id="L149" class="blob-num js-line-number" data-line-number="149"></td> - <td id="LC149" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">IllegalArgumentException</span>(<span class="pl-s"><span class="pl-pds">&quot;</span>Invalid port<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L150" class="blob-num js-line-number" data-line-number="150"></td> - <td id="LC150" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L151" class="blob-num js-line-number" data-line-number="151"></td> - <td id="LC151" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Map&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span> params <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-k">HashMap&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span>();</td> - </tr> - <tr> - <td id="L152" class="blob-num js-line-number" data-line-number="152"></td> - <td id="LC152" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewRemoteHost<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L153" class="blob-num js-line-number" data-line-number="153"></td> - <td id="LC153" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewProtocol<span class="pl-pds">&quot;</span></span>, udp <span class="pl-k">?</span> <span class="pl-s"><span class="pl-pds">&quot;</span>UDP<span class="pl-pds">&quot;</span></span> <span class="pl-k">:</span> <span class="pl-s"><span class="pl-pds">&quot;</span>TCP<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L154" class="blob-num js-line-number" data-line-number="154"></td> - <td id="LC154" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewInternalClient<span class="pl-pds">&quot;</span></span>, iface<span class="pl-k">.</span>getHostAddress());</td> - </tr> - <tr> - <td id="L155" class="blob-num js-line-number" data-line-number="155"></td> - <td id="LC155" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewExternalPort<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> port);</td> - </tr> - <tr> - <td id="L156" class="blob-num js-line-number" data-line-number="156"></td> - <td id="LC156" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewInternalPort<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> port);</td> - </tr> - <tr> - <td id="L157" class="blob-num js-line-number" data-line-number="157"></td> - <td id="LC157" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewEnabled<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span>1<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L158" class="blob-num js-line-number" data-line-number="158"></td> - <td id="LC158" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewPortMappingDescription<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span>WaifUPnP<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L159" class="blob-num js-line-number" data-line-number="159"></td> - <td id="LC159" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewLeaseDuration<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span>0<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L160" class="blob-num js-line-number" data-line-number="160"></td> - <td id="LC160" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> {</td> - </tr> - <tr> - <td id="L161" class="blob-num js-line-number" data-line-number="161"></td> - <td id="LC161" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Map&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span> r <span class="pl-k">=</span> command(<span class="pl-s"><span class="pl-pds">&quot;</span>AddPortMapping<span class="pl-pds">&quot;</span></span>, params);</td> - </tr> - <tr> - <td id="L162" class="blob-num js-line-number" data-line-number="162"></td> - <td id="LC162" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> r<span class="pl-k">.</span>get(<span class="pl-s"><span class="pl-pds">&quot;</span>errorCode<span class="pl-pds">&quot;</span></span>) <span class="pl-k">==</span> <span class="pl-c1">null</span>;</td> - </tr> - <tr> - <td id="L163" class="blob-num js-line-number" data-line-number="163"></td> - <td id="LC163" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Exception</span> ex) {</td> - </tr> - <tr> - <td id="L164" class="blob-num js-line-number" data-line-number="164"></td> - <td id="LC164" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> <span class="pl-c1">false</span>;</td> - </tr> - <tr> - <td id="L165" class="blob-num js-line-number" data-line-number="165"></td> - <td id="LC165" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L166" class="blob-num js-line-number" data-line-number="166"></td> - <td id="LC166" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L167" class="blob-num js-line-number" data-line-number="167"></td> - <td id="LC167" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L168" class="blob-num js-line-number" data-line-number="168"></td> - <td id="LC168" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">boolean</span> <span class="pl-en">closePort</span>(<span class="pl-k">int</span> <span class="pl-v">port</span>, <span class="pl-k">boolean</span> <span class="pl-v">udp</span>) {</td> - </tr> - <tr> - <td id="L169" class="blob-num js-line-number" data-line-number="169"></td> - <td id="LC169" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (port <span class="pl-k">&lt;</span> <span class="pl-c1">0</span> <span class="pl-k">||</span> port <span class="pl-k">&gt;</span> <span class="pl-c1">65535</span>) {</td> - </tr> - <tr> - <td id="L170" class="blob-num js-line-number" data-line-number="170"></td> - <td id="LC170" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">IllegalArgumentException</span>(<span class="pl-s"><span class="pl-pds">&quot;</span>Invalid port<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L171" class="blob-num js-line-number" data-line-number="171"></td> - <td id="LC171" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L172" class="blob-num js-line-number" data-line-number="172"></td> - <td id="LC172" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Map&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span> params <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-k">HashMap&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span>();</td> - </tr> - <tr> - <td id="L173" class="blob-num js-line-number" data-line-number="173"></td> - <td id="LC173" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewRemoteHost<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L174" class="blob-num js-line-number" data-line-number="174"></td> - <td id="LC174" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewProtocol<span class="pl-pds">&quot;</span></span>, udp <span class="pl-k">?</span> <span class="pl-s"><span class="pl-pds">&quot;</span>UDP<span class="pl-pds">&quot;</span></span> <span class="pl-k">:</span> <span class="pl-s"><span class="pl-pds">&quot;</span>TCP<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L175" class="blob-num js-line-number" data-line-number="175"></td> - <td id="LC175" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewExternalPort<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> port);</td> - </tr> - <tr> - <td id="L176" class="blob-num js-line-number" data-line-number="176"></td> - <td id="LC176" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> {</td> - </tr> - <tr> - <td id="L177" class="blob-num js-line-number" data-line-number="177"></td> - <td id="LC177" class="blob-code blob-code-inner js-file-line"> command(<span class="pl-s"><span class="pl-pds">&quot;</span>DeletePortMapping<span class="pl-pds">&quot;</span></span>, params);</td> - </tr> - <tr> - <td id="L178" class="blob-num js-line-number" data-line-number="178"></td> - <td id="LC178" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> <span class="pl-c1">true</span>;</td> - </tr> - <tr> - <td id="L179" class="blob-num js-line-number" data-line-number="179"></td> - <td id="LC179" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Exception</span> ex) {</td> - </tr> - <tr> - <td id="L180" class="blob-num js-line-number" data-line-number="180"></td> - <td id="LC180" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> <span class="pl-c1">false</span>;</td> - </tr> - <tr> - <td id="L181" class="blob-num js-line-number" data-line-number="181"></td> - <td id="LC181" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L182" class="blob-num js-line-number" data-line-number="182"></td> - <td id="LC182" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L183" class="blob-num js-line-number" data-line-number="183"></td> - <td id="LC183" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L184" class="blob-num js-line-number" data-line-number="184"></td> - <td id="LC184" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">boolean</span> <span class="pl-en">isMapped</span>(<span class="pl-k">int</span> <span class="pl-v">port</span>, <span class="pl-k">boolean</span> <span class="pl-v">udp</span>) {</td> - </tr> - <tr> - <td id="L185" class="blob-num js-line-number" data-line-number="185"></td> - <td id="LC185" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (port <span class="pl-k">&lt;</span> <span class="pl-c1">0</span> <span class="pl-k">||</span> port <span class="pl-k">&gt;</span> <span class="pl-c1">65535</span>) {</td> - </tr> - <tr> - <td id="L186" class="blob-num js-line-number" data-line-number="186"></td> - <td id="LC186" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">IllegalArgumentException</span>(<span class="pl-s"><span class="pl-pds">&quot;</span>Invalid port<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L187" class="blob-num js-line-number" data-line-number="187"></td> - <td id="LC187" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L188" class="blob-num js-line-number" data-line-number="188"></td> - <td id="LC188" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Map&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span> params <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-k">HashMap&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span>();</td> - </tr> - <tr> - <td id="L189" class="blob-num js-line-number" data-line-number="189"></td> - <td id="LC189" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewRemoteHost<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L190" class="blob-num js-line-number" data-line-number="190"></td> - <td id="LC190" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewProtocol<span class="pl-pds">&quot;</span></span>, udp <span class="pl-k">?</span> <span class="pl-s"><span class="pl-pds">&quot;</span>UDP<span class="pl-pds">&quot;</span></span> <span class="pl-k">:</span> <span class="pl-s"><span class="pl-pds">&quot;</span>TCP<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L191" class="blob-num js-line-number" data-line-number="191"></td> - <td id="LC191" class="blob-code blob-code-inner js-file-line"> params<span class="pl-k">.</span>put(<span class="pl-s"><span class="pl-pds">&quot;</span>NewExternalPort<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> port);</td> - </tr> - <tr> - <td id="L192" class="blob-num js-line-number" data-line-number="192"></td> - <td id="LC192" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> {</td> - </tr> - <tr> - <td id="L193" class="blob-num js-line-number" data-line-number="193"></td> - <td id="LC193" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Map&lt;<span class="pl-smi">String</span>, <span class="pl-smi">String</span>&gt;</span> r <span class="pl-k">=</span> command(<span class="pl-s"><span class="pl-pds">&quot;</span>GetSpecificPortMappingEntry<span class="pl-pds">&quot;</span></span>, params);</td> - </tr> - <tr> - <td id="L194" class="blob-num js-line-number" data-line-number="194"></td> - <td id="LC194" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (r<span class="pl-k">.</span>get(<span class="pl-s"><span class="pl-pds">&quot;</span>errorCode<span class="pl-pds">&quot;</span></span>) <span class="pl-k">!=</span> <span class="pl-c1">null</span>) {</td> - </tr> - <tr> - <td id="L195" class="blob-num js-line-number" data-line-number="195"></td> - <td id="LC195" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">Exception</span>();</td> - </tr> - <tr> - <td id="L196" class="blob-num js-line-number" data-line-number="196"></td> - <td id="LC196" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L197" class="blob-num js-line-number" data-line-number="197"></td> - <td id="LC197" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> r<span class="pl-k">.</span>get(<span class="pl-s"><span class="pl-pds">&quot;</span>NewInternalPort<span class="pl-pds">&quot;</span></span>) <span class="pl-k">!=</span> <span class="pl-c1">null</span>;</td> - </tr> - <tr> - <td id="L198" class="blob-num js-line-number" data-line-number="198"></td> - <td id="LC198" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Exception</span> ex) {</td> - </tr> - <tr> - <td id="L199" class="blob-num js-line-number" data-line-number="199"></td> - <td id="LC199" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> <span class="pl-c1">false</span>;</td> - </tr> - <tr> - <td id="L200" class="blob-num js-line-number" data-line-number="200"></td> - <td id="LC200" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L201" class="blob-num js-line-number" data-line-number="201"></td> - <td id="LC201" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L202" class="blob-num js-line-number" data-line-number="202"></td> - <td id="LC202" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L203" class="blob-num js-line-number" data-line-number="203"></td> - <td id="LC203" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L204" class="blob-num js-line-number" data-line-number="204"></td> - <td id="LC204" class="blob-code blob-code-inner js-file-line">}</td> - </tr> -</table> - - <details class="details-reset details-overlay BlobToolbar position-absolute js-file-line-actions dropdown d-none" aria-hidden="true"> - <summary class="btn-octicon ml-0 px-2 p-0 bg-white border border-gray-dark rounded-1" aria-label="Inline file action toolbar"> - <svg class="octicon octicon-kebab-horizontal" viewBox="0 0 13 16" version="1.1" width="13" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm5 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM13 7.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/></svg> - </summary> - <details-menu> - <ul class="BlobToolbar-dropdown dropdown-menu dropdown-menu-se mt-2" style="width:185px"> - <li><clipboard-copy role="menuitem" class="dropdown-item" id="js-copy-lines" style="cursor:pointer;" data-original-text="Copy lines">Copy lines</clipboard-copy></li> - <li><clipboard-copy role="menuitem" class="dropdown-item" id="js-copy-permalink" style="cursor:pointer;" data-original-text="Copy permalink">Copy permalink</clipboard-copy></li> - <li><a class="dropdown-item js-update-url-with-hash" id="js-view-git-blame" role="menuitem" href="/adolfintel/WaifUPnP/blame/d6381a8c6f24c7d0f5879ba037abd018ba428561/src/com/dosse/upnp/Gateway.java">View git blame</a></li> - <li><a class="dropdown-item" id="js-new-issue" role="menuitem" href="/adolfintel/WaifUPnP/issues/new">Reference in new issue</a></li> - </ul> - </details-menu> - </details> - - </div> - - </div> - - - - <details class="details-reset details-overlay details-overlay-dark"> - <summary data-hotkey="l" aria-label="Jump to line"></summary> - <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast linejump" aria-label="Jump to line"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="js-jump-to-line-form Box-body d-flex" action="" accept-charset="UTF-8" method="get"><input name="utf8" type="hidden" value="&#x2713;" /> - <input class="form-control flex-auto mr-3 linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line&hellip;" aria-label="Jump to line" autofocus> - <button type="submit" class="btn" data-close-dialog>Go</button> -</form> </details-dialog> - </details> - - - - </div> - <div class="modal-backdrop js-touch-events"></div> -</div> - - </main> - </div> - - - </div> - - -<div class="footer container-lg width-full p-responsive" role="contentinfo"> - <div class="position-relative d-flex flex-row-reverse flex-lg-row flex-wrap flex-lg-nowrap flex-justify-center flex-lg-justify-between pt-6 pb-2 mt-6 f6 text-gray border-top border-gray-light "> - <ul class="list-style-none d-flex flex-wrap col-12 col-lg-5 flex-justify-center flex-lg-justify-between mb-2 mb-lg-0"> - <li class="mr-3 mr-lg-0">&copy; 2019 <span title="0.34492s from unicorn-88f4ddb55-c64d9">GitHub</span>, Inc.</li> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to terms, text:terms" href="https://github.com/site/terms">Terms</a></li> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to privacy, text:privacy" href="https://github.com/site/privacy">Privacy</a></li> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to security, text:security" href="https://github.com/security">Security</a></li> - <li class="mr-3 mr-lg-0"><a href="https://githubstatus.com/" data-ga-click="Footer, go to status, text:status">Status</a></li> - <li><a data-ga-click="Footer, go to help, text:help" href="https://help.github.com">Help</a></li> - </ul> - - <a aria-label="Homepage" title="GitHub" class="footer-octicon d-none d-lg-block mx-lg-4" href="https://github.com"> - <svg height="24" class="octicon octicon-mark-github" viewBox="0 0 16 16" version="1.1" width="24" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg> -</a> - <ul class="list-style-none d-flex flex-wrap col-12 col-lg-5 flex-justify-center flex-lg-justify-between mb-2 mb-lg-0"> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to contact, text:contact" href="https://github.com/contact">Contact GitHub</a></li> - <li class="mr-3 mr-lg-0"><a href="https://github.com/pricing" data-ga-click="Footer, go to Pricing, text:Pricing">Pricing</a></li> - <li class="mr-3 mr-lg-0"><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li> - <li class="mr-3 mr-lg-0"><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li> - <li class="mr-3 mr-lg-0"><a href="https://github.blog" data-ga-click="Footer, go to blog, text:blog">Blog</a></li> - <li><a data-ga-click="Footer, go to about, text:about" href="https://github.com/about">About</a></li> - - </ul> - </div> - <div class="d-flex flex-justify-center pb-6"> - <span class="f6 text-gray-light"></span> - </div> -</div> - - - - <div id="ajax-error-message" class="ajax-error-message flash flash-error"> - <svg class="octicon octicon-alert" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"/></svg> - <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error"> - <svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg> - </button> - You can’t perform that action at this time. - </div> - - - <script crossorigin="anonymous" integrity="sha512-BlCvumXWTvpASEdhCGiahDUDf7Bwb8QXA2XnnSnqJ9QafxcNcrNYUNYS2wXmd3nEpO//+zlZa9DSV9zmu5MqRg==" type="application/javascript" src="https://github.githubassets.com/assets/compat-bootstrap-90c0ace0.js"></script> - <script crossorigin="anonymous" integrity="sha512-/PxjwfwA7IQQAc/3OBA+EvAAOgs24JUmL+yYRnEl/N7pMvQRi+hBftbGJweH00j3z9d1mUOQpmR0D33CE5Wt7g==" type="application/javascript" src="https://github.githubassets.com/assets/frameworks-f1ce1e70.js"></script> - - <script crossorigin="anonymous" async="async" integrity="sha512-41RCZRCF3ndqncgjVi28zesDHQIA/pjp+qtail1asqbRM8BUPv4Vih2Lvlgv0cHACwKlcJJYxJO4+9iNf+rtRQ==" type="application/javascript" src="https://github.githubassets.com/assets/github-bootstrap-98914a0f.js"></script> - - - - <div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner" hidden - > - <svg class="octicon octicon-alert" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"/></svg> - <span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span> - <span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span> - </div> - <template id="site-details-dialog"> - <details class="details-reset details-overlay details-overlay-dark lh-default text-gray-dark hx_rsm" open> - <summary role="button" aria-label="Close dialog"></summary> - <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast hx_rsm-dialog hx_rsm-modal"> - <button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog> - <svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg> - </button> - <div class="octocat-spinner my-6 js-details-dialog-spinner"></div> - </details-dialog> - </details> -</template> - - <div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;" tabindex="0"> - <div class="Popover-message Popover-message--bottom-left Popover-message--large Box box-shadow-large" style="width:360px;"> - </div> -</div> - - <div aria-live="polite" class="js-global-screen-reader-notice sr-only"></div> - - </body> -</html> - +/* + * Copyright (C) 2015 Federico Dossena (adolfintel.com). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package com.dosse.upnp; + +import java.net.HttpURLConnection; +import java.net.Inet4Address; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; +import javax.xml.parsers.DocumentBuilderFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.traversal.DocumentTraversal; +import org.w3c.dom.traversal.NodeFilter; +import org.w3c.dom.traversal.NodeIterator; + +/** + * + * @author Federico + */ +class Gateway { + + private Inet4Address iface; + + private String serviceType = null, controlURL = null; + + public Gateway(byte[] data, Inet4Address ip) throws Exception { + iface = ip; + String location = null; + StringTokenizer st = new StringTokenizer(new String(data), "\n"); + while (st.hasMoreTokens()) { + String s = st.nextToken().trim(); + if (s.isEmpty() || s.startsWith("HTTP/1.") || s.startsWith("NOTIFY *")) { + continue; + } + String name = s.substring(0, s.indexOf(':')), val = s.length() >= name.length() ? s.substring(name.length() + 1).trim() : null; + if (name.equalsIgnoreCase("location")) { + location = val; + } + } + if (location == null) { + throw new Exception("Unsupported Gateway"); + } + Document d; + d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(location); + NodeList services = d.getElementsByTagName("service"); + for (int i = 0; i < services.getLength(); i++) { + Node service = services.item(i); + NodeList n = service.getChildNodes(); + String serviceType = null, controlURL = null; + for (int j = 0; j < n.getLength(); j++) { + Node x = n.item(j); + if (x.getNodeName().trim().equalsIgnoreCase("serviceType")) { + serviceType = x.getFirstChild().getNodeValue(); + } else if (x.getNodeName().trim().equalsIgnoreCase("controlURL")) { + controlURL = x.getFirstChild().getNodeValue(); + } + } + if (serviceType == null || controlURL == null) { + continue; + } + if (serviceType.trim().toLowerCase().contains(":wanipconnection:") || serviceType.trim().toLowerCase().contains(":wanpppconnection:")) { + this.serviceType = serviceType.trim(); + this.controlURL = controlURL.trim(); + } + } + if (controlURL == null) { + throw new Exception("Unsupported Gateway"); + } + int slash = location.indexOf("/", 7); //finds first slash after http:// + if (slash == -1) { + throw new Exception("Unsupported Gateway"); + } + location = location.substring(0, slash); + if (!controlURL.startsWith("/")) { + controlURL = "/" + controlURL; + } + controlURL = location + controlURL; + } + + private Map<String, String> command(String action, Map<String, String> params) throws Exception { + Map<String, String> ret = new HashMap<String, String>(); + String soap = "<?xml version=\"1.0\"?>\r\n" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" + + "<SOAP-ENV:Body>" + + "<m:" + action + " xmlns:m=\"" + serviceType + "\">"; + if (params != null) { + for (Map.Entry<String, String> entry : params.entrySet()) { + soap += "<" + entry.getKey() + ">" + entry.getValue() + "</" + entry.getKey() + ">"; + } + } + soap += "</m:" + action + "></SOAP-ENV:Body></SOAP-ENV:Envelope>"; + byte[] req = soap.getBytes(); + HttpURLConnection conn = (HttpURLConnection) new URL(controlURL).openConnection(); + conn.setRequestMethod("POST"); + conn.setDoOutput(true); + conn.setRequestProperty("Content-Type", "text/xml"); + conn.setRequestProperty("SOAPAction", "\"" + serviceType + "#" + action + "\""); + conn.setRequestProperty("Connection", "Close"); + conn.setRequestProperty("Content-Length", "" + req.length); + conn.getOutputStream().write(req); + Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(conn.getInputStream()); + NodeIterator iter = ((DocumentTraversal) d).createNodeIterator(d.getDocumentElement(), NodeFilter.SHOW_ELEMENT, null, true); + Node n; + while ((n = iter.nextNode()) != null) { + try { + if (n.getFirstChild().getNodeType() == Node.TEXT_NODE) { + ret.put(n.getNodeName(), n.getTextContent()); + } + } catch (Throwable t) { + } + } + conn.disconnect(); + return ret; + } + + public String getLocalIP() { + return iface.getHostAddress(); + } + + public String getExternalIP() { + try { + Map<String, String> r = command("GetExternalIPAddress", null); + return r.get("NewExternalIPAddress"); + } catch (Throwable t) { + return null; + } + } + + public boolean openPort(int port, boolean udp) { + if (port < 0 || port > 65535) { + throw new IllegalArgumentException("Invalid port"); + } + Map<String, String> params = new HashMap<String, String>(); + params.put("NewRemoteHost", ""); + params.put("NewProtocol", udp ? "UDP" : "TCP"); + params.put("NewInternalClient", iface.getHostAddress()); + params.put("NewExternalPort", "" + port); + params.put("NewInternalPort", "" + port); + params.put("NewEnabled", "1"); + params.put("NewPortMappingDescription", "WaifUPnP"); + params.put("NewLeaseDuration", "0"); + try { + Map<String, String> r = command("AddPortMapping", params); + return r.get("errorCode") == null; + } catch (Exception ex) { + return false; + } + } + + public boolean closePort(int port, boolean udp) { + if (port < 0 || port > 65535) { + throw new IllegalArgumentException("Invalid port"); + } + Map<String, String> params = new HashMap<String, String>(); + params.put("NewRemoteHost", ""); + params.put("NewProtocol", udp ? "UDP" : "TCP"); + params.put("NewExternalPort", "" + port); + try { + command("DeletePortMapping", params); + return true; + } catch (Exception ex) { + return false; + } + } + + public boolean isMapped(int port, boolean udp) { + if (port < 0 || port > 65535) { + throw new IllegalArgumentException("Invalid port"); + } + Map<String, String> params = new HashMap<String, String>(); + params.put("NewRemoteHost", ""); + params.put("NewProtocol", udp ? "UDP" : "TCP"); + params.put("NewExternalPort", "" + port); + try { + Map<String, String> r = command("GetSpecificPortMappingEntry", params); + if (r.get("errorCode") != null) { + throw new Exception(); + } + return r.get("NewInternalPort") != null; + } catch (Exception ex) { + return false; + } + + } + +} diff --git a/src/WaifUPnP/GatewayFinder.java b/src/WaifUPnP/GatewayFinder.java @@ -1,1669 +1,132 @@ - - - - - - -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <link rel="dns-prefetch" href="https://github.githubassets.com"> - <link rel="dns-prefetch" href="https://avatars0.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars1.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars2.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars3.githubusercontent.com"> - <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com"> - <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/"> - - - - <link crossorigin="anonymous" media="all" integrity="sha512-kBwTI/PLZvQ8eHdCgA2vpn0uJe4kEM/Ft7Zz5SAkc9BAifCxBxQS4VTaEIDJpVrbrlAhCeRJvf7DQWaA4dEUUQ==" rel="stylesheet" href="https://github.githubassets.com/assets/frameworks-da88be2d386821a8fa8de15789a23d23.css" /> - - <link crossorigin="anonymous" media="all" integrity="sha512-nxbIj3bfB8KtcNqQMnlOaPPMDmP9FiDWwjUpBLQy96vbpF72WO9aDrOU4TSu7T+fHKrBCeBWaRb9+keZgwcQlg==" rel="stylesheet" href="https://github.githubassets.com/assets/github-d7e1e4a3feb3fbdf6b2de5e69a10cb6e.css" /> - - - - - - <meta name="viewport" content="width=device-width"> - - <title>WaifUPnP/GatewayFinder.java at master · adolfintel/WaifUPnP</title> - <meta name="description" content=" UPnP Port Forwarding for Java couldn&#39;t get any easier! - adolfintel/WaifUPnP"> - <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub"> - <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub"> - <meta property="fb:app_id" content="1401488693436528"> - - <meta name="twitter:image:src" content="https://avatars3.githubusercontent.com/u/16307689?s=400&amp;v=4" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary" /><meta name="twitter:title" content="adolfintel/WaifUPnP" /><meta name="twitter:description" content=" UPnP Port Forwarding for Java couldn&#39;t get any easier! - adolfintel/WaifUPnP" /> - <meta property="og:image" content="https://avatars3.githubusercontent.com/u/16307689?s=400&amp;v=4" /><meta property="og:site_name" content="GitHub" /><meta property="og:type" content="object" /><meta property="og:title" content="adolfintel/WaifUPnP" /><meta property="og:url" content="https://github.com/adolfintel/WaifUPnP" /><meta property="og:description" content=" UPnP Port Forwarding for Java couldn&#39;t get any easier! - adolfintel/WaifUPnP" /> - - <link rel="assets" href="https://github.githubassets.com/"> - <link rel="web-socket" href="wss://live.github.com/_sockets/VjI6NDI2ODEwNTUzOjE0NDVlZDM0MjM1MmRlNWMzN2M4MDkxYTYyMzM4NTM3NzFlOTBjZGUxYzVmMTJhODIyZWQ3YTE3ZGY3ZWJjOTM=--a532bcfa90e6ec0fc6830c8b3a84d8321eb832e6"> - <meta name="pjax-timeout" content="1000"> - <link rel="sudo-modal" href="/sessions/sudo_modal"> - <meta name="request-id" content="86A4:43DB:134E6E:219D1F:5D49A994" data-pjax-transient> - - - - - <meta name="selected-link" value="repo_source" data-pjax-transient> - - <meta name="google-site-verification" content="KT5gs8h0wvaagLKAVWq8bbeNwnZZK1r1XQysX3xurLU"> - <meta name="google-site-verification" content="ZzhVyEFwb7w3e0-uOTltm8Jsck2F5StVihD0exw2fsA"> - <meta name="google-site-verification" content="GXs5KoUUkNCoaAZn7wPN-t01Pywp9M3sEjnt_3_ZWPc"> - - <meta name="octolytics-host" content="collector.githubapp.com" /><meta name="octolytics-app-id" content="github" /><meta name="octolytics-event-url" content="https://collector.githubapp.com/github-external/browser_event" /><meta name="octolytics-dimension-request_id" content="86A4:43DB:134E6E:219D1F:5D49A994" /><meta name="octolytics-dimension-region_edge" content="iad" /><meta name="octolytics-dimension-region_render" content="iad" /><meta name="octolytics-actor-id" content="36491773" /><meta name="octolytics-actor-login" content="joshiemoore" /><meta name="octolytics-actor-hash" content="9fb9350a5ba47535efbba66a9fcc4ea37914a763e681b8faf401c837136a34a7" /> -<meta name="analytics-location" content="/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show" data-pjax-transient="true" /> - - - - - <meta class="js-ga-set" name="userId" content="70e439b4adcf1202f8343b7daf395cbf"> - -<meta class="js-ga-set" name="dimension1" content="Logged In"> - - - - - - <meta name="hostname" content="github.com"> - <meta name="user-login" content="joshiemoore"> - - <meta name="expected-hostname" content="github.com"> - <meta name="js-proxy-site-detection-payload" content="MDdlODY3MGY0NjljNjRjNDIwY2IyMjA0M2E0YzEzOTZhZDM4MDQzN2I4ODQxNzZhMGEyNDJiYWNkYjI1ZDBkNnx7InJlbW90ZV9hZGRyZXNzIjoiNzEuMTE1LjE1MS4xNCIsInJlcXVlc3RfaWQiOiI4NkE0OjQzREI6MTM0RTZFOjIxOUQxRjo1RDQ5QTk5NCIsInRpbWVzdGFtcCI6MTU2NTEwODY1MiwiaG9zdCI6ImdpdGh1Yi5jb20ifQ=="> - - <meta name="enabled-features" content="MARKETPLACE_FEATURED_BLOG_POSTS,MARKETPLACE_INVOICED_BILLING,MARKETPLACE_SOCIAL_PROOF_CUSTOMERS,MARKETPLACE_TRENDING_SOCIAL_PROOF,MARKETPLACE_RECOMMENDATIONS,MARKETPLACE_PENDING_INSTALLATIONS,NOTIFY_ON_BLOCK,RELATED_ISSUES"> - - <meta name="html-safe-nonce" content="21324b34db3b2bdbb5f491c2f72dc9dfc36873ac"> - - <meta http-equiv="x-pjax-version" content="5a9990041a6b9c1bf57398c337e95d61"> - - - <link href="https://github.com/adolfintel/WaifUPnP/commits/master.atom" rel="alternate" title="Recent Commits to WaifUPnP:master" type="application/atom+xml"> - - <meta name="go-import" content="github.com/adolfintel/WaifUPnP git https://github.com/adolfintel/WaifUPnP.git"> - - <meta name="octolytics-dimension-user_id" content="16307689" /><meta name="octolytics-dimension-user_login" content="adolfintel" /><meta name="octolytics-dimension-repository_id" content="48129574" /><meta name="octolytics-dimension-repository_nwo" content="adolfintel/WaifUPnP" /><meta name="octolytics-dimension-repository_public" content="true" /><meta name="octolytics-dimension-repository_is_fork" content="false" /><meta name="octolytics-dimension-repository_network_root_id" content="48129574" /><meta name="octolytics-dimension-repository_network_root_nwo" content="adolfintel/WaifUPnP" /><meta name="octolytics-dimension-repository_explore_github_marketplace_ci_cta_shown" content="false" /> - - - <link rel="canonical" href="https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/GatewayFinder.java" data-pjax-transient> - - - <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats"> - - <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors"> - - <link rel="mask-icon" href="https://github.githubassets.com/pinned-octocat.svg" color="#000000"> - <link rel="icon" type="image/x-icon" class="js-site-favicon" href="https://github.githubassets.com/favicon.ico"> - -<meta name="theme-color" content="#1e2327"> - - - - - - <link rel="manifest" href="/manifest.json" crossOrigin="use-credentials"> - - </head> - - <body class="logged-in env-production page-responsive page-blob"> - - - <div class="position-relative js-header-wrapper "> - <a href="#start-of-content" tabindex="1" class="p-3 bg-blue text-white show-on-focus js-skip-to-content">Skip to content</a> - <div id="js-pjax-loader-bar" class="pjax-loader-bar"><div class="progress"></div></div> - - - - - - - <header class="Header js-details-container Details flex-wrap flex-lg-nowrap p-responsive" role="banner"> - - <div class="Header-item d-none d-lg-flex"> - <a class="Header-link" href="https://github.com/" data-hotkey="g d" aria-label="Homepage" data-ga-click="Header, go to dashboard, icon:logo"> - <svg class="octicon octicon-mark-github v-align-middle" height="32" viewBox="0 0 16 16" version="1.1" width="32" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg> -</a> - - </div> - - <div class="Header-item d-lg-none"> - <button class="Header-link btn-link js-details-target" type="button" aria-label="Toggle navigation" aria-expanded="false"> - <svg height="24" class="octicon octicon-three-bars" viewBox="0 0 12 16" version="1.1" width="18" aria-hidden="true"><path fill-rule="evenodd" d="M11.41 9H.59C0 9 0 8.59 0 8c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zm0-4H.59C0 5 0 4.59 0 4c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zM.59 11H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1H.59C0 13 0 12.59 0 12c0-.59 0-1 .59-1z"/></svg> - </button> - </div> - - <div class="Header-item Header-item--full flex-column flex-lg-row width-full flex-order-2 flex-lg-order-none mr-0 mr-lg-3 mt-3 mt-lg-0 Details-content--hidden"> - <div class="header-search flex-self-stretch flex-lg-self-auto mr-0 mr-lg-3 mb-3 mb-lg-0 scoped-search site-scoped-search js-site-search position-relative js-jump-to" - role="combobox" - aria-owns="jump-to-results" - aria-label="Search or jump to" - aria-haspopup="listbox" - aria-expanded="false" -> - <div class="position-relative"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="js-site-search-form" role="search" aria-label="Site" data-scope-type="Repository" data-scope-id="48129574" data-scoped-search-url="/adolfintel/WaifUPnP/search" data-unscoped-search-url="/search" action="/adolfintel/WaifUPnP/search" accept-charset="UTF-8" method="get"><input name="utf8" type="hidden" value="&#x2713;" /> - <label class="form-control input-sm header-search-wrapper p-0 header-search-wrapper-jump-to position-relative d-flex flex-justify-between flex-items-center js-chromeless-input-container"> - <input type="text" - class="form-control input-sm header-search-input jump-to-field js-jump-to-field js-site-search-focus js-site-search-field is-clearable" - data-hotkey="s,/" - name="q" - value="" - placeholder="Search or jump to…" - data-unscoped-placeholder="Search or jump to…" - data-scoped-placeholder="Search or jump to…" - autocapitalize="off" - aria-autocomplete="list" - aria-controls="jump-to-results" - aria-label="Search or jump to…" - data-jump-to-suggestions-path="/_graphql/GetSuggestedNavigationDestinations#csrf-token=7n1WudprqDXdSD0OFiYLcBJ7Pj4swMPW9w/J67AFzSxCB18wT9Eu2nqVSBOSwKEMaAAiXKvspfgHe8wUWMyGSw==" - spellcheck="false" - autocomplete="off" - > - <input type="hidden" class="js-site-search-type-field" name="type" > - <img src="https://github.githubassets.com/images/search-key-slash.svg" alt="" class="mr-2 header-search-key-slash"> - - <div class="Box position-absolute overflow-hidden d-none jump-to-suggestions js-jump-to-suggestions-container"> - -<ul class="d-none js-jump-to-suggestions-template-container"> - - -<li class="d-flex flex-justify-start flex-items-center p-0 f5 navigation-item js-navigation-item js-jump-to-suggestion" role="option"> - <a tabindex="-1" class="no-underline d-flex flex-auto flex-items-center jump-to-suggestions-path js-jump-to-suggestion-path js-navigation-open p-2" href=""> - <div class="jump-to-octicon js-jump-to-octicon flex-shrink-0 mr-2 text-center d-none"> - <svg height="16" width="16" class="octicon octicon-repo flex-shrink-0 js-jump-to-octicon-repo d-none" title="Repository" aria-label="Repository" viewBox="0 0 12 16" version="1.1" role="img"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <svg height="16" width="16" class="octicon octicon-project flex-shrink-0 js-jump-to-octicon-project d-none" title="Project" aria-label="Project" viewBox="0 0 15 16" version="1.1" role="img"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - <svg height="16" width="16" class="octicon octicon-search flex-shrink-0 js-jump-to-octicon-search d-none" title="Search" aria-label="Search" viewBox="0 0 16 16" version="1.1" role="img"><path fill-rule="evenodd" d="M15.7 13.3l-3.81-3.83A5.93 5.93 0 0 0 13 6c0-3.31-2.69-6-6-6S1 2.69 1 6s2.69 6 6 6c1.3 0 2.48-.41 3.47-1.11l3.83 3.81c.19.2.45.3.7.3.25 0 .52-.09.7-.3a.996.996 0 0 0 0-1.41v.01zM7 10.7c-2.59 0-4.7-2.11-4.7-4.7 0-2.59 2.11-4.7 4.7-4.7 2.59 0 4.7 2.11 4.7 4.7 0 2.59-2.11 4.7-4.7 4.7z"/></svg> - </div> - - <img class="avatar mr-2 flex-shrink-0 js-jump-to-suggestion-avatar d-none" alt="" aria-label="Team" src="" width="28" height="28"> - - <div class="jump-to-suggestion-name js-jump-to-suggestion-name flex-auto overflow-hidden text-left no-wrap css-truncate css-truncate-target"> - </div> - - <div class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none js-jump-to-badge-search"> - <span class="js-jump-to-badge-search-text-default d-none" aria-label="in this repository"> - In this repository - </span> - <span class="js-jump-to-badge-search-text-global d-none" aria-label="in all of GitHub"> - All GitHub - </span> - <span aria-hidden="true" class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - - <div aria-hidden="true" class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none d-on-nav-focus js-jump-to-badge-jump"> - Jump to - <span class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - </a> -</li> - -</ul> - -<ul class="d-none js-jump-to-no-results-template-container"> - <li class="d-flex flex-justify-center flex-items-center f5 d-none js-jump-to-suggestion p-2"> - <span class="text-gray">No suggested jump to results</span> - </li> -</ul> - -<ul id="jump-to-results" role="listbox" class="p-0 m-0 js-navigation-container jump-to-suggestions-results-container js-jump-to-suggestions-results-container"> - - -<li class="d-flex flex-justify-start flex-items-center p-0 f5 navigation-item js-navigation-item js-jump-to-scoped-search d-none" role="option"> - <a tabindex="-1" class="no-underline d-flex flex-auto flex-items-center jump-to-suggestions-path js-jump-to-suggestion-path js-navigation-open p-2" href=""> - <div class="jump-to-octicon js-jump-to-octicon flex-shrink-0 mr-2 text-center d-none"> - <svg height="16" width="16" class="octicon octicon-repo flex-shrink-0 js-jump-to-octicon-repo d-none" title="Repository" aria-label="Repository" viewBox="0 0 12 16" version="1.1" role="img"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <svg height="16" width="16" class="octicon octicon-project flex-shrink-0 js-jump-to-octicon-project d-none" title="Project" aria-label="Project" viewBox="0 0 15 16" version="1.1" role="img"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - <svg height="16" width="16" class="octicon octicon-search flex-shrink-0 js-jump-to-octicon-search d-none" title="Search" aria-label="Search" viewBox="0 0 16 16" version="1.1" role="img"><path fill-rule="evenodd" d="M15.7 13.3l-3.81-3.83A5.93 5.93 0 0 0 13 6c0-3.31-2.69-6-6-6S1 2.69 1 6s2.69 6 6 6c1.3 0 2.48-.41 3.47-1.11l3.83 3.81c.19.2.45.3.7.3.25 0 .52-.09.7-.3a.996.996 0 0 0 0-1.41v.01zM7 10.7c-2.59 0-4.7-2.11-4.7-4.7 0-2.59 2.11-4.7 4.7-4.7 2.59 0 4.7 2.11 4.7 4.7 0 2.59-2.11 4.7-4.7 4.7z"/></svg> - </div> - - <img class="avatar mr-2 flex-shrink-0 js-jump-to-suggestion-avatar d-none" alt="" aria-label="Team" src="" width="28" height="28"> - - <div class="jump-to-suggestion-name js-jump-to-suggestion-name flex-auto overflow-hidden text-left no-wrap css-truncate css-truncate-target"> - </div> - - <div class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none js-jump-to-badge-search"> - <span class="js-jump-to-badge-search-text-default d-none" aria-label="in this repository"> - In this repository - </span> - <span class="js-jump-to-badge-search-text-global d-none" aria-label="in all of GitHub"> - All GitHub - </span> - <span aria-hidden="true" class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - - <div aria-hidden="true" class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none d-on-nav-focus js-jump-to-badge-jump"> - Jump to - <span class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - </a> -</li> - - - -<li class="d-flex flex-justify-start flex-items-center p-0 f5 navigation-item js-navigation-item js-jump-to-global-search d-none" role="option"> - <a tabindex="-1" class="no-underline d-flex flex-auto flex-items-center jump-to-suggestions-path js-jump-to-suggestion-path js-navigation-open p-2" href=""> - <div class="jump-to-octicon js-jump-to-octicon flex-shrink-0 mr-2 text-center d-none"> - <svg height="16" width="16" class="octicon octicon-repo flex-shrink-0 js-jump-to-octicon-repo d-none" title="Repository" aria-label="Repository" viewBox="0 0 12 16" version="1.1" role="img"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <svg height="16" width="16" class="octicon octicon-project flex-shrink-0 js-jump-to-octicon-project d-none" title="Project" aria-label="Project" viewBox="0 0 15 16" version="1.1" role="img"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - <svg height="16" width="16" class="octicon octicon-search flex-shrink-0 js-jump-to-octicon-search d-none" title="Search" aria-label="Search" viewBox="0 0 16 16" version="1.1" role="img"><path fill-rule="evenodd" d="M15.7 13.3l-3.81-3.83A5.93 5.93 0 0 0 13 6c0-3.31-2.69-6-6-6S1 2.69 1 6s2.69 6 6 6c1.3 0 2.48-.41 3.47-1.11l3.83 3.81c.19.2.45.3.7.3.25 0 .52-.09.7-.3a.996.996 0 0 0 0-1.41v.01zM7 10.7c-2.59 0-4.7-2.11-4.7-4.7 0-2.59 2.11-4.7 4.7-4.7 2.59 0 4.7 2.11 4.7 4.7 0 2.59-2.11 4.7-4.7 4.7z"/></svg> - </div> - - <img class="avatar mr-2 flex-shrink-0 js-jump-to-suggestion-avatar d-none" alt="" aria-label="Team" src="" width="28" height="28"> - - <div class="jump-to-suggestion-name js-jump-to-suggestion-name flex-auto overflow-hidden text-left no-wrap css-truncate css-truncate-target"> - </div> - - <div class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none js-jump-to-badge-search"> - <span class="js-jump-to-badge-search-text-default d-none" aria-label="in this repository"> - In this repository - </span> - <span class="js-jump-to-badge-search-text-global d-none" aria-label="in all of GitHub"> - All GitHub - </span> - <span aria-hidden="true" class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - - <div aria-hidden="true" class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none d-on-nav-focus js-jump-to-badge-jump"> - Jump to - <span class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - </a> -</li> - - - <li class="d-flex flex-justify-center flex-items-center p-0 f5 js-jump-to-suggestion"> - <img src="https://github.githubassets.com/images/spinners/octocat-spinner-128.gif" alt="Octocat Spinner Icon" class="m-2" width="28"> - </li> -</ul> - - </div> - </label> -</form> </div> -</div> - - - <nav class="d-flex flex-column flex-lg-row flex-self-stretch flex-lg-self-auto" aria-label="Global"> - <a class="Header-link d-block d-lg-none py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-ga-click="Header, click, Nav menu - item:dashboard:user" aria-label="Dashboard" href="/dashboard"> - Dashboard -</a> - <a class="js-selected-navigation-item Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-hotkey="g p" data-ga-click="Header, click, Nav menu - item:pulls context:user" aria-label="Pull requests you created" data-selected-links="/pulls /pulls/assigned /pulls/mentioned /pulls" href="/pulls"> - Pull requests -</a> - <a class="js-selected-navigation-item Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-hotkey="g i" data-ga-click="Header, click, Nav menu - item:issues context:user" aria-label="Issues you created" data-selected-links="/issues /issues/assigned /issues/mentioned /issues" href="/issues"> - Issues -</a> - <div class="mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15"> - <a class="js-selected-navigation-item Header-link" data-ga-click="Header, click, Nav menu - item:marketplace context:user" data-octo-click="marketplace_click" data-octo-dimensions="location:nav_bar" data-selected-links=" /marketplace" href="/marketplace"> - Marketplace -</a> - </div> - - <a class="js-selected-navigation-item Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-ga-click="Header, click, Nav menu - item:explore" data-selected-links="/explore /trending /trending/developers /integrations /integrations/feature/code /integrations/feature/collaborate /integrations/feature/ship showcases showcases_search showcases_landing /explore" href="/explore"> - Explore -</a> - - - <a class="Header-link d-block d-lg-none mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" href="https://github.com/joshiemoore"> - <img class="avatar" height="20" width="20" alt="@joshiemoore" src="https://avatars3.githubusercontent.com/u/36491773?s=60&amp;v=4" /> - joshiemoore -</a> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form action="/logout" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="3k087fsYjtYKFmUwjMGA/9DstcDFgYmHmBhXnkd3Jpsv6r/OOlhp6vgMizCmBjcHBrnm0F+hdI/uJwa02ZPaOQ==" /> - <button type="submit" class="Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15 d-lg-none btn-link d-block width-full text-left" data-ga-click="Header, sign out, icon:logout" style="padding-left: 2px;"> - <svg class="octicon octicon-sign-out v-align-middle" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 9V7H8V5h4V3l4 3-4 3zm-2 3H6V3L2 1h8v3h1V1c0-.55-.45-1-1-1H1C.45 0 0 .45 0 1v11.38c0 .39.22.73.55.91L6 16.01V13h4c.55 0 1-.45 1-1V8h-1v4z"/></svg> - Sign out - </button> -</form></nav> - - </div> - - <div class="Header-item Header-item--full flex-justify-center d-lg-none position-relative"> - <div class="css-truncate css-truncate-target width-fit position-absolute left-0 right-0 text-center"> - <svg class="octicon octicon-repo" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <a class="Header-link" href="/adolfintel">adolfintel</a> - / - <a class="Header-link" href="/adolfintel/WaifUPnP">WaifUPnP</a> - -</div> - </div> - - <div class="Header-item position-relative d-none d-lg-flex"> - - - </div> - - <div class="Header-item mr-0 mr-lg-3 flex-order-1 flex-lg-order-none"> - - - <a aria-label="You have no unread notifications" class="Header-link notification-indicator position-relative tooltipped tooltipped-s js-socket-channel js-notification-indicator" data-hotkey="g n" data-ga-click="Header, go to notifications, icon:read" data-channel="notification-changed:36491773" href="/notifications"> - <span class="mail-status "></span> - <svg class="octicon octicon-bell" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14 12v1H0v-1l.73-.58c.77-.77.81-2.55 1.19-4.42C2.69 3.23 6 2 6 2c0-.55.45-1 1-1s1 .45 1 1c0 0 3.39 1.23 4.16 5 .38 1.88.42 3.66 1.19 4.42l.66.58H14zm-7 4c1.11 0 2-.89 2-2H5c0 1.11.89 2 2 2z"/></svg> -</a> - </div> - - - <div class="Header-item position-relative d-none d-lg-flex"> - <details class="details-overlay details-reset"> - <summary class="Header-link" - aria-label="Create new…" - data-ga-click="Header, create new, icon:add"> - <svg class="octicon octicon-plus" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 9H7v5H5V9H0V7h5V2h2v5h5v2z"/></svg> <span class="dropdown-caret"></span> - </summary> - <details-menu class="dropdown-menu dropdown-menu-sw"> - -<a role="menuitem" class="dropdown-item" href="/new" data-ga-click="Header, create new repository"> - New repository -</a> - - <a role="menuitem" class="dropdown-item" href="/new/import" data-ga-click="Header, import a repository"> - Import repository - </a> - -<a role="menuitem" class="dropdown-item" href="https://gist.github.com/" data-ga-click="Header, create new gist"> - New gist -</a> - - <a role="menuitem" class="dropdown-item" href="/organizations/new" data-ga-click="Header, create new organization"> - New organization - </a> - - - <div role="none" class="dropdown-divider"></div> - <div class="dropdown-header"> - <span title="adolfintel/WaifUPnP">This repository</span> - </div> - <a role="menuitem" class="dropdown-item" href="/adolfintel/WaifUPnP/issues/new" data-ga-click="Header, create new issue" data-skip-pjax> - New issue - </a> - - - </details-menu> -</details> - - </div> - - <div class="Header-item position-relative mr-0 d-none d-lg-flex"> - -<details class="details-overlay details-reset"> - <summary class="Header-link" - aria-label="View profile and more" - data-ga-click="Header, show menu, icon:avatar"> - <img alt="@joshiemoore" class="avatar" src="https://avatars0.githubusercontent.com/u/36491773?s=40&amp;v=4" height="20" width="20"> - <span class="dropdown-caret"></span> - </summary> - <details-menu class="dropdown-menu dropdown-menu-sw mt-2" style="width: 180px"> - <div class="header-nav-current-user css-truncate"><a role="menuitem" class="no-underline user-profile-link px-3 pt-2 pb-2 mb-n2 mt-n1 d-block" href="/joshiemoore" data-ga-click="Header, go to profile, text:Signed in as">Signed in as <strong class="css-truncate-target">joshiemoore</strong></a></div> - <div role="none" class="dropdown-divider"></div> - - <div class="pl-3 pr-3 f6 user-status-container js-user-status-context pb-1" data-url="/users/status?compact=1&amp;link_mentions=0&amp;truncate=1"> - -<div class="js-user-status-container - user-status-compact rounded-1 px-2 py-1 mt-2 - border - " data-team-hovercards-enabled> - <details class="js-user-status-details details-reset details-overlay details-overlay-dark"> - <summary class="btn-link btn-block link-gray no-underline js-toggle-user-status-edit toggle-user-status-edit " aria-haspopup="dialog" role="menuitem" data-hydro-click="{&quot;event_type&quot;:&quot;user_profile.click&quot;,&quot;payload&quot;:{&quot;profile_user_id&quot;:16307689,&quot;target&quot;:&quot;EDIT_USER_STATUS&quot;,&quot;user_id&quot;:36491773,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134E6E:219D1F:5D49A994&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/GatewayFinder.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;}}" data-hydro-click-hmac="baee4efa61cdac526235867adc1cd96bb008a2d8f2287c1db5deb656a9036d8b"> - <div class="d-flex"> - <div class="f6 lh-condensed user-status-header - d-inline-block v-align-middle - user-status-emoji-only-header circle - pr-2 -" - style="max-width: 29px" - > - <div class="user-status-emoji-container flex-shrink-0 mr-1 mt-1 lh-condensed-ultra v-align-bottom" style=""> - <svg class="octicon octicon-smiley" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm4.81 12.81a6.72 6.72 0 0 1-2.17 1.45c-.83.36-1.72.53-2.64.53-.92 0-1.81-.17-2.64-.53-.81-.34-1.55-.83-2.17-1.45a6.773 6.773 0 0 1-1.45-2.17A6.59 6.59 0 0 1 1.21 8c0-.92.17-1.81.53-2.64.34-.81.83-1.55 1.45-2.17.62-.62 1.36-1.11 2.17-1.45A6.59 6.59 0 0 1 8 1.21c.92 0 1.81.17 2.64.53.81.34 1.55.83 2.17 1.45.62.62 1.11 1.36 1.45 2.17.36.83.53 1.72.53 2.64 0 .92-.17 1.81-.53 2.64-.34.81-.83 1.55-1.45 2.17zM4 6.8v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2H5.2C4.53 8 4 7.47 4 6.8zm5 0v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2h-.59C9.53 8 9 7.47 9 6.8zm4 3.2c-.72 1.88-2.91 3-5 3s-4.28-1.13-5-3c-.14-.39.23-1 .66-1h8.59c.41 0 .89.61.75 1z"/></svg> - </div> - </div> - <div class=" - d-inline-block v-align-middle - - - css-truncate css-truncate-target - user-status-message-wrapper f6" - style="line-height: 20px;" > - <div class="d-inline-block text-gray-dark v-align-text-top text-left"> - <span class="text-gray ml-2">Set status</span> - </div> - </div> - </div> -</summary> <details-dialog class="details-dialog rounded-1 anim-fade-in fast Box Box--overlay" role="dialog" tabindex="-1"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="position-relative flex-auto js-user-status-form" action="/users/status?compact=1&amp;link_mentions=0&amp;truncate=1" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="_method" value="put" /><input type="hidden" name="authenticity_token" value="yLOXDNqd+3Nl7pzV2q0ZlZ+GFIDF6gx2AUGJ4GxTVnNLjWX+8EgdMrKHdv0emUymeMTyg1O45cO8Rc7/CemPuw==" /> - <div class="Box-header bg-gray border-bottom p-3"> - <button class="Box-btn-octicon js-toggle-user-status-edit btn-octicon float-right" type="reset" aria-label="Close dialog" data-close-dialog> - <svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg> - </button> - <h3 class="Box-title f5 text-bold text-gray-dark">Edit status</h3> - </div> - <input type="hidden" name="emoji" class="js-user-status-emoji-field" value=""> - <input type="hidden" name="organization_id" class="js-user-status-org-id-field" value=""> - <div class="px-3 py-2 text-gray-dark"> - <div class="js-characters-remaining-container position-relative mt-2"> - <div class="input-group d-table form-group my-0 js-user-status-form-group"> - <span class="input-group-button d-table-cell v-align-middle" style="width: 1%"> - <button type="button" aria-label="Choose an emoji" class="btn-outline btn js-toggle-user-status-emoji-picker btn-open-emoji-picker p-0"> - <span class="js-user-status-original-emoji" hidden></span> - <span class="js-user-status-custom-emoji"></span> - <span class="js-user-status-no-emoji-icon" > - <svg class="octicon octicon-smiley" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm4.81 12.81a6.72 6.72 0 0 1-2.17 1.45c-.83.36-1.72.53-2.64.53-.92 0-1.81-.17-2.64-.53-.81-.34-1.55-.83-2.17-1.45a6.773 6.773 0 0 1-1.45-2.17A6.59 6.59 0 0 1 1.21 8c0-.92.17-1.81.53-2.64.34-.81.83-1.55 1.45-2.17.62-.62 1.36-1.11 2.17-1.45A6.59 6.59 0 0 1 8 1.21c.92 0 1.81.17 2.64.53.81.34 1.55.83 2.17 1.45.62.62 1.11 1.36 1.45 2.17.36.83.53 1.72.53 2.64 0 .92-.17 1.81-.53 2.64-.34.81-.83 1.55-1.45 2.17zM4 6.8v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2H5.2C4.53 8 4 7.47 4 6.8zm5 0v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2h-.59C9.53 8 9 7.47 9 6.8zm4 3.2c-.72 1.88-2.91 3-5 3s-4.28-1.13-5-3c-.14-.39.23-1 .66-1h8.59c.41 0 .89.61.75 1z"/></svg> - </span> - </button> - </span> - <text-expander keys=": @" data-mention-url="/autocomplete/user-suggestions" data-emoji-url="/autocomplete/emoji"> - <input - type="text" - autocomplete="off" - data-no-org-url="/autocomplete/user-suggestions" - data-org-url="/suggestions?mention_suggester=1" - data-maxlength="80" - class="d-table-cell width-full form-control js-user-status-message-field js-characters-remaining-field" - placeholder="What's happening?" - name="message" - value="" - aria-label="What is your current status?"> - </text-expander> - <div class="error">Could not update your status, please try again.</div> - </div> - <div style="margin-left: 53px" class="my-1 text-small label-characters-remaining js-characters-remaining" data-suffix="remaining" hidden> - 80 remaining - </div> - </div> - <include-fragment class="js-user-status-emoji-picker" data-url="/users/status/emoji"></include-fragment> - <div class="overflow-auto ml-n3 mr-n3 px-3 border-bottom" style="max-height: 33vh"> - <div class="user-status-suggestions js-user-status-suggestions collapsed overflow-hidden"> - <h4 class="f6 text-normal my-3">Suggestions:</h4> - <div class="mx-3 mt-2 clearfix"> - <div class="float-left col-6"> - <button type="button" value=":palm_tree:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="palm_tree" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f334.png">🌴</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - On vacation - </div> - </button> - <button type="button" value=":face_with_thermometer:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="face_with_thermometer" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f912.png">🤒</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - Out sick - </div> - </button> - </div> - <div class="float-left col-6"> - <button type="button" value=":house:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="house" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f3e0.png">🏠</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - Working from home - </div> - </button> - <button type="button" value=":dart:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="dart" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f3af.png">🎯</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - Focusing - </div> - </button> - </div> - </div> - </div> - <div class="user-status-limited-availability-container"> - <div class="form-checkbox my-0"> - <input type="checkbox" name="limited_availability" value="1" class="js-user-status-limited-availability-checkbox" data-default-message="I may be slow to respond." aria-describedby="limited-availability-help-text-truncate-true-compact-true" id="limited-availability-truncate-true-compact-true"> - <label class="d-block f5 text-gray-dark mb-1" for="limited-availability-truncate-true-compact-true"> - Busy - </label> - <p class="note" id="limited-availability-help-text-truncate-true-compact-true"> - When others mention you, assign you, or request your review, - GitHub will let them know that you have limited availability. - </p> - </div> - </div> - </div> - - -<div class="d-inline-block f5 mr-2 pt-3 pb-2" > - <div class="d-inline-block mr-1"> - Clear status - </div> - - <details class="js-user-status-expire-drop-down f6 dropdown details-reset details-overlay d-inline-block mr-2"> - <summary class="f5 btn-link link-gray-dark border px-2 py-1 rounded-1" aria-haspopup="true"> - <div class="js-user-status-expiration-interval-selected d-inline-block v-align-baseline"> - Never - </div> - <div class="dropdown-caret"></div> - </summary> - - <ul class="dropdown-menu dropdown-menu-se pl-0 overflow-auto" style="width: 220px; max-height: 15.5em"> - <li> - <button type="button" class="btn-link dropdown-item js-user-status-expire-button ws-normal" title="Never"> - <span class="d-inline-block text-bold mb-1">Never</span> - <div class="f6 lh-condensed">Keep this status until you clear your status or edit your status.</div> - </button> - </li> - <li class="dropdown-divider" role="none"></li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="in 30 minutes" value="2019-08-06T12:54:12-04:00"> - in 30 minutes - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="in 1 hour" value="2019-08-06T13:24:12-04:00"> - in 1 hour - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="in 4 hours" value="2019-08-06T16:24:12-04:00"> - in 4 hours - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="today" value="2019-08-06T23:59:59-04:00"> - today - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="this week" value="2019-08-11T23:59:59-04:00"> - this week - </button> - </li> - </ul> - </details> - <input class="js-user-status-expiration-date-input" type="hidden" name="expires_at" value=""> -</div> - - <include-fragment class="js-user-status-org-picker" data-url="/users/status/organizations"></include-fragment> - </div> - <div class="d-flex flex-items-center flex-justify-between p-3 border-top"> - <button type="submit" disabled class="width-full btn btn-primary mr-2 js-user-status-submit"> - Set status - </button> - <button type="button" disabled class="width-full js-clear-user-status-button btn ml-2 "> - Clear status - </button> - </div> -</form> </details-dialog> - </details> -</div> - - </div> - <div role="none" class="dropdown-divider"></div> - - - <a role="menuitem" class="dropdown-item" href="/joshiemoore" data-ga-click="Header, go to profile, text:your profile">Your profile</a> - - - <a role="menuitem" class="dropdown-item" href="/joshiemoore?tab=repositories" data-ga-click="Header, go to repositories, text:your repositories">Your repositories</a> - - <a role="menuitem" class="dropdown-item" href="/joshiemoore?tab=projects" data-ga-click="Header, go to projects, text:your projects">Your projects</a> - - <a role="menuitem" class="dropdown-item" href="/joshiemoore?tab=stars" data-ga-click="Header, go to starred repos, text:your stars">Your stars</a> - <a role="menuitem" class="dropdown-item" href="https://gist.github.com/mine" data-ga-click="Header, your gists, text:your gists">Your gists</a> - - - <div role="none" class="dropdown-divider"></div> - <a role="menuitem" class="dropdown-item" href="https://help.github.com" data-ga-click="Header, go to help, text:help">Help</a> - <a role="menuitem" class="dropdown-item" href="/settings/profile" data-ga-click="Header, go to settings, icon:settings">Settings</a> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="logout-form" action="/logout" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="utlrbCMLpPZ7jCMSCsjUMJdvnpkJNZRzPP4PsXNaDvNLfuhP4ktDyomWzRIgD2PIQTrNiZMVaXtKwV6b7b7yUQ==" /> - - <button type="submit" class="dropdown-item dropdown-signout" data-ga-click="Header, sign out, icon:logout" role="menuitem"> - Sign out - </button> -</form> </details-menu> -</details> - - </div> - - </header> - - - - </div> - - <div id="start-of-content" class="show-on-focus"></div> - - - <div id="js-flash-container"> - -</div> - - - - <div class="application-main " data-commit-hovercards-enabled> - <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class=""> - <main > - - - - - - - - - - - - - <div class="pagehead repohead instapaper_ignore readability-menu experiment-repo-nav pt-0 pt-lg-4 "> - <div class="repohead-details-container clearfix container-lg p-responsive d-none d-lg-block"> - - <ul class="pagehead-actions"> - - - - - <li> - - <!-- '"` --><!-- </textarea></xmp> --></option></form><form data-remote="true" class="clearfix js-social-form js-social-container" action="/notifications/subscribe" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="xoZovm8MSTikyhRLQMuNBMpvYSScuVsg6y1FtCy7lgQDArfvSBTJ5mecz6Fse7hlDqZ+v01ue0qoBNv/BCZ5hA==" /> <input type="hidden" name="repository_id" value="48129574"> - - <details class="details-reset details-overlay select-menu float-left"> - <summary class="select-menu-button float-left btn btn-sm btn-with-count" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;WATCH_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134E6E:219D1F:5D49A994&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/GatewayFinder.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="00caf5c3a99da4b5ffd8843665b47a6e66f448d41a025536d2d68cd9828a54af" data-ga-click="Repository, click Watch settings, action:blob#show"> <span data-menu-button> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Watch - </span> -</summary> <details-menu - class="select-menu-modal position-absolute mt-5" - style="z-index: 99;"> - <div class="select-menu-header"> - <span class="select-menu-title">Notifications</span> - </div> - <div class="select-menu-list"> - <button type="submit" name="do" value="included" class="select-menu-item width-full" aria-checked="true" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Not watching</span> - <span class="description">Be notified only when participating or @mentioned.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Watch - </span> - </div> - </button> - - <button type="submit" name="do" value="release_only" class="select-menu-item width-full" aria-checked="false" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Releases only</span> - <span class="description">Be notified of new releases, and when participating or @mentioned.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Unwatch releases - </span> - </div> - </button> - - <button type="submit" name="do" value="subscribed" class="select-menu-item width-full" aria-checked="false" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Watching</span> - <span class="description">Be notified of all conversations.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Unwatch - </span> - </div> - </button> - - <button type="submit" name="do" value="ignore" class="select-menu-item width-full" aria-checked="false" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Ignoring</span> - <span class="description">Never be notified.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-mute v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 2.81v10.38c0 .67-.81 1-1.28.53L3 10H1c-.55 0-1-.45-1-1V7c0-.55.45-1 1-1h2l3.72-3.72C7.19 1.81 8 2.14 8 2.81zm7.53 3.22l-1.06-1.06-1.97 1.97-1.97-1.97-1.06 1.06L11.44 8 9.47 9.97l1.06 1.06 1.97-1.97 1.97 1.97 1.06-1.06L13.56 8l1.97-1.97z"/></svg> - Stop ignoring - </span> - </div> - </button> - </div> - </details-menu> - </details> - <a class="social-count js-social-count" - href="/adolfintel/WaifUPnP/watchers" - aria-label="4 users are watching this repository"> - 4 - </a> -</form> - </li> - - <li> - <div class="js-toggler-container js-social-container starring-container on"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="starred js-social-form" action="/adolfintel/WaifUPnP/unstar" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="vN4gkvN38esjsuTUvgNzekAohaz8jzIbp2S62B5mIvukiECl4OTEVaSC8u/jkefvlwR/Qf9nATZOAoHf8+1r8w==" /> - <input type="hidden" name="context" value="repository"></input> - <button type="submit" class="btn btn-sm btn-with-count js-toggler-target" aria-label="Unstar this repository" title="Unstar adolfintel/WaifUPnP" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;UNSTAR_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134E6E:219D1F:5D49A994&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/GatewayFinder.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="6b2dfb3a9db6922521a001ff2960f370168471c27e92771070504ea51f2cfeac" data-ga-click="Repository, click unstar button, action:blob#show; text:Unstar"> <svg class="octicon octicon-star v-align-text-bottom" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74L14 6z"/></svg> - Unstar -</button> <a class="social-count js-social-count" href="/adolfintel/WaifUPnP/stargazers" - aria-label="25 users starred this repository"> - 25 - </a> -</form> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="unstarred js-social-form" action="/adolfintel/WaifUPnP/star" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="DB0QmuG1tkYMaqB89iOlOuUEN06nk7MgHyFtJ3IvXCWeBKSUXYHqSZqSB7kx+ohLDLfLT/zAy3dUVTSRwjRjGA==" /> - <input type="hidden" name="context" value="repository"></input> - <button type="submit" class="btn btn-sm btn-with-count js-toggler-target" aria-label="Unstar this repository" title="Star adolfintel/WaifUPnP" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;STAR_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134E6E:219D1F:5D49A994&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/GatewayFinder.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="e3e09015ca8779c191873072cbf6d418cd52f6b5fb33af2a8299f4bddde65d93" data-ga-click="Repository, click star button, action:blob#show; text:Star"> <svg class="octicon octicon-star v-align-text-bottom" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74L14 6z"/></svg> - Star -</button> <a class="social-count js-social-count" href="/adolfintel/WaifUPnP/stargazers" - aria-label="25 users starred this repository"> - 25 - </a> -</form> </div> - - </li> - - <li> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="btn-with-count" action="/adolfintel/WaifUPnP/fork" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="kOy4wr6kVzij7yJ2ZWBywYbDAwxWqWLBpJaZ3zi5UhciEmYhgFs6tAOlUflG4MonNO75h9zOGirZidFFZB4XvQ==" /> - <button class="btn btn-sm btn-with-count" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;FORK_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134E6E:219D1F:5D49A994&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/GatewayFinder.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="613c97475abb0370753d44886e988f84f8516602dee70afe104350b8bc959d23" data-ga-click="Repository, show fork modal, action:blob#show; text:Fork" type="submit" title="Fork your own copy of adolfintel/WaifUPnP to your account" aria-label="Fork your own copy of adolfintel/WaifUPnP to your account"> <svg class="octicon octicon-repo-forked v-align-text-bottom" viewBox="0 0 10 16" version="1.1" width="10" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 1a1.993 1.993 0 0 0-1 3.72V6L5 8 3 6V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V6.5l3 3v1.78A1.993 1.993 0 0 0 5 15a1.993 1.993 0 0 0 1-3.72V9.5l3-3V4.72A1.993 1.993 0 0 0 8 1zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3 10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3-10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg> - Fork -</button></form> - <a href="/adolfintel/WaifUPnP/network/members" class="social-count" - aria-label="6 users forked this repository"> - 6 - </a> - </li> -</ul> - - <h1 class="public "> - <svg class="octicon octicon-repo" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <span class="author" itemprop="author"><a class="url fn" rel="author" data-hovercard-type="user" data-hovercard-url="/hovercards?user_id=16307689" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/adolfintel">adolfintel</a></span><!-- ---><span class="path-divider">/</span><!-- ---><strong itemprop="name"><a data-pjax="#js-repo-pjax-container" href="/adolfintel/WaifUPnP">WaifUPnP</a></strong> - - -</h1> - - </div> - -<nav class="hx_reponav reponav js-repo-nav js-sidenav-container-pjax container-lg p-responsive d-none d-lg-block" - itemscope - itemtype="http://schema.org/BreadcrumbList" - aria-label="Repository" - data-pjax="#js-repo-pjax-container"> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a class="js-selected-navigation-item selected reponav-item" itemprop="url" data-hotkey="g c" aria-current="page" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches repo_packages /adolfintel/WaifUPnP" href="/adolfintel/WaifUPnP"> - <svg class="octicon octicon-code" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M9.5 3L8 4.5 11.5 8 8 11.5 9.5 13 14 8 9.5 3zm-5 0L0 8l4.5 5L6 11.5 2.5 8 6 4.5 4.5 3z"/></svg> - <span itemprop="name">Code</span> - <meta itemprop="position" content="1"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" data-hotkey="g i" class="js-selected-navigation-item reponav-item" data-selected-links="repo_issues repo_labels repo_milestones /adolfintel/WaifUPnP/issues" href="/adolfintel/WaifUPnP/issues"> - <svg class="octicon octicon-issue-opened" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"/></svg> - <span itemprop="name">Issues</span> - <span class="Counter">2</span> - <meta itemprop="position" content="2"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a data-hotkey="g p" itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_pulls checks /adolfintel/WaifUPnP/pulls" href="/adolfintel/WaifUPnP/pulls"> - <svg class="octicon octicon-git-pull-request" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg> - <span itemprop="name">Pull requests</span> - <span class="Counter">2</span> - <meta itemprop="position" content="3"> -</a> </span> - - - <a data-hotkey="g b" class="js-selected-navigation-item reponav-item" data-selected-links="repo_projects new_repo_project repo_project /adolfintel/WaifUPnP/projects" href="/adolfintel/WaifUPnP/projects"> - <svg class="octicon octicon-project" viewBox="0 0 15 16" version="1.1" width="15" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - Projects - <span class="Counter" >0</span> -</a> - - <a class="js-selected-navigation-item reponav-item" data-hotkey="g w" data-selected-links="repo_wiki /adolfintel/WaifUPnP/wiki" href="/adolfintel/WaifUPnP/wiki"> - <svg class="octicon octicon-book" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M3 5h4v1H3V5zm0 3h4V7H3v1zm0 2h4V9H3v1zm11-5h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm2-6v9c0 .55-.45 1-1 1H9.5l-1 1-1-1H2c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h5.5l1 1 1-1H15c.55 0 1 .45 1 1zm-8 .5L7.5 3H2v9h6V3.5zm7-.5H9.5l-.5.5V12h6V3z"/></svg> - Wiki -</a> - <a data-skip-pjax="true" class="js-selected-navigation-item reponav-item" data-selected-links="security alerts policy /adolfintel/WaifUPnP/security/advisories" href="/adolfintel/WaifUPnP/security/advisories"> - <svg class="octicon octicon-shield" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M0 2l7-2 7 2v6.02C14 12.69 8.69 16 7 16c-1.69 0-7-3.31-7-7.98V2zm1 .75L7 1l6 1.75v5.268C13 12.104 8.449 15 7 15c-1.449 0-6-2.896-6-6.982V2.75zm1 .75L7 2v12c-1.207 0-5-2.482-5-5.985V3.5z"/></svg> - Security -</a> - <a class="js-selected-navigation-item reponav-item" data-selected-links="repo_graphs repo_contributors dependency_graph pulse people /adolfintel/WaifUPnP/pulse" href="/adolfintel/WaifUPnP/pulse"> - <svg class="octicon octicon-graph" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z"/></svg> - Insights -</a> - -</nav> - - <div class="reponav-wrapper reponav-small d-lg-none"> - <nav class="reponav js-reponav text-center no-wrap" - itemscope - itemtype="http://schema.org/BreadcrumbList"> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a class="js-selected-navigation-item selected reponav-item" itemprop="url" aria-current="page" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches repo_packages /adolfintel/WaifUPnP" href="/adolfintel/WaifUPnP"> - <span itemprop="name">Code</span> - <meta itemprop="position" content="1"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_issues repo_labels repo_milestones /adolfintel/WaifUPnP/issues" href="/adolfintel/WaifUPnP/issues"> - <span itemprop="name">Issues</span> - <span class="Counter">2</span> - <meta itemprop="position" content="2"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_pulls checks /adolfintel/WaifUPnP/pulls" href="/adolfintel/WaifUPnP/pulls"> - <span itemprop="name">Pull requests</span> - <span class="Counter">2</span> - <meta itemprop="position" content="3"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_projects new_repo_project repo_project /adolfintel/WaifUPnP/projects" href="/adolfintel/WaifUPnP/projects"> - <span itemprop="name">Projects</span> - <span class="Counter">0</span> - <meta itemprop="position" content="4"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_wiki /adolfintel/WaifUPnP/wiki" href="/adolfintel/WaifUPnP/wiki"> - <span itemprop="name">Wiki</span> - <meta itemprop="position" content="5"> -</a> </span> - - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="security alerts policy /adolfintel/WaifUPnP/security/advisories" href="/adolfintel/WaifUPnP/security/advisories"> - <span itemprop="name">Security</span> - <meta itemprop="position" content="6"> -</a> - <a class="js-selected-navigation-item reponav-item" data-selected-links="pulse /adolfintel/WaifUPnP/pulse" href="/adolfintel/WaifUPnP/pulse"> - Pulse -</a> - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="community /adolfintel/WaifUPnP/community" href="/adolfintel/WaifUPnP/community"> - Community -</a> </span> - - </nav> -</div> - - - </div> -<div class="container-lg clearfix new-discussion-timeline experiment-repo-nav p-responsive"> - <div class="repository-content "> - - - - - - - - - <a class="d-none js-permalink-shortcut" data-hotkey="y" href="/adolfintel/WaifUPnP/blob/d6381a8c6f24c7d0f5879ba037abd018ba428561/src/com/dosse/upnp/GatewayFinder.java">Permalink</a> - - <!-- blob contrib key: blob_contributors:v21:1807d04c9390e419fb88b47fd68d7e25 --> - - - <div class="d-flex flex-items-start flex-shrink-0 pb-3 flex-column flex-md-row"> - <span class="d-flex flex-justify-between width-full width-md-auto"> - -<details class="details-reset details-overlay select-menu branch-select-menu hx_rsm" id="branch-select-menu"> - <summary class="btn btn-sm select-menu-button css-truncate" - data-hotkey="w" - - title="Switch branches or tags"> - <i>Branch:</i> - <span class="css-truncate-target">master</span> - </summary> - - <details-menu class="select-menu-modal hx_rsm-modal position-absolute" style="z-index: 99;" src="/adolfintel/WaifUPnP/ref-list/master/src/com/dosse/upnp/GatewayFinder.java?source_action=show&amp;source_controller=blob" preload> - <include-fragment class="select-menu-loading-overlay anim-pulse"> - <svg height="32" class="octicon octicon-octoface" viewBox="0 0 16 16" version="1.1" width="32" aria-hidden="true"><path fill-rule="evenodd" d="M14.7 5.34c.13-.32.55-1.59-.13-3.31 0 0-1.05-.33-3.44 1.3-1-.28-2.07-.32-3.13-.32s-2.13.04-3.13.32c-2.39-1.64-3.44-1.3-3.44-1.3-.68 1.72-.26 2.99-.13 3.31C.49 6.21 0 7.33 0 8.69 0 13.84 3.33 15 7.98 15S16 13.84 16 8.69c0-1.36-.49-2.48-1.3-3.35zM8 14.02c-3.3 0-5.98-.15-5.98-3.35 0-.76.38-1.48 1.02-2.07 1.07-.98 2.9-.46 4.96-.46 2.07 0 3.88-.52 4.96.46.65.59 1.02 1.3 1.02 2.07 0 3.19-2.68 3.35-5.98 3.35zM5.49 9.01c-.66 0-1.2.8-1.2 1.78s.54 1.79 1.2 1.79c.66 0 1.2-.8 1.2-1.79s-.54-1.78-1.2-1.78zm5.02 0c-.66 0-1.2.79-1.2 1.78s.54 1.79 1.2 1.79c.66 0 1.2-.8 1.2-1.79s-.53-1.78-1.2-1.78z"/></svg> - </include-fragment> - </details-menu> -</details> - - <div class="BtnGroup flex-shrink-0 d-md-none"> - <a href="/adolfintel/WaifUPnP/find/master" - class="js-pjax-capture-input btn btn-sm BtnGroup-item" - data-pjax - data-hotkey="t"> - Find file - </a> - <clipboard-copy value="src/com/dosse/upnp/GatewayFinder.java" class="btn btn-sm BtnGroup-item"> - Copy path - </clipboard-copy> - </div> - </span> - <h2 id="blob-path" class="breadcrumb flex-auto min-width-0 text-normal flex-md-self-center ml-md-2 mr-md-3 my-2 my-md-0"> - <span class="js-repo-root text-bold"><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP"><span>WaifUPnP</span></a></span></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src"><span>src</span></a></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src/com"><span>com</span></a></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src/com/dosse"><span>dosse</span></a></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp"><span>upnp</span></a></span><span class="separator">/</span><strong class="final-path">GatewayFinder.java</strong> - </h2> - - <div class="BtnGroup flex-shrink-0 d-none d-md-inline-block"> - <a href="/adolfintel/WaifUPnP/find/master" - class="js-pjax-capture-input btn btn-sm BtnGroup-item" - data-pjax - data-hotkey="t"> - Find file - </a> - <clipboard-copy value="src/com/dosse/upnp/GatewayFinder.java" class="btn btn-sm BtnGroup-item"> - Copy path - </clipboard-copy> - </div> - </div> - - - - <include-fragment src="/adolfintel/WaifUPnP/contributors/master/src/com/dosse/upnp/GatewayFinder.java" class="Box Box--condensed commit-loader"> - <div class="Box-body bg-blue-light f6"> - Fetching contributors&hellip; - </div> - - <div class="Box-body d-flex flex-items-center" > - <img alt="" class="loader-loading mr-2" src="https://github.githubassets.com/images/spinners/octocat-spinner-32-EAF2F5.gif" width="16" height="16" /> - <span class="text-red h6 loader-error">Cannot retrieve contributors at this time</span> - </div> -</include-fragment> - - - - - <div class="Box mt-3 position-relative"> - -<div class="Box-header py-2 d-flex flex-column flex-shrink-0 flex-md-row flex-md-items-center"> - - <div class="text-mono f6 flex-auto pr-3 flex-order-2 flex-md-order-1 mt-2 mt-md-0"> - 133 lines (118 sloc) - <span class="file-info-divider"></span> - 4.56 KB - </div> - - <div class="d-flex py-1 py-md-0 flex-auto flex-order-1 flex-md-order-2 flex-sm-grow-0 flex-justify-between"> - - <div class="BtnGroup"> - <a id="raw-url" class="btn btn-sm BtnGroup-item" href="/adolfintel/WaifUPnP/raw/master/src/com/dosse/upnp/GatewayFinder.java">Raw</a> - <a class="btn btn-sm js-update-url-with-hash BtnGroup-item" data-hotkey="b" href="/adolfintel/WaifUPnP/blame/master/src/com/dosse/upnp/GatewayFinder.java">Blame</a> - <a rel="nofollow" class="btn btn-sm BtnGroup-item" href="/adolfintel/WaifUPnP/commits/master/src/com/dosse/upnp/GatewayFinder.java">History</a> - </div> - - - <div> - - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="inline-form js-update-url-with-hash" action="/adolfintel/WaifUPnP/edit/master/src/com/dosse/upnp/GatewayFinder.java" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="WNDAjwSBc549gi01UM2BKmnNvlKczJROQAPAlDI5TYsK30nfLLo8PyljX9VwYKLCbEUOqj6prj2Y3qZfF2CQEA==" /> - <button class="btn-octicon tooltipped tooltipped-nw" type="submit" - aria-label="Fork this project and edit the file" data-hotkey="e" data-disable-with> - <svg class="octicon octicon-pencil" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M0 12v3h3l8-8-3-3-8 8zm3 2H1v-2h1v1h1v1zm10.3-9.3L12 6 9 3l1.3-1.3a.996.996 0 0 1 1.41 0l1.59 1.59c.39.39.39 1.02 0 1.41z"/></svg> - </button> -</form> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="inline-form" action="/adolfintel/WaifUPnP/delete/master/src/com/dosse/upnp/GatewayFinder.java" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="brE+cfwvq8M5K3g+B2Q67ZaTDIWybx/ZKco2TygaQOAUlR/wQXwvjDvD9CUg0A7tPDFuLIVu8+XdvEuSK3VeAA==" /> - <button class="btn-octicon btn-octicon-danger tooltipped tooltipped-nw" type="submit" - aria-label="Fork this project and delete the file" data-disable-with> - <svg class="octicon octicon-trashcan" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M11 2H9c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1H2c-.55 0-1 .45-1 1v1c0 .55.45 1 1 1v9c0 .55.45 1 1 1h7c.55 0 1-.45 1-1V5c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 12H3V5h1v8h1V5h1v8h1V5h1v8h1V5h1v9zm1-10H2V3h9v1z"/></svg> - </button> -</form> </div> - </div> -</div> - - - - - - - <div itemprop="text" class="Box-body p-0 blob-wrapper data type-java "> - -<table class="highlight tab-size js-file-line-container" data-tab-size="8"> - <tr> - <td id="L1" class="blob-num js-line-number" data-line-number="1"></td> - <td id="LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">/*</span></span></td> - </tr> - <tr> - <td id="L2" class="blob-num js-line-number" data-line-number="2"></td> - <td id="LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Copyright (C) 2015 Federico Dossena (adolfintel.com).</span></td> - </tr> - <tr> - <td id="L3" class="blob-num js-line-number" data-line-number="3"></td> - <td id="LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> *</span></td> - </tr> - <tr> - <td id="L4" class="blob-num js-line-number" data-line-number="4"></td> - <td id="LC4" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * This library is free software; you can redistribute it and/or</span></td> - </tr> - <tr> - <td id="L5" class="blob-num js-line-number" data-line-number="5"></td> - <td id="LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * modify it under the terms of the GNU Lesser General Public</span></td> - </tr> - <tr> - <td id="L6" class="blob-num js-line-number" data-line-number="6"></td> - <td id="LC6" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * License as published by the Free Software Foundation; either</span></td> - </tr> - <tr> - <td id="L7" class="blob-num js-line-number" data-line-number="7"></td> - <td id="LC7" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * version 2.1 of the License, or (at your option) any later version.</span></td> - </tr> - <tr> - <td id="L8" class="blob-num js-line-number" data-line-number="8"></td> - <td id="LC8" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> *</span></td> - </tr> - <tr> - <td id="L9" class="blob-num js-line-number" data-line-number="9"></td> - <td id="LC9" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * This library is distributed in the hope that it will be useful,</span></td> - </tr> - <tr> - <td id="L10" class="blob-num js-line-number" data-line-number="10"></td> - <td id="LC10" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</span></td> - </tr> - <tr> - <td id="L11" class="blob-num js-line-number" data-line-number="11"></td> - <td id="LC11" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</span></td> - </tr> - <tr> - <td id="L12" class="blob-num js-line-number" data-line-number="12"></td> - <td id="LC12" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Lesser General Public License for more details.</span></td> - </tr> - <tr> - <td id="L13" class="blob-num js-line-number" data-line-number="13"></td> - <td id="LC13" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> *</span></td> - </tr> - <tr> - <td id="L14" class="blob-num js-line-number" data-line-number="14"></td> - <td id="LC14" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * You should have received a copy of the GNU Lesser General Public</span></td> - </tr> - <tr> - <td id="L15" class="blob-num js-line-number" data-line-number="15"></td> - <td id="LC15" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * License along with this library; if not, write to the Free Software</span></td> - </tr> - <tr> - <td id="L16" class="blob-num js-line-number" data-line-number="16"></td> - <td id="LC16" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,</span></td> - </tr> - <tr> - <td id="L17" class="blob-num js-line-number" data-line-number="17"></td> - <td id="LC17" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * MA 02110-1301 USA</span></td> - </tr> - <tr> - <td id="L18" class="blob-num js-line-number" data-line-number="18"></td> - <td id="LC18" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L19" class="blob-num js-line-number" data-line-number="19"></td> - <td id="LC19" class="blob-code blob-code-inner js-file-line"><span class="pl-k">package</span> <span class="pl-smi">com.dosse.upnp</span>;</td> - </tr> - <tr> - <td id="L20" class="blob-num js-line-number" data-line-number="20"></td> - <td id="LC20" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L21" class="blob-num js-line-number" data-line-number="21"></td> - <td id="LC21" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.net.DatagramPacket</span>;</td> - </tr> - <tr> - <td id="L22" class="blob-num js-line-number" data-line-number="22"></td> - <td id="LC22" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.net.DatagramSocket</span>;</td> - </tr> - <tr> - <td id="L23" class="blob-num js-line-number" data-line-number="23"></td> - <td id="LC23" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.net.Inet4Address</span>;</td> - </tr> - <tr> - <td id="L24" class="blob-num js-line-number" data-line-number="24"></td> - <td id="LC24" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.net.InetAddress</span>;</td> - </tr> - <tr> - <td id="L25" class="blob-num js-line-number" data-line-number="25"></td> - <td id="LC25" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.net.InetSocketAddress</span>;</td> - </tr> - <tr> - <td id="L26" class="blob-num js-line-number" data-line-number="26"></td> - <td id="LC26" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.net.NetworkInterface</span>;</td> - </tr> - <tr> - <td id="L27" class="blob-num js-line-number" data-line-number="27"></td> - <td id="LC27" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.net.SocketTimeoutException</span>;</td> - </tr> - <tr> - <td id="L28" class="blob-num js-line-number" data-line-number="28"></td> - <td id="LC28" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.util.Enumeration</span>;</td> - </tr> - <tr> - <td id="L29" class="blob-num js-line-number" data-line-number="29"></td> - <td id="LC29" class="blob-code blob-code-inner js-file-line"><span class="pl-k">import</span> <span class="pl-smi">java.util.LinkedList</span>;</td> - </tr> - <tr> - <td id="L30" class="blob-num js-line-number" data-line-number="30"></td> - <td id="LC30" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L31" class="blob-num js-line-number" data-line-number="31"></td> - <td id="LC31" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L32" class="blob-num js-line-number" data-line-number="32"></td> - <td id="LC32" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> *</span></td> - </tr> - <tr> - <td id="L33" class="blob-num js-line-number" data-line-number="33"></td> - <td id="LC33" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@author</span> Federico</span></td> - </tr> - <tr> - <td id="L34" class="blob-num js-line-number" data-line-number="34"></td> - <td id="LC34" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L35" class="blob-num js-line-number" data-line-number="35"></td> - <td id="LC35" class="blob-code blob-code-inner js-file-line"><span class="pl-k">abstract</span> <span class="pl-k">class</span> <span class="pl-en">GatewayFinder</span> {</td> - </tr> - <tr> - <td id="L36" class="blob-num js-line-number" data-line-number="36"></td> - <td id="LC36" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L37" class="blob-num js-line-number" data-line-number="37"></td> - <td id="LC37" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-k">static</span> <span class="pl-k">final</span> <span class="pl-k">String</span>[] <span class="pl-c1">SEARCH_MESSAGES</span>;</td> - </tr> - <tr> - <td id="L38" class="blob-num js-line-number" data-line-number="38"></td> - <td id="LC38" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L39" class="blob-num js-line-number" data-line-number="39"></td> - <td id="LC39" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">static</span> {</td> - </tr> - <tr> - <td id="L40" class="blob-num js-line-number" data-line-number="40"></td> - <td id="LC40" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">LinkedList&lt;<span class="pl-smi">String</span>&gt;</span> m <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-k">LinkedList&lt;<span class="pl-smi">String</span>&gt;</span>();</td> - </tr> - <tr> - <td id="L41" class="blob-num js-line-number" data-line-number="41"></td> - <td id="LC41" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">for</span> (<span class="pl-smi">String</span> type <span class="pl-k">:</span> <span class="pl-k">new</span> <span class="pl-smi">String</span>[]{<span class="pl-s"><span class="pl-pds">&quot;</span>urn:schemas-upnp-org:device:InternetGatewayDevice:1<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span>urn:schemas-upnp-org:service:WANIPConnection:1<span class="pl-pds">&quot;</span></span>, <span class="pl-s"><span class="pl-pds">&quot;</span>urn:schemas-upnp-org:service:WANPPPConnection:1<span class="pl-pds">&quot;</span></span>}) {</td> - </tr> - <tr> - <td id="L42" class="blob-num js-line-number" data-line-number="42"></td> - <td id="LC42" class="blob-code blob-code-inner js-file-line"> m<span class="pl-k">.</span>add(<span class="pl-s"><span class="pl-pds">&quot;</span>M-SEARCH * HTTP/1.1<span class="pl-cce">\r\n</span>HOST: 239.255.255.250:1900<span class="pl-cce">\r\n</span>ST: <span class="pl-pds">&quot;</span></span> <span class="pl-k">+</span> type <span class="pl-k">+</span> <span class="pl-s"><span class="pl-pds">&quot;</span><span class="pl-cce">\r\n</span>MAN: <span class="pl-cce">\&quot;</span>ssdp:discover<span class="pl-cce">\&quot;\r\n</span>MX: 2<span class="pl-cce">\r\n\r\n</span><span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L43" class="blob-num js-line-number" data-line-number="43"></td> - <td id="LC43" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L44" class="blob-num js-line-number" data-line-number="44"></td> - <td id="LC44" class="blob-code blob-code-inner js-file-line"> <span class="pl-c1">SEARCH_MESSAGES</span> <span class="pl-k">=</span> m<span class="pl-k">.</span>toArray(<span class="pl-k">new</span> <span class="pl-smi">String</span>[]{});</td> - </tr> - <tr> - <td id="L45" class="blob-num js-line-number" data-line-number="45"></td> - <td id="LC45" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L46" class="blob-num js-line-number" data-line-number="46"></td> - <td id="LC46" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L47" class="blob-num js-line-number" data-line-number="47"></td> - <td id="LC47" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-k">class</span> <span class="pl-en">GatewayListener</span> <span class="pl-k">extends</span> <span class="pl-e">Thread</span> {</td> - </tr> - <tr> - <td id="L48" class="blob-num js-line-number" data-line-number="48"></td> - <td id="LC48" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L49" class="blob-num js-line-number" data-line-number="49"></td> - <td id="LC49" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-smi">Inet4Address</span> ip;</td> - </tr> - <tr> - <td id="L50" class="blob-num js-line-number" data-line-number="50"></td> - <td id="LC50" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-smi">String</span> req;</td> - </tr> - <tr> - <td id="L51" class="blob-num js-line-number" data-line-number="51"></td> - <td id="LC51" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L52" class="blob-num js-line-number" data-line-number="52"></td> - <td id="LC52" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-en">GatewayListener</span>(<span class="pl-smi">Inet4Address</span> <span class="pl-v">ip</span>, <span class="pl-smi">String</span> <span class="pl-v">req</span>) {</td> - </tr> - <tr> - <td id="L53" class="blob-num js-line-number" data-line-number="53"></td> - <td id="LC53" class="blob-code blob-code-inner js-file-line"> setName(<span class="pl-s"><span class="pl-pds">&quot;</span>WaifUPnP - Gateway Listener<span class="pl-pds">&quot;</span></span>);</td> - </tr> - <tr> - <td id="L54" class="blob-num js-line-number" data-line-number="54"></td> - <td id="LC54" class="blob-code blob-code-inner js-file-line"> <span class="pl-c1">this</span><span class="pl-k">.</span>ip <span class="pl-k">=</span> ip;</td> - </tr> - <tr> - <td id="L55" class="blob-num js-line-number" data-line-number="55"></td> - <td id="LC55" class="blob-code blob-code-inner js-file-line"> <span class="pl-c1">this</span><span class="pl-k">.</span>req <span class="pl-k">=</span> req;</td> - </tr> - <tr> - <td id="L56" class="blob-num js-line-number" data-line-number="56"></td> - <td id="LC56" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L57" class="blob-num js-line-number" data-line-number="57"></td> - <td id="LC57" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L58" class="blob-num js-line-number" data-line-number="58"></td> - <td id="LC58" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">@Override</span></td> - </tr> - <tr> - <td id="L59" class="blob-num js-line-number" data-line-number="59"></td> - <td id="LC59" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">void</span> <span class="pl-en">run</span>() {</td> - </tr> - <tr> - <td id="L60" class="blob-num js-line-number" data-line-number="60"></td> - <td id="LC60" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> {</td> - </tr> - <tr> - <td id="L61" class="blob-num js-line-number" data-line-number="61"></td> - <td id="LC61" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">byte</span>[] req <span class="pl-k">=</span> <span class="pl-c1">this</span><span class="pl-k">.</span>req<span class="pl-k">.</span>getBytes();</td> - </tr> - <tr> - <td id="L62" class="blob-num js-line-number" data-line-number="62"></td> - <td id="LC62" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">DatagramSocket</span> s <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-smi">DatagramSocket</span>(<span class="pl-k">new</span> <span class="pl-smi">InetSocketAddress</span>(ip, <span class="pl-c1">0</span>));</td> - </tr> - <tr> - <td id="L63" class="blob-num js-line-number" data-line-number="63"></td> - <td id="LC63" class="blob-code blob-code-inner js-file-line"> s<span class="pl-k">.</span>send(<span class="pl-k">new</span> <span class="pl-smi">DatagramPacket</span>(req, req<span class="pl-k">.</span>length, <span class="pl-k">new</span> <span class="pl-smi">InetSocketAddress</span>(<span class="pl-s"><span class="pl-pds">&quot;</span>239.255.255.250<span class="pl-pds">&quot;</span></span>, <span class="pl-c1">1900</span>)));</td> - </tr> - <tr> - <td id="L64" class="blob-num js-line-number" data-line-number="64"></td> - <td id="LC64" class="blob-code blob-code-inner js-file-line"> s<span class="pl-k">.</span>setSoTimeout(<span class="pl-c1">3000</span>);</td> - </tr> - <tr> - <td id="L65" class="blob-num js-line-number" data-line-number="65"></td> - <td id="LC65" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">for</span> (;;) {</td> - </tr> - <tr> - <td id="L66" class="blob-num js-line-number" data-line-number="66"></td> - <td id="LC66" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> {</td> - </tr> - <tr> - <td id="L67" class="blob-num js-line-number" data-line-number="67"></td> - <td id="LC67" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">DatagramPacket</span> recv <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-smi">DatagramPacket</span>(<span class="pl-k">new</span> <span class="pl-smi">byte</span>[<span class="pl-c1">1536</span>], <span class="pl-c1">1536</span>);</td> - </tr> - <tr> - <td id="L68" class="blob-num js-line-number" data-line-number="68"></td> - <td id="LC68" class="blob-code blob-code-inner js-file-line"> s<span class="pl-k">.</span>receive(recv);</td> - </tr> - <tr> - <td id="L69" class="blob-num js-line-number" data-line-number="69"></td> - <td id="LC69" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Gateway</span> gw <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-smi">Gateway</span>(recv<span class="pl-k">.</span>getData(), ip);</td> - </tr> - <tr> - <td id="L70" class="blob-num js-line-number" data-line-number="70"></td> - <td id="LC70" class="blob-code blob-code-inner js-file-line"> gatewayFound(gw);</td> - </tr> - <tr> - <td id="L71" class="blob-num js-line-number" data-line-number="71"></td> - <td id="LC71" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">SocketTimeoutException</span> t) {</td> - </tr> - <tr> - <td id="L72" class="blob-num js-line-number" data-line-number="72"></td> - <td id="LC72" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">break</span>;</td> - </tr> - <tr> - <td id="L73" class="blob-num js-line-number" data-line-number="73"></td> - <td id="LC73" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Throwable</span> t) {</td> - </tr> - <tr> - <td id="L74" class="blob-num js-line-number" data-line-number="74"></td> - <td id="LC74" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L75" class="blob-num js-line-number" data-line-number="75"></td> - <td id="LC75" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L76" class="blob-num js-line-number" data-line-number="76"></td> - <td id="LC76" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Throwable</span> t) {</td> - </tr> - <tr> - <td id="L77" class="blob-num js-line-number" data-line-number="77"></td> - <td id="LC77" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L78" class="blob-num js-line-number" data-line-number="78"></td> - <td id="LC78" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L79" class="blob-num js-line-number" data-line-number="79"></td> - <td id="LC79" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L80" class="blob-num js-line-number" data-line-number="80"></td> - <td id="LC80" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L81" class="blob-num js-line-number" data-line-number="81"></td> - <td id="LC81" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-k">LinkedList&lt;<span class="pl-smi">GatewayListener</span>&gt;</span> listeners <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-k">LinkedList&lt;<span class="pl-smi">GatewayListener</span>&gt;</span>();</td> - </tr> - <tr> - <td id="L82" class="blob-num js-line-number" data-line-number="82"></td> - <td id="LC82" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L83" class="blob-num js-line-number" data-line-number="83"></td> - <td id="LC83" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-en">GatewayFinder</span>() {</td> - </tr> - <tr> - <td id="L84" class="blob-num js-line-number" data-line-number="84"></td> - <td id="LC84" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">for</span> (<span class="pl-smi">Inet4Address</span> ip <span class="pl-k">:</span> getLocalIPs()) {</td> - </tr> - <tr> - <td id="L85" class="blob-num js-line-number" data-line-number="85"></td> - <td id="LC85" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">for</span> (<span class="pl-smi">String</span> req <span class="pl-k">:</span> <span class="pl-c1">SEARCH_MESSAGES</span>) {</td> - </tr> - <tr> - <td id="L86" class="blob-num js-line-number" data-line-number="86"></td> - <td id="LC86" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">GatewayListener</span> l <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-smi">GatewayListener</span>(ip, req);</td> - </tr> - <tr> - <td id="L87" class="blob-num js-line-number" data-line-number="87"></td> - <td id="LC87" class="blob-code blob-code-inner js-file-line"> l<span class="pl-k">.</span>start();</td> - </tr> - <tr> - <td id="L88" class="blob-num js-line-number" data-line-number="88"></td> - <td id="LC88" class="blob-code blob-code-inner js-file-line"> listeners<span class="pl-k">.</span>add(l);</td> - </tr> - <tr> - <td id="L89" class="blob-num js-line-number" data-line-number="89"></td> - <td id="LC89" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L90" class="blob-num js-line-number" data-line-number="90"></td> - <td id="LC90" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L91" class="blob-num js-line-number" data-line-number="91"></td> - <td id="LC91" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L92" class="blob-num js-line-number" data-line-number="92"></td> - <td id="LC92" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L93" class="blob-num js-line-number" data-line-number="93"></td> - <td id="LC93" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">boolean</span> <span class="pl-en">isSearching</span>() {</td> - </tr> - <tr> - <td id="L94" class="blob-num js-line-number" data-line-number="94"></td> - <td id="LC94" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">for</span> (<span class="pl-smi">GatewayListener</span> l <span class="pl-k">:</span> listeners) {</td> - </tr> - <tr> - <td id="L95" class="blob-num js-line-number" data-line-number="95"></td> - <td id="LC95" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (l<span class="pl-k">.</span>isAlive()) {</td> - </tr> - <tr> - <td id="L96" class="blob-num js-line-number" data-line-number="96"></td> - <td id="LC96" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> <span class="pl-c1">true</span>;</td> - </tr> - <tr> - <td id="L97" class="blob-num js-line-number" data-line-number="97"></td> - <td id="LC97" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L98" class="blob-num js-line-number" data-line-number="98"></td> - <td id="LC98" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L99" class="blob-num js-line-number" data-line-number="99"></td> - <td id="LC99" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> <span class="pl-c1">false</span>;</td> - </tr> - <tr> - <td id="L100" class="blob-num js-line-number" data-line-number="100"></td> - <td id="LC100" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L101" class="blob-num js-line-number" data-line-number="101"></td> - <td id="LC101" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L102" class="blob-num js-line-number" data-line-number="102"></td> - <td id="LC102" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">abstract</span> <span class="pl-k">void</span> <span class="pl-en">gatewayFound</span>(<span class="pl-smi">Gateway</span> <span class="pl-v">g</span>);</td> - </tr> - <tr> - <td id="L103" class="blob-num js-line-number" data-line-number="103"></td> - <td id="LC103" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L104" class="blob-num js-line-number" data-line-number="104"></td> - <td id="LC104" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-k">static</span> <span class="pl-k">Inet4Address</span>[] <span class="pl-en">getLocalIPs</span>() {</td> - </tr> - <tr> - <td id="L105" class="blob-num js-line-number" data-line-number="105"></td> - <td id="LC105" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">LinkedList&lt;<span class="pl-smi">Inet4Address</span>&gt;</span> ret <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-k">LinkedList&lt;<span class="pl-smi">Inet4Address</span>&gt;</span>();</td> - </tr> - <tr> - <td id="L106" class="blob-num js-line-number" data-line-number="106"></td> - <td id="LC106" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> {</td> - </tr> - <tr> - <td id="L107" class="blob-num js-line-number" data-line-number="107"></td> - <td id="LC107" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Enumeration&lt;<span class="pl-smi">NetworkInterface</span>&gt;</span> ifaces <span class="pl-k">=</span> <span class="pl-smi">NetworkInterface</span><span class="pl-k">.</span>getNetworkInterfaces();</td> - </tr> - <tr> - <td id="L108" class="blob-num js-line-number" data-line-number="108"></td> - <td id="LC108" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">while</span> (ifaces<span class="pl-k">.</span>hasMoreElements()) {</td> - </tr> - <tr> - <td id="L109" class="blob-num js-line-number" data-line-number="109"></td> - <td id="LC109" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> {</td> - </tr> - <tr> - <td id="L110" class="blob-num js-line-number" data-line-number="110"></td> - <td id="LC110" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">NetworkInterface</span> iface <span class="pl-k">=</span> ifaces<span class="pl-k">.</span>nextElement();</td> - </tr> - <tr> - <td id="L111" class="blob-num js-line-number" data-line-number="111"></td> - <td id="LC111" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (<span class="pl-k">!</span>iface<span class="pl-k">.</span>isUp() <span class="pl-k">||</span> iface<span class="pl-k">.</span>isLoopback() <span class="pl-k">||</span> iface<span class="pl-k">.</span>isVirtual() <span class="pl-k">||</span> iface<span class="pl-k">.</span>isPointToPoint()) {</td> - </tr> - <tr> - <td id="L112" class="blob-num js-line-number" data-line-number="112"></td> - <td id="LC112" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">continue</span>;</td> - </tr> - <tr> - <td id="L113" class="blob-num js-line-number" data-line-number="113"></td> - <td id="LC113" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L114" class="blob-num js-line-number" data-line-number="114"></td> - <td id="LC114" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">Enumeration&lt;<span class="pl-smi">InetAddress</span>&gt;</span> addrs <span class="pl-k">=</span> iface<span class="pl-k">.</span>getInetAddresses();</td> - </tr> - <tr> - <td id="L115" class="blob-num js-line-number" data-line-number="115"></td> - <td id="LC115" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (addrs <span class="pl-k">==</span> <span class="pl-c1">null</span>) {</td> - </tr> - <tr> - <td id="L116" class="blob-num js-line-number" data-line-number="116"></td> - <td id="LC116" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">continue</span>;</td> - </tr> - <tr> - <td id="L117" class="blob-num js-line-number" data-line-number="117"></td> - <td id="LC117" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L118" class="blob-num js-line-number" data-line-number="118"></td> - <td id="LC118" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">while</span> (addrs<span class="pl-k">.</span>hasMoreElements()) {</td> - </tr> - <tr> - <td id="L119" class="blob-num js-line-number" data-line-number="119"></td> - <td id="LC119" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">InetAddress</span> addr <span class="pl-k">=</span> addrs<span class="pl-k">.</span>nextElement();</td> - </tr> - <tr> - <td id="L120" class="blob-num js-line-number" data-line-number="120"></td> - <td id="LC120" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (addr <span class="pl-k">instanceof</span> <span class="pl-smi">Inet4Address</span>) {</td> - </tr> - <tr> - <td id="L121" class="blob-num js-line-number" data-line-number="121"></td> - <td id="LC121" class="blob-code blob-code-inner js-file-line"> ret<span class="pl-k">.</span>add((<span class="pl-smi">Inet4Address</span>) addr);</td> - </tr> - <tr> - <td id="L122" class="blob-num js-line-number" data-line-number="122"></td> - <td id="LC122" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L123" class="blob-num js-line-number" data-line-number="123"></td> - <td id="LC123" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L124" class="blob-num js-line-number" data-line-number="124"></td> - <td id="LC124" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Throwable</span> t) {</td> - </tr> - <tr> - <td id="L125" class="blob-num js-line-number" data-line-number="125"></td> - <td id="LC125" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L126" class="blob-num js-line-number" data-line-number="126"></td> - <td id="LC126" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L127" class="blob-num js-line-number" data-line-number="127"></td> - <td id="LC127" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">Throwable</span> t) {</td> - </tr> - <tr> - <td id="L128" class="blob-num js-line-number" data-line-number="128"></td> - <td id="LC128" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L129" class="blob-num js-line-number" data-line-number="129"></td> - <td id="LC129" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> ret<span class="pl-k">.</span>toArray(<span class="pl-k">new</span> <span class="pl-smi">Inet4Address</span>[]{});</td> - </tr> - <tr> - <td id="L130" class="blob-num js-line-number" data-line-number="130"></td> - <td id="LC130" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L131" class="blob-num js-line-number" data-line-number="131"></td> - <td id="LC131" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L132" class="blob-num js-line-number" data-line-number="132"></td> - <td id="LC132" class="blob-code blob-code-inner js-file-line">}</td> - </tr> -</table> - - <details class="details-reset details-overlay BlobToolbar position-absolute js-file-line-actions dropdown d-none" aria-hidden="true"> - <summary class="btn-octicon ml-0 px-2 p-0 bg-white border border-gray-dark rounded-1" aria-label="Inline file action toolbar"> - <svg class="octicon octicon-kebab-horizontal" viewBox="0 0 13 16" version="1.1" width="13" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm5 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM13 7.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/></svg> - </summary> - <details-menu> - <ul class="BlobToolbar-dropdown dropdown-menu dropdown-menu-se mt-2" style="width:185px"> - <li><clipboard-copy role="menuitem" class="dropdown-item" id="js-copy-lines" style="cursor:pointer;" data-original-text="Copy lines">Copy lines</clipboard-copy></li> - <li><clipboard-copy role="menuitem" class="dropdown-item" id="js-copy-permalink" style="cursor:pointer;" data-original-text="Copy permalink">Copy permalink</clipboard-copy></li> - <li><a class="dropdown-item js-update-url-with-hash" id="js-view-git-blame" role="menuitem" href="/adolfintel/WaifUPnP/blame/d6381a8c6f24c7d0f5879ba037abd018ba428561/src/com/dosse/upnp/GatewayFinder.java">View git blame</a></li> - <li><a class="dropdown-item" id="js-new-issue" role="menuitem" href="/adolfintel/WaifUPnP/issues/new">Reference in new issue</a></li> - </ul> - </details-menu> - </details> - - </div> - - </div> - - - - <details class="details-reset details-overlay details-overlay-dark"> - <summary data-hotkey="l" aria-label="Jump to line"></summary> - <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast linejump" aria-label="Jump to line"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="js-jump-to-line-form Box-body d-flex" action="" accept-charset="UTF-8" method="get"><input name="utf8" type="hidden" value="&#x2713;" /> - <input class="form-control flex-auto mr-3 linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line&hellip;" aria-label="Jump to line" autofocus> - <button type="submit" class="btn" data-close-dialog>Go</button> -</form> </details-dialog> - </details> - - - - </div> - <div class="modal-backdrop js-touch-events"></div> -</div> - - </main> - </div> - - - </div> - - -<div class="footer container-lg width-full p-responsive" role="contentinfo"> - <div class="position-relative d-flex flex-row-reverse flex-lg-row flex-wrap flex-lg-nowrap flex-justify-center flex-lg-justify-between pt-6 pb-2 mt-6 f6 text-gray border-top border-gray-light "> - <ul class="list-style-none d-flex flex-wrap col-12 col-lg-5 flex-justify-center flex-lg-justify-between mb-2 mb-lg-0"> - <li class="mr-3 mr-lg-0">&copy; 2019 <span title="0.39879s from unicorn-6c7bfddc88-6p84m">GitHub</span>, Inc.</li> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to terms, text:terms" href="https://github.com/site/terms">Terms</a></li> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to privacy, text:privacy" href="https://github.com/site/privacy">Privacy</a></li> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to security, text:security" href="https://github.com/security">Security</a></li> - <li class="mr-3 mr-lg-0"><a href="https://githubstatus.com/" data-ga-click="Footer, go to status, text:status">Status</a></li> - <li><a data-ga-click="Footer, go to help, text:help" href="https://help.github.com">Help</a></li> - </ul> - - <a aria-label="Homepage" title="GitHub" class="footer-octicon d-none d-lg-block mx-lg-4" href="https://github.com"> - <svg height="24" class="octicon octicon-mark-github" viewBox="0 0 16 16" version="1.1" width="24" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg> -</a> - <ul class="list-style-none d-flex flex-wrap col-12 col-lg-5 flex-justify-center flex-lg-justify-between mb-2 mb-lg-0"> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to contact, text:contact" href="https://github.com/contact">Contact GitHub</a></li> - <li class="mr-3 mr-lg-0"><a href="https://github.com/pricing" data-ga-click="Footer, go to Pricing, text:Pricing">Pricing</a></li> - <li class="mr-3 mr-lg-0"><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li> - <li class="mr-3 mr-lg-0"><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li> - <li class="mr-3 mr-lg-0"><a href="https://github.blog" data-ga-click="Footer, go to blog, text:blog">Blog</a></li> - <li><a data-ga-click="Footer, go to about, text:about" href="https://github.com/about">About</a></li> - - </ul> - </div> - <div class="d-flex flex-justify-center pb-6"> - <span class="f6 text-gray-light"></span> - </div> -</div> - - - - <div id="ajax-error-message" class="ajax-error-message flash flash-error"> - <svg class="octicon octicon-alert" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"/></svg> - <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error"> - <svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg> - </button> - You can’t perform that action at this time. - </div> - - - <script crossorigin="anonymous" integrity="sha512-BlCvumXWTvpASEdhCGiahDUDf7Bwb8QXA2XnnSnqJ9QafxcNcrNYUNYS2wXmd3nEpO//+zlZa9DSV9zmu5MqRg==" type="application/javascript" src="https://github.githubassets.com/assets/compat-bootstrap-90c0ace0.js"></script> - <script crossorigin="anonymous" integrity="sha512-/PxjwfwA7IQQAc/3OBA+EvAAOgs24JUmL+yYRnEl/N7pMvQRi+hBftbGJweH00j3z9d1mUOQpmR0D33CE5Wt7g==" type="application/javascript" src="https://github.githubassets.com/assets/frameworks-f1ce1e70.js"></script> - - <script crossorigin="anonymous" async="async" integrity="sha512-41RCZRCF3ndqncgjVi28zesDHQIA/pjp+qtail1asqbRM8BUPv4Vih2Lvlgv0cHACwKlcJJYxJO4+9iNf+rtRQ==" type="application/javascript" src="https://github.githubassets.com/assets/github-bootstrap-98914a0f.js"></script> - - - - <div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner" hidden - > - <svg class="octicon octicon-alert" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"/></svg> - <span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span> - <span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span> - </div> - <template id="site-details-dialog"> - <details class="details-reset details-overlay details-overlay-dark lh-default text-gray-dark hx_rsm" open> - <summary role="button" aria-label="Close dialog"></summary> - <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast hx_rsm-dialog hx_rsm-modal"> - <button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog> - <svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg> - </button> - <div class="octocat-spinner my-6 js-details-dialog-spinner"></div> - </details-dialog> - </details> -</template> - - <div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;" tabindex="0"> - <div class="Popover-message Popover-message--bottom-left Popover-message--large Box box-shadow-large" style="width:360px;"> - </div> -</div> - - <div aria-live="polite" class="js-global-screen-reader-notice sr-only"></div> - - </body> -</html> - +/* + * Copyright (C) 2015 Federico Dossena (adolfintel.com). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package com.dosse.upnp; + +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.SocketTimeoutException; +import java.util.Enumeration; +import java.util.LinkedList; + +/** + * + * @author Federico + */ +abstract class GatewayFinder { + + private static final String[] SEARCH_MESSAGES; + + static { + LinkedList<String> m = new LinkedList<String>(); + for (String type : new String[]{"urn:schemas-upnp-org:device:InternetGatewayDevice:1", "urn:schemas-upnp-org:service:WANIPConnection:1", "urn:schemas-upnp-org:service:WANPPPConnection:1"}) { + m.add("M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nST: " + type + "\r\nMAN: \"ssdp:discover\"\r\nMX: 2\r\n\r\n"); + } + SEARCH_MESSAGES = m.toArray(new String[]{}); + } + + private class GatewayListener extends Thread { + + private Inet4Address ip; + private String req; + + public GatewayListener(Inet4Address ip, String req) { + setName("WaifUPnP - Gateway Listener"); + this.ip = ip; + this.req = req; + } + + @Override + public void run() { + try { + byte[] req = this.req.getBytes(); + DatagramSocket s = new DatagramSocket(new InetSocketAddress(ip, 0)); + s.send(new DatagramPacket(req, req.length, new InetSocketAddress("239.255.255.250", 1900))); + s.setSoTimeout(3000); + for (;;) { + try { + DatagramPacket recv = new DatagramPacket(new byte[1536], 1536); + s.receive(recv); + Gateway gw = new Gateway(recv.getData(), ip); + gatewayFound(gw); + } catch (SocketTimeoutException t) { + break; + } catch (Throwable t) { + } + } + } catch (Throwable t) { + } + } + } + + private LinkedList<GatewayListener> listeners = new LinkedList<GatewayListener>(); + + public GatewayFinder() { + for (Inet4Address ip : getLocalIPs()) { + for (String req : SEARCH_MESSAGES) { + GatewayListener l = new GatewayListener(ip, req); + l.start(); + listeners.add(l); + } + } + } + + public boolean isSearching() { + for (GatewayListener l : listeners) { + if (l.isAlive()) { + return true; + } + } + return false; + } + + public abstract void gatewayFound(Gateway g); + + private static Inet4Address[] getLocalIPs() { + LinkedList<Inet4Address> ret = new LinkedList<Inet4Address>(); + try { + Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); + while (ifaces.hasMoreElements()) { + try { + NetworkInterface iface = ifaces.nextElement(); + if (!iface.isUp() || iface.isLoopback() || iface.isVirtual() || iface.isPointToPoint()) { + continue; + } + Enumeration<InetAddress> addrs = iface.getInetAddresses(); + if (addrs == null) { + continue; + } + while (addrs.hasMoreElements()) { + InetAddress addr = addrs.nextElement(); + if (addr instanceof Inet4Address) { + ret.add((Inet4Address) addr); + } + } + } catch (Throwable t) { + } + } + } catch (Throwable t) { + } + return ret.toArray(new Inet4Address[]{}); + } + +} diff --git a/src/WaifUPnP/UPnP.java b/src/WaifUPnP/UPnP.java @@ -1,1787 +1,154 @@ - - - - - - -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <link rel="dns-prefetch" href="https://github.githubassets.com"> - <link rel="dns-prefetch" href="https://avatars0.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars1.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars2.githubusercontent.com"> - <link rel="dns-prefetch" href="https://avatars3.githubusercontent.com"> - <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com"> - <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/"> - - - - <link crossorigin="anonymous" media="all" integrity="sha512-kBwTI/PLZvQ8eHdCgA2vpn0uJe4kEM/Ft7Zz5SAkc9BAifCxBxQS4VTaEIDJpVrbrlAhCeRJvf7DQWaA4dEUUQ==" rel="stylesheet" href="https://github.githubassets.com/assets/frameworks-da88be2d386821a8fa8de15789a23d23.css" /> - - <link crossorigin="anonymous" media="all" integrity="sha512-nxbIj3bfB8KtcNqQMnlOaPPMDmP9FiDWwjUpBLQy96vbpF72WO9aDrOU4TSu7T+fHKrBCeBWaRb9+keZgwcQlg==" rel="stylesheet" href="https://github.githubassets.com/assets/github-d7e1e4a3feb3fbdf6b2de5e69a10cb6e.css" /> - - - - - - <meta name="viewport" content="width=device-width"> - - <title>WaifUPnP/UPnP.java at master · adolfintel/WaifUPnP</title> - <meta name="description" content=" UPnP Port Forwarding for Java couldn&#39;t get any easier! - adolfintel/WaifUPnP"> - <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub"> - <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub"> - <meta property="fb:app_id" content="1401488693436528"> - - <meta name="twitter:image:src" content="https://avatars3.githubusercontent.com/u/16307689?s=400&amp;v=4" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary" /><meta name="twitter:title" content="adolfintel/WaifUPnP" /><meta name="twitter:description" content=" UPnP Port Forwarding for Java couldn&#39;t get any easier! - adolfintel/WaifUPnP" /> - <meta property="og:image" content="https://avatars3.githubusercontent.com/u/16307689?s=400&amp;v=4" /><meta property="og:site_name" content="GitHub" /><meta property="og:type" content="object" /><meta property="og:title" content="adolfintel/WaifUPnP" /><meta property="og:url" content="https://github.com/adolfintel/WaifUPnP" /><meta property="og:description" content=" UPnP Port Forwarding for Java couldn&#39;t get any easier! - adolfintel/WaifUPnP" /> - - <link rel="assets" href="https://github.githubassets.com/"> - <link rel="web-socket" href="wss://live.github.com/_sockets/VjI6NDI2ODEwNTUzOjEzNjg0ZGU2ZTI5NmE2Nzg2OTM4MWI2YjYyZDdhZTQyZTFjM2E2MjhiZWI1N2EwZTg4MTA1MmIxM2Y1NGJiODM=--50a6f8992bab885d8c365c60992f06593b131e36"> - <meta name="pjax-timeout" content="1000"> - <link rel="sudo-modal" href="/sessions/sudo_modal"> - <meta name="request-id" content="86A4:43DB:134EC6:21A0CC:5D49A9AC" data-pjax-transient> - - - - - <meta name="selected-link" value="repo_source" data-pjax-transient> - - <meta name="google-site-verification" content="KT5gs8h0wvaagLKAVWq8bbeNwnZZK1r1XQysX3xurLU"> - <meta name="google-site-verification" content="ZzhVyEFwb7w3e0-uOTltm8Jsck2F5StVihD0exw2fsA"> - <meta name="google-site-verification" content="GXs5KoUUkNCoaAZn7wPN-t01Pywp9M3sEjnt_3_ZWPc"> - - <meta name="octolytics-host" content="collector.githubapp.com" /><meta name="octolytics-app-id" content="github" /><meta name="octolytics-event-url" content="https://collector.githubapp.com/github-external/browser_event" /><meta name="octolytics-dimension-request_id" content="86A4:43DB:134EC6:21A0CC:5D49A9AC" /><meta name="octolytics-dimension-region_edge" content="iad" /><meta name="octolytics-dimension-region_render" content="iad" /><meta name="octolytics-actor-id" content="36491773" /><meta name="octolytics-actor-login" content="joshiemoore" /><meta name="octolytics-actor-hash" content="9fb9350a5ba47535efbba66a9fcc4ea37914a763e681b8faf401c837136a34a7" /> -<meta name="analytics-location" content="/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show" data-pjax-transient="true" /> - - - - - <meta class="js-ga-set" name="userId" content="70e439b4adcf1202f8343b7daf395cbf"> - -<meta class="js-ga-set" name="dimension1" content="Logged In"> - - - - - - <meta name="hostname" content="github.com"> - <meta name="user-login" content="joshiemoore"> - - <meta name="expected-hostname" content="github.com"> - <meta name="js-proxy-site-detection-payload" content="OWM0OTY0NGYyYzgyMDI5ZDEwOWI5OTQ2YTFiODZjZDllYTM5MTE1YmFkMzIyYjg4OWJmZGIwOGZhOTlkMGMwM3x7InJlbW90ZV9hZGRyZXNzIjoiNzEuMTE1LjE1MS4xNCIsInJlcXVlc3RfaWQiOiI4NkE0OjQzREI6MTM0RUM2OjIxQTBDQzo1RDQ5QTlBQyIsInRpbWVzdGFtcCI6MTU2NTEwODY1NywiaG9zdCI6ImdpdGh1Yi5jb20ifQ=="> - - <meta name="enabled-features" content="MARKETPLACE_FEATURED_BLOG_POSTS,MARKETPLACE_INVOICED_BILLING,MARKETPLACE_SOCIAL_PROOF_CUSTOMERS,MARKETPLACE_TRENDING_SOCIAL_PROOF,MARKETPLACE_RECOMMENDATIONS,MARKETPLACE_PENDING_INSTALLATIONS,NOTIFY_ON_BLOCK,RELATED_ISSUES"> - - <meta name="html-safe-nonce" content="21324b34db3b2bdbb5f491c2f72dc9dfc36873ac"> - - <meta http-equiv="x-pjax-version" content="5a9990041a6b9c1bf57398c337e95d61"> - - - <link href="https://github.com/adolfintel/WaifUPnP/commits/master.atom" rel="alternate" title="Recent Commits to WaifUPnP:master" type="application/atom+xml"> - - <meta name="go-import" content="github.com/adolfintel/WaifUPnP git https://github.com/adolfintel/WaifUPnP.git"> - - <meta name="octolytics-dimension-user_id" content="16307689" /><meta name="octolytics-dimension-user_login" content="adolfintel" /><meta name="octolytics-dimension-repository_id" content="48129574" /><meta name="octolytics-dimension-repository_nwo" content="adolfintel/WaifUPnP" /><meta name="octolytics-dimension-repository_public" content="true" /><meta name="octolytics-dimension-repository_is_fork" content="false" /><meta name="octolytics-dimension-repository_network_root_id" content="48129574" /><meta name="octolytics-dimension-repository_network_root_nwo" content="adolfintel/WaifUPnP" /><meta name="octolytics-dimension-repository_explore_github_marketplace_ci_cta_shown" content="false" /> - - - <link rel="canonical" href="https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/UPnP.java" data-pjax-transient> - - - <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats"> - - <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors"> - - <link rel="mask-icon" href="https://github.githubassets.com/pinned-octocat.svg" color="#000000"> - <link rel="icon" type="image/x-icon" class="js-site-favicon" href="https://github.githubassets.com/favicon.ico"> - -<meta name="theme-color" content="#1e2327"> - - - - - - <link rel="manifest" href="/manifest.json" crossOrigin="use-credentials"> - - </head> - - <body class="logged-in env-production page-responsive page-blob"> - - - <div class="position-relative js-header-wrapper "> - <a href="#start-of-content" tabindex="1" class="p-3 bg-blue text-white show-on-focus js-skip-to-content">Skip to content</a> - <div id="js-pjax-loader-bar" class="pjax-loader-bar"><div class="progress"></div></div> - - - - - - - <header class="Header js-details-container Details flex-wrap flex-lg-nowrap p-responsive" role="banner"> - - <div class="Header-item d-none d-lg-flex"> - <a class="Header-link" href="https://github.com/" data-hotkey="g d" aria-label="Homepage" data-ga-click="Header, go to dashboard, icon:logo"> - <svg class="octicon octicon-mark-github v-align-middle" height="32" viewBox="0 0 16 16" version="1.1" width="32" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg> -</a> - - </div> - - <div class="Header-item d-lg-none"> - <button class="Header-link btn-link js-details-target" type="button" aria-label="Toggle navigation" aria-expanded="false"> - <svg height="24" class="octicon octicon-three-bars" viewBox="0 0 12 16" version="1.1" width="18" aria-hidden="true"><path fill-rule="evenodd" d="M11.41 9H.59C0 9 0 8.59 0 8c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zm0-4H.59C0 5 0 4.59 0 4c0-.59 0-1 .59-1H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1h.01zM.59 11H11.4c.59 0 .59.41.59 1 0 .59 0 1-.59 1H.59C0 13 0 12.59 0 12c0-.59 0-1 .59-1z"/></svg> - </button> - </div> - - <div class="Header-item Header-item--full flex-column flex-lg-row width-full flex-order-2 flex-lg-order-none mr-0 mr-lg-3 mt-3 mt-lg-0 Details-content--hidden"> - <div class="header-search flex-self-stretch flex-lg-self-auto mr-0 mr-lg-3 mb-3 mb-lg-0 scoped-search site-scoped-search js-site-search position-relative js-jump-to" - role="combobox" - aria-owns="jump-to-results" - aria-label="Search or jump to" - aria-haspopup="listbox" - aria-expanded="false" -> - <div class="position-relative"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="js-site-search-form" role="search" aria-label="Site" data-scope-type="Repository" data-scope-id="48129574" data-scoped-search-url="/adolfintel/WaifUPnP/search" data-unscoped-search-url="/search" action="/adolfintel/WaifUPnP/search" accept-charset="UTF-8" method="get"><input name="utf8" type="hidden" value="&#x2713;" /> - <label class="form-control input-sm header-search-wrapper p-0 header-search-wrapper-jump-to position-relative d-flex flex-justify-between flex-items-center js-chromeless-input-container"> - <input type="text" - class="form-control input-sm header-search-input jump-to-field js-jump-to-field js-site-search-focus js-site-search-field is-clearable" - data-hotkey="s,/" - name="q" - value="" - placeholder="Search or jump to…" - data-unscoped-placeholder="Search or jump to…" - data-scoped-placeholder="Search or jump to…" - autocapitalize="off" - aria-autocomplete="list" - aria-controls="jump-to-results" - aria-label="Search or jump to…" - data-jump-to-suggestions-path="/_graphql/GetSuggestedNavigationDestinations#csrf-token=N+xHZn3BdRdarhSHZDWvyz/MpcEJE3H9+nL7OLNG99ublk7v6Hvz+P1zYZrg0wW3Rbe5o44/F9MKBv7HW4+8vA==" - spellcheck="false" - autocomplete="off" - > - <input type="hidden" class="js-site-search-type-field" name="type" > - <img src="https://github.githubassets.com/images/search-key-slash.svg" alt="" class="mr-2 header-search-key-slash"> - - <div class="Box position-absolute overflow-hidden d-none jump-to-suggestions js-jump-to-suggestions-container"> - -<ul class="d-none js-jump-to-suggestions-template-container"> - - -<li class="d-flex flex-justify-start flex-items-center p-0 f5 navigation-item js-navigation-item js-jump-to-suggestion" role="option"> - <a tabindex="-1" class="no-underline d-flex flex-auto flex-items-center jump-to-suggestions-path js-jump-to-suggestion-path js-navigation-open p-2" href=""> - <div class="jump-to-octicon js-jump-to-octicon flex-shrink-0 mr-2 text-center d-none"> - <svg height="16" width="16" class="octicon octicon-repo flex-shrink-0 js-jump-to-octicon-repo d-none" title="Repository" aria-label="Repository" viewBox="0 0 12 16" version="1.1" role="img"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <svg height="16" width="16" class="octicon octicon-project flex-shrink-0 js-jump-to-octicon-project d-none" title="Project" aria-label="Project" viewBox="0 0 15 16" version="1.1" role="img"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - <svg height="16" width="16" class="octicon octicon-search flex-shrink-0 js-jump-to-octicon-search d-none" title="Search" aria-label="Search" viewBox="0 0 16 16" version="1.1" role="img"><path fill-rule="evenodd" d="M15.7 13.3l-3.81-3.83A5.93 5.93 0 0 0 13 6c0-3.31-2.69-6-6-6S1 2.69 1 6s2.69 6 6 6c1.3 0 2.48-.41 3.47-1.11l3.83 3.81c.19.2.45.3.7.3.25 0 .52-.09.7-.3a.996.996 0 0 0 0-1.41v.01zM7 10.7c-2.59 0-4.7-2.11-4.7-4.7 0-2.59 2.11-4.7 4.7-4.7 2.59 0 4.7 2.11 4.7 4.7 0 2.59-2.11 4.7-4.7 4.7z"/></svg> - </div> - - <img class="avatar mr-2 flex-shrink-0 js-jump-to-suggestion-avatar d-none" alt="" aria-label="Team" src="" width="28" height="28"> - - <div class="jump-to-suggestion-name js-jump-to-suggestion-name flex-auto overflow-hidden text-left no-wrap css-truncate css-truncate-target"> - </div> - - <div class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none js-jump-to-badge-search"> - <span class="js-jump-to-badge-search-text-default d-none" aria-label="in this repository"> - In this repository - </span> - <span class="js-jump-to-badge-search-text-global d-none" aria-label="in all of GitHub"> - All GitHub - </span> - <span aria-hidden="true" class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - - <div aria-hidden="true" class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none d-on-nav-focus js-jump-to-badge-jump"> - Jump to - <span class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - </a> -</li> - -</ul> - -<ul class="d-none js-jump-to-no-results-template-container"> - <li class="d-flex flex-justify-center flex-items-center f5 d-none js-jump-to-suggestion p-2"> - <span class="text-gray">No suggested jump to results</span> - </li> -</ul> - -<ul id="jump-to-results" role="listbox" class="p-0 m-0 js-navigation-container jump-to-suggestions-results-container js-jump-to-suggestions-results-container"> - - -<li class="d-flex flex-justify-start flex-items-center p-0 f5 navigation-item js-navigation-item js-jump-to-scoped-search d-none" role="option"> - <a tabindex="-1" class="no-underline d-flex flex-auto flex-items-center jump-to-suggestions-path js-jump-to-suggestion-path js-navigation-open p-2" href=""> - <div class="jump-to-octicon js-jump-to-octicon flex-shrink-0 mr-2 text-center d-none"> - <svg height="16" width="16" class="octicon octicon-repo flex-shrink-0 js-jump-to-octicon-repo d-none" title="Repository" aria-label="Repository" viewBox="0 0 12 16" version="1.1" role="img"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <svg height="16" width="16" class="octicon octicon-project flex-shrink-0 js-jump-to-octicon-project d-none" title="Project" aria-label="Project" viewBox="0 0 15 16" version="1.1" role="img"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - <svg height="16" width="16" class="octicon octicon-search flex-shrink-0 js-jump-to-octicon-search d-none" title="Search" aria-label="Search" viewBox="0 0 16 16" version="1.1" role="img"><path fill-rule="evenodd" d="M15.7 13.3l-3.81-3.83A5.93 5.93 0 0 0 13 6c0-3.31-2.69-6-6-6S1 2.69 1 6s2.69 6 6 6c1.3 0 2.48-.41 3.47-1.11l3.83 3.81c.19.2.45.3.7.3.25 0 .52-.09.7-.3a.996.996 0 0 0 0-1.41v.01zM7 10.7c-2.59 0-4.7-2.11-4.7-4.7 0-2.59 2.11-4.7 4.7-4.7 2.59 0 4.7 2.11 4.7 4.7 0 2.59-2.11 4.7-4.7 4.7z"/></svg> - </div> - - <img class="avatar mr-2 flex-shrink-0 js-jump-to-suggestion-avatar d-none" alt="" aria-label="Team" src="" width="28" height="28"> - - <div class="jump-to-suggestion-name js-jump-to-suggestion-name flex-auto overflow-hidden text-left no-wrap css-truncate css-truncate-target"> - </div> - - <div class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none js-jump-to-badge-search"> - <span class="js-jump-to-badge-search-text-default d-none" aria-label="in this repository"> - In this repository - </span> - <span class="js-jump-to-badge-search-text-global d-none" aria-label="in all of GitHub"> - All GitHub - </span> - <span aria-hidden="true" class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - - <div aria-hidden="true" class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none d-on-nav-focus js-jump-to-badge-jump"> - Jump to - <span class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - </a> -</li> - - - -<li class="d-flex flex-justify-start flex-items-center p-0 f5 navigation-item js-navigation-item js-jump-to-global-search d-none" role="option"> - <a tabindex="-1" class="no-underline d-flex flex-auto flex-items-center jump-to-suggestions-path js-jump-to-suggestion-path js-navigation-open p-2" href=""> - <div class="jump-to-octicon js-jump-to-octicon flex-shrink-0 mr-2 text-center d-none"> - <svg height="16" width="16" class="octicon octicon-repo flex-shrink-0 js-jump-to-octicon-repo d-none" title="Repository" aria-label="Repository" viewBox="0 0 12 16" version="1.1" role="img"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <svg height="16" width="16" class="octicon octicon-project flex-shrink-0 js-jump-to-octicon-project d-none" title="Project" aria-label="Project" viewBox="0 0 15 16" version="1.1" role="img"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - <svg height="16" width="16" class="octicon octicon-search flex-shrink-0 js-jump-to-octicon-search d-none" title="Search" aria-label="Search" viewBox="0 0 16 16" version="1.1" role="img"><path fill-rule="evenodd" d="M15.7 13.3l-3.81-3.83A5.93 5.93 0 0 0 13 6c0-3.31-2.69-6-6-6S1 2.69 1 6s2.69 6 6 6c1.3 0 2.48-.41 3.47-1.11l3.83 3.81c.19.2.45.3.7.3.25 0 .52-.09.7-.3a.996.996 0 0 0 0-1.41v.01zM7 10.7c-2.59 0-4.7-2.11-4.7-4.7 0-2.59 2.11-4.7 4.7-4.7 2.59 0 4.7 2.11 4.7 4.7 0 2.59-2.11 4.7-4.7 4.7z"/></svg> - </div> - - <img class="avatar mr-2 flex-shrink-0 js-jump-to-suggestion-avatar d-none" alt="" aria-label="Team" src="" width="28" height="28"> - - <div class="jump-to-suggestion-name js-jump-to-suggestion-name flex-auto overflow-hidden text-left no-wrap css-truncate css-truncate-target"> - </div> - - <div class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none js-jump-to-badge-search"> - <span class="js-jump-to-badge-search-text-default d-none" aria-label="in this repository"> - In this repository - </span> - <span class="js-jump-to-badge-search-text-global d-none" aria-label="in all of GitHub"> - All GitHub - </span> - <span aria-hidden="true" class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - - <div aria-hidden="true" class="border rounded-1 flex-shrink-0 bg-gray px-1 text-gray-light ml-1 f6 d-none d-on-nav-focus js-jump-to-badge-jump"> - Jump to - <span class="d-inline-block ml-1 v-align-middle">↵</span> - </div> - </a> -</li> - - - <li class="d-flex flex-justify-center flex-items-center p-0 f5 js-jump-to-suggestion"> - <img src="https://github.githubassets.com/images/spinners/octocat-spinner-128.gif" alt="Octocat Spinner Icon" class="m-2" width="28"> - </li> -</ul> - - </div> - </label> -</form> </div> -</div> - - - <nav class="d-flex flex-column flex-lg-row flex-self-stretch flex-lg-self-auto" aria-label="Global"> - <a class="Header-link d-block d-lg-none py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-ga-click="Header, click, Nav menu - item:dashboard:user" aria-label="Dashboard" href="/dashboard"> - Dashboard -</a> - <a class="js-selected-navigation-item Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-hotkey="g p" data-ga-click="Header, click, Nav menu - item:pulls context:user" aria-label="Pull requests you created" data-selected-links="/pulls /pulls/assigned /pulls/mentioned /pulls" href="/pulls"> - Pull requests -</a> - <a class="js-selected-navigation-item Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-hotkey="g i" data-ga-click="Header, click, Nav menu - item:issues context:user" aria-label="Issues you created" data-selected-links="/issues /issues/assigned /issues/mentioned /issues" href="/issues"> - Issues -</a> - <div class="mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15"> - <a class="js-selected-navigation-item Header-link" data-ga-click="Header, click, Nav menu - item:marketplace context:user" data-octo-click="marketplace_click" data-octo-dimensions="location:nav_bar" data-selected-links=" /marketplace" href="/marketplace"> - Marketplace -</a> - </div> - - <a class="js-selected-navigation-item Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" data-ga-click="Header, click, Nav menu - item:explore" data-selected-links="/explore /trending /trending/developers /integrations /integrations/feature/code /integrations/feature/collaborate /integrations/feature/ship showcases showcases_search showcases_landing /explore" href="/explore"> - Explore -</a> - - - <a class="Header-link d-block d-lg-none mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15" href="https://github.com/joshiemoore"> - <img class="avatar" height="20" width="20" alt="@joshiemoore" src="https://avatars3.githubusercontent.com/u/36491773?s=60&amp;v=4" /> - joshiemoore -</a> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form action="/logout" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="9wBeTRfvrsXT6VhBUqb2b8XQ/rBfZnYmkdSCmQEp1aAGp91u1q9J+SHztkF4YUGXE4WtoMVGiy7n69Ozn80pAg==" /> - <button type="submit" class="Header-link mr-0 mr-lg-3 py-2 py-lg-0 border-top border-lg-top-0 border-white-fade-15 d-lg-none btn-link d-block width-full text-left" data-ga-click="Header, sign out, icon:logout" style="padding-left: 2px;"> - <svg class="octicon octicon-sign-out v-align-middle" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 9V7H8V5h4V3l4 3-4 3zm-2 3H6V3L2 1h8v3h1V1c0-.55-.45-1-1-1H1C.45 0 0 .45 0 1v11.38c0 .39.22.73.55.91L6 16.01V13h4c.55 0 1-.45 1-1V8h-1v4z"/></svg> - Sign out - </button> -</form></nav> - - </div> - - <div class="Header-item Header-item--full flex-justify-center d-lg-none position-relative"> - <div class="css-truncate css-truncate-target width-fit position-absolute left-0 right-0 text-center"> - <svg class="octicon octicon-repo" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <a class="Header-link" href="/adolfintel">adolfintel</a> - / - <a class="Header-link" href="/adolfintel/WaifUPnP">WaifUPnP</a> - -</div> - </div> - - <div class="Header-item position-relative d-none d-lg-flex"> - - - </div> - - <div class="Header-item mr-0 mr-lg-3 flex-order-1 flex-lg-order-none"> - - - <a aria-label="You have no unread notifications" class="Header-link notification-indicator position-relative tooltipped tooltipped-s js-socket-channel js-notification-indicator" data-hotkey="g n" data-ga-click="Header, go to notifications, icon:read" data-channel="notification-changed:36491773" href="/notifications"> - <span class="mail-status "></span> - <svg class="octicon octicon-bell" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14 12v1H0v-1l.73-.58c.77-.77.81-2.55 1.19-4.42C2.69 3.23 6 2 6 2c0-.55.45-1 1-1s1 .45 1 1c0 0 3.39 1.23 4.16 5 .38 1.88.42 3.66 1.19 4.42l.66.58H14zm-7 4c1.11 0 2-.89 2-2H5c0 1.11.89 2 2 2z"/></svg> -</a> - </div> - - - <div class="Header-item position-relative d-none d-lg-flex"> - <details class="details-overlay details-reset"> - <summary class="Header-link" - aria-label="Create new…" - data-ga-click="Header, create new, icon:add"> - <svg class="octicon octicon-plus" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 9H7v5H5V9H0V7h5V2h2v5h5v2z"/></svg> <span class="dropdown-caret"></span> - </summary> - <details-menu class="dropdown-menu dropdown-menu-sw"> - -<a role="menuitem" class="dropdown-item" href="/new" data-ga-click="Header, create new repository"> - New repository -</a> - - <a role="menuitem" class="dropdown-item" href="/new/import" data-ga-click="Header, import a repository"> - Import repository - </a> - -<a role="menuitem" class="dropdown-item" href="https://gist.github.com/" data-ga-click="Header, create new gist"> - New gist -</a> - - <a role="menuitem" class="dropdown-item" href="/organizations/new" data-ga-click="Header, create new organization"> - New organization - </a> - - - <div role="none" class="dropdown-divider"></div> - <div class="dropdown-header"> - <span title="adolfintel/WaifUPnP">This repository</span> - </div> - <a role="menuitem" class="dropdown-item" href="/adolfintel/WaifUPnP/issues/new" data-ga-click="Header, create new issue" data-skip-pjax> - New issue - </a> - - - </details-menu> -</details> - - </div> - - <div class="Header-item position-relative mr-0 d-none d-lg-flex"> - -<details class="details-overlay details-reset"> - <summary class="Header-link" - aria-label="View profile and more" - data-ga-click="Header, show menu, icon:avatar"> - <img alt="@joshiemoore" class="avatar" src="https://avatars0.githubusercontent.com/u/36491773?s=40&amp;v=4" height="20" width="20"> - <span class="dropdown-caret"></span> - </summary> - <details-menu class="dropdown-menu dropdown-menu-sw mt-2" style="width: 180px"> - <div class="header-nav-current-user css-truncate"><a role="menuitem" class="no-underline user-profile-link px-3 pt-2 pb-2 mb-n2 mt-n1 d-block" href="/joshiemoore" data-ga-click="Header, go to profile, text:Signed in as">Signed in as <strong class="css-truncate-target">joshiemoore</strong></a></div> - <div role="none" class="dropdown-divider"></div> - - <div class="pl-3 pr-3 f6 user-status-container js-user-status-context pb-1" data-url="/users/status?compact=1&amp;link_mentions=0&amp;truncate=1"> - -<div class="js-user-status-container - user-status-compact rounded-1 px-2 py-1 mt-2 - border - " data-team-hovercards-enabled> - <details class="js-user-status-details details-reset details-overlay details-overlay-dark"> - <summary class="btn-link btn-block link-gray no-underline js-toggle-user-status-edit toggle-user-status-edit " aria-haspopup="dialog" role="menuitem" data-hydro-click="{&quot;event_type&quot;:&quot;user_profile.click&quot;,&quot;payload&quot;:{&quot;profile_user_id&quot;:16307689,&quot;target&quot;:&quot;EDIT_USER_STATUS&quot;,&quot;user_id&quot;:36491773,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134EC6:21A0CC:5D49A9AC&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/UPnP.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;}}" data-hydro-click-hmac="0de96a08d82f20acb6b39d7e77bd3eb71400631c458d54e126b11974c5e11dc3"> - <div class="d-flex"> - <div class="f6 lh-condensed user-status-header - d-inline-block v-align-middle - user-status-emoji-only-header circle - pr-2 -" - style="max-width: 29px" - > - <div class="user-status-emoji-container flex-shrink-0 mr-1 mt-1 lh-condensed-ultra v-align-bottom" style=""> - <svg class="octicon octicon-smiley" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm4.81 12.81a6.72 6.72 0 0 1-2.17 1.45c-.83.36-1.72.53-2.64.53-.92 0-1.81-.17-2.64-.53-.81-.34-1.55-.83-2.17-1.45a6.773 6.773 0 0 1-1.45-2.17A6.59 6.59 0 0 1 1.21 8c0-.92.17-1.81.53-2.64.34-.81.83-1.55 1.45-2.17.62-.62 1.36-1.11 2.17-1.45A6.59 6.59 0 0 1 8 1.21c.92 0 1.81.17 2.64.53.81.34 1.55.83 2.17 1.45.62.62 1.11 1.36 1.45 2.17.36.83.53 1.72.53 2.64 0 .92-.17 1.81-.53 2.64-.34.81-.83 1.55-1.45 2.17zM4 6.8v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2H5.2C4.53 8 4 7.47 4 6.8zm5 0v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2h-.59C9.53 8 9 7.47 9 6.8zm4 3.2c-.72 1.88-2.91 3-5 3s-4.28-1.13-5-3c-.14-.39.23-1 .66-1h8.59c.41 0 .89.61.75 1z"/></svg> - </div> - </div> - <div class=" - d-inline-block v-align-middle - - - css-truncate css-truncate-target - user-status-message-wrapper f6" - style="line-height: 20px;" > - <div class="d-inline-block text-gray-dark v-align-text-top text-left"> - <span class="text-gray ml-2">Set status</span> - </div> - </div> - </div> -</summary> <details-dialog class="details-dialog rounded-1 anim-fade-in fast Box Box--overlay" role="dialog" tabindex="-1"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="position-relative flex-auto js-user-status-form" action="/users/status?compact=1&amp;link_mentions=0&amp;truncate=1" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="_method" value="put" /><input type="hidden" name="authenticity_token" value="2SPNBOW9NTi9uj77vaenARaGPg50/dHYIN8fjvCFcaRaHT/2z2jTeWrT1NN5k/Iy8cTYDeKvOG2d21iRlT+obA==" /> - <div class="Box-header bg-gray border-bottom p-3"> - <button class="Box-btn-octicon js-toggle-user-status-edit btn-octicon float-right" type="reset" aria-label="Close dialog" data-close-dialog> - <svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg> - </button> - <h3 class="Box-title f5 text-bold text-gray-dark">Edit status</h3> - </div> - <input type="hidden" name="emoji" class="js-user-status-emoji-field" value=""> - <input type="hidden" name="organization_id" class="js-user-status-org-id-field" value=""> - <div class="px-3 py-2 text-gray-dark"> - <div class="js-characters-remaining-container position-relative mt-2"> - <div class="input-group d-table form-group my-0 js-user-status-form-group"> - <span class="input-group-button d-table-cell v-align-middle" style="width: 1%"> - <button type="button" aria-label="Choose an emoji" class="btn-outline btn js-toggle-user-status-emoji-picker btn-open-emoji-picker p-0"> - <span class="js-user-status-original-emoji" hidden></span> - <span class="js-user-status-custom-emoji"></span> - <span class="js-user-status-no-emoji-icon" > - <svg class="octicon octicon-smiley" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm4.81 12.81a6.72 6.72 0 0 1-2.17 1.45c-.83.36-1.72.53-2.64.53-.92 0-1.81-.17-2.64-.53-.81-.34-1.55-.83-2.17-1.45a6.773 6.773 0 0 1-1.45-2.17A6.59 6.59 0 0 1 1.21 8c0-.92.17-1.81.53-2.64.34-.81.83-1.55 1.45-2.17.62-.62 1.36-1.11 2.17-1.45A6.59 6.59 0 0 1 8 1.21c.92 0 1.81.17 2.64.53.81.34 1.55.83 2.17 1.45.62.62 1.11 1.36 1.45 2.17.36.83.53 1.72.53 2.64 0 .92-.17 1.81-.53 2.64-.34.81-.83 1.55-1.45 2.17zM4 6.8v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2H5.2C4.53 8 4 7.47 4 6.8zm5 0v-.59c0-.66.53-1.19 1.2-1.19h.59c.66 0 1.19.53 1.19 1.19v.59c0 .67-.53 1.2-1.19 1.2h-.59C9.53 8 9 7.47 9 6.8zm4 3.2c-.72 1.88-2.91 3-5 3s-4.28-1.13-5-3c-.14-.39.23-1 .66-1h8.59c.41 0 .89.61.75 1z"/></svg> - </span> - </button> - </span> - <text-expander keys=": @" data-mention-url="/autocomplete/user-suggestions" data-emoji-url="/autocomplete/emoji"> - <input - type="text" - autocomplete="off" - data-no-org-url="/autocomplete/user-suggestions" - data-org-url="/suggestions?mention_suggester=1" - data-maxlength="80" - class="d-table-cell width-full form-control js-user-status-message-field js-characters-remaining-field" - placeholder="What's happening?" - name="message" - value="" - aria-label="What is your current status?"> - </text-expander> - <div class="error">Could not update your status, please try again.</div> - </div> - <div style="margin-left: 53px" class="my-1 text-small label-characters-remaining js-characters-remaining" data-suffix="remaining" hidden> - 80 remaining - </div> - </div> - <include-fragment class="js-user-status-emoji-picker" data-url="/users/status/emoji"></include-fragment> - <div class="overflow-auto ml-n3 mr-n3 px-3 border-bottom" style="max-height: 33vh"> - <div class="user-status-suggestions js-user-status-suggestions collapsed overflow-hidden"> - <h4 class="f6 text-normal my-3">Suggestions:</h4> - <div class="mx-3 mt-2 clearfix"> - <div class="float-left col-6"> - <button type="button" value=":palm_tree:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="palm_tree" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f334.png">🌴</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - On vacation - </div> - </button> - <button type="button" value=":face_with_thermometer:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="face_with_thermometer" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f912.png">🤒</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - Out sick - </div> - </button> - </div> - <div class="float-left col-6"> - <button type="button" value=":house:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="house" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f3e0.png">🏠</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - Working from home - </div> - </button> - <button type="button" value=":dart:" class="d-flex flex-items-baseline flex-items-stretch lh-condensed f6 btn-link link-gray no-underline js-predefined-user-status mb-1"> - <div class="emoji-status-width mr-2 v-align-middle js-predefined-user-status-emoji"> - <g-emoji alias="dart" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f3af.png">🎯</g-emoji> - </div> - <div class="d-flex flex-items-center no-underline js-predefined-user-status-message ws-normal text-left" style="border-left: 1px solid transparent"> - Focusing - </div> - </button> - </div> - </div> - </div> - <div class="user-status-limited-availability-container"> - <div class="form-checkbox my-0"> - <input type="checkbox" name="limited_availability" value="1" class="js-user-status-limited-availability-checkbox" data-default-message="I may be slow to respond." aria-describedby="limited-availability-help-text-truncate-true-compact-true" id="limited-availability-truncate-true-compact-true"> - <label class="d-block f5 text-gray-dark mb-1" for="limited-availability-truncate-true-compact-true"> - Busy - </label> - <p class="note" id="limited-availability-help-text-truncate-true-compact-true"> - When others mention you, assign you, or request your review, - GitHub will let them know that you have limited availability. - </p> - </div> - </div> - </div> - - -<div class="d-inline-block f5 mr-2 pt-3 pb-2" > - <div class="d-inline-block mr-1"> - Clear status - </div> - - <details class="js-user-status-expire-drop-down f6 dropdown details-reset details-overlay d-inline-block mr-2"> - <summary class="f5 btn-link link-gray-dark border px-2 py-1 rounded-1" aria-haspopup="true"> - <div class="js-user-status-expiration-interval-selected d-inline-block v-align-baseline"> - Never - </div> - <div class="dropdown-caret"></div> - </summary> - - <ul class="dropdown-menu dropdown-menu-se pl-0 overflow-auto" style="width: 220px; max-height: 15.5em"> - <li> - <button type="button" class="btn-link dropdown-item js-user-status-expire-button ws-normal" title="Never"> - <span class="d-inline-block text-bold mb-1">Never</span> - <div class="f6 lh-condensed">Keep this status until you clear your status or edit your status.</div> - </button> - </li> - <li class="dropdown-divider" role="none"></li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="in 30 minutes" value="2019-08-06T12:54:17-04:00"> - in 30 minutes - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="in 1 hour" value="2019-08-06T13:24:17-04:00"> - in 1 hour - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="in 4 hours" value="2019-08-06T16:24:17-04:00"> - in 4 hours - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="today" value="2019-08-06T23:59:59-04:00"> - today - </button> - </li> - <li> - <button type="button" class="btn-link dropdown-item ws-normal js-user-status-expire-button" title="this week" value="2019-08-11T23:59:59-04:00"> - this week - </button> - </li> - </ul> - </details> - <input class="js-user-status-expiration-date-input" type="hidden" name="expires_at" value=""> -</div> - - <include-fragment class="js-user-status-org-picker" data-url="/users/status/organizations"></include-fragment> - </div> - <div class="d-flex flex-items-center flex-justify-between p-3 border-top"> - <button type="submit" disabled class="width-full btn btn-primary mr-2 js-user-status-submit"> - Set status - </button> - <button type="button" disabled class="width-full js-clear-user-status-button btn ml-2 "> - Clear status - </button> - </div> -</form> </details-dialog> - </details> -</div> - - </div> - <div role="none" class="dropdown-divider"></div> - - - <a role="menuitem" class="dropdown-item" href="/joshiemoore" data-ga-click="Header, go to profile, text:your profile">Your profile</a> - - - <a role="menuitem" class="dropdown-item" href="/joshiemoore?tab=repositories" data-ga-click="Header, go to repositories, text:your repositories">Your repositories</a> - - <a role="menuitem" class="dropdown-item" href="/joshiemoore?tab=projects" data-ga-click="Header, go to projects, text:your projects">Your projects</a> - - <a role="menuitem" class="dropdown-item" href="/joshiemoore?tab=stars" data-ga-click="Header, go to starred repos, text:your stars">Your stars</a> - <a role="menuitem" class="dropdown-item" href="https://gist.github.com/mine" data-ga-click="Header, your gists, text:your gists">Your gists</a> - - - <div role="none" class="dropdown-divider"></div> - <a role="menuitem" class="dropdown-item" href="https://help.github.com" data-ga-click="Header, go to help, text:help">Help</a> - <a role="menuitem" class="dropdown-item" href="/settings/profile" data-ga-click="Header, go to settings, icon:settings">Settings</a> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="logout-form" action="/logout" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="TIm2gogECUZpa/qdgKth9ERjE3cEyzyATx4bq5kDQVu9LjWhSUTueptxFJ2qbNYMkjZAZ57rwYg5IUqBB+e9+Q==" /> - - <button type="submit" class="dropdown-item dropdown-signout" data-ga-click="Header, sign out, icon:logout" role="menuitem"> - Sign out - </button> -</form> </details-menu> -</details> - - </div> - - </header> - - - - </div> - - <div id="start-of-content" class="show-on-focus"></div> - - - <div id="js-flash-container"> - -</div> - - - - <div class="application-main " data-commit-hovercards-enabled> - <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class=""> - <main > - - - - - - - - - - - - - <div class="pagehead repohead instapaper_ignore readability-menu experiment-repo-nav pt-0 pt-lg-4 "> - <div class="repohead-details-container clearfix container-lg p-responsive d-none d-lg-block"> - - <ul class="pagehead-actions"> - - - - - <li> - - <!-- '"` --><!-- </textarea></xmp> --></option></form><form data-remote="true" class="clearfix js-social-form js-social-container" action="/notifications/subscribe" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="WN1n0g3wNiHAgQcaXQ2GSGbHtxPTEMPJlxFgs+GIdtSdWbiDKui2/wPX3PBxvbMpog6oiALH46PUOP74yRWZVA==" /> <input type="hidden" name="repository_id" value="48129574"> - - <details class="details-reset details-overlay select-menu float-left"> - <summary class="select-menu-button float-left btn btn-sm btn-with-count" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;WATCH_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134EC6:21A0CC:5D49A9AC&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/UPnP.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="87d0d3d3cce487484f6132d07509f5b8bd909e5eb601c971eaf4b824bca0bf6f" data-ga-click="Repository, click Watch settings, action:blob#show"> <span data-menu-button> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Watch - </span> -</summary> <details-menu - class="select-menu-modal position-absolute mt-5" - style="z-index: 99;"> - <div class="select-menu-header"> - <span class="select-menu-title">Notifications</span> - </div> - <div class="select-menu-list"> - <button type="submit" name="do" value="included" class="select-menu-item width-full" aria-checked="true" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Not watching</span> - <span class="description">Be notified only when participating or @mentioned.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Watch - </span> - </div> - </button> - - <button type="submit" name="do" value="release_only" class="select-menu-item width-full" aria-checked="false" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Releases only</span> - <span class="description">Be notified of new releases, and when participating or @mentioned.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Unwatch releases - </span> - </div> - </button> - - <button type="submit" name="do" value="subscribed" class="select-menu-item width-full" aria-checked="false" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Watching</span> - <span class="description">Be notified of all conversations.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-eye v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg> - Unwatch - </span> - </div> - </button> - - <button type="submit" name="do" value="ignore" class="select-menu-item width-full" aria-checked="false" role="menuitemradio"> - <svg class="octicon octicon-check select-menu-item-icon" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5L12 5z"/></svg> - <div class="select-menu-item-text"> - <span class="select-menu-item-heading">Ignoring</span> - <span class="description">Never be notified.</span> - <span class="hidden-select-button-text" data-menu-button-contents> - <svg class="octicon octicon-mute v-align-text-bottom" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 2.81v10.38c0 .67-.81 1-1.28.53L3 10H1c-.55 0-1-.45-1-1V7c0-.55.45-1 1-1h2l3.72-3.72C7.19 1.81 8 2.14 8 2.81zm7.53 3.22l-1.06-1.06-1.97 1.97-1.97-1.97-1.06 1.06L11.44 8 9.47 9.97l1.06 1.06 1.97-1.97 1.97 1.97 1.06-1.06L13.56 8l1.97-1.97z"/></svg> - Stop ignoring - </span> - </div> - </button> - </div> - </details-menu> - </details> - <a class="social-count js-social-count" - href="/adolfintel/WaifUPnP/watchers" - aria-label="4 users are watching this repository"> - 4 - </a> -</form> - </li> - - <li> - <div class="js-toggler-container js-social-container starring-container on"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="starred js-social-form" action="/adolfintel/WaifUPnP/unstar" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="p7ww7EYxFU+xlIS/k6xSx0fq1tDAIJRnswEekTCdg+6/6lDbVaIg8TakkoTOPsZSkMYsPcPIp0paZyWW3RbK5g==" /> - <input type="hidden" name="context" value="repository"></input> - <button type="submit" class="btn btn-sm btn-with-count js-toggler-target" aria-label="Unstar this repository" title="Unstar adolfintel/WaifUPnP" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;UNSTAR_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134EC6:21A0CC:5D49A9AC&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/UPnP.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="ce9b81a417d4658af8b1817fecdb4a17b334a10a181407733f6d0246d18b2ecd" data-ga-click="Repository, click unstar button, action:blob#show; text:Unstar"> <svg class="octicon octicon-star v-align-text-bottom" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74L14 6z"/></svg> - Unstar -</button> <a class="social-count js-social-count" href="/adolfintel/WaifUPnP/stargazers" - aria-label="25 users starred this repository"> - 25 - </a> -</form> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="unstarred js-social-form" action="/adolfintel/WaifUPnP/star" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="64/vu5gDXJ+yjOKQ+jjfvV0z+6v9zQ3wj+4aOE4gIZt5llu1JDcAkCR0RVU94fLMtIAHqqaedafEmkOO/jsepg==" /> - <input type="hidden" name="context" value="repository"></input> - <button type="submit" class="btn btn-sm btn-with-count js-toggler-target" aria-label="Unstar this repository" title="Star adolfintel/WaifUPnP" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;STAR_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134EC6:21A0CC:5D49A9AC&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/UPnP.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="623f0b57f3cbc826235ac5bc115317549fa37ac0bfe0a4cd5a4e22adb4b32243" data-ga-click="Repository, click star button, action:blob#show; text:Star"> <svg class="octicon octicon-star v-align-text-bottom" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74L14 6z"/></svg> - Star -</button> <a class="social-count js-social-count" href="/adolfintel/WaifUPnP/stargazers" - aria-label="25 users starred this repository"> - 25 - </a> -</form> </div> - - </li> - - <li> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="btn-with-count" action="/adolfintel/WaifUPnP/fork" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="RCZIO8RS2EQ6d8HEW7PQmVapY+waMNpb6A7tamGwWq322JbY+q21yJo9skt4M2h/5ISZZ5BXorCVEaXwPRcfBw==" /> - <button class="btn btn-sm btn-with-count" data-hydro-click="{&quot;event_type&quot;:&quot;repository.click&quot;,&quot;payload&quot;:{&quot;target&quot;:&quot;FORK_BUTTON&quot;,&quot;repository_id&quot;:48129574,&quot;client_id&quot;:&quot;1760325610.1562227847&quot;,&quot;originating_request_id&quot;:&quot;86A4:43DB:134EC6:21A0CC:5D49A9AC&quot;,&quot;originating_url&quot;:&quot;https://github.com/adolfintel/WaifUPnP/blob/master/src/com/dosse/upnp/UPnP.java&quot;,&quot;referrer&quot;:&quot;https://github.com/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp&quot;,&quot;user_id&quot;:36491773}}" data-hydro-click-hmac="fb125c0bb9c367f3cb94b2b3d4abfa40798df27eaee87c89a284ca3bc2f31b40" data-ga-click="Repository, show fork modal, action:blob#show; text:Fork" type="submit" title="Fork your own copy of adolfintel/WaifUPnP to your account" aria-label="Fork your own copy of adolfintel/WaifUPnP to your account"> <svg class="octicon octicon-repo-forked v-align-text-bottom" viewBox="0 0 10 16" version="1.1" width="10" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8 1a1.993 1.993 0 0 0-1 3.72V6L5 8 3 6V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V6.5l3 3v1.78A1.993 1.993 0 0 0 5 15a1.993 1.993 0 0 0 1-3.72V9.5l3-3V4.72A1.993 1.993 0 0 0 8 1zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3 10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3-10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg> - Fork -</button></form> - <a href="/adolfintel/WaifUPnP/network/members" class="social-count" - aria-label="6 users forked this repository"> - 6 - </a> - </li> -</ul> - - <h1 class="public "> - <svg class="octicon octicon-repo" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg> - <span class="author" itemprop="author"><a class="url fn" rel="author" data-hovercard-type="user" data-hovercard-url="/hovercards?user_id=16307689" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/adolfintel">adolfintel</a></span><!-- ---><span class="path-divider">/</span><!-- ---><strong itemprop="name"><a data-pjax="#js-repo-pjax-container" href="/adolfintel/WaifUPnP">WaifUPnP</a></strong> - - -</h1> - - </div> - -<nav class="hx_reponav reponav js-repo-nav js-sidenav-container-pjax container-lg p-responsive d-none d-lg-block" - itemscope - itemtype="http://schema.org/BreadcrumbList" - aria-label="Repository" - data-pjax="#js-repo-pjax-container"> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a class="js-selected-navigation-item selected reponav-item" itemprop="url" data-hotkey="g c" aria-current="page" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches repo_packages /adolfintel/WaifUPnP" href="/adolfintel/WaifUPnP"> - <svg class="octicon octicon-code" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M9.5 3L8 4.5 11.5 8 8 11.5 9.5 13 14 8 9.5 3zm-5 0L0 8l4.5 5L6 11.5 2.5 8 6 4.5 4.5 3z"/></svg> - <span itemprop="name">Code</span> - <meta itemprop="position" content="1"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" data-hotkey="g i" class="js-selected-navigation-item reponav-item" data-selected-links="repo_issues repo_labels repo_milestones /adolfintel/WaifUPnP/issues" href="/adolfintel/WaifUPnP/issues"> - <svg class="octicon octicon-issue-opened" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"/></svg> - <span itemprop="name">Issues</span> - <span class="Counter">2</span> - <meta itemprop="position" content="2"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a data-hotkey="g p" itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_pulls checks /adolfintel/WaifUPnP/pulls" href="/adolfintel/WaifUPnP/pulls"> - <svg class="octicon octicon-git-pull-request" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg> - <span itemprop="name">Pull requests</span> - <span class="Counter">2</span> - <meta itemprop="position" content="3"> -</a> </span> - - - <a data-hotkey="g b" class="js-selected-navigation-item reponav-item" data-selected-links="repo_projects new_repo_project repo_project /adolfintel/WaifUPnP/projects" href="/adolfintel/WaifUPnP/projects"> - <svg class="octicon octicon-project" viewBox="0 0 15 16" version="1.1" width="15" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg> - Projects - <span class="Counter" >0</span> -</a> - - <a class="js-selected-navigation-item reponav-item" data-hotkey="g w" data-selected-links="repo_wiki /adolfintel/WaifUPnP/wiki" href="/adolfintel/WaifUPnP/wiki"> - <svg class="octicon octicon-book" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M3 5h4v1H3V5zm0 3h4V7H3v1zm0 2h4V9H3v1zm11-5h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm2-6v9c0 .55-.45 1-1 1H9.5l-1 1-1-1H2c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h5.5l1 1 1-1H15c.55 0 1 .45 1 1zm-8 .5L7.5 3H2v9h6V3.5zm7-.5H9.5l-.5.5V12h6V3z"/></svg> - Wiki -</a> - <a data-skip-pjax="true" class="js-selected-navigation-item reponav-item" data-selected-links="security alerts policy /adolfintel/WaifUPnP/security/advisories" href="/adolfintel/WaifUPnP/security/advisories"> - <svg class="octicon octicon-shield" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M0 2l7-2 7 2v6.02C14 12.69 8.69 16 7 16c-1.69 0-7-3.31-7-7.98V2zm1 .75L7 1l6 1.75v5.268C13 12.104 8.449 15 7 15c-1.449 0-6-2.896-6-6.982V2.75zm1 .75L7 2v12c-1.207 0-5-2.482-5-5.985V3.5z"/></svg> - Security -</a> - <a class="js-selected-navigation-item reponav-item" data-selected-links="repo_graphs repo_contributors dependency_graph pulse people /adolfintel/WaifUPnP/pulse" href="/adolfintel/WaifUPnP/pulse"> - <svg class="octicon octicon-graph" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z"/></svg> - Insights -</a> - -</nav> - - <div class="reponav-wrapper reponav-small d-lg-none"> - <nav class="reponav js-reponav text-center no-wrap" - itemscope - itemtype="http://schema.org/BreadcrumbList"> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a class="js-selected-navigation-item selected reponav-item" itemprop="url" aria-current="page" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches repo_packages /adolfintel/WaifUPnP" href="/adolfintel/WaifUPnP"> - <span itemprop="name">Code</span> - <meta itemprop="position" content="1"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_issues repo_labels repo_milestones /adolfintel/WaifUPnP/issues" href="/adolfintel/WaifUPnP/issues"> - <span itemprop="name">Issues</span> - <span class="Counter">2</span> - <meta itemprop="position" content="2"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_pulls checks /adolfintel/WaifUPnP/pulls" href="/adolfintel/WaifUPnP/pulls"> - <span itemprop="name">Pull requests</span> - <span class="Counter">2</span> - <meta itemprop="position" content="3"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_projects new_repo_project repo_project /adolfintel/WaifUPnP/projects" href="/adolfintel/WaifUPnP/projects"> - <span itemprop="name">Projects</span> - <span class="Counter">0</span> - <meta itemprop="position" content="4"> -</a> </span> - - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="repo_wiki /adolfintel/WaifUPnP/wiki" href="/adolfintel/WaifUPnP/wiki"> - <span itemprop="name">Wiki</span> - <meta itemprop="position" content="5"> -</a> </span> - - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="security alerts policy /adolfintel/WaifUPnP/security/advisories" href="/adolfintel/WaifUPnP/security/advisories"> - <span itemprop="name">Security</span> - <meta itemprop="position" content="6"> -</a> - <a class="js-selected-navigation-item reponav-item" data-selected-links="pulse /adolfintel/WaifUPnP/pulse" href="/adolfintel/WaifUPnP/pulse"> - Pulse -</a> - <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement"> - <a itemprop="url" class="js-selected-navigation-item reponav-item" data-selected-links="community /adolfintel/WaifUPnP/community" href="/adolfintel/WaifUPnP/community"> - Community -</a> </span> - - </nav> -</div> - - - </div> -<div class="container-lg clearfix new-discussion-timeline experiment-repo-nav p-responsive"> - <div class="repository-content "> - - - - - - - - - <a class="d-none js-permalink-shortcut" data-hotkey="y" href="/adolfintel/WaifUPnP/blob/d6381a8c6f24c7d0f5879ba037abd018ba428561/src/com/dosse/upnp/UPnP.java">Permalink</a> - - <!-- blob contrib key: blob_contributors:v21:7508a6f2722fa66c1807589ce72546e4 --> - - - <div class="d-flex flex-items-start flex-shrink-0 pb-3 flex-column flex-md-row"> - <span class="d-flex flex-justify-between width-full width-md-auto"> - -<details class="details-reset details-overlay select-menu branch-select-menu hx_rsm" id="branch-select-menu"> - <summary class="btn btn-sm select-menu-button css-truncate" - data-hotkey="w" - - title="Switch branches or tags"> - <i>Branch:</i> - <span class="css-truncate-target">master</span> - </summary> - - <details-menu class="select-menu-modal hx_rsm-modal position-absolute" style="z-index: 99;" src="/adolfintel/WaifUPnP/ref-list/master/src/com/dosse/upnp/UPnP.java?source_action=show&amp;source_controller=blob" preload> - <include-fragment class="select-menu-loading-overlay anim-pulse"> - <svg height="32" class="octicon octicon-octoface" viewBox="0 0 16 16" version="1.1" width="32" aria-hidden="true"><path fill-rule="evenodd" d="M14.7 5.34c.13-.32.55-1.59-.13-3.31 0 0-1.05-.33-3.44 1.3-1-.28-2.07-.32-3.13-.32s-2.13.04-3.13.32c-2.39-1.64-3.44-1.3-3.44-1.3-.68 1.72-.26 2.99-.13 3.31C.49 6.21 0 7.33 0 8.69 0 13.84 3.33 15 7.98 15S16 13.84 16 8.69c0-1.36-.49-2.48-1.3-3.35zM8 14.02c-3.3 0-5.98-.15-5.98-3.35 0-.76.38-1.48 1.02-2.07 1.07-.98 2.9-.46 4.96-.46 2.07 0 3.88-.52 4.96.46.65.59 1.02 1.3 1.02 2.07 0 3.19-2.68 3.35-5.98 3.35zM5.49 9.01c-.66 0-1.2.8-1.2 1.78s.54 1.79 1.2 1.79c.66 0 1.2-.8 1.2-1.79s-.54-1.78-1.2-1.78zm5.02 0c-.66 0-1.2.79-1.2 1.78s.54 1.79 1.2 1.79c.66 0 1.2-.8 1.2-1.79s-.53-1.78-1.2-1.78z"/></svg> - </include-fragment> - </details-menu> -</details> - - <div class="BtnGroup flex-shrink-0 d-md-none"> - <a href="/adolfintel/WaifUPnP/find/master" - class="js-pjax-capture-input btn btn-sm BtnGroup-item" - data-pjax - data-hotkey="t"> - Find file - </a> - <clipboard-copy value="src/com/dosse/upnp/UPnP.java" class="btn btn-sm BtnGroup-item"> - Copy path - </clipboard-copy> - </div> - </span> - <h2 id="blob-path" class="breadcrumb flex-auto min-width-0 text-normal flex-md-self-center ml-md-2 mr-md-3 my-2 my-md-0"> - <span class="js-repo-root text-bold"><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP"><span>WaifUPnP</span></a></span></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src"><span>src</span></a></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src/com"><span>com</span></a></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src/com/dosse"><span>dosse</span></a></span><span class="separator">/</span><span class="js-path-segment"><a data-pjax="true" href="/adolfintel/WaifUPnP/tree/master/src/com/dosse/upnp"><span>upnp</span></a></span><span class="separator">/</span><strong class="final-path">UPnP.java</strong> - </h2> - - <div class="BtnGroup flex-shrink-0 d-none d-md-inline-block"> - <a href="/adolfintel/WaifUPnP/find/master" - class="js-pjax-capture-input btn btn-sm BtnGroup-item" - data-pjax - data-hotkey="t"> - Find file - </a> - <clipboard-copy value="src/com/dosse/upnp/UPnP.java" class="btn btn-sm BtnGroup-item"> - Copy path - </clipboard-copy> - </div> - </div> - - - - - <div class="Box Box--condensed d-flex flex-column flex-shrink-0"> - <div class="Box-body d-flex flex-justify-between bg-blue-light flex-column flex-md-row flex-items-start flex-md-items-center"> - <span class="pr-md-4 f6"> - <a rel="contributor" data-skip-pjax="true" data-hovercard-type="user" data-hovercard-url="/hovercards?user_id=9736369" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/jredfox"><img class="avatar" src="https://avatars3.githubusercontent.com/u/9736369?s=40&amp;v=4" width="20" height="20" alt="@jredfox" /></a> - <a class="text-bold link-gray-dark lh-default v-align-middle" rel="contributor" data-hovercard-type="user" data-hovercard-url="/hovercards?user_id=9736369" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/jredfox">jredfox</a> - <span class="lh-default v-align-middle"> - <a data-pjax="true" title="UPNP Port Close Fix - -the booleans for close tcp and udp ports was inverted this fixes it" class="link-gray" href="/adolfintel/WaifUPnP/commit/339fee21bc435bf672d33e0c98c354e9fb8774cb">UPNP Port Close Fix</a> - </span> - </span> - <span class="d-inline-block flex-shrink-0 v-align-bottom f6 mt-2 mt-md-0"> - <a class="pr-2 text-mono link-gray" href="/adolfintel/WaifUPnP/commit/339fee21bc435bf672d33e0c98c354e9fb8774cb" data-pjax>339fee2</a> - <relative-time datetime="2018-06-24T04:25:15Z">Jun 24, 2018</relative-time> - </span> - </div> - - <div class="Box-body d-flex flex-items-center flex-auto f6 border-bottom-0 flex-wrap" > - <details class="details-reset details-overlay details-overlay-dark lh-default text-gray-dark float-left mr-2" id="blob_contributors_box"> - <summary class="btn-link" aria-haspopup="dialog"> - <span><strong>2</strong> contributors</span> - </summary> - <details-dialog - class="Box Box--overlay d-flex flex-column anim-fade-in fast" - aria-label="Users who have contributed to this file" - src="/adolfintel/WaifUPnP/contributors/master/src/com/dosse/upnp/UPnP.java/list" preload> - <div class="Box-header"> - <button class="Box-btn-octicon btn-octicon float-right" type="button" aria-label="Close dialog" data-close-dialog> - <svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg> - </button> - <h3 class="Box-title"> - Users who have contributed to this file - </h3> - </div> - <include-fragment class="octocat-spinner my-3" aria-label="Loading..."></include-fragment> - </details-dialog> - </details> - <span class=""> - <a class="avatar-link" data-hovercard-type="user" data-hovercard-url="/hovercards?user_id=9736369" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/adolfintel/WaifUPnP/commits/master/src/com/dosse/upnp/UPnP.java?author=jredfox"> - <img class="avatar mr-1" src="https://avatars3.githubusercontent.com/u/9736369?s=40&amp;v=4" width="20" height="20" alt="@jredfox" /> -</a> <a class="avatar-link" data-hovercard-type="user" data-hovercard-url="/hovercards?user_id=16307689" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/adolfintel/WaifUPnP/commits/master/src/com/dosse/upnp/UPnP.java?author=adolfintel"> - <img class="avatar mr-1" src="https://avatars0.githubusercontent.com/u/16307689?s=40&amp;v=4" width="20" height="20" alt="@adolfintel" /> -</a> -</span> - - </div> - </div> - - - - - - <div class="Box mt-3 position-relative"> - -<div class="Box-header py-2 d-flex flex-column flex-shrink-0 flex-md-row flex-md-items-center"> - - <div class="text-mono f6 flex-auto pr-3 flex-order-2 flex-md-order-1 mt-2 mt-md-0"> - 155 lines (141 sloc) - <span class="file-info-divider"></span> - 4.57 KB - </div> - - <div class="d-flex py-1 py-md-0 flex-auto flex-order-1 flex-md-order-2 flex-sm-grow-0 flex-justify-between"> - - <div class="BtnGroup"> - <a id="raw-url" class="btn btn-sm BtnGroup-item" href="/adolfintel/WaifUPnP/raw/master/src/com/dosse/upnp/UPnP.java">Raw</a> - <a class="btn btn-sm js-update-url-with-hash BtnGroup-item" data-hotkey="b" href="/adolfintel/WaifUPnP/blame/master/src/com/dosse/upnp/UPnP.java">Blame</a> - <a rel="nofollow" class="btn btn-sm BtnGroup-item" href="/adolfintel/WaifUPnP/commits/master/src/com/dosse/upnp/UPnP.java">History</a> - </div> - - - <div> - - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="inline-form js-update-url-with-hash" action="/adolfintel/WaifUPnP/edit/master/src/com/dosse/upnp/UPnP.java" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="/V313jLSmqhsPCjry5XBE+GRWE8HRBZ0fPdTHvz0pqryrGMDUkiI5hDee5zKOycyoD4+S/mFuBpnmMS3unP9jA==" /> - <button class="btn-octicon tooltipped tooltipped-nw" type="submit" - aria-label="Fork this project and edit the file" data-hotkey="e" data-disable-with> - <svg class="octicon octicon-pencil" viewBox="0 0 14 16" version="1.1" width="14" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M0 12v3h3l8-8-3-3-8 8zm3 2H1v-2h1v1h1v1zm10.3-9.3L12 6 9 3l1.3-1.3a.996.996 0 0 1 1.41 0l1.59 1.59c.39.39.39 1.02 0 1.41z"/></svg> - </button> -</form> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="inline-form" action="/adolfintel/WaifUPnP/delete/master/src/com/dosse/upnp/UPnP.java" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="Miqi+jIv9EvYVavspYNKo5EyOqkexWGGrdgoSbGhF3Gmlt/OM+Ic7Q9HWm1s+Sl+PPymVI8q19Xg7g1RMOa70w==" /> - <button class="btn-octicon btn-octicon-danger tooltipped tooltipped-nw" type="submit" - aria-label="Fork this project and delete the file" data-disable-with> - <svg class="octicon octicon-trashcan" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M11 2H9c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1H2c-.55 0-1 .45-1 1v1c0 .55.45 1 1 1v9c0 .55.45 1 1 1h7c.55 0 1-.45 1-1V5c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 12H3V5h1v8h1V5h1v8h1V5h1v8h1V5h1v9zm1-10H2V3h9v1z"/></svg> - </button> -</form> </div> - </div> -</div> - - - - - - - <div itemprop="text" class="Box-body p-0 blob-wrapper data type-java "> - -<table class="highlight tab-size js-file-line-container" data-tab-size="8"> - <tr> - <td id="L1" class="blob-num js-line-number" data-line-number="1"></td> - <td id="LC1" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">/*</span></span></td> - </tr> - <tr> - <td id="L2" class="blob-num js-line-number" data-line-number="2"></td> - <td id="LC2" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Copyright (C) 2015 Federico Dossena (adolfintel.com).</span></td> - </tr> - <tr> - <td id="L3" class="blob-num js-line-number" data-line-number="3"></td> - <td id="LC3" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> *</span></td> - </tr> - <tr> - <td id="L4" class="blob-num js-line-number" data-line-number="4"></td> - <td id="LC4" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * This library is free software; you can redistribute it and/or</span></td> - </tr> - <tr> - <td id="L5" class="blob-num js-line-number" data-line-number="5"></td> - <td id="LC5" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * modify it under the terms of the GNU Lesser General Public</span></td> - </tr> - <tr> - <td id="L6" class="blob-num js-line-number" data-line-number="6"></td> - <td id="LC6" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * License as published by the Free Software Foundation; either</span></td> - </tr> - <tr> - <td id="L7" class="blob-num js-line-number" data-line-number="7"></td> - <td id="LC7" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * version 2.1 of the License, or (at your option) any later version.</span></td> - </tr> - <tr> - <td id="L8" class="blob-num js-line-number" data-line-number="8"></td> - <td id="LC8" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> *</span></td> - </tr> - <tr> - <td id="L9" class="blob-num js-line-number" data-line-number="9"></td> - <td id="LC9" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * This library is distributed in the hope that it will be useful,</span></td> - </tr> - <tr> - <td id="L10" class="blob-num js-line-number" data-line-number="10"></td> - <td id="LC10" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</span></td> - </tr> - <tr> - <td id="L11" class="blob-num js-line-number" data-line-number="11"></td> - <td id="LC11" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</span></td> - </tr> - <tr> - <td id="L12" class="blob-num js-line-number" data-line-number="12"></td> - <td id="LC12" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Lesser General Public License for more details.</span></td> - </tr> - <tr> - <td id="L13" class="blob-num js-line-number" data-line-number="13"></td> - <td id="LC13" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> *</span></td> - </tr> - <tr> - <td id="L14" class="blob-num js-line-number" data-line-number="14"></td> - <td id="LC14" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * You should have received a copy of the GNU Lesser General Public</span></td> - </tr> - <tr> - <td id="L15" class="blob-num js-line-number" data-line-number="15"></td> - <td id="LC15" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * License along with this library; if not, write to the Free Software</span></td> - </tr> - <tr> - <td id="L16" class="blob-num js-line-number" data-line-number="16"></td> - <td id="LC16" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,</span></td> - </tr> - <tr> - <td id="L17" class="blob-num js-line-number" data-line-number="17"></td> - <td id="LC17" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * MA 02110-1301 USA</span></td> - </tr> - <tr> - <td id="L18" class="blob-num js-line-number" data-line-number="18"></td> - <td id="LC18" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L19" class="blob-num js-line-number" data-line-number="19"></td> - <td id="LC19" class="blob-code blob-code-inner js-file-line"><span class="pl-k">package</span> <span class="pl-smi">com.dosse.upnp</span>;</td> - </tr> - <tr> - <td id="L20" class="blob-num js-line-number" data-line-number="20"></td> - <td id="LC20" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L21" class="blob-num js-line-number" data-line-number="21"></td> - <td id="LC21" class="blob-code blob-code-inner js-file-line"><span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L22" class="blob-num js-line-number" data-line-number="22"></td> - <td id="LC22" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * This class contains static methods that allow quick access to UPnP Port Mapping.&lt;<span class="pl-ent">br</span>&gt;</span></td> - </tr> - <tr> - <td id="L23" class="blob-num js-line-number" data-line-number="23"></td> - <td id="LC23" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Commands will be sent to the default gateway.</span></td> - </tr> - <tr> - <td id="L24" class="blob-num js-line-number" data-line-number="24"></td> - <td id="LC24" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * </span></td> - </tr> - <tr> - <td id="L25" class="blob-num js-line-number" data-line-number="25"></td> - <td id="LC25" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@author</span> Federico</span></td> - </tr> - <tr> - <td id="L26" class="blob-num js-line-number" data-line-number="26"></td> - <td id="LC26" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L27" class="blob-num js-line-number" data-line-number="27"></td> - <td id="LC27" class="blob-code blob-code-inner js-file-line"><span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-en">UPnP</span> {</td> - </tr> - <tr> - <td id="L28" class="blob-num js-line-number" data-line-number="28"></td> - <td id="LC28" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L29" class="blob-num js-line-number" data-line-number="29"></td> - <td id="LC29" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-k">static</span> <span class="pl-smi">Gateway</span> defaultGW <span class="pl-k">=</span> <span class="pl-c1">null</span>;</td> - </tr> - <tr> - <td id="L30" class="blob-num js-line-number" data-line-number="30"></td> - <td id="LC30" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">private</span> <span class="pl-k">static</span> <span class="pl-k">final</span> <span class="pl-smi">GatewayFinder</span> finder <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-smi">GatewayFinder</span>() {</td> - </tr> - <tr> - <td id="L31" class="blob-num js-line-number" data-line-number="31"></td> - <td id="LC31" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">@Override</span></td> - </tr> - <tr> - <td id="L32" class="blob-num js-line-number" data-line-number="32"></td> - <td id="LC32" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">void</span> <span class="pl-en">gatewayFound</span>(<span class="pl-smi">Gateway</span> <span class="pl-v">g</span>) {</td> - </tr> - <tr> - <td id="L33" class="blob-num js-line-number" data-line-number="33"></td> - <td id="LC33" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">synchronized</span> (finder) {</td> - </tr> - <tr> - <td id="L34" class="blob-num js-line-number" data-line-number="34"></td> - <td id="LC34" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span> (defaultGW <span class="pl-k">==</span> <span class="pl-c1">null</span>) {</td> - </tr> - <tr> - <td id="L35" class="blob-num js-line-number" data-line-number="35"></td> - <td id="LC35" class="blob-code blob-code-inner js-file-line"> defaultGW <span class="pl-k">=</span> g;</td> - </tr> - <tr> - <td id="L36" class="blob-num js-line-number" data-line-number="36"></td> - <td id="LC36" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L37" class="blob-num js-line-number" data-line-number="37"></td> - <td id="LC37" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L38" class="blob-num js-line-number" data-line-number="38"></td> - <td id="LC38" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L39" class="blob-num js-line-number" data-line-number="39"></td> - <td id="LC39" class="blob-code blob-code-inner js-file-line"> };</td> - </tr> - <tr> - <td id="L40" class="blob-num js-line-number" data-line-number="40"></td> - <td id="LC40" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L41" class="blob-num js-line-number" data-line-number="41"></td> - <td id="LC41" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L42" class="blob-num js-line-number" data-line-number="42"></td> - <td id="LC42" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Waits for UPnP to be initialized (takes ~3 seconds).&lt;<span class="pl-ent">br</span>&gt;</span></td> - </tr> - <tr> - <td id="L43" class="blob-num js-line-number" data-line-number="43"></td> - <td id="LC43" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * It is not necessary to call this method manually before using UPnP functions</span></td> - </tr> - <tr> - <td id="L44" class="blob-num js-line-number" data-line-number="44"></td> - <td id="LC44" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L45" class="blob-num js-line-number" data-line-number="45"></td> - <td id="LC45" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">waitInit</span>() {</td> - </tr> - <tr> - <td id="L46" class="blob-num js-line-number" data-line-number="46"></td> - <td id="LC46" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">while</span> (finder<span class="pl-k">.</span>isSearching()) {</td> - </tr> - <tr> - <td id="L47" class="blob-num js-line-number" data-line-number="47"></td> - <td id="LC47" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">try</span> {</td> - </tr> - <tr> - <td id="L48" class="blob-num js-line-number" data-line-number="48"></td> - <td id="LC48" class="blob-code blob-code-inner js-file-line"> <span class="pl-smi">Thread</span><span class="pl-k">.</span>sleep(<span class="pl-c1">1</span>);</td> - </tr> - <tr> - <td id="L49" class="blob-num js-line-number" data-line-number="49"></td> - <td id="LC49" class="blob-code blob-code-inner js-file-line"> } <span class="pl-k">catch</span> (<span class="pl-smi">InterruptedException</span> ex) {</td> - </tr> - <tr> - <td id="L50" class="blob-num js-line-number" data-line-number="50"></td> - <td id="LC50" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L51" class="blob-num js-line-number" data-line-number="51"></td> - <td id="LC51" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L52" class="blob-num js-line-number" data-line-number="52"></td> - <td id="LC52" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L53" class="blob-num js-line-number" data-line-number="53"></td> - <td id="LC53" class="blob-code blob-code-inner js-file-line"> </td> - </tr> - <tr> - <td id="L54" class="blob-num js-line-number" data-line-number="54"></td> - <td id="LC54" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L55" class="blob-num js-line-number" data-line-number="55"></td> - <td id="LC55" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Is there an UPnP gateway?&lt;<span class="pl-ent">br</span>&gt;</span></td> - </tr> - <tr> - <td id="L56" class="blob-num js-line-number" data-line-number="56"></td> - <td id="LC56" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * This method is blocking if UPnP is still initializing&lt;<span class="pl-ent">br</span>&gt;</span></td> - </tr> - <tr> - <td id="L57" class="blob-num js-line-number" data-line-number="57"></td> - <td id="LC57" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * All UPnP commands will fail if UPnP is not available</span></td> - </tr> - <tr> - <td id="L58" class="blob-num js-line-number" data-line-number="58"></td> - <td id="LC58" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * </span></td> - </tr> - <tr> - <td id="L59" class="blob-num js-line-number" data-line-number="59"></td> - <td id="LC59" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@return</span> true if available, false if not</span></td> - </tr> - <tr> - <td id="L60" class="blob-num js-line-number" data-line-number="60"></td> - <td id="LC60" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L61" class="blob-num js-line-number" data-line-number="61"></td> - <td id="LC61" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">boolean</span> <span class="pl-en">isUPnPAvailable</span>(){</td> - </tr> - <tr> - <td id="L62" class="blob-num js-line-number" data-line-number="62"></td> - <td id="LC62" class="blob-code blob-code-inner js-file-line"> waitInit();</td> - </tr> - <tr> - <td id="L63" class="blob-num js-line-number" data-line-number="63"></td> - <td id="LC63" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> defaultGW<span class="pl-k">!=</span><span class="pl-c1">null</span>;</td> - </tr> - <tr> - <td id="L64" class="blob-num js-line-number" data-line-number="64"></td> - <td id="LC64" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L65" class="blob-num js-line-number" data-line-number="65"></td> - <td id="LC65" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L66" class="blob-num js-line-number" data-line-number="66"></td> - <td id="LC66" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L67" class="blob-num js-line-number" data-line-number="67"></td> - <td id="LC67" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Opens a TCP port on the gateway</span></td> - </tr> - <tr> - <td id="L68" class="blob-num js-line-number" data-line-number="68"></td> - <td id="LC68" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * </span></td> - </tr> - <tr> - <td id="L69" class="blob-num js-line-number" data-line-number="69"></td> - <td id="LC69" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@param</span> port TCP port (0-65535)</span></td> - </tr> - <tr> - <td id="L70" class="blob-num js-line-number" data-line-number="70"></td> - <td id="LC70" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@return</span> true if the operation was successful, false otherwise</span></td> - </tr> - <tr> - <td id="L71" class="blob-num js-line-number" data-line-number="71"></td> - <td id="LC71" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L72" class="blob-num js-line-number" data-line-number="72"></td> - <td id="LC72" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">boolean</span> <span class="pl-en">openPortTCP</span>(<span class="pl-k">int</span> <span class="pl-v">port</span>) {</td> - </tr> - <tr> - <td id="L73" class="blob-num js-line-number" data-line-number="73"></td> - <td id="LC73" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span>(<span class="pl-k">!</span>isUPnPAvailable()) <span class="pl-k">return</span> <span class="pl-c1">false</span>;</td> - </tr> - <tr> - <td id="L74" class="blob-num js-line-number" data-line-number="74"></td> - <td id="LC74" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> defaultGW<span class="pl-k">.</span>openPort(port, <span class="pl-c1">false</span>);</td> - </tr> - <tr> - <td id="L75" class="blob-num js-line-number" data-line-number="75"></td> - <td id="LC75" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L76" class="blob-num js-line-number" data-line-number="76"></td> - <td id="LC76" class="blob-code blob-code-inner js-file-line"> </td> - </tr> - <tr> - <td id="L77" class="blob-num js-line-number" data-line-number="77"></td> - <td id="LC77" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L78" class="blob-num js-line-number" data-line-number="78"></td> - <td id="LC78" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Opens a UDP port on the gateway</span></td> - </tr> - <tr> - <td id="L79" class="blob-num js-line-number" data-line-number="79"></td> - <td id="LC79" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * </span></td> - </tr> - <tr> - <td id="L80" class="blob-num js-line-number" data-line-number="80"></td> - <td id="LC80" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@param</span> port UDP port (0-65535)</span></td> - </tr> - <tr> - <td id="L81" class="blob-num js-line-number" data-line-number="81"></td> - <td id="LC81" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@return</span> true if the operation was successful, false otherwise</span></td> - </tr> - <tr> - <td id="L82" class="blob-num js-line-number" data-line-number="82"></td> - <td id="LC82" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L83" class="blob-num js-line-number" data-line-number="83"></td> - <td id="LC83" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">boolean</span> <span class="pl-en">openPortUDP</span>(<span class="pl-k">int</span> <span class="pl-v">port</span>) {</td> - </tr> - <tr> - <td id="L84" class="blob-num js-line-number" data-line-number="84"></td> - <td id="LC84" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span>(<span class="pl-k">!</span>isUPnPAvailable()) <span class="pl-k">return</span> <span class="pl-c1">false</span>;</td> - </tr> - <tr> - <td id="L85" class="blob-num js-line-number" data-line-number="85"></td> - <td id="LC85" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> defaultGW<span class="pl-k">.</span>openPort(port, <span class="pl-c1">true</span>);</td> - </tr> - <tr> - <td id="L86" class="blob-num js-line-number" data-line-number="86"></td> - <td id="LC86" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L87" class="blob-num js-line-number" data-line-number="87"></td> - <td id="LC87" class="blob-code blob-code-inner js-file-line"> </td> - </tr> - <tr> - <td id="L88" class="blob-num js-line-number" data-line-number="88"></td> - <td id="LC88" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L89" class="blob-num js-line-number" data-line-number="89"></td> - <td id="LC89" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Closes a TCP port on the gateway&lt;<span class="pl-ent">br</span>&gt;</span></td> - </tr> - <tr> - <td id="L90" class="blob-num js-line-number" data-line-number="90"></td> - <td id="LC90" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Most gateways seem to refuse to do this</span></td> - </tr> - <tr> - <td id="L91" class="blob-num js-line-number" data-line-number="91"></td> - <td id="LC91" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * </span></td> - </tr> - <tr> - <td id="L92" class="blob-num js-line-number" data-line-number="92"></td> - <td id="LC92" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@param</span> port TCP port (0-65535)</span></td> - </tr> - <tr> - <td id="L93" class="blob-num js-line-number" data-line-number="93"></td> - <td id="LC93" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@return</span> true if the operation was successful, false otherwise</span></td> - </tr> - <tr> - <td id="L94" class="blob-num js-line-number" data-line-number="94"></td> - <td id="LC94" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L95" class="blob-num js-line-number" data-line-number="95"></td> - <td id="LC95" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">boolean</span> <span class="pl-en">closePortTCP</span>(<span class="pl-k">int</span> <span class="pl-v">port</span>) {</td> - </tr> - <tr> - <td id="L96" class="blob-num js-line-number" data-line-number="96"></td> - <td id="LC96" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span>(<span class="pl-k">!</span>isUPnPAvailable()) <span class="pl-k">return</span> <span class="pl-c1">false</span>;</td> - </tr> - <tr> - <td id="L97" class="blob-num js-line-number" data-line-number="97"></td> - <td id="LC97" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> defaultGW<span class="pl-k">.</span>closePort(port, <span class="pl-c1">false</span>);</td> - </tr> - <tr> - <td id="L98" class="blob-num js-line-number" data-line-number="98"></td> - <td id="LC98" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L99" class="blob-num js-line-number" data-line-number="99"></td> - <td id="LC99" class="blob-code blob-code-inner js-file-line"> </td> - </tr> - <tr> - <td id="L100" class="blob-num js-line-number" data-line-number="100"></td> - <td id="LC100" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L101" class="blob-num js-line-number" data-line-number="101"></td> - <td id="LC101" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Closes a UDP port on the gateway&lt;<span class="pl-ent">br</span>&gt;</span></td> - </tr> - <tr> - <td id="L102" class="blob-num js-line-number" data-line-number="102"></td> - <td id="LC102" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Most gateways seem to refuse to do this</span></td> - </tr> - <tr> - <td id="L103" class="blob-num js-line-number" data-line-number="103"></td> - <td id="LC103" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * </span></td> - </tr> - <tr> - <td id="L104" class="blob-num js-line-number" data-line-number="104"></td> - <td id="LC104" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@param</span> port UDP port (0-65535)</span></td> - </tr> - <tr> - <td id="L105" class="blob-num js-line-number" data-line-number="105"></td> - <td id="LC105" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@return</span> true if the operation was successful, false otherwise</span></td> - </tr> - <tr> - <td id="L106" class="blob-num js-line-number" data-line-number="106"></td> - <td id="LC106" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L107" class="blob-num js-line-number" data-line-number="107"></td> - <td id="LC107" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">boolean</span> <span class="pl-en">closePortUDP</span>(<span class="pl-k">int</span> <span class="pl-v">port</span>) {</td> - </tr> - <tr> - <td id="L108" class="blob-num js-line-number" data-line-number="108"></td> - <td id="LC108" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span>(<span class="pl-k">!</span>isUPnPAvailable()) <span class="pl-k">return</span> <span class="pl-c1">false</span>;</td> - </tr> - <tr> - <td id="L109" class="blob-num js-line-number" data-line-number="109"></td> - <td id="LC109" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> defaultGW<span class="pl-k">.</span>closePort(port, <span class="pl-c1">true</span>);</td> - </tr> - <tr> - <td id="L110" class="blob-num js-line-number" data-line-number="110"></td> - <td id="LC110" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L111" class="blob-num js-line-number" data-line-number="111"></td> - <td id="LC111" class="blob-code blob-code-inner js-file-line"> </td> - </tr> - <tr> - <td id="L112" class="blob-num js-line-number" data-line-number="112"></td> - <td id="LC112" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L113" class="blob-num js-line-number" data-line-number="113"></td> - <td id="LC113" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Checks if a TCP port is mapped&lt;<span class="pl-ent">br</span>&gt;</span></td> - </tr> - <tr> - <td id="L114" class="blob-num js-line-number" data-line-number="114"></td> - <td id="LC114" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * </span></td> - </tr> - <tr> - <td id="L115" class="blob-num js-line-number" data-line-number="115"></td> - <td id="LC115" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@param</span> port TCP port (0-65535)</span></td> - </tr> - <tr> - <td id="L116" class="blob-num js-line-number" data-line-number="116"></td> - <td id="LC116" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@return</span> true if the port is mapped, false otherwise</span></td> - </tr> - <tr> - <td id="L117" class="blob-num js-line-number" data-line-number="117"></td> - <td id="LC117" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L118" class="blob-num js-line-number" data-line-number="118"></td> - <td id="LC118" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">boolean</span> <span class="pl-en">isMappedTCP</span>(<span class="pl-k">int</span> <span class="pl-v">port</span>) {</td> - </tr> - <tr> - <td id="L119" class="blob-num js-line-number" data-line-number="119"></td> - <td id="LC119" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span>(<span class="pl-k">!</span>isUPnPAvailable()) <span class="pl-k">return</span> <span class="pl-c1">false</span>;</td> - </tr> - <tr> - <td id="L120" class="blob-num js-line-number" data-line-number="120"></td> - <td id="LC120" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> defaultGW<span class="pl-k">.</span>isMapped(port, <span class="pl-c1">false</span>);</td> - </tr> - <tr> - <td id="L121" class="blob-num js-line-number" data-line-number="121"></td> - <td id="LC121" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L122" class="blob-num js-line-number" data-line-number="122"></td> - <td id="LC122" class="blob-code blob-code-inner js-file-line"> </td> - </tr> - <tr> - <td id="L123" class="blob-num js-line-number" data-line-number="123"></td> - <td id="LC123" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L124" class="blob-num js-line-number" data-line-number="124"></td> - <td id="LC124" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Checks if a UDP port is mapped&lt;<span class="pl-ent">br</span>&gt;</span></td> - </tr> - <tr> - <td id="L125" class="blob-num js-line-number" data-line-number="125"></td> - <td id="LC125" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * </span></td> - </tr> - <tr> - <td id="L126" class="blob-num js-line-number" data-line-number="126"></td> - <td id="LC126" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@param</span> port UDP port (0-65535)</span></td> - </tr> - <tr> - <td id="L127" class="blob-num js-line-number" data-line-number="127"></td> - <td id="LC127" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@return</span> true if the port is mapped, false otherwise</span></td> - </tr> - <tr> - <td id="L128" class="blob-num js-line-number" data-line-number="128"></td> - <td id="LC128" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L129" class="blob-num js-line-number" data-line-number="129"></td> - <td id="LC129" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">boolean</span> <span class="pl-en">isMappedUDP</span>(<span class="pl-k">int</span> <span class="pl-v">port</span>) {</td> - </tr> - <tr> - <td id="L130" class="blob-num js-line-number" data-line-number="130"></td> - <td id="LC130" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span>(<span class="pl-k">!</span>isUPnPAvailable()) <span class="pl-k">return</span> <span class="pl-c1">false</span>;</td> - </tr> - <tr> - <td id="L131" class="blob-num js-line-number" data-line-number="131"></td> - <td id="LC131" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> defaultGW<span class="pl-k">.</span>isMapped(port, <span class="pl-c1">false</span>);</td> - </tr> - <tr> - <td id="L132" class="blob-num js-line-number" data-line-number="132"></td> - <td id="LC132" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L133" class="blob-num js-line-number" data-line-number="133"></td> - <td id="LC133" class="blob-code blob-code-inner js-file-line"> </td> - </tr> - <tr> - <td id="L134" class="blob-num js-line-number" data-line-number="134"></td> - <td id="LC134" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L135" class="blob-num js-line-number" data-line-number="135"></td> - <td id="LC135" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Gets the external IP address of the default gateway</span></td> - </tr> - <tr> - <td id="L136" class="blob-num js-line-number" data-line-number="136"></td> - <td id="LC136" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * </span></td> - </tr> - <tr> - <td id="L137" class="blob-num js-line-number" data-line-number="137"></td> - <td id="LC137" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@return</span> external IP address as string, or null if not available</span></td> - </tr> - <tr> - <td id="L138" class="blob-num js-line-number" data-line-number="138"></td> - <td id="LC138" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L139" class="blob-num js-line-number" data-line-number="139"></td> - <td id="LC139" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-smi">String</span> <span class="pl-en">getExternalIP</span>(){</td> - </tr> - <tr> - <td id="L140" class="blob-num js-line-number" data-line-number="140"></td> - <td id="LC140" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span>(<span class="pl-k">!</span>isUPnPAvailable()) <span class="pl-k">return</span> <span class="pl-c1">null</span>;</td> - </tr> - <tr> - <td id="L141" class="blob-num js-line-number" data-line-number="141"></td> - <td id="LC141" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> defaultGW<span class="pl-k">.</span>getExternalIP();</td> - </tr> - <tr> - <td id="L142" class="blob-num js-line-number" data-line-number="142"></td> - <td id="LC142" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L143" class="blob-num js-line-number" data-line-number="143"></td> - <td id="LC143" class="blob-code blob-code-inner js-file-line"> </td> - </tr> - <tr> - <td id="L144" class="blob-num js-line-number" data-line-number="144"></td> - <td id="LC144" class="blob-code blob-code-inner js-file-line"> <span class="pl-c"><span class="pl-c">/**</span></span></td> - </tr> - <tr> - <td id="L145" class="blob-num js-line-number" data-line-number="145"></td> - <td id="LC145" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * Gets the internal IP address of this machine</span></td> - </tr> - <tr> - <td id="L146" class="blob-num js-line-number" data-line-number="146"></td> - <td id="LC146" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * </span></td> - </tr> - <tr> - <td id="L147" class="blob-num js-line-number" data-line-number="147"></td> - <td id="LC147" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> * <span class="pl-k">@return</span> internal IP address as string, or null if not available</span></td> - </tr> - <tr> - <td id="L148" class="blob-num js-line-number" data-line-number="148"></td> - <td id="LC148" class="blob-code blob-code-inner js-file-line"><span class="pl-c"> <span class="pl-c">*/</span></span></td> - </tr> - <tr> - <td id="L149" class="blob-num js-line-number" data-line-number="149"></td> - <td id="LC149" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-smi">String</span> <span class="pl-en">getLocalIP</span>(){</td> - </tr> - <tr> - <td id="L150" class="blob-num js-line-number" data-line-number="150"></td> - <td id="LC150" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">if</span>(<span class="pl-k">!</span>isUPnPAvailable()) <span class="pl-k">return</span> <span class="pl-c1">null</span>;</td> - </tr> - <tr> - <td id="L151" class="blob-num js-line-number" data-line-number="151"></td> - <td id="LC151" class="blob-code blob-code-inner js-file-line"> <span class="pl-k">return</span> defaultGW<span class="pl-k">.</span>getLocalIP();</td> - </tr> - <tr> - <td id="L152" class="blob-num js-line-number" data-line-number="152"></td> - <td id="LC152" class="blob-code blob-code-inner js-file-line"> }</td> - </tr> - <tr> - <td id="L153" class="blob-num js-line-number" data-line-number="153"></td> - <td id="LC153" class="blob-code blob-code-inner js-file-line"> -</td> - </tr> - <tr> - <td id="L154" class="blob-num js-line-number" data-line-number="154"></td> - <td id="LC154" class="blob-code blob-code-inner js-file-line">}</td> - </tr> -</table> - - <details class="details-reset details-overlay BlobToolbar position-absolute js-file-line-actions dropdown d-none" aria-hidden="true"> - <summary class="btn-octicon ml-0 px-2 p-0 bg-white border border-gray-dark rounded-1" aria-label="Inline file action toolbar"> - <svg class="octicon octicon-kebab-horizontal" viewBox="0 0 13 16" version="1.1" width="13" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm5 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM13 7.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/></svg> - </summary> - <details-menu> - <ul class="BlobToolbar-dropdown dropdown-menu dropdown-menu-se mt-2" style="width:185px"> - <li><clipboard-copy role="menuitem" class="dropdown-item" id="js-copy-lines" style="cursor:pointer;" data-original-text="Copy lines">Copy lines</clipboard-copy></li> - <li><clipboard-copy role="menuitem" class="dropdown-item" id="js-copy-permalink" style="cursor:pointer;" data-original-text="Copy permalink">Copy permalink</clipboard-copy></li> - <li><a class="dropdown-item js-update-url-with-hash" id="js-view-git-blame" role="menuitem" href="/adolfintel/WaifUPnP/blame/d6381a8c6f24c7d0f5879ba037abd018ba428561/src/com/dosse/upnp/UPnP.java">View git blame</a></li> - <li><a class="dropdown-item" id="js-new-issue" role="menuitem" href="/adolfintel/WaifUPnP/issues/new">Reference in new issue</a></li> - </ul> - </details-menu> - </details> - - </div> - - </div> - - - - <details class="details-reset details-overlay details-overlay-dark"> - <summary data-hotkey="l" aria-label="Jump to line"></summary> - <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast linejump" aria-label="Jump to line"> - <!-- '"` --><!-- </textarea></xmp> --></option></form><form class="js-jump-to-line-form Box-body d-flex" action="" accept-charset="UTF-8" method="get"><input name="utf8" type="hidden" value="&#x2713;" /> - <input class="form-control flex-auto mr-3 linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line&hellip;" aria-label="Jump to line" autofocus> - <button type="submit" class="btn" data-close-dialog>Go</button> -</form> </details-dialog> - </details> - - - - </div> - <div class="modal-backdrop js-touch-events"></div> -</div> - - </main> - </div> - - - </div> - - -<div class="footer container-lg width-full p-responsive" role="contentinfo"> - <div class="position-relative d-flex flex-row-reverse flex-lg-row flex-wrap flex-lg-nowrap flex-justify-center flex-lg-justify-between pt-6 pb-2 mt-6 f6 text-gray border-top border-gray-light "> - <ul class="list-style-none d-flex flex-wrap col-12 col-lg-5 flex-justify-center flex-lg-justify-between mb-2 mb-lg-0"> - <li class="mr-3 mr-lg-0">&copy; 2019 <span title="0.43275s from unicorn-7d95996c98-rtxhm">GitHub</span>, Inc.</li> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to terms, text:terms" href="https://github.com/site/terms">Terms</a></li> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to privacy, text:privacy" href="https://github.com/site/privacy">Privacy</a></li> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to security, text:security" href="https://github.com/security">Security</a></li> - <li class="mr-3 mr-lg-0"><a href="https://githubstatus.com/" data-ga-click="Footer, go to status, text:status">Status</a></li> - <li><a data-ga-click="Footer, go to help, text:help" href="https://help.github.com">Help</a></li> - </ul> - - <a aria-label="Homepage" title="GitHub" class="footer-octicon d-none d-lg-block mx-lg-4" href="https://github.com"> - <svg height="24" class="octicon octicon-mark-github" viewBox="0 0 16 16" version="1.1" width="24" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg> -</a> - <ul class="list-style-none d-flex flex-wrap col-12 col-lg-5 flex-justify-center flex-lg-justify-between mb-2 mb-lg-0"> - <li class="mr-3 mr-lg-0"><a data-ga-click="Footer, go to contact, text:contact" href="https://github.com/contact">Contact GitHub</a></li> - <li class="mr-3 mr-lg-0"><a href="https://github.com/pricing" data-ga-click="Footer, go to Pricing, text:Pricing">Pricing</a></li> - <li class="mr-3 mr-lg-0"><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li> - <li class="mr-3 mr-lg-0"><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li> - <li class="mr-3 mr-lg-0"><a href="https://github.blog" data-ga-click="Footer, go to blog, text:blog">Blog</a></li> - <li><a data-ga-click="Footer, go to about, text:about" href="https://github.com/about">About</a></li> - - </ul> - </div> - <div class="d-flex flex-justify-center pb-6"> - <span class="f6 text-gray-light"></span> - </div> -</div> - - - - <div id="ajax-error-message" class="ajax-error-message flash flash-error"> - <svg class="octicon octicon-alert" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"/></svg> - <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error"> - <svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg> - </button> - You can’t perform that action at this time. - </div> - - - <script crossorigin="anonymous" integrity="sha512-BlCvumXWTvpASEdhCGiahDUDf7Bwb8QXA2XnnSnqJ9QafxcNcrNYUNYS2wXmd3nEpO//+zlZa9DSV9zmu5MqRg==" type="application/javascript" src="https://github.githubassets.com/assets/compat-bootstrap-90c0ace0.js"></script> - <script crossorigin="anonymous" integrity="sha512-/PxjwfwA7IQQAc/3OBA+EvAAOgs24JUmL+yYRnEl/N7pMvQRi+hBftbGJweH00j3z9d1mUOQpmR0D33CE5Wt7g==" type="application/javascript" src="https://github.githubassets.com/assets/frameworks-f1ce1e70.js"></script> - - <script crossorigin="anonymous" async="async" integrity="sha512-41RCZRCF3ndqncgjVi28zesDHQIA/pjp+qtail1asqbRM8BUPv4Vih2Lvlgv0cHACwKlcJJYxJO4+9iNf+rtRQ==" type="application/javascript" src="https://github.githubassets.com/assets/github-bootstrap-98914a0f.js"></script> - - - - <div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner" hidden - > - <svg class="octicon octicon-alert" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"/></svg> - <span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span> - <span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span> - </div> - <template id="site-details-dialog"> - <details class="details-reset details-overlay details-overlay-dark lh-default text-gray-dark hx_rsm" open> - <summary role="button" aria-label="Close dialog"></summary> - <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast hx_rsm-dialog hx_rsm-modal"> - <button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog> - <svg class="octicon octicon-x" viewBox="0 0 12 16" version="1.1" width="12" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"/></svg> - </button> - <div class="octocat-spinner my-6 js-details-dialog-spinner"></div> - </details-dialog> - </details> -</template> - - <div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;" tabindex="0"> - <div class="Popover-message Popover-message--bottom-left Popover-message--large Box box-shadow-large" style="width:360px;"> - </div> -</div> - - <div aria-live="polite" class="js-global-screen-reader-notice sr-only"></div> - - </body> -</html> - +/* + * Copyright (C) 2015 Federico Dossena (adolfintel.com). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package com.dosse.upnp; + +/** + * This class contains static methods that allow quick access to UPnP Port Mapping.<br> + * Commands will be sent to the default gateway. + * + * @author Federico + */ +public class UPnP { + + private static Gateway defaultGW = null; + private static final GatewayFinder finder = new GatewayFinder() { + @Override + public void gatewayFound(Gateway g) { + synchronized (finder) { + if (defaultGW == null) { + defaultGW = g; + } + } + } + }; + + /** + * Waits for UPnP to be initialized (takes ~3 seconds).<br> + * It is not necessary to call this method manually before using UPnP functions + */ + public static void waitInit() { + while (finder.isSearching()) { + try { + Thread.sleep(1); + } catch (InterruptedException ex) { + } + } + } + + /** + * Is there an UPnP gateway?<br> + * This method is blocking if UPnP is still initializing<br> + * All UPnP commands will fail if UPnP is not available + * + * @return true if available, false if not + */ + public static boolean isUPnPAvailable(){ + waitInit(); + return defaultGW!=null; + } + + /** + * Opens a TCP port on the gateway + * + * @param port TCP port (0-65535) + * @return true if the operation was successful, false otherwise + */ + public static boolean openPortTCP(int port) { + if(!isUPnPAvailable()) return false; + return defaultGW.openPort(port, false); + } + + /** + * Opens a UDP port on the gateway + * + * @param port UDP port (0-65535) + * @return true if the operation was successful, false otherwise + */ + public static boolean openPortUDP(int port) { + if(!isUPnPAvailable()) return false; + return defaultGW.openPort(port, true); + } + + /** + * Closes a TCP port on the gateway<br> + * Most gateways seem to refuse to do this + * + * @param port TCP port (0-65535) + * @return true if the operation was successful, false otherwise + */ + public static boolean closePortTCP(int port) { + if(!isUPnPAvailable()) return false; + return defaultGW.closePort(port, false); + } + + /** + * Closes a UDP port on the gateway<br> + * Most gateways seem to refuse to do this + * + * @param port UDP port (0-65535) + * @return true if the operation was successful, false otherwise + */ + public static boolean closePortUDP(int port) { + if(!isUPnPAvailable()) return false; + return defaultGW.closePort(port, true); + } + + /** + * Checks if a TCP port is mapped<br> + * + * @param port TCP port (0-65535) + * @return true if the port is mapped, false otherwise + */ + public static boolean isMappedTCP(int port) { + if(!isUPnPAvailable()) return false; + return defaultGW.isMapped(port, false); + } + + /** + * Checks if a UDP port is mapped<br> + * + * @param port UDP port (0-65535) + * @return true if the port is mapped, false otherwise + */ + public static boolean isMappedUDP(int port) { + if(!isUPnPAvailable()) return false; + return defaultGW.isMapped(port, false); + } + + /** + * Gets the external IP address of the default gateway + * + * @return external IP address as string, or null if not available + */ + public static String getExternalIP(){ + if(!isUPnPAvailable()) return null; + return defaultGW.getExternalIP(); + } + + /** + * Gets the internal IP address of this machine + * + * @return internal IP address as string, or null if not available + */ + public static String getLocalIP(){ + if(!isUPnPAvailable()) return null; + return defaultGW.getLocalIP(); + } + +}