I'm creating a function to calculate packet capture delay using Python and pcap, but this error happens. I'm taking this function from a C example as I'm new to Python. This is the error:
Traceback (most recent call last):
File "prototype_sniffer_v1.py", line 266, in processing_pkts
Bps = ((pkt + 8) * 8 * 1000000) / (delay) TypeError: unsupported operand type(s) for +: 'LP_c_ubyte' and 'int'
Exception ignored on calling ctypes callback function: <function processing_pkts at 0x7fbed299df70>
This link Gathering Statistics on the network traffic contain the C code example.
This is C example:
#include <stdlib.h>
#include <stdio.h>
#include <pcap.h>
#include <tchar.h>
BOOL LoadNpcapDlls()
{
_TCHAR npcap_dir[512];
UINT len;
len = GetSystemDirectory(npcap_dir, 480);
if (!len) {
fprintf(stderr, "Error in GetSystemDirectory: %x", GetLastError());
return FALSE;
}
_tcscat_s(npcap_dir, 512, _T("\\Npcap"));
if (SetDllDirectory(npcap_dir) == 0) {
fprintf(stderr, "Error in SetDllDirectory: %x", GetLastError());
return FALSE;
}
return TRUE;
}
void usage();
void dispatcher_handler(u_char *, const struct pcap_pkthdr *, const u_char *);
void main(int argc, char **argv)
{
pcap_t *fp;
char errbuf[PCAP_ERRBUF_SIZE];
struct timeval st_ts;
u_int netmask;
struct bpf_program fcode;
/* Load Npcap and its functions. */
if (!LoadNpcapDlls())
{
fprintf(stderr, "Couldn't load Npcap\n");
exit(1);
}
/* Check the validity of the command line */
if (argc != 2)
{
usage();
return;
}
/* Open the output adapter */
if ( (fp= pcap_open(argv[1], 100, PCAP_OPENFLAG_PROMISCUOUS,
1000, NULL, errbuf) ) == NULL)
{
fprintf(stderr,"\nUnable to open adapter %s.\n", errbuf);
return;
}
/* Don't care about netmask, it won't be used for this filter */
netmask=0xffffff;
//compile the filter
if (pcap_compile(fp, &fcode, "tcp", 1, netmask) <0 )
{
fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
/* Free the device list */
return;
}
//set the filter
if (pcap_setfilter(fp, &fcode)<0)
{
fprintf(stderr,"\nError setting the filter.\n");
pcap_close(fp);
/* Free the device list */
return;
}
/* Put the interface in statstics mode */
if (pcap_setmode(fp, MODE_STAT)<0)
{
fprintf(stderr,"\nError setting the mode.\n");
pcap_close(fp);
/* Free the device list */
return;
}
printf("TCP traffic summary:\n");
/* Start the main loop */
pcap_loop(fp, 0, dispatcher_handler, (PUCHAR)&st_ts);
pcap_close(fp);
return;
}
void dispatcher_handler(u_char *state,
const struct pcap_pkthdr *header,
const u_char *pkt_data)
{
struct timeval *old_ts = (struct timeval *)state;
u_int delay;
LARGE_INTEGER Bps,Pps;
struct tm ltime;
char timestr[16];
time_t local_tv_sec;
/* Calculate the delay in microseconds from the last sample. This value
* is obtained from the timestamp that the associated with the sample. */
delay = (header->ts.tv_sec - old_ts->tv_sec) * 1000000
- old_ts->tv_usec + header->ts.tv_usec;
/* Get the number of Bits per second */
Bps.QuadPart=(((*(LONGLONG*)(pkt_data + 8)) * 8 * 1000000) / (delay));
/* ^ ^
| |
| |
| |
converts bytes in bits -- |
|
delay is expressed in microseconds --
*/
/* Get the number of Packets per second */
Pps.QuadPart=(((*(LONGLONG*)(pkt_data)) * 1000000) / (delay));
/* Convert the timestamp to readable format */
local_tv_sec = header->ts.tv_sec;
localtime_s(<ime, &local_tv_sec);
strftime( timestr, sizeof timestr, "%H:%M:%S", <ime);
/* Print timestamp*/
printf("%s ", timestr);
/* Print the samples */
printf("BPS=%I64u ", Bps.QuadPart);
printf("PPS=%I64u\n", Pps.QuadPart);
//store current timestamp
old_ts->tv_sec=header->ts.tv_sec;
old_ts->tv_usec=header->ts.tv_usec;
}
void usage()
{
printf("\nShows the TCP traffic load, in bits per second and packets per second."
"\nCopyright (C) 2002 Loris Degioanni.\n");
printf("\nUsage:\n");
printf("\t tcptop adapter\n");
printf("\t You can use \"WinDump -D\" if you don't know the name of your adapters.\n");
exit(0);
}
This is my Python function:
import libpcap as pcap
import ctypes as ct
import socket
import getopt
import os
import time
import funcoes_auxiliares
from struct import *
from libpcap._platform import sockaddr, sockaddr_in, sockaddr_in6
from pcaptestutils import *
pd = ct.POINTER(pcap.pcap_t)()
if not is_windows:
breaksigint = False
#static void sigint_handler(int signum _U_)
def sigint_handler(signum):
global pd
global breaksigint
if breaksigint:
pcap.breakloop(pd)
def main(argv=sys.argv[1:]):
global program_name
program_name = os.path.basename(sys.argv[0])
global pd
global breaksigint
global ip_afinet
global ip_afinet6
# Exceção para os parâmetros
try:
opts, args = getopt.getopt(argv, "i:mnt:" if is_windows else "bi:mnrst:")
except getopt.GetoptError:
usage()
device = None
timeout = 1000
nonblock = 0
immediate = False
if not is_windows:
sigrestart = False
catchsigint = False
for opt, optarg in opts:
if not is_windows and opt == '-b':
breaksigint = True
elif opt == '-i':
device = optarg.encode("utf-8")
elif opt == '-m':
immediate = True
elif opt == '-n':
nonblock = 1
elif not is_windows and opt == '-r':
sigrestart = True
elif not is_windows and opt == '-s':
catchsigint = True
elif opt == '-t':
try:
timeout = int(optarg)
except:
error('Timeout value "{}" is not a number', optarg)
if timeout < 0:
error("Timeout value {:d} is negative", timeout)
if timeout > INT_MAX:
error("Timeout value {:d} is too large (> {:d})",
timeout, INT_MAX)
else:
usage()
expression = args
errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE)
# ----------------------------------------------------------
# Lista de dispositivos disponíveis
if device is None:
deviceList = ct.POINTER(pcap.pcap_if_t)()
if pcap.findalldevs(ct.byref(deviceList), errbuf) == -1:
error("{}", ebuf2str(errbuf))
if not deviceList:
error("Não há interfaces disponíveis para captura")
print('\nAvailable network devices:')
devices = deviceList
while devices:
device = devices.contents
print("\t[*] {}".format(device.name.decode("utf-8")))
devices = device.next
device = deviceList[0].name
ip_tuple = funcoes_auxiliares.getStdIp(deviceList[0])
(ip_afinet, ip_afinet6) = ip_tuple
# print(ip_afinet)
# print(ip_afinet6)
pcap.freealldevs(deviceList)
# ----------------------------------------------------------
errbuf[0] = b"\0"
# if not is_windows:
# # If we were told to catch SIGINT, do so.
# if catchsigint:
# action = sigaction()
# action.sa_handler = sigint_handler
# sigemptyset(ct.byref(action.sa_mask))
# # Should SIGINT interrupt, or restart, system calls?
# action.sa_flags = SA_RESTART if sigrestart else 0
# if sigaction(SIGINT, ct.byref(action), NULL) == -1:
# error("Can't catch SIGINT: {}", strerror(errno))
pd = pcap.create(device, errbuf)
if not pd:
error("{}", ebuf2str(errbuf))
# define o comprimento do instantâneo a ser usado
# em um identificador de captura quando o
# identificador é ativado para snaplen.
status = pcap.set_snaplen(pd, 65535)
if status != 0:
error("{}: pcap.set_snaplen failed: {}",
device2str(device), status2str(status));
if immediate:
try:
status = pcap.set_immediate_mode(pd, 1)
except AttributeError:
error("pcap.set_immediate_mode is not available on this platform")
if status != 0:
error("{}: pcap.set_immediate_mode failed: {}",
device2str(device), status2str(status))
status = pcap.set_timeout(pd, timeout)
if status != 0:
error("{}: pcap.set_timeout failed: {}",
device2str(device), status2str(status))
status = pcap.activate(pd)
if status < 0:
# pcap.activate() failed.
error("{}: {}\n({})",
device2str(device), status2str(status), geterr2str(pd))
elif status > 0:
# pcap.activate() succeeded, but it's warning us
# of a problem it had.
warning("{}: {}\n({})",
device2str(device), status2str(status), geterr2str(pd))
localnet = pcap.bpf_u_int32()
netmask = pcap.bpf_u_int32()
if pcap.lookupnet(device, ct.byref(localnet), ct.byref(netmask), errbuf) < 0:
localnet = pcap.bpf_u_int32(0)
netmask = pcap.bpf_u_int32(0)
warning("{}", ebuf2str(errbuf))
fcode = pcap.bpf_program()
cmdbuf = " ".join(expression).encode("utf-8")
if pcap.compile(pd, ct.byref(fcode), cmdbuf, 1, netmask) < 0:
error("{}", geterr2str(pd))
if pcap.setfilter(pd, ct.byref(fcode)) < 0:
error("{}", geterr2str(pd))
if pcap.setnonblock(pd, nonblock, errbuf) == -1:
error("pcap.setnonblock failed: {}", ebuf2str(errbuf))
# -----------------------------------------
# create a save file for write
savefile = 'testsavefile'
savefile = savefile.encode('utf-8')
pdd = pcap.dump_open_append(pd, savefile)
if not pdd:
error("{}", geterr2str(pd))
# -----------------------------------------
print("\nSniffing on device: \n\t*{}*".format(device2str(device)))
if os.path.exists("qtdPktpTime.txt"):
os.remove("qtdPktpTime.txt")
cont_i = 0
while cont_i <= 10:
# while True:
packet_count = ct.c_int(0)
status = pcap.dispatch(pd, -1, processing_pkts,
ct.cast(ct.pointer(packet_count), ct.POINTER(ct.c_ubyte)))
# execute for write in save file
pcap.dispatch(pd, -1, pcap.dump,
ct.cast(pdd, ct.POINTER(ct.c_ubyte)))
if status < 0:
break
if status != 0:
print("\n{:d} packets seen, {:d} packets counted after "
"pcap.dispatch returns".format(status, packet_count.value))
ps = pcap.stat()
pcap.stats(pd, ct.byref(ps))
print("{:d} ps_recv, {:d} ps_drop, {:d} ps_ifdrop".format(
ps.ps_recv, ps.ps_drop, ps.ps_ifdrop))
print("\n")
cont_i += 1
if status == pcap.PCAP_ERROR_BREAK:
# We got interrupted, so perhaps we didn't manage to finish a
# line we were printing. Print an extra newline, just in case.
print()
print("Broken out of loop from SIGINT handler")
sys.stdout.flush()
if status == pcap.PCAP_ERROR:
# Error. Report it.
print("{}: pcap.dispatch: {}".format(program_name, geterr2str(pd)),
file=sys.stderr)
pcap.freecode(ct.byref(fcode))
pcap.close(pd)
funcoes_auxiliares.plotGraf1()
return 1 if status == -1 else 0
# --------------------------------------------------------------------------------------
# AUXILIAR FUNCTIONS
# --------------------------------------------------------------------------------------
# Convert a string of 6 characters of ethernet address into a dash separated hex string
def eth_addr (a) :
b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (ord(a[0]) , ord(a[1]) , ord(a[2]), ord(a[3]), ord(a[4]) , ord(a[5]))
return b
# Função callback usada no processamento dos pacotes
#pcap.pcap_handler
def processing_pkts(arg, hdr, pkt):
counterp = ct.cast(arg, ct.POINTER(ct.c_int))
counterp[0] += 1
old_ts_tv_sec = 0
old_ts_tv_usec = 0
pkt_addr = hdr.contents
pkt_time_cap = pkt_addr.ts
pkt_len = pkt_addr.len
pkt_caplen = pkt_addr.caplen
eth_length = 14
eth_header = pkt[:eth_length]
eth = unpack('!6s6sH' , bytes(eth_header))
eth_protocol = socket.ntohs(eth[2])
count_pkt = 0
delay = (pkt_time_cap.tv_sec - old_ts_tv_sec) * 1000000 - old_ts_tv_usec + pkt_time_cap.tv_usec
Bps = (ct.cast(pkt,ct.POINTER(ct.c_uint64))[1] * 8 * 1000000) / (delay)
Pps = (ct.cast(pkt,ct.POINTER(ct.c_uint64))[0] * 1000000) / delay
old_ts_tv_sec = pkt_time_cap.tv_sec
old_ts_tv_usec = pkt_time_cap.tv_usec
print('Bps: ' + str(int(Bps)))
print('Pps: ' + str(int(Pps)))
time_cap = time.ctime(pkt_time_cap.tv_sec)
# Parser IP packets
if eth_protocol == 8:
ip_header = pkt[eth_length:20+eth_length]
iph = unpack('!BBHHHBBH4s4s' , bytes(ip_header))
version_ihl = iph[0]
version = version_ihl >> 4
ihl = version_ihl & 0xF
iph_length = ihl * 4
ttl = iph[5]
protocol = iph[6]
s_addr = socket.inet_ntoa(iph[8]);
d_addr = socket.inet_ntoa(iph[9]);
# print('Version: ' + str(version) + '| IP Header Length: ' + str(ihl) + ' | ' + 'TTL: ' + str(ttl) + ' | ' + 'Protocol: ' + str(protocol) + ' | ' +'Source Address: ' + str(s_addr) + ' | ' +'Destination Address: ' + str(d_addr) + ' | ' + 'length: ' + str(pkt_len) + ' | ' + 'cap length: ' + str(pkt_caplen) + ' | ' + 'Cap time: ' + str(pkt_time_cap))
print('\nVersion: ' + str(version) + '| IP Header Length: ' + str(ihl) + ' | ' + 'TTL: ' + str(ttl) + ' | ' + 'Protocol: ' + str(protocol) + ' | ' +'Source Address: ' + str(s_addr) + ' | ' +'Destination Address: ' + str(d_addr) + ' | ' + 'length: ' + str(pkt_len))
count_pkt = 0
if s_addr == ip_afinet:
# print('confirma ip')
count_pkt += 1
arq_qtdPktpTime = open("qtdPktpTime.txt", "a")
arq_qtdPktpTime.write(time_cap + ',' + str(counterp[0]) + '\n')
# funcoes_auxiliares.plotGraf1()
# TCP protocol
if protocol == 6:
t = iph_length + eth_length
tcp_header = pkt[t:t+20]
tcph = unpack('!HHLLBBHHH' , bytes(tcp_header))
source_port = tcph[0]
dest_port = tcph[1]
sequence = tcph[2]
acknowledgement = tcph[3]
doff_reserved = tcph[4]
tcph_length = doff_reserved >> 4
print('Source Port: ' + str(source_port) + ' >> Dest Port: ' + str(dest_port) + ' >> Sequence Number: ' + str(sequence) + ' >> Acknowledgement: ' + str(acknowledgement) + ' >> TCP header length: ' + str(tcph_length))
h_size = eth_length + iph_length + tcph_length * 4
# data_size = len(pkt) - h_size
# data_size = pkt_len - h_size
#get data from the packet
data = pkt[h_size:pkt_len]
# print('Data : ' + str(data))
# UDP procotol
elif protocol == 17:
u = iph_length + eth_length
udph_length = 8
udp_header = pkt[u:u+8]
udph = unpack('!HHHH' , bytes(udp_header))
source_port = udph[0]
dest_port = udph[1]
length = udph[2]
checksum = udph[3]
# print('Source Port: ' + str(source_port) + ' >> Dest Port: ' + str(dest_port) + '>> Length: ' + str(length) + ' >> Checksum: ' + str(checksum))
print('Source Port: ' + str(source_port) + ' >> Dest Port: ' + str(dest_port) + ' >> Checksum: ' + str(checksum))
h_size = eth_length + iph_length + udph_length
# data = pkt[h_size:pkt_len]
# print(data)
# pcap.dump
# função para captura e uso de parametros no execução do código no terminal
def usage():
print("Usage: {} [ {} ] [ -i interface ] [ -t timeout] "
"[ expression ]".format(program_name,
"-mn" if is_windows else "-bmnrs"), file=sys.stderr)
sys.exit(1)
# --------------------------------------------------------------------------------------
if __name__.rpartition(".")[-1] == "__main__":
sys.exit(main())
Can help me to solve this ?? I appreciate any tips
The C code the OP is porting and generating an error in Python is:
/* Calculate the delay in microseconds from the last sample. This value
* is obtained from the timestamp that the associated with the sample. */
delay = (header->ts.tv_sec - old_ts->tv_sec) * 1000000
- old_ts->tv_usec + header->ts.tv_usec;
/* Get the number of Bits per second */
Bps.QuadPart=(((*(LONGLONG*)(pkt_data + 8)) * 8 * 1000000) / (delay));
/* ^ ^
| |
| |
| |
converts bytes in bits -- |
|
delay is expressed in microseconds --
*/
/* Get the number of Packets per second */
Pps.QuadPart=(((*(LONGLONG*)(pkt_data)) * 1000000) / (delay));
The Python code is missing the casting and dereferencing of the pkt_data + 8 byte pointer calculation. Since *(LONGLONG*)(pkt_data + 8) == ((LONGLONG*)(pkt_data))[1], the Python code implements cast and dereference of the latter version:
delay = (pkt_time_cap.tv_sec - old_ts_tv_sec) * 1000000 - old_ts_tv_usec + pkt_time_cap.tv_usec
Bps = ct.cast(pkt,ct.POINTER(ct.c_uint64))[1] * 8 * 1000000 / delay
Pps = ct.cast(pkt,ct.POINTER(ct.c_uint64))[0] * 1000000 / delay
Since there isn't a functional example I'll demonstrate by creating a byte pointer to two 64-bit values to test the code is correct. The original code was adding 8 to a byte pointer, casting to a 64-bit pointer and dereferencing it. That's the same thing as casting directly to a 64-bit pointer and indexing the 2nd value, e.g. *(LONGLONG*)(pkt_data + 8) == ((LONGLONG*)(pkt_data))[1]:
>>> import ctypes as ct
>>> data = (ct.c_uint64 * 2)(100,200)
>>> pkt = ct.cast(ct.byref(data), ct.POINTER(ct.c_ubyte))
>>> pkt
<__main__.LP_c_ubyte object at 0x000002D38C9BA5C0>
>>> pkt + 8
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'LP_c_ubyte' and 'int'
Above demonstrates the same error as the OP due to pkt being a byte pointer. Below casts the pointer back to a 64-bit pointer and accesses the 2nd value:
>>> ct.cast(pkt,ct.POINTER(ct.c_uint64))[1]
200
Related
I am attempting to access a function in a C file using Python ctypes. The code is below.
class PacketInfo_t(Structure):
_fields_ = [("pPayload",c_char_p),
("Payload_len",c_uint),
("usSrcPort",c_ushort),
("usDstPort",c_ushort),
("unSrcIP",c_uint),
("unDstIP",c_uint),
("enDirection",c_uint)
]
def func(self):
packets = [(packet,direction) for packet, direction in self.flow.packets]
c_packets = []
packet_num = len(packets)
packet_info_p_array = (POINTER(PacketInfo_t) * packet_num)()
for i,(packet,dire) in enumerate(packets):
if "TCP" in packet:
sport = packet["TCP"].sport
dport = packet["TCP"].dport
payload = packet["TCP"].payload
elif "UDP" in packet:
sport = packet["UDP"].sport
dport = packet["UDP"].dport
payload = packet["UDP"].payload
cpayload=cast(bytes(payload), c_char_p)
if dire == PacketDirection.FORWARD:
int_dire = 0
else:
int_dire = 1
# print sport in python
print("sport in python : ", sport)
packet_info_value = [cpayload,
c_uint(len(payload)),
c_ushort(sport),
c_ushort(dport),
c_uint(ip2long(packet["IP"].src)),
c_uint(ip2long(packet["IP"].dst)),
c_uint(int_dire)]
packet_obj = PacketInfo_t(*packet_info_value)
packet_info_p_array[i] = pointer(packet_obj)
# pdb.set_trace()
print("before into C function, pram's address is ", byref(packet_info_p_array))
print("before into C function, packet_num is ", packet_num)
res = solib.Check_MKCP(byref(packet_info_p_array), packet_num)
return res
The processing object of the program is the network flow, which contains a lot of data packets.
int func_C(PacketInfo_t ** ppPacketInfo, int nPacket){
int i = 0;
unsigned int payload_len = 0;
unsigned int tmplen,f;
unsigned char *payload;
// address
printf("ppPacketInfo's address is %p\n", ppPacketInfo);
printf("start func_C function! nPacket = %u\n", nPacket);
for(i=0;i<nPacket;i++){
payload_len = ppPacketInfo[i]->Payload_len;
// print sport in C
printf("sport = %u\n",ppPacketInfo[i]->usSrcPort);
if(payload_len != 0){
break;
}
}
...
}
But The content of multiple pointer is different in python and C code. image:
enter image description here
Why does this problem occur and how should I solve or think about it?
The minimal case can be download by https://drive.google.com/file/d/1Pkca1J0kJmTd5jp1HkCAxCCsQY2wlUOY/view?usp=sharing
I have a piece of code in python. It is related to client Socket programming. I want to get the NTRIP data from "www.rtk2go.com". The code written in python works well and serves the purpose.
import socket
import base64
server = "www.rtk2go.com"
port = "2101"
mountpoint = "leedgps"
username = ""
password = ""
def getHTTPBasicAuthString(username, password):
inputstring = username + ':' + password
pwd_bytes = base64.standard_b64encode(inputstring.encode("utf-8"))
pwd = pwd_bytes.decode("utf-8").replace('\n', '')
return pwd
pwd = getHTTPBasicAuthString(username, password)
print(pwd)
header = "GET /{} HTTP/1.0\r\n".format(mountpoint) + \
"User-Agent: NTRIP u-blox\r\n" + \
"Accept: */*\r\n" + \
"Authorization: Basic {}\r\n".format(pwd) + \
"Connection: close\r\n\r\n"
print(header)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((server, int(port)))
s.sendto(header.encode('utf-8'), (server, int(port)))
resp = s.recv(1024)
try:
while True:
try:
data = s.recv(2048)
except:
pass
finally:
s.close()
I wanted to implement the same thing in c++ code and after going through few online tutorials, I wrote the following code in C++ (I am very new to C++)
#include <iostream>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <netdb.h>
using namespace std;
#define SIZE 1000
#define PORT 2101
string base64Encoder(string input_str, int len_str) {
char char_set[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *res_str = (char *) malloc(SIZE * sizeof(char));
int index, no_of_bits = 0, padding = 0, val = 0, count = 0, temp;
int i, j, k = 0;
for (i = 0; i < len_str; i += 3) {
val = 0, count = 0, no_of_bits = 0;
for (j = i; j < len_str && j <= i + 2; j++) {
val = val << 8;
val = val | input_str[j];
count++;
}
no_of_bits = count * 8;
padding = no_of_bits % 3;
while (no_of_bits != 0) {
// retrieve the value of each block
if (no_of_bits >= 6) {
temp = no_of_bits - 6;
// binary of 63 is (111111) f
index = (val >> temp) & 63;
no_of_bits -= 6;
} else {
temp = 6 - no_of_bits;
// append zeros to right if bits are less than 6
index = (val << temp) & 63;
no_of_bits = 0;
}
res_str[k++] = char_set[index];
}
}
for (i = 1; i <= padding; i++) {
res_str[k++] = '=';
}
res_str[k] = '\0';
string a = res_str;
return a;
}
int main() {
string input_str = ":";
int len_str;
len_str = input_str.length();
string pwd = base64Encoder(input_str, len_str);
string mountpoint = "leedgps";
string header = "GET /" + mountpoint + " HTTP/1.0\r\n" + \
"User-Agent: NTRIP u-blox\r\n" + \
"Accept: */*\r\n" + \
"Authorization: Basic " + pwd + "\r\n" + \
"Connection: close\r\n\r\n";
struct hostent *h;
if ((h = gethostbyname("www.rtk2go.com")) == NULL) { // Lookup the hostname
cout << "cannot look up hostname" << endl;
}
struct sockaddr_in saddr;
int sockfd, connfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0) < 0;
if (sockfd) {
printf("Error creating socket\n");
}
saddr.sin_family = AF_INET;
saddr.sin_port = htons(2101);
if(inet_pton(AF_INET, "3.23.52.207", &saddr.sin_addr)<=0) //
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
cout << connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) << endl;
return 0;
}
But the connect method always returns -1 (in C++). Any idea what am I doing wrong?
sockfd = socket(AF_INET, SOCK_STREAM, 0) < 0;
means that sockfd is either 0 or 1, which is not a valid socket.
Do this instead:
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Error creating socket\n");
}
I'm working with some code that does a mathematical conversion from Earth Centered Earth Fixed Coordinates to Latitude/Longitude/Altitude Coordinates. One iteration of this function is written in Python- another in C. The C method came after the Python method was written and is supposed to be a direct translation. However, I'm finding that the Python method, although it's using floating point values for it's calculations, gets a correct answer, while the C method, even when using doubles, seems to only be rounding after only 5 decimal places and therefore gets an incorrect answer when attempting to convert ECEF to LLA coordinates. Here is the Python method for the conversion, along with an example coordinate:
import math
import numpy as np
def ecef2lla(eceflist):
x = float(eceflist[0])
y = float(eceflist[1])
z = float(eceflist[2])
a = 6378137 # radius
e = 8.1819190842622e-2 # eccentricity
e_string = "E value:" + " " + str(e)
print(e_string)
asq = math.pow(a,2)
asq_string = "asq value:" + " " + str(asq)
print(asq_string)
esq=math.pow(e,2)
esq_string = "esq value:" + " " + str(esq)
print(esq_string)
b = math.sqrt( asq * (1-esq) )
b_string = "b value:" + " " + str(b)
print(b_string)
bsq = math.pow(b,2)
ep = math.sqrt( (asq - bsq)/bsq)
ep_string = "ep value:" + " " + str(ep)
print(ep_string)
p = math.sqrt( math.pow(x,2) + math.pow(y,2) )
p_string = "p value:" + " " + str(p)
print(p_string)
th = math.atan2(a*z, b*p)
th_string = "th value:" + " " + str(th)
print(th_string)
lon = math.atan2(y,x)
lon_string = "lon value:" + " " + str(lon)
print(lon_string)
lat = math.atan2( (z + math.pow(ep,2)*b*math.pow(math.sin(th),3) ), (p - esq*a*math.pow(math.cos(th),3)))
lat_string = "lat value:" + " " + str(lat)
print(lat_string)
N = a/( math.sqrt(1-esq*math.pow(math.sin(lat),2)) )
N_divisor = math.sqrt(1-esq*math.pow(math.sin(lat),2))
ND_string = "N divisor value is" + " " + str(N_divisor)
print(ND_string)
N_string = "N value:" + " " + str(N)
print(N_string)
alt = p / math.cos(lat) - N
alt_string = "alt value:" + " " + str(alt)
print(alt_string)
lon = lon % (2*math.pi)
ret = [lat*180/math.pi, lon*180/math.pi, alt]
return ret
if __name__ == '__main__':
lla_coords = ecef2lla([2155172.63, 2966340.65, 5201390])
print(lla_coords)
The following method is the translated C method, using double data types, with thinking being this would ensure maximum precision:
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
void ecef_to_lla(double *coordinate){
double ecef_latitude = coordinate[0];
double ecef_longitude = coordinate[1];
double ecef_altitude = coordinate[2];
double a = 6378137;
//double e = 8.1819190842622e-2;
double e = 0.081819190842622;
printf("E value: %.16f\n",e);
double asq = pow(a,2);
printf("asq string: %.16f\n",asq);
double esq = pow(e,2);
printf("esq string: %.16f\n",esq);
double b = sqrt(asq * (1-esq));
printf("b string: %.16f\n",b);
double bsq = pow(b,2);
double ep = sqrt((asq-bsq)/bsq);
printf("ep string: %.16f\n",ep);
double p = sqrt(pow(ecef_latitude,2) + pow(ecef_longitude,2));
printf("p string: %.16f\n",p);
double th = atan2(a*ecef_altitude,b*p);
printf("th string: %.16f\n",th);
double lla_longitude = atan2(ecef_longitude,ecef_latitude);
double lla_latitude = atan2((ecef_altitude + pow(ep,2)*b*pow(sin(th),2)),p-esq*a*pow(cos(th),3));
printf("Lat is %.16f\n",lla_latitude);
double n = a/(sqrt(1-esq*pow(sin(lla_latitude),2)));
double n_divisor = sqrt(1-esq*pow(sin(lla_latitude),2));
printf("n_divisor is %.16f\n",n_divisor);
printf("n is %.16f\n",n);
double lla_altitude = p / cos(lla_latitude) - n;
printf("alt is %.16f\n",lla_altitude);
lla_longitude = fmod(lla_longitude ,(2 * M_PI));
lla_latitude = fmod(lla_latitude ,(2 * M_PI));
lla_latitude = lla_latitude * 180/M_PI;
lla_longitude = lla_longitude * 180/M_PI;
coordinate[0] = lla_latitude;
coordinate[1] = lla_longitude;
coordinate[2] = lla_altitude;
}
int main(void){
double coordinates[3] = {2155172.63, 2966340.65, 5201390};
ecef_to_lla(coordinates);
}
The LLA coordinates returned by the Python method are:
54.99999538240099, 54.00000006037918, 8.26665045041591
while those returned by the C method are:
55.0268382213345930,54.0000000603791790,4279.4874338442459702
So the altitude calculationseems to be the issue
There's a tiny transcription error. Change the line
double lla_latitude = atan2((ecef_altitude + pow(ep,2)*b*pow(sin(th),2)),p-esq*a*pow(cos(th),3));
to
double lla_latitude = atan2((ecef_altitude + pow(ep,2)*b*pow(sin(th),3)),p-esq*a*pow(cos(th),3));
When I make that change, I get 8.2666504495 for the altitude.
I got a system where I would send a command from my host computer using Python Socket (the computer is the server) and the MKR1000 (client) would send back information depends on the command sent.
Unfortunately, the bidirectional communication is unstable. I can guarantee the MKR1000 received the command and (maybe) sending information back, but for some reason, my host computer would not receive the command.
Anyway, this is my first time trying out socket, so I would like some guru to review my code and maybe spot the mistake in here? Thanks a lot.
Python:
import socket
import time
def coor2bytes(coor_fnc):
coorByte = [0, 0, 0, 0, 0, 0]
if (coor_fnc[0] >= 0):
coorByte[0] = (coor_fnc[0] >> 8) & 0xFF # High byte of X
coorByte[1] = coor_fnc[0] & 0xFF # Low byte of X
else:
coor_fnc[0] = coor_fnc[0]*(-1)
coorByte[0] = (coor_fnc[0] >> 8) & 0xFF # High byte of X
coorByte[0] = coorByte[0] ^ 0x80
coorByte[1] = coor_fnc[0] & 0xFF # Low byte of X
if (coor_fnc[1] >= 0):
coorByte[2] = (coor_fnc[1] >> 8) & 0xFF # High byte of Y
coorByte[3] = coor_fnc[1] & 0xFF # Low byte of Y
else:
coor_fnc[1] = coor_fnc[1]*(-1)
coorByte[2] = (coor_fnc[1] >> 8) & 0xFF # High byte of X
coorByte[2] = coorByte[2] ^ 0x80
coorByte[3] = coor_fnc[1] & 0xFF # Low byte of X
if (coor_fnc[2] >= 0):
coorByte[4] = (coor_fnc[2] >> 8) & 0xFF # High byte of Phi
coorByte[5] = coor_fnc[2] & 0xFF # Low byte of Phi
else:
coor_fnc[2] = coor_fnc[2]*(-1)
coorByte[4] = (coor_fnc[2] >> 8) & 0xFF # High byte of Phi
coorByte[4] = coorByte[4] ^ 0x80
coorByte[5] = coor_fnc[2] & 0xFF # Low byte of Phi
return coorByte
def bytes2coor(byte_fnc):
receivedCoor_fnc = [0, 0, 0]
receivedCoor_fnc[0] = ((-1)**(byte_fnc[0]>>7)) * ((byte_fnc[1]) | (((byte_fnc[0]&0x7f)<<8)))
receivedCoor_fnc[1] = ((-1)**(byte_fnc[2]>>7)) * ((byte_fnc[3]) | (((byte_fnc[2]&0x7f)<<8)))
receivedCoor_fnc[2] = ((-1)**(byte_fnc[4]>>7)) * ((byte_fnc[5]) | (((byte_fnc[4]&0x7f)<<8)))
return receivedCoor_fnc
if __name__ == '__main__':
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1234)) # bind(ip, port)
print("Done binding.")
s.listen(2)
clientsocket, address = s.accept()
print(f"Connection from {address} has been established!")
clientsocket.settimeout(1)
while True:
print();
print("What you want to do?")
print("0. Send target")
print("1. Get current coordinate")
print("2. Set current coordinate (not yet implement)")
try:
a = int(input("I choose: "))
except Exception:
print("Error.")
a = -1;
if (a == 0):
coor = [0, 0, 0]
try:
coor[0] = int(input("X: "))
coor[1] = -int(input("y: "))
coor[2] = int(input("phi: "))
coorByte = coor2bytes(coor)
clientsocket.send(bytes([0]))
clientsocket.send(bytes(coorByte))
print("I already sent the target.")
except Exception:
print("Error.")
elif (a == 1):
receive = 0
while (not receive):
try:
clientsocket.send(bytes([1]))
bytesReceived = []
full_msg = []
while (len(full_msg) < 8):
bytesReceived = clientsocket.recv(8)
for x in range(len(bytesReceived)):
full_msg.append(bytesReceived[x])
receivedCoor = bytes2coor(full_msg)
print("coordinate received: " + str(receivedCoor))
receive = 1
except socket.timeout:
print("Time out. Will try again.")
elif (a == 2):
setCoor = [0, 0, 0]
try:
setCoor[0] = int(input("X: "))
setCoor[1] = -int(input("y: "))
setCoor[2] = int(input("phi: "))
setcoorByte = coor2bytes(setCoor)
clientsocket.send(bytes([2]))
clientsocket.send(bytes(setcoorByte))
print("I already sent the new coordinate.")
except Exception:
print("Error.")
else:
print("Not yet implement.")
Arduino:
#include <WiFi101.h>
#include <SPI.h>
// To connect to the server on laptop
char ssid[] = "iPhone";
char pass[] = "00000000";
int status = WL_IDLE_STATUS;
IPAddress server(172,20,10,3);
WiFiClient client;
// Random variable
int a, i, j, k, m;
byte buf0[7];
byte buf1[7];
byte buf2[7];
long start = millis();
int elapsedTime = 0;
int timeout = 0;
void setup() {
// put your setup code here, to run once:
// Serial.begin(115200);
Serial.begin(115200);
Serial1.begin(115200);
// status = WiFi.begin(ssid, pass);
while (status != WL_CONNECTED) {
status = WiFi.begin(ssid, pass);
}
j = client.connect(server, 1234);
while (j != 1) {
j = client.connect(server, 1234);
}
}
void loop()
{
if (client.available()) {
a = client.read();
Serial.print("I got: ");
Serial.println(a);
if (a == 0) { // Send new target to Due
Serial.println("I send target.");
j = 0;
start = millis();
while(j<6) {
elapsedTime = millis() - start;
if (elapsedTime > 1000) {
timeout = 1;
break;
}
if (client.available()>0) {
buf0[j] = client.read();
Serial.println(buf0[j]);
j++;
}
}
if (timeout != 1) {
Serial1.write((byte) 0);
// Send coordinate back to Due
for (i = 0; i<6; i++) {
Serial1.write(buf0[i]);
}
} else {
timeout = 0;
}
} else if (a == 1) {
// Get the coordinate from the Due
Serial.println("I receive coordinate.");
Serial1.write((byte) 1);
k = 0;
start = millis();
while(k < 6) {
elapsedTime = millis() - start;
if (elapsedTime > 1000) {
timeout = 1;
break;
}
if (Serial1.available() > 0) {
buf1[k] = Serial1.read();
Serial.println(buf1[k]);
k++;
}
}
if (timeout != 1) {
for (i=0;i<6;i++) {
client.write(buf1[i]);
delay(10);
}
client.write((byte) 0); // fill in the blank size
delay(10);
client.write((byte) 0);
} else {
timeout = 0;
}
// for (int i = 0; i<8; i++) {
// client.write((byte) 0);
// }
} else if (a == 2) { // set the current coordinnate to be something else.
Serial.println("I set coordinate.");
m = 0;
while(m<6) {
if (client.available()>0) {
buf2[m] = client.read();
Serial.println(buf2[m]);
m++;
}
}
Serial1.write((byte) 2);
// Send coordinate back to Due
for (i = 0; i<6; i++) {
Serial1.write(buf2[i]);
}
} else if (a == 3) { // identify yourself
Serial.println("Identify myself.");
client.write((byte) 1);
}
}
}
If you have time to read through the Arduino code, then you would see that I actually have serial communication between my MKR and Due too. I also can guarantee that the MKR can receive all those data from the Due and not stuck in some infinite loop.
Thank you!
Ok so for some reason if I added a delay right after the MKR connecting to WiFi, before connecting to the server, then everything just works.
Whenever I send a SYN packet using my program, I get no reply.I know the server is working because I can connect to it using the normal socket connect() method but when I try using RAW sockets to do it I get no reply, not even an RST.
Here is my packet according to Wireshark
Transmission Control Protocol, Src Port: 5173 (5173), Dst Port: 5005 n (5005), Seq: 0, Len: 0
Source Port: 5173
Destination Port: 5005
[Stream index: 15]
[TCP Segment Len: 0]
Sequence number: 0 (relative sequence number)
Acknowledgment number: 0
Header Length: 40 bytes
Flags: 0x002 (SYN)
000. .... .... = Reserved: Not set
...0 .... .... = Nonce: Not set
.... 0... .... = Congestion Window Reduced (CWR): Not set
.... .0.. .... = ECN-Echo: Not set
.... ..0. .... = Urgent: Not set
.... ...0 .... = Acknowledgment: Not set
.... .... 0... = Push: Not set
.... .... .0.. = Reset: Not set
.... .... ..1. = Syn: Set
.... .... ...0 = Fin: Not set
[TCP Flags: **********S*]
Window size value: 53270
[Calculated window size: 53270]
Checksum: 0x9f18 [incorrect, should be 0x90ae (maybe caused by "TCP checksum offload"?)]
Urgent pointer: 0
Options: (20 bytes), Maximum segment size, SACK permitted, Timestamps, No-Operation (NOP), Window scale
Maximum segment size: 65495 bytes
Kind: Maximum Segment Size (2)
Length: 4
MSS Value: 65495
TCP SACK Permitted Option: True
Kind: SACK Permitted (4)
Length: 2
Timestamps: TSval 378701, TSecr 0
Kind: Time Stamp Option (8)
Length: 10
Timestamp value: 378701
Timestamp echo reply: 0
No-Operation (NOP)
Type: 1
0... .... = Copy on fragmentation: No
.00. .... = Class: Control (0)
...0 0001 = Number: No-Operation (NOP) (1)
Window scale: 7 (multiply by 128)
[SEQ/ACK analysis]
And here is my Python code
#!/usr/bin/python
import socket
from struct import *
import random
s = socket.socket()
host = "127.0.0.1"
destination = "127.0.0.1"
CLRF = '\r\n'
#socket.gethostname()
print destination
port = 5173
#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#s.connect((host, 5005))
try:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
except socket.error , msg:
print 'Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
ipSource = '192.168.0.106'
#IP header
ipIHL = 5 # Header Length
ipVersion = 4 # ipv4/v6
ipTOS = 0 # type of service
ipTotalLen = 0 ## Kernel will fill correct length apparently
ipPackID = random.randint(1,1000)
#Flags
ipReserved = 0
ipNoFrag = 1
ipMoreFrags = 0
ipFragOffset = 0 #Fragment offset
ipTTL = 64
ipProtocol = socket.IPPROTO_TCP
ipChecksum = 0 # Magic kernel filling in at work again
ipSource = socket.inet_aton (host)
ipDest = socket.inet_aton (destination)
#Packing IP flags
ipFlags = ipMoreFrags + (ipNoFrag << 1) + (ipReserved << 2)
ipFragOffset = (ipFlags << 13) + ipFragOffset
ipIHLVersion = (ipVersion << 4) + ipIHL
headerIP = pack('!BBHHHBBH4s4s',ipIHLVersion, ipTOS, ipTotalLen, ipPackID, ipFragOffset, ipTTL, ipProtocol, ipChecksum, ipSource, ipDest)
#Checksum function
def carry_around_add(a, b):
c = a + b
return (c & 0xffff) + (c >> 16)
def checksum(msg):
s = 0
for i in range(0, len(msg), 2):
w = ord(msg[i]) + (ord(msg[i+1]) << 8)
s = carry_around_add(s, w)
return ~s & 0xffff
#TCP Header
tcpSourcePort = port #Source Port
tcpDestPort = 5005 #Destination Port
tcpSeqNum = 0 #Packet sequence
tcpAckNum = 0 #Ackknowledge Number
tcpOffset = 10 #Size of tcp header 20 bytes
#tcpReserved = 0
#tcpECN = 0
#Control Flags
tcpURG = 0
tcpACK = 0
tcpPSH = 0
tcpRST = 0
tcpSYN = 1
tcpFIN = 0
tcpWindow = socket.htons (5840) #Dunno how this works
tcpChecksum = 0
tcpUrgentPointer = 0
#TCP Options
tcpMaxSegmentSize = (2 << 24) + (4 << 16) + 65495 # Kind + Length + Max Segment Size
tcpSACKPermitted = (4 << 8) + 2#Kind + Length
#Split TCP TImestamps into 2 because too large
tcpTimestampPartOne = (8 << 8) + (10) #Kind + Length
tcpTimestampPartTwo = (378701 << 32) + 0 #Timestamp Value + Timestamp echo reply
tcpNoOp = (0 << 7) + (0 << 5) + 1 #Copy on fragmentation + Class + Number
tcpWindowScale = (3 << 16)+ (3 << 8) + 7 #Kind + Length(Bytes) +Shift CountS
#Combine both due to length issues
tcpNoOpAndWindowScale = (tcpNoOp << 24) + tcpWindowScale
tcpOffsetResult = (tcpOffset << 4) + 0 #Shift 4 bytes to left
#Putting together all the TCP Control Flags
tcpFlags = tcpFIN + (tcpSYN << 1) + (tcpRST << 2) + (tcpPSH << 3) + (tcpACK << 4) + (tcpURG << 5)
#Packing the pseudo TCP header
headerTCP = pack('!HHLLBBHHHLHHQL', tcpSourcePort, tcpDestPort, tcpSeqNum, tcpAckNum, tcpOffsetResult, tcpFlags, tcpWindow, tcpChecksum, tcpUrgentPointer, tcpMaxSegmentSize, tcpSACKPermitted, tcpTimestampPartOne, tcpTimestampPartTwo, tcpNoOpAndWindowScale)
#headerTCP = pack('!HHLLBBHHH', tcpSourcePort, tcpDestPort, tcpSeqNum, tcpAckNum, tcpOffsetResult, tcpFlags, tcpWindow, tcpChecksum, tcpUrgentPointer)
#data = 'GET ./asd HTTP/1.1'
data = ''
#Checksum Calculation
#Pseudo Header Fields
sourceAddr = socket.inet_aton(host)
destAddr = socket.inet_aton(destination)
placeholder = 0
protocol = socket.IPPROTO_TCP
tcpLen = len(headerTCP) + len(data)
psh = pack('!4s4sBBH', sourceAddr, destAddr, placeholder, protocol, tcpLen);
psh = psh + headerTCP + data;
#Calc checksum
tcpChecksumReal = (checksum(psh) << 1)
print(tcpChecksumReal)
#Pack actual tcp header with checksum
headerTCP = pack('!HHLLBBH', tcpSourcePort, tcpDestPort, tcpSeqNum, tcpAckNum, tcpOffsetResult, tcpFlags, tcpWindow) + pack('!H', 40728) + pack ('!H', tcpUrgentPointer) + pack('!LHHQL', tcpMaxSegmentSize, tcpSACKPermitted, tcpTimestampPartOne, tcpTimestampPartTwo, tcpNoOpAndWindowScale)
#Build full packet / ip with tcp with data
packet = headerIP + headerTCP + data
#print [hex(ord(c)) for c in packet]
s.sendto(packet, (destination,0))
Any help would be appreciated, thanks in advance.
Credits to #KenCheung for the answer
Turns out it was the checksum, the checksum from the headers I used as reference also were incorrect but the network card was offloading them.