pcapdotnet in windows7 how to sniffer a port without specify a device or with the ip 0.0.0.0? - sockets

I have 2 software working together through the port 8888 in one computer, I want to know how they works. It's really nice if I can get another way, like software to do this job:)
I download the pcapdotnet and try the sample code on http://pcapdotnet.codeplex.com/wikipage?title=Pcap.Net%20User%20Guide&referringTitle=Home
It can got all messages on the local network but not for me.
I use netstat -a get this " TCP 0.0.0.0:8888 ZC01N00278:0 LISTENING"
I'm really confusing about this 0.0.0.0.
so I disable all my network device(this cause my pcap can't work, cause it need at least one device), but it still there. I suppose the 2 software communication each other without a Ethernet, is it true?
I am a newbie in socket, in which way I can get the packet in this port?
Here's the code, it mostly from the tutorial sample.
using System;
using System.Collections.Generic;
using PcapDotNet.Core;
using PcapDotNet.Packets;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.Transport;
using System.IO;
namespace pcap_test1
{
class Program
{
static StreamWriter sw;
static void Main(string[] args)
{
sw = new StreamWriter(#"C:\sunxin\pcap.txt");
// Retrieve the device list from the local machine
IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine;
if (allDevices.Count == 0)
{
Console.WriteLine("No interfaces found! Make sure WinPcap is installed.");
return;
}
// Print the list
for (int i = 0; i != allDevices.Count; ++i)
{
LivePacketDevice device = allDevices[i];
Console.Write((i + 1) + ". " + device.Name);
if (device.Description != null)
Console.WriteLine(" (" + device.Description + ")");
else
Console.WriteLine(" (No description available)");
}
int deviceIndex = 0;
do
{
Console.WriteLine("Enter the interface number (1-" + allDevices.Count + "):");
string deviceIndexString = Console.ReadLine();
if (!int.TryParse(deviceIndexString, out deviceIndex) ||
deviceIndex < 1 || deviceIndex > allDevices.Count)
{
deviceIndex = 0;
}
} while (deviceIndex == 0);
// Take the selected adapter
PacketDevice selectedDevice = allDevices[deviceIndex - 1];
// Open the device
using (PacketCommunicator communicator =
selectedDevice.Open(65536, // portion of the packet to capture
// 65536 guarantees that the whole packet will be captured on all the link layers
PacketDeviceOpenAttributes.Promiscuous, // promiscuous mode
1000)) // read timeout
{
// Check the link layer. We support only Ethernet for simplicity.
if (communicator.DataLink.Kind != DataLinkKind.Ethernet)
{
Console.WriteLine("This program works only on Ethernet networks.");
return;
}
// Compile the filter
using (BerkeleyPacketFilter filter = communicator.CreateFilter("port 8888"))
{
// Set the filter
communicator.SetFilter(filter);
}
Console.WriteLine("Listening on " + selectedDevice.Description + "...");
// start the capture
communicator.ReceivePackets(0, PacketHandler);
}
}
// Callback function invoked by libpcap for every incoming packet
private static void PacketHandler(Packet packet)
{
// print timestamp and length of the packet
Console.WriteLine(packet.Timestamp.ToString("yyyy-MM-dd hh:mm:ss.fff") + " length:" + packet.Ethernet);
sw.WriteLine(packet.Timestamp.ToString("yyyy-MM-dd hh:mm:ss.fff") + packet.Ethernet);
IpV4Datagram ip = packet.Ethernet.IpV4;
UdpDatagram udp = ip.Udp;
for (int i = ip.HeaderLength; i < packet.Length; ++i)
{
Console.Write(Convert.ToChar(packet.Buffer[i]));
sw.Write(Convert.ToChar(packet.Buffer[i]));
}
Console.WriteLine();
sw.WriteLine();
// print ip addresses and udp ports
//Console.WriteLine(ip.Source + ":" + udp.SourcePort + " -> " + ip.Destination + ":" + udp.DestinationPort);
//sw.WriteLine(ip.Source + ":" + udp.SourcePort + " -> " + ip.Destination + ":" + udp.DestinationPort);
sw.Flush();
}
}
}

Wireshark's wiki tells that WinPcap cannot capture packets between endpoints on the same computer in Windows (Pcap.Net uses WinPcap). It recommends to use RawCap.

Related

Plc4x library Modbus serial (RTU) get is not retrieving data

I am trying to write a sample program to retrieve temperature data from SHT20 temperature sensor using serial port with apache plc4x library.
private void plcRtuReader() {
String connectionString =
"modbus:serial://COM5?unit-identifier=1&baudRate=19200&stopBits=" + SerialPort.ONE_STOP_BIT + "&parityBits=" + SerialPort.NO_PARITY + "&dataBits=8";
try (PlcConnection plcConnection = new PlcDriverManager().getConnection(connectionString)) {
if (!plcConnection.getMetadata().canRead()) {
System.out.println("This connection doesn't support reading.");
return;
}
PlcReadRequest.Builder builder = plcConnection.readRequestBuilder();
builder.addItem("value-1", "holding-register:258[2]");
PlcReadRequest readRequest = builder.build();
PlcReadResponse response = readRequest.execute().get();
for (String fieldName : response.getFieldNames()) {
if (response.getResponseCode(fieldName) == PlcResponseCode.OK) {
int numValues = response.getNumberOfValues(fieldName);
// If it's just one element, output just one single line.
if (numValues == 1) {
System.out.println("Value[" + fieldName + "]: " + response.getObject(fieldName));
}
// If it's more than one element, output each in a single row.
else {
System.out.println("Value[" + fieldName + "]:");
for (int i = 0; i < numValues; i++) {
System.out.println(" - " + response.getObject(fieldName, i));
}
}
}
// Something went wrong, to output an error message instead.
else {
System.out.println(
"Error[" + fieldName + "]: " + response.getResponseCode(fieldName).name());
}
}
System.exit(0);
} catch (PlcConnectionException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
Connection is established with the device using serial communication. But it fails to get data and instead prints the below warning messages continously.
debugger hangs at below line:
PlcReadResponse response = readRequest.execute().get();
with below logs printing continuously.
2021-06-03-17:41:48.425 [nioEventLoopGroup-2-1] WARN io.netty.channel.nio.NioEventLoop - Selector.select() returned prematurely 512 times in a row; rebuilding Selector org.apache.plc4x.java.transport.serial.SerialPollingSelector#131f8986.
2021-06-03-17:41:55.080 [nioEventLoopGroup-2-1] WARN io.netty.channel.nio.NioEventLoop - Selector.select() returned prematurely 512 times in a row; rebuilding Selector org.apache.plc4x.java.transport.serial.SerialPollingSelector#48c328c5.
With same URL data (i.e baudrate,stopBits etc..) using modpoll.exe it works and returns the data over RTU. I am not sure what is missing here.
Kindly shed some light here.

ESP32 WebServer: How to get ip address of incoming clients

With the help of this tutorial i created a simple WebServer on my ESP32:
void setup() {
Serial.begin(115200);
// Connect to Wi-Fi network with SSID and password
WiFi.softAP(ssid, password);
IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP); //IP address of my ESP32
server.begin();
}
void loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects
Serial.println("New Client"); // print a message out in the serial port
//...
}
}
How to get the ip addess of this connecting client?^^ So thats maybe something there like
String ipaddress = /*...*/;
Function remoteIP returns the IP address as IPAddress object.
IPAddress ip = client.remoteIP();
IPAddress implements Printable so it can be used with println.
Serial.println(ip);
If you insist on getting the IP as String, the ESP32 core version of IPAddress has toString method.
String ipaddress = ip.toString();
There is no function to print the IPAddress object to characters array. You could use CStringBuilder class from my StreamLib to print the IPAddress to characters array. CStringBuilder allows to fill characters array with Arduino Stream class functions. The StreamLib library is in Library Manager.
If you don't want to use the StreamLib library here is a (maybe not ideal) function to format the IPAddress to characters array.
void ip2str(const IPAddress& ip, char* s) {
itoa(ip[0], s, 10);
size_t l = strlen(s);
s[l] = '.';
itoa(ip[1], s + l + 1, 10);
l = strlen(s);
s[l] = '.';
itoa(ip[2], s + l + 1, 10);
l = strlen(s);
s[l] = '.';
itoa(ip[3], s + l + 1, 10);
}

Interpreting keypresses sent to raspberry-pi through uv4l-webrtc datachannel

I apologize if this doesn't make sense since I'm still a newbie with using a raspberry pi and this is my first time posting on StackOverflow.
I am making a web app that lets me stream video to and from a raspberry pi while also letting me send keycodes. The sent keycodes would ultimately let me control servos on a drone. After scouring the internet, I figured that the simplest way to stream 2-way video is by using uv4l so I have it installed along with uv4l-webrtc on my raspberry pi. I hooked up some GPIO pins to a flight controller and I am using pigpio to send PWM signals to it, which I then monitor using CleanFlight.
Right now, I can manipulate with keypresses the roll, pitch, etc. of the flight controller using a python script if I access the pi remotely using VNC, but I would like to ultimately be able to do this through my custom web page that is being served by the uv4l-server. I am trying to use the WebRTC Data Channels, but I'm having some trouble understanding what I would need to do to recognize the messages sent through the data channels. I know that the data channels are opened when a video call is initiated and I've tried the test in this link to see if I can indeed send keycodes to the pi (and I can).
My problem right now is that I have no idea where those sent messages go or how I can get them so I can incorporate them into my python script. Would I need to make a server that would listen for the keycodes being sent to the pi?
tl;dr I have a python script on a raspberry pi to control servos on a flight controller using keypresses and a separate webpage that streams video using WebRTC, but I have no idea how to combine them together using WebRTC data channels.
Thanks to #adminkiam for the solution. Here's a version of the python script that now listens to the socket. It's essentially a variation of this code by the person who made pigpio:
import socket
import time
import pigpio
socket_path = '/tmp/uv4l.socket'
try:
os.unlink(socket_path)
except OSError:
if os.path.exists(socket_path):
raise
s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
ROLL_PIN = 13
PITCH_PIN = 14
YAW_PIN = 15
MIN_PW = 1000
MID_PW = 1500
MAX_PW = 2000
NONE = 0
LEFT_ARROW = 1
RIGHT_ARROW = 2
UP_ARROW = 3
DOWN_ARROW = 4
LESS_BTN = 5
GREATER_BTN = 6
print 'socket_path: %s' % socket_path
s.bind(socket_path)
s.listen(1)
def getch(keyCode):
key = NONE
if keyCode == 188:
key = LESS_BTN
elif keyCode == 190:
key = GREATER_BTN
elif keyCode == 37:
key = LEFT_ARROW
elif keyCode == 39:
key = RIGHT_ARROW
elif keyCode == 38:
key = UP_ARROW
elif keyCode == 40:
key = DOWN_ARROW
return key
def cleanup():
pi.set_servo_pulsewidth(ROLL_PIN, 0)
pi.set_servo_pulsewidth(PITCH_PIN, 0)
pi.set_servo_pulsewidth(YAW_PIN, 0)
pi.stop()
while True:
print 'awaiting connection...'
connection, client_address = s.accept()
print 'client_address %s' % client_address
try:
print 'established connection with', client_address
pi = pigpio.pi()
rollPulsewidth = MID_PW
pitchPulsewidth = MID_PW
yawPulsewidth = MID_PW
pi.set_servo_pulsewidth(ROLL_PIN, rollPulsewidth)
pi.set_servo_pulsewidth(PITCH_PIN, pitchPulsewidth)
pi.set_servo_pulsewidth(YAW_PIN, yawPulsewidth)
while True:
data = connection.recv(16)
print 'received message"%s"' % data
time.sleep(0.01)
key = getch(int(data))
rollPW = rollPulsewidth
pitchPW = pitchPulsewidth
yawPW = yawPulsewidth
if key == UP_ARROW:
pitchPW = pitchPW + 10
if pitchPW > MAX_PW:
pitchPW = MAX_PW
elif key == DOWN_ARROW:
pitchPW = pitchPW - 10
if pitchPW < MIN_PW:
pitchPW = MIN_PW
elif key == LEFT_ARROW:
rollPW = rollPW - 10
if rollPW < MIN_PW:
rollPW = MIN_PW
elif key == RIGHT_ARROW:
rollPW = rollPW + 10
if rollPW > MAX_PW:
rollPW = MAX_PW
elif key == GREATER_BTN:
yawPW = yawPW + 10
if yawPW > MAX_PW:
yawPW = MAX_PW
elif key == LESS_BTN:
yawPW = yawPW - 10
if yawPW < MIN_PW:
yawPW = MIN_PW
if rollPW != rollPulsewidth:
rollPulsewidth = rollPW
pi.set_servo_pulsewidth(ROLL_PIN, rollPulsewidth)
if pitchPW != pitchPulsewidth:
pitchPulsewidth = pitchPW
pi.set_servo_pulsewidth(PITCH_PIN, pitchPulsewidth)
if yawPW != yawPulsewidth:
yawPulsewidth = yawPW
pi.set_servo_pulsewidth(YAW_PIN, yawPulsewidth)
if data:
print 'echo data to client'
connection.sendall(data)
else:
print 'no more data from', client_address
break
finally:
# Clean up the connection
cleanup()
connection.close()
When a WebRTC data channel is created between UV4L and the other WebRTC peer (i.e. a browser, Janus Gateway, etc...), UV4L creates a full-duplex Unix Domain Socket (/tmp/uv4l.socket by default) from/to which you can receive/send messages on the Raspberry Pi. Your python script should just open, listen and read to the socket for the incoming messages from the e.g. web application and/or write the messages to the same socket for the web app to receive them. An example doing this in C++ is under the link to the tutorial you pointed out in your question:
/*
Copyright (c) 2016 info#linux-projects.org
All rights reserved.
Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are
duplicated in all such forms and that any documentation,
advertising materials, and other materials related to such
distribution and use acknowledge that the software was developed
by the linux-projects.org. The name of the
linux-projects.org may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
* This is a simple echo server.
* It creates to a unix domain socket of type SOCK_SEQPACKET specified by
* command line, listens to it waiting for incoming messages from clients
* (e.g. UV4L) and replies the received messages back to the senders.
*
* Example:
* $ ./datachannel_server /tmp/uv4l.socket
*
* To compile this program you need boost v1.60 or greater, for example:
* g++ -Wall -I/path/to/boost/include/ -std=c++11 datachannel_server.cpp -L/path/to/boost/lib -l:libboost_coroutine.a -l:libboost_context.a -l:libboost_system.a -l:libboost_thread.a -pthread -o datachannel_server
*/
#include <boost/asio/io_service.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio.hpp>
#include <memory>
#include <cstdio>
#include <array>
#include <functional>
#include <iostream>
#if !defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
#error Local sockets not available on this platform.
#endif
constexpr std::size_t MAX_PACKET_SIZE = 1024 * 16;
namespace seqpacket {
struct seqpacket_protocol {
int type() const {
return SOCK_SEQPACKET;
}
int protocol() const {
return 0;
}
int family() const {
return AF_UNIX;
}
using endpoint = boost::asio::local::basic_endpoint<seqpacket_protocol>;
using socket = boost::asio::generic::seq_packet_protocol::socket;
using acceptor = boost::asio::basic_socket_acceptor<seqpacket_protocol>;
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// The UNIX domain iostream type.
using iostream = boost::asio::basic_socket_iostream<seqpacket_protocol>;
#endif
};
}
using seqpacket::seqpacket_protocol;
struct session : public std::enable_shared_from_this<session> {
explicit session(seqpacket_protocol::socket socket) : socket_(std::move(socket)) {}
~session() {
//std::cerr << "session closed\n";
}
void echo(boost::asio::yield_context yield) {
auto self = shared_from_this();
try {
for (;;) {
seqpacket_protocol::socket::message_flags in_flags = MSG_WAITALL, out_flags = MSG_WAITALL;
// Wait for the message from the client
auto bytes_transferred = socket_.async_receive(boost::asio::buffer(data_), in_flags, yield);
// Write the same message back to the client
socket_.async_send(boost::asio::buffer(data_, bytes_transferred), out_flags, yield);
}
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
socket_.close();
}
}
void go() {
boost::asio::spawn(socket_.get_io_service(), std::bind(&session::echo, this, std::placeholders::_1));
}
private:
seqpacket_protocol::socket socket_;
std::array<char, MAX_PACKET_SIZE> data_;
};
int main(int argc, char* argv[]) {
try {
if (argc != 2) {
std::cerr << "Usage: datachannel_server <file> (e.g. /tmp/uv4l.socket)\n";
std::cerr << "*** WARNING: existing file is removed ***\n";
return EXIT_FAILURE;
}
boost::asio::io_service io_service;
std::remove(argv[1]);
boost::asio::spawn(io_service, [&](boost::asio::yield_context yield) {
seqpacket_protocol::acceptor acceptor_(io_service, seqpacket_protocol::endpoint(argv[1]));
for (;;) {
boost::system::error_code ec;
seqpacket_protocol::socket socket_(io_service);
acceptor_.async_accept(socket_, yield[ec]);
if (!ec)
std::make_shared<session>(std::move(socket_))->go();
}
});
io_service.run();
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << "\n";
return EXIT_FAILURE;
}
}

IdHTTP->ConnectTimeout works in Windows 7, does not work on XP

Using Embarcadero C++ Builder 2010, I'm trying to detect specific web server devices connected to a network.
I'm interrogating those devices by calling a CGI function using TIdHTTP and analyzing the answer on a range of IP address.
I am using IdHTTP->ConnectTimeout and IdHTTP->ReadTimeout parameters to throws an exception if there's no connection by the time the timeout elapses. This should happen when TIdHTTP is interrogating an unexpected devices, in this case I release IdHTTP by calling IdHTTP->Free().
It works fine on Windows 7, but on Windows XP the timeout doesn't apply, so it can take up to 10 minutes before IdHTTP.get() stop.
By removing those two parameters the app work a bit faster on Windows XP but still take to long compare to the timeout than I am expecting.
I found this related subject without real solutions: Indy 10 + SSL = works in Windows 7, does not work on XP
This is a part of the source code:
#include "winsock2.h"
String url = "http://" + anIpAddress + "/myCGIFunction.cgi";
TMemoryStream *XML = new TMemoryStream;
AnsiString answer="";
p_IdHTTP = new TIdHTTP(NULL);
try
{
p_IdHTTP->ConnectTimeout = 2000;
p_IdHTTP->Get(url,XML);
XML->Position = 0;
answer=ReadStringFromStream(XML);
p_IdHTTP->Free();
}
catch (...)
{
p_IdHTTP->Free();
}
My questions are:
Why does IdHTTP->ConnectTimeout isn't working on Windows XP?
And do you have any idea to replace this parameter to release/destroyed the IdHTTP after a specific time?
Update:
void __fastcall Func::MyFunc()
{
AnsiString anIpAddress= "20.20.20.11";
String url = "http://" + anIpAddress + "/myCGIFunction.cgi";
TMemoryStream *XML = new TMemoryStream;
AnsiString answer="";
p_IdHTTP = new TIdHTTP(NULL);
try
{
p_SSLHandler=new TIdSSLIOHandlerSocketOpenSSL(p_IdHTTP);
p_SSLHandler->SSLOptions->Method= sslvSSLv23;
p_IdHTTP->ConnectTimeout = 2000;
p_IdHTTP->ReadTimeout=400;
p_IdHTTP->IOHandler=p_SSLHandler;
p_IdHTTP->OnConnected= IdHTTPConnected;
p_IdHTTP->OnStatus= IdHTTPStatus;
p_IdHTTP->Get(url,XML);
XML->Position = 0;
answer=ReadStringFromStream(XML);
p_IdHTTP->Free();
}
catch (...)
{
p_IdHTTP->Free();
}
}
void __fastcall Func::IdHTTPStatus(TObject *Sender, TIdStatus const AStatus, String const AStatusText){
String msgtest = ipAddress ;
switch (AStatus){
case (hsResolving):
msgtest+= " resolving...";
break;
case (hsConnecting):
msgtest+= " connecting...";
break;
case (hsConnected):
msgtest+= " connected...";
break;
case (hsDisconnecting):
msgtest+= " disconnecting...";
break;
case (hsDisconnected):
msgtest+= " disconnected...";
break;
case (hsStatusText):
msgtest+= " hsStatusText: " + AStatusText;
break;
default:
msgtest+= " Other status ";
break;
}
aListBox->Items->Add(msgtest);
Application->ProcessMessages();
}
void __fastcall Func::IdHTTPConnected(TObject *Sender){
struct timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;
setsockopt((unsigned int) p_IdHTTP->Socket->Binding, SOL_SOCKET,
SO_RCVTIMEO, (char *)&timeout, sizeof(timeout) );
setsockopt ((unsigned int) p_IdHTTP->Socket->Binding, SOL_SOCKET, SO_SNDTIMEO,
(char *)&timeout, sizeof(timeout));
}

How to send Protocol Buffer object using Winsock2?

I am creating a client server app using a simple socket to transfer Protocol Buffer objects between C++ and Java. I have it created on the Java side both as the client and receiver. I even got the Java to send to C++ but I am having trouble with sending from C++ to Java. Not sure how to write it. First I am sending the size and then reading the proto object.
I am using Visual Studio C++ 2008. DataGram and Bookmartlet are my proto objects.
Here is my C++ Sender Client
int loopt = 99;
do {
DataGram dataGram;
dataGram.set_state("ACK");
time ( &rawtime );
dataGram.set_status(ctime(&rawtime));
Bookmarklet* bookmarklet = dataGram.mutable_bookmarklet();
bookmarklet->set_name("TEST");
bookmarklet->set_utl("TEST");
dataGram.SerializeToArray(recvbuf,recvbuflen);
dataGram.ByteSize();
//Trouble SPOT
send(ConnectSocket,size,1,0);
send(ConnectSocket,recvbuf,recvbuflen,0);
} while (loopt > 0);
This is what I am trying to replicate from Java.
OutputStream output = socket.getOutputStream();
try {
int testtimes = 99;
while (socket.isConnected() && testtimes > 0) {
Thread.sleep(1000); // do nothing for 1000 miliseconds (1
// second)
DataGram dataGram = null;
Bookmarklet bookmarklet = Bookmarklet.newBuilder()
.setName("TEST").setUtl("TEST").build();
if (testtimes % 2 == 0) {
dataGram = DataGram.newBuilder().setState("ACK")
.setBookmarklet(bookmarklet)
.setStatus(new Date().toGMTString()).build();
} else {
dataGram = DataGram.newBuilder().setState("ACK")
.setStatus(new Date().toGMTString()).build();
}
output.write(dataGram.getSerializedSize());
output.write(dataGram.toByteArray());
testtimes--;
}
} catch (Exception e) {
e.printStackTrace();
}
Any help would be great. Thanks.
Client in Java for Reference:
InputStream input = socket.getInputStream();
int count = input.read();
int counter = 0;
while (count > 0) {
byte[] buffer = new byte[count];
count = input.read(buffer);
DataGram dataGram = DataGram.parseFrom(buffer);
Bookmarklet bookmarklet = null;
if ((bookmarklet = dataGram.getBookmarklet()) != null) {
System.out.println(bookmarklet.toString());
}
System.out.println(dataGram.getState() + " "
+ dataGram.getStatus());
count = input.read();
System.out.println(++counter);
}