Skip to content
This repository was archived by the owner on Jul 3, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ ebin
deps
.DS_Store
erl_crash.dump
.rebar/
59 changes: 37 additions & 22 deletions src/nat_upnp_proto.erl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ discover1(Sock, MSearch, Timeout, Tries) ->
ok = gen_udp:send(Sock, "239.255.255.250", 1900, MSearch),
receive
{udp, _Sock, Ip, _Port, Packet} ->
case get_location(Packet) of
case get_location(http_bin, Packet) of
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hrm why do you start by reading the full response? Sounds like it will break other parsing but I may be mistaken

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably add some tests for each device type I think.

Main reason for this is that just doing httph_bin as before doesn't work. I did wonder if your devices have a different setup and so my change breaks yours, but I figured at least a simple patch to get started.

The "router" is a typically crappy TGv588 (Thomson) router, this firmware is sadly very common across Europe.

%% binary is Packet from #L59 above
{ok, Context} = nat_upnp:discover().
<<72,84,84,80,47,49,46,49,32,50,48,48,32,79,75,13,10,67,65,67,72,69,45,67,79,78,84,82,79,76,58,109,97,120,45,97,103,101,61,49,56,48,48,13,10,69,88,84,58,13,10,76,79,67,65,84,73,79,78,58,104,116,116,112,58,47,47,49,48,46,48,46,48,46,49,51,56,58,56,48,48,48,47,119,110,53,57,109,116,100,100,120,104,105,47,73,71,68,47,117,112,110,112,47,73,71,68,46,120,109,108,13,10,83,69,82,86,69,82,58,77,101,100,105,97,65,99,99,101,115,115,32,84,71,32,53,56,56,118,32,49,48,46,53,46,52,46,87,32,85,80,110,80,47,49,46,48,32,40,57,67,45,57,55,45,50,54,45,56,67,45,70,50,45,51,52,41,13,10,83,84,58,117,114,110,58,115,99,104,101,109,97,115,45,117,112,110,112,45,111,114,103,58,100,101,118,105,99,101,58,73,110,116,101,114,110,101,116,71,97,116,101,119,97,121,68,101,118,105,99,101,58,49,13,10,85,83,78,58,117,117,105,100,58,50,53,49,51,51,98,98,50,45,55,57,52,101,45,53,49,50,102,45,57,101,49,98,45,49,102,52,55,49,49,100,49,57,48,98,55,58,58,117,114,110,58,115,99,104,101,109,97,115,45,117,112,110,112,45,111,114,103,58,100,101,118,105,99,101,58,73,110,116,101,114,110,101,116,71,97,116,101,119,97,121,68,101,118,105,99,101,58,49,13,10,13,10>>

{ok,{nat_upnp,"http://10.0.0.138:8000/wn59mtddxhi/IGD/upnp/control/igd/wanpppc_1_4_1",
              "10.0.0.1"}}

error ->
discover1(Sock, MSearch, Timeout, Tries-1);
Location ->
Expand Down Expand Up @@ -177,14 +177,18 @@ get_myip(Ip) ->
[{_, {MyIp, _}}|_] = nat_upnp_util:route(Ip),
inet_parse:ntoa(MyIp).

get_location(Raw) ->
case erlang:decode_packet(httph_bin, Raw, []) of
get_location(Type, Raw) ->
case erlang:decode_packet(Type, Raw, []) of
{ok, {http_response, _, _Code, _Resp}, Rest} ->
get_location(httph_bin, Rest);
{ok, {http_error, _}, Rest} ->
get_location(Rest);
get_location(httph_bin, Rest);
{ok, {http_header, _, 'Location', _, Location}, _Rest} ->
Location;
% {ok, {http_header, _, 'LOCATION', _, Location}, _Rest} ->
% Location;
{ok, {http_header, _, _H, _, _V}, Rest} ->
get_location(Rest);
get_location(httph_bin, Rest);
_ ->
error
end.
Expand All @@ -211,7 +215,7 @@ get_wan_device(D, RootUrl) ->
{ok, D1} ->
get_connection_device(D1, RootUrl);
_ ->
{erro, no_wan_device}
{error, no_wan_device}
end.

get_connection_device(D, RootUrl) ->
Expand All @@ -225,26 +229,37 @@ get_connection_device(D, RootUrl) ->


get_connection_url(D, RootUrl) ->
case get_service(D, "urn:schemas-upnp-org:service:WANIPConnection:1") of
case get_service_url(D, "urn:schemas-upnp-org:service:WANIPConnection:1", RootUrl) of
Resp = {ok, _} -> Resp;
{error, no_service_url} ->
case get_service_url(D, "urn:schemas-upnp-org:service:WANPPPConnection:1", RootUrl) of
Resp = {ok, _} -> Resp;
Resp = {error, _} -> Resp
end;
Resp = {error, _} -> Resp
end.

get_service_url(D, Urn, RootUrl) ->
case get_service(D, Urn) of
{ok, S} ->
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there may well be a better approach than nested case here - any better suggestion?

Url = extract_txt(xmerl_xpath:string("controlURL/text()",
S)),
case split(RootUrl, "://") of
[Scheme, Rest] ->
case split(Rest, "/") of
[NetLoc| _] ->
CtlUrl = Scheme ++ "://" ++ NetLoc ++ Url,
{ok, CtlUrl};
_Else ->
{error, invalid_control_url}
end;
_Else ->
Url = extract_txt(xmerl_xpath:string("controlURL/text()", S)),
get_control_url(Url, RootUrl);
_ ->
{error, no_service_url}
end.

get_control_url(Url, RootUrl) ->
case split(RootUrl, "://") of
[Scheme, Rest] ->
case split(Rest, "/") of
[NetLoc| _] ->
CtlUrl = Scheme ++ "://" ++ NetLoc ++ Url,
{ok, CtlUrl};
_Else ->
{error, invalid_control_url}

end;
_ ->
{error, no_wanipconnection}
_Else ->
{error, invalid_control_url}
end.


Expand Down