nodejs / node-addon-api Public
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
About socket-sendto Error? #1116
Comments
|
Hi @southorange1228, |
|
yeah, this is a client code. // iping.h
#include <iostream>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
using namespace std;
#define PACK_SIZE 32
#define IP_HEADER_SIZE 20
#define ICMP_ECHO 8
#define ICMP_ECHO_REPLY 0
struct PingOptions {
char * addr;
int timeout;
int retry;
};
struct IP_HEADER {
unsigned char header_length :4; // header of length
unsigned char version :4; // version
unsigned char tos; // type of service
unsigned short total_length; // total length of packet
unsigned short identifier; // id
unsigned short frag_and_flags; // fragment and flag
unsigned char ttl; // ttl
unsigned char protocol; // protocol eg: TCP UDP etc.
unsigned short checksum; // checksum
unsigned long source_ip; // source ip
unsigned long dest_ip; // destination ip
} ;
struct ICMP_HEADER {
unsigned char icmp_type;
unsigned char icmp_code;
unsigned short icmp_checksum;
unsigned short icmp_id;
unsigned short icmp_seq;
unsigned long timestamp_s;
unsigned long timestamp_us;
};
class Ping {
public:
Ping();
~Ping();
void CreateSocket();
void SendPacket();
void RecvPacket();
private:
PingOptions options;
unsigned short CheckSum(unsigned short *header,int length);
int GeneratePacket();
int ResolvePacket(int pack_size);
std::string input_domain;
std::string backup_ip;
int sock_fd;
int max_wait_time;
int send_pack_num;
int recv_pack_num;
int lost_pack_num;
struct sockaddr_in send_addr;
struct sockaddr_in recv_addr;
char send_pack[PACK_SIZE];
char recv_pack[PACK_SIZE + IP_HEADER_SIZE];
struct timeval first_send_time;
struct timeval recv_time;
double min_time;
double max_time;
double sum_time;
unsigned short pid = 0;
};// iping.cpp
#include "iping.h"
#include "iostream"
Ping::Ping() {
this->send_pack_num = 10;
this->recv_pack_num = 0;
this->lost_pack_num = 0;
this->min_time = 0;
this->max_time = 60 * 1000;
this->sum_time = 0;
this->input_domain = "127.0.0.1";
}
Ping::~Ping() {
cout << "1243" << endl;
if(close(sock_fd) == -1) {
fprintf(stderr, "Close socket error:%s \n\a", strerror(errno));
exit(1);
}
}
unsigned short Ping::CheckSum(unsigned short * header, int length) {
int check_sum = 0;
int nleft = length;
unsigned short * p = header;
while(nleft > 1){
check_sum += *p++;
nleft -= sizeof(unsigned short);
}
if (nleft){
check_sum += *(unsigned char*)p;
}
check_sum = (check_sum >> 16) + (check_sum & 0xffff);
check_sum += (check_sum >> 16);
return (unsigned short)(~check_sum);
}
void Ping::CreateSocket() {
struct protoent * protocol;
unsigned long in_addr;
struct hostent *host_pointer;
if((protocol = getprotobyname("icmp")) == NULL){
fprintf(stderr, "Get protocol error:%s \n\a", strerror(errno));
exit(1);
}
// MACOS use SOCK_DGRAM
#ifdef __APPLE__
if((sock_fd = socket(AF_INET, SOCK_DGRAM, protocol->p_proto)) == -1){
fprintf(stderr, "Greate RAW socket error:%s \n\a", strerror(errno));
exit(1);
}
#endif
send_addr.sin_family = AF_INET;
if((in_addr = inet_addr(input_domain.c_str())) == INADDR_NONE){
host_pointer = gethostbyname(input_domain.c_str());
if(host_pointer == NULL){
fprintf(stderr, "Get host by name error:%s \n\a", strerror(errno));
exit(1);
} else{
this->send_addr.sin_addr.s_addr = (*(struct in_addr *)host_pointer->h_addr).s_addr;
}
} else{
this->send_addr.sin_addr.s_addr = in_addr;
}
this->backup_ip = inet_ntoa(send_addr.sin_addr);
gettimeofday(&first_send_time, NULL);
}
int Ping::GeneratePacket()
{
int pack_size;
ICMP_HEADER *icmp_pointer;
struct timeval time_pointer;
gettimeofday(&time_pointer, NULL);
pack_size = PACK_SIZE;
memset(send_pack,0,sizeof(send_pack));
memset(recv_pack,0,sizeof(recv_pack));
icmp_pointer = (ICMP_HEADER *)send_pack;
icmp_pointer->icmp_type = ICMP_ECHO;
icmp_pointer->icmp_code = 0;
icmp_pointer->icmp_seq = send_pack_num + 1;
icmp_pointer->icmp_id = getpid();
icmp_pointer->timestamp_s = time_pointer.tv_sec;
icmp_pointer->timestamp_us = time_pointer.tv_usec;
icmp_pointer->icmp_checksum = CheckSum((unsigned short *)send_pack, pack_size);
return pack_size;
}
void Ping::SendPacket() {
int pack_size = this->GeneratePacket();
if((sendto(sock_fd, send_pack, pack_size, 0, (const struct sockaddr *)&send_addr, sizeof(send_addr))) < 0){
fprintf(stderr, "Sendto error:%s \n\a", strerror(errno));
exit(1);
}
this->send_pack_num++;
}
int Ping::ResolvePacket(int pack_size) {
int icmp_len, ip_header_len;
IP_HEADER *ip_pointer = (IP_HEADER *)recv_pack;
double rtt;
unsigned long time_send;
ip_header_len = ip_pointer->header_length << 2;
ICMP_HEADER *icmp_pointer = (ICMP_HEADER *)(recv_pack + ip_header_len);
icmp_len = pack_size - ip_header_len;
if(icmp_len < 8) {
printf("received ICMP pack length:%d(%d) is error!\n", pack_size, icmp_len);
lost_pack_num++;
return -1;
}
if((icmp_pointer->icmp_type == ICMP_ECHO_REPLY) && (backup_ip == inet_ntoa(recv_addr.sin_addr))){
struct timeval time_pointer_end;
gettimeofday(&time_pointer_end, NULL);
unsigned long time_send_s = icmp_pointer->timestamp_s;
unsigned long time_send_us = icmp_pointer->timestamp_us;
if(time_pointer_end.tv_usec - time_send_us < 0) {
--time_pointer_end.tv_sec;
time_pointer_end.tv_usec += 10000000;
}
rtt = (time_pointer_end.tv_sec - time_send_s) * 1000 + (double)time_pointer_end.tv_usec / 1000.0;
printf("%d byte from %s : icmp_seq=%u ttl=%d time=%.1fms\n",
icmp_len,
inet_ntoa(recv_addr.sin_addr),
icmp_pointer->icmp_seq,
ip_pointer->ttl,
rtt);
recv_pack_num++;
} else{
if(close(sock_fd) == -1) {
fprintf(stderr, "Close socket error:%s \n\a", strerror(errno));
exit(1);
}
sock_fd = 0;
}
}
void Ping::RecvPacket() {
int recv_size, fromlen;
fromlen = sizeof(struct sockaddr);
if((recv_size = recvfrom(sock_fd, recv_pack, sizeof(recv_pack),
0, (struct sockaddr *)&recv_addr, (socklen_t *)&fromlen)) < 0) {
fprintf(stderr, "packet error(size:%d):%s \n\a", recv_size, strerror(errno));
lost_pack_num++;
} else{
ResolvePacket(recv_size);
}
}
// main.cpp
#include "iping.cpp"
int main() {
Ping ping;
ping.CreateSocket();
ping.SendPacket();
ping.RecvPacket();
}
Result |
|
There is node-addon-api project. // ping.h
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include "napi.h"
using namespace std;
#define PACK_SIZE 32
#define IP_HEADER_SIZE 20
#define ICMP_ECHO 0
#define ICMP_ECHO_REPLY 8
#define ICMP_REPLY_CODE 0
struct PingOptions {
string addr;
int timeout;
int retry;
};
struct IP_HEADER {
unsigned char header_length : 4; // header of length
unsigned char version : 4; // version
unsigned char tos; // type of service
unsigned short total_length; // total length of packet
unsigned short identifier; // id
unsigned short frag_and_flags; // fragment and flag
unsigned char ttl; // ttl
unsigned char protocol; // protocol eg: TCP UDP etc.
unsigned short checksum; // checksum
unsigned long source_ip; // source ip
unsigned long dest_ip; // destination ip
};
struct ICMP_HEADER {
unsigned char icmp_type;
unsigned char icmp_code;
unsigned short icmp_checksum;
unsigned short icmp_id;
unsigned short icmp_seq;
unsigned long timestamp_s;
unsigned long timestamp_us;
};
class Ping : public Napi::ObjectWrap<Ping> {
public:
static Napi::Object Init(Napi::Env env, Napi::Object exports);
Ping(const Napi::CallbackInfo &info);
~Ping();
private:
Napi::Value start(const Napi::CallbackInfo &info);
unsigned short CheckSum(unsigned short *header, int length);
void CreateSocket();
void SendPacket();
void RecvPacket();
int GeneratePacket();
int ResolvePacket(int pack_size);
unsigned short GetPid();
PingOptions options;
std::string backup_ip;
int sock_fd;
int send_pack_num;
int recv_pack_num;
int lost_pack_num;
struct sockaddr_in send_addr;
struct sockaddr_in recv_addr;
char send_pack[PACK_SIZE];
char recv_pack[PACK_SIZE + IP_HEADER_SIZE];
struct timeval first_send_time;
struct timeval recv_time;
Napi::Env env = NULL;
};// ping.cpp
#include "ping.h"
Napi::Object Ping::Init(Napi::Env env, Napi::Object exports) {
Napi::Function func = DefineClass(env, "Ping",
{
InstanceMethod("start", &Ping::start),
});
Napi::FunctionReference *constructor = new Napi::FunctionReference();
*constructor = Napi::Persistent(func);
env.SetInstanceData(constructor);
exports.Set("Ping", func);
return exports;
}
Ping::Ping(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Ping>(info) {
Napi::Env env = info.Env();
this->env = env;
int length = info.Length();
if (length <= 0) {
Napi::TypeError::New(env, "Option should provide").ThrowAsJavaScriptException();
return;
}
if (!info[0].IsObject()) {
Napi::TypeError::New(env, "Option should be object").ThrowAsJavaScriptException();
return;
}
Napi::Object obj = info[0].ToObject();
if (obj.Has("addr") && obj.Get("addr").IsString()) {
string originAddr = obj.Get("addr").As<Napi::String>();
this->options.addr = originAddr;
} else {
Napi::TypeError::New(env, "addr should be string").ThrowAsJavaScriptException();
return;
}
if (obj.Has("retry") && obj.Get("retry").IsNumber()) {
this->options.retry = obj.Get("retry").As<Napi::Number>();
} else {
Napi::TypeError::New(env, "retry should be number").ThrowAsJavaScriptException();
return;
}
if (obj.Has("timeout")) {
if (obj.Get("timeout").IsNumber()) {
this->options.timeout = obj.Get("timeout").As<Napi::Number>();
} else {
Napi::TypeError::New(env, "retry should be number").ThrowAsJavaScriptException();
return;
}
} else {
this->options.timeout = 60 * 1000;
}
this->send_pack_num = 0;
this->recv_pack_num = 0;
this->lost_pack_num = 0;
}
Ping::~Ping() {
if (close(sock_fd) == -1) {
fprintf(stderr, "Close socket error:%s \n\a", strerror(errno));
Napi::TypeError::New(env, "Close socket Error").ThrowAsJavaScriptException();
exit(1);
}
}
unsigned short Ping::CheckSum(unsigned short *header, int length) {
int check_sum = 0;
int nleft = length;
unsigned short *p = header;
while (nleft > 1) {
check_sum += *p++;
nleft -= sizeof(unsigned short);
}
if (nleft) {
check_sum += *(unsigned char *)p;
}
check_sum = (check_sum >> 16) + (check_sum & 0xffff);
check_sum += (check_sum >> 16);
return (unsigned short)(~check_sum);
}
unsigned short Ping::GetPid() {
unsigned short pid = getpid();
// MACOS pid will be more than short
#ifdef __APPLE__
pid = getpid() >> 1;
#endif
return pid;
}
void Ping::CreateSocket() {
struct protoent *protocol;
unsigned long in_addr;
struct hostent *host_pointer;
if ((protocol = getprotobyname("icmp")) == NULL) {
fprintf(stderr, "Get protocol error:%s \n\a", strerror(errno));
exit(1);
}
// MACOS use SOCK_DGRAM
#ifdef __APPLE__
if ((sock_fd = socket(AF_INET, SOCK_DGRAM, protocol->p_proto)) == -1) {
fprintf(stderr, "Create RAW socket error:%s \n\a", strerror(errno));
exit(1);
}
#endif
send_addr.sin_family = AF_INET;
if ((in_addr = inet_addr(options.addr.c_str())) == INADDR_NONE) {
host_pointer = gethostbyname(options.addr.c_str());
if (host_pointer == NULL) {
fprintf(stderr, "Get host by name error:%s \n\a", strerror(errno));
exit(1);
} else {
this->send_addr.sin_addr.s_addr = (*(struct in_addr *)host_pointer->h_addr).s_addr;
}
} else {
this->send_addr.sin_addr.s_addr = in_addr;
}
this->backup_ip = inet_ntoa(send_addr.sin_addr);
gettimeofday(&first_send_time, NULL);
}
int Ping::GeneratePacket() {
int pack_size;
ICMP_HEADER *icmp_pointer;
struct timeval time_pointer;
gettimeofday(&time_pointer, NULL);
pack_size = PACK_SIZE;
memset(send_pack, 0, sizeof(send_pack));
memset(recv_pack, 0, sizeof(recv_pack));
icmp_pointer = (ICMP_HEADER *)send_pack;
icmp_pointer->icmp_type = ICMP_ECHO;
icmp_pointer->icmp_code = 0;
icmp_pointer->icmp_seq = send_pack_num + 1;
icmp_pointer->icmp_id = this->GetPid();
icmp_pointer->timestamp_s = time_pointer.tv_sec;
icmp_pointer->timestamp_us = time_pointer.tv_usec;
icmp_pointer->icmp_checksum = this->CheckSum((unsigned short *)send_pack, pack_size);
return pack_size;
}
void Ping::SendPacket() {
int pack_size = this->GeneratePacket();
if((sendto(sock_fd, send_pack, pack_size, 0, (const struct sockaddr *)&send_addr, sizeof(send_addr))) < 0){
fprintf(stderr, "Sendto error:%s \n\a", strerror(errno));
exit(1);
}
this->send_pack_num++;
}
int Ping::ResolvePacket(int pack_size) {
int icmp_len, ip_header_len;
ICMP_HEADER *icmp_pointer;
IP_HEADER *ip_pointer = (IP_HEADER *)recv_pack;
double rtt;
struct timeval time_end;
gettimeofday(&time_end, NULL);
ip_header_len = ip_pointer->header_length << 2;
icmp_pointer = (ICMP_HEADER *)(recv_pack + ip_header_len);
icmp_len = pack_size - ip_header_len;
//收到的ICMP包长度小于报头
if (icmp_len < 8) {
printf("received ICMP pack length:%d(%d) is error!\n", pack_size, icmp_len);
lost_pack_num++;
return -1;
}
if ((icmp_pointer->icmp_type == ICMP_ECHO_REPLY) && (backup_ip == inet_ntoa(recv_addr.sin_addr)) &&
(icmp_pointer->icmp_code == ICMP_REPLY_CODE)) {
unsigned long time_send_s = icmp_pointer->timestamp_s;
unsigned long time_send_us = icmp_pointer->timestamp_us;
if ((recv_time.tv_usec - time_send_us) < 0) {
--recv_time.tv_sec;
recv_time.tv_usec += 10000000;
}
rtt = (recv_time.tv_sec - time_send_s) * 1000 + (double)recv_time.tv_usec / 1000.0;
printf("%d byte from %s : icmp_seq=%u ttl=%d time=%.1fms\n", icmp_len, inet_ntoa(recv_addr.sin_addr),
icmp_pointer->icmp_seq, ip_pointer->ttl, rtt);
recv_pack_num++;
return 0;
} else {
lost_pack_num++;
return -1;
}
}
void Ping::RecvPacket() {
int recv_size, fromlen;
fromlen = sizeof(struct sockaddr);
if ((recv_size = recvfrom(sock_fd, recv_pack, sizeof(recv_pack), 0, (struct sockaddr *)&recv_addr,
(socklen_t *)&fromlen)) < 0) {
fprintf(stderr, "packet error(size:%d):%s \n\a", recv_size, strerror(errno));
lost_pack_num++;
} else {
gettimeofday(&recv_time, NULL);
ResolvePacket(recv_size);
}
}
Napi::Value Ping::start(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
CreateSocket();
SendPacket();
RecvPacket();
return Napi::Number::New(env, 100);
}// init.cc
#include "ping.cpp"
Napi::Object Init(Napi::Env env, Napi::Object exports) {
Ping::Init(env, exports);
return exports;
}
NODE_API_MODULE(ping, Init)// test.js
'use strict';
const ping = require('bindings')('ping');
const a = new ping.Ping({
addr: '127.0.0.1',
retry: 10,
timeout: 10
})
a.start()Result |
|
Hi, @NickNaso , |
|
This issue is stale because it has been open many days with no activity. It will be closed soon unless the stale label is removed or a comment is made. |

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.



i try to create a
icmppacket with node-addon-api.but i always get
invalid argumenterror when calledsendto.But,i can send msg when i created a socket in a normal cpp project.
Is there some difference with node-addon-api and normal cpp project? And do you need any more information?
The text was updated successfully, but these errors were encountered: