Get client ip on server side with lua - tcp

I want to know the client ip that connects to my lua server to find out if the connection comes from internet or intranet.
srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
print(conn)
conn:on("receive",function(conn,payload)
ip = conn:getpeername()
print(ip)
conn:send("<h1> TEST.</h1>")
end)
conn:on("sent",function(conn) conn:close() end)
end)
I get the error:
PANIC: unprotected error in call to Lua API (stdin:2: attempt to call method 'getpeername' (a nil value))
Note: Im using this on the esp8266 chip and I have no experience with lua!
How can I find the IP of the client who connects?

With the new patch: ip,port = conn:getpeer() works.

Related

Reading value from Real BACnet Device on using BAC0

I was trying to use BAC0 package in python 3 to get value from BACnet device available in BACnet network.
import BAC0
bacnet = BAC0.lite(ip='192.168.5.10/24' ,port=47809)
value = bacnet.read("192.168.5.13:47808 analogInput 1 presentValue")
Where 192.168.5.10 is my local PC Host address and 192.168.5.13 is the ip address of BACnet Device
Getting error :
BAC0.core.io.IOExceptions.NoResponseFromController: APDU Abort Reason : Timeout
First off - for the benefit of others, you're missing a new-line after the 'import BAC0' statement.
I've just tested with a slight variant (- not that I'm a Python developer), but it seemed to work; I've masked the exact IP addresses that I tested with):
import BAC0
BAC0.log_level('info')
bacnet = BAC0.lite(ip = '192.168.n.h/24', port = 47809)
value = bacnet.read("195.n.n.h:47808 analogInput 1 presentValue")
print(value)
Are you sure you've got the correct (IP address and) port #?
Has the default gateway been set upon the 'server'/serving/target device (- at least in the case whereby the BACnet client & server are sitting within different subnets)?
Are you sure that this target/'server' device does not also have a DNET & DADR pair of values associated with it - i.e. also require them to be specified?
Is there a F/W blocking communication?
Is the device currently (marked as) 'out-of-service' (or encountering an issue)?
Has it got a valid BACnet license and/or BACnet configuration applied?
You might need to diagnose further with Wireshark, to see what response octets/bytes are been sent back (if any - and maybe even what 'service' request octets/bytes are been sent); or maybe even 'VTS' (Visual Test Shell) instead/too.

Port specification on an asio tcp client application

I'm rewriting a python twisted server in C++ using asio. I have set up the following examples from
http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/tutorial.html:
Daytime.1 - A synchronous TCP daytime client
Daytime.3 - An asynchronous TCP daytime server
and they seem to be functioning correctly. However, what is puzzling me is that when I created the twisted server both it and the client side required explicit specification of the IP addresses and port numbers. I am having a slightly different experience here:
On the client application no specification of the port number is required. I can successfully connect to the server by using only 127.0.0.1 as a command line argument.
Also, I appear to be able to connect to the same server with any legal variant of this IP address, as long as the first byte is 127 (eg 127.1.2.3 connects).
There's a literal in the client code specifying to connect using what I assume is an OS provided "daytime" TCP service. However, there is no reference to this in the server code. Why do I have to specify a particular service to connect to? I also suspect that this service could be related to the behaviour in points 1 and 2.
Now I know that the server has an acceptor socket listening that only establishes the connection once it receives a request but I would like some more details here.
Daytime is well known service in *nix world. You can get the list of known service by looking at /etc/services file and you can see below records in it:
daytime 13/udp # Daytime (RFC 867)
daytime 13/tcp # Daytime (RFC 867)
When service_name is provided with the host name, the tcp endpoint uses below version of getaddrinfo:
int error = ::getaddrinfo(host, service, &hints, result);
Looking at the man page [Emphasis mine]:
int
getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
The hostname and servname arguments are either pointers to NUL-terminated strings or the null pointer. An acceptable
value for hostname is either a valid host name or a numeric host address string consisting of a dotted decimal IPv4
address or an IPv6 address. The servname is either a decimal port number or a *service name listed in services(5)*. At
least one of hostname and servname must be non-null.
So, in short, provided the correct service name, it knows the correct port number to use. 13 in case of "daytime" service.

Creating an HTTP server in NodeMCU through an access point created by the board

I am coding a robot, using NodeMCU (ESP8266) and want it to be remote controlled. My current solution is connecting to a nearby router, to the internet and creating a TCP HTTP server. Data is streamed from the mobile device (remote) to the NodeMCU (robot) via HTTP requests. The remote is loaded onto the mobile device through a browser with HTML/CSS/JavaScript.
What I want instead is for the NodeMCU to create its own hotspot, because:
A router is not required
The connection is more direct
I want the same TCP HTTP solution, but I don't know how to serve a webpage through a custom hotspot.
This is my code:
-- Connect to router
wifi.sta.config("ssid","password")
wifi.sta.connect()
-- Code for waiting for connection
-- Create server
srv = net.createServer(net.TCP)
srv:listen(80,function(conn)
conn:on("receive",function(conn,payload)
for line in string.gmatch(payload,'[^\r\n]+') do
s = string.find(line, "GET /&")
-- If query is there, control robot
if s ~= nil then
-- Do stuff with query
break;
-- If no query, serve webpage
else
file.open("index.html", "r")
while true do
s = file.read(1460)
if s == nil then
break
end
conn:send(s)
end
file.close()
end
break
end
conn:on("sent", function(conn) conn:close() end)
end)
end)
Creating custom hotspot:
wifi.setmode(wifi.STATIONAP)
cfg={}
cfg.ssid="custom_ssid"
cfg.pwd="custom_password"
wifi.ap.config(cfg)
So how do I make it so the mobile can access the server? How do I get/set the IP of the server? Basically, I just need it to work. Thanks!
Not sure I fully understand but I believe you're really close. Check the documentation for the AP functions at http://nodemcu.readthedocs.io/en/latest/en/modules/wifi/#wifiap-module.
wifi.ap.config(cfg) sets SSID and pwd as you noted. Your client then connects to this AP by joining the network.
If you then print wifi.ap.getip() you'll see that the device has the IP address 192.168.1.4 by default. Hence, for clients which joined this network your server is reachable at 192.168.1.4:80 unless you set a custom IP explicitly.
However, the sending of data seems broken. You have multiple conn:send(s) (in the loop) yet you also have conn:on("sent", function(conn) conn:close() end) which means that the connection will be closed after the first conn:send! Check the docs at http://nodemcu.readthedocs.io/en/latest/en/modules/net/#netsocketsend for an example as for how to do that properly.

Asynchronous UDP server using Java NIO - How to identify the client?

I'm trying to write an Asynchronous UDP server using Java NIO ,
My problem is to find an identifier per client like IP address or somthing like that .
according to this article :http://thushw.blogspot.com/2011/06/asynchronous-udp-server-using-java-nio.html
In UDP there is only one socket for communicate with all clients , I want to hold an Hushtable that will save the data per client in buuffers . somthing like ( IP , ClientBuffer ) .
for every receive of data that a spcific client is sending i want to add it to his buffer .
I notice thet in datagramPacket i can recive the IP ,by the method datagramPacket.getSocketAddress() but i did'nt find the way to get the datagramPacket from the chanel ,we are only get the data , not the whole package with the addresse.
Thanks in advance!!!!
Rivka :)
You can only use the DatagramChannel.read() method if it is connected to the client, so you must already know the remote address:port. Otherwise you have to call receive(), when you get the remote ip:port in the DatagramPacket. So either way you have it.

HTTP Error: 400 when sending msmq message over http

I am developing a solution which will utilize msmq to transmit data between two machines. Due to the seperation of said machines, we need to use HTTP transport for the messages.
In my test environment I am using a Windows 7 x64 development machine, which is attempting to send messages using a homebrew app to any of several test machines I have control over.
All machines are either windows server 2003 or server 2008 with msmq and msmq http support installed.
For any test destination, I can use the following queue path name with success:
FORMATNAME:DIRECT=TCP:[machine_name_or_ip]\private$\test_queue
But for any test destination, the following always fails
FORMATNAME:DIRECT=$/test_queue
I have used all permutations of machine names/ips available. I have created mappings using the method described at this blog post. All result in the same HTTP Error: 400.
The following is the code used to send messages:
MessageQueue mq = new MessageQueue(queuepath);
System.Messaging.Message msg = new System.Messaging.Message
{
Priority = MessagePriority.Normal,
Formatter = new XmlMessageFormatter(),
Label = "test"
};
msg.Body = txtMessageBody.Text;
msg.UseDeadLetterQueue = true;
msg.UseJournalQueue = true;
msg.AcknowledgeType = AcknowledgeTypes.FullReachQueue | AcknowledgeTypes.FullReceive;
msg.AdministrationQueue = new MessageQueue(#".\private$\Ack");
if (SendTransactional)
mq.Send(msg, MessageQueueTransactionType.Single);
else
mq.Send(msg);
Additional Information: in the IIS logs on the destination machines I can see each message I send being recorded as a POST with a status code of 200.
I am open to any suggestions.
The problem can be caused by the IP address of the destination server having been NAT'ed through a Firewall.
In this case the IIS server receives the message okay and passes it on to MSMQ. MSMQ then reads the message and sees the destination of the message as being something different than the known IP addresses of the server. At this point MSMQ rejects the message and IIS returns a HTTP status 400.
Fortunately the solution is fairly straightforward. Look in %windir%\System32\msmq\mapping. This folder can contain a bunch of xml files (often sample files are provided) that each contain mappings between one address and another. The name of the file can be anything you like, here is an example of the xml formatted contents:
<redirections xmlns="msmq-queue-redirections.xml">
<redirection>
<from>http://external_host/msmq/external_queue</from>
<to>http://internal_host/msmq/internal_queue</to>
</redirection>
</redirections>
The MSMQ service then needs restarting to pickup the new configuration, for instance from the command line:
net stop msmq
net start msmq
References:
http://blogs.msdn.com/b/johnbreakwell/archive/2008/01/29/unable-to-send-msmq-3-0-http-messages.aspx
http://msdn.microsoft.com/en-us/library/ms701477(v=vs.85).aspx
Maybe you have to encode the $ as %24.

Resources