浏览代码

#IQRV #comment [PublicFunc] 添加Ping的功能实现

gifur 4 年之前
父节点
当前提交
8536304683

+ 5 - 0
Other/libpublicFun/CMakeLists.txt

@@ -6,6 +6,7 @@ set(${MODULE_PREFIX}_SRCS
     publicFunExport.cpp
     publicFunExport.h
     ${ThirdPartyHeadRoot}/CJson/cJSON.c
+    ping.cpp
 )
 
 add_library(${MODULE_NAME} SHARED ${${MODULE_PREFIX}_SRCS})
@@ -36,3 +37,7 @@ install(TARGETS ${MODULE_NAME}
     LIBRARY DESTINATION "${RVC_RUNTIME_PATH}"
     COMPONENT libraries)
 endif(MSVC)
+
+if(BUILD_TESTING)
+add_subdirectory(test)
+endif(BUILD_TESTING)

+ 205 - 0
Other/libpublicFun/ping.cpp

@@ -0,0 +1,205 @@
+//
+// THIS CODE IS BASED ON THE CODE FROM 
+// THE BOOK WINSOCK 2.0 BY LEWIS NAPPER...
+// 
+//
+
+#include "publicFunExport.h"
+#include<sys/socket.h>
+#include<sys/types.h>
+#include<netinet/in.h>
+#include<netinet/ip_icmp.h>
+#include<arpa/inet.h>
+#include<unistd.h>
+#include<sys/time.h>
+
+typedef uint32_t DWORD;
+typedef   int  SOCKET;
+typedef struct sockaddr_in* LPSOCKADDR_IN;
+typedef struct hostent* LPHOSTENT;
+
+#define SOCKET_ERROR (-1)
+#define FAILURE   (-1)
+#define SIZE_LINE_NORMAL (1024)
+#define SUCCESS (0)
+
+#pragma pack(1)
+#define ICMP_ECHOREPLY	0
+#define ICMP_ECHOREQ	8
+
+// IP Header -- RFC 791
+typedef struct tagIPHDR
+{
+    u_char  VIHL;			// Version and IHL
+    u_char	TOS;			    // Type Of Service
+    short	TotLen;			// Total Length
+    short	ID;				// Identification
+    short	FlagOff;		// Flags and Fragment Offset
+    u_char	TTL;			     // Time To Live
+    u_char	Protocol;		// Protocol
+    u_short	Checksum;		// Checksum
+    struct	in_addr iaSrc;	// Internet Address - Source
+    struct	in_addr iaDst;	// Internet Address - Destination
+} IPHDR, * PIPHDR;
+
+
+// ICMP Header - RFC 792
+typedef struct tagICMPHDR
+{
+    u_char	Type;		     	// Type
+    u_char	Code;			    // Code
+    u_short	Checksum;		// Checksum
+    u_short	ID;				   // Identification
+    u_short	Seq;			       // Sequence
+    char	Data;			       // Data
+} ICMPHDR, * PICMPHDR;
+
+
+#define REQ_DATASIZE 32		// Echo Request Data size
+
+// ICMP Echo Request
+typedef struct tagECHOREQUEST
+{
+    ICMPHDR icmpHdr;
+    DWORD	dwTime;
+    char	cData[REQ_DATASIZE];
+} ECHOREQUEST, * PECHOREQUEST;
+
+
+// ICMP Echo Reply
+typedef struct tagECHOREPLY
+{
+    IPHDR	ipHdr;
+    ECHOREQUEST	echoRequest;
+    char    cFiller[256];
+} ECHOREPLY, * PECHOREPLY;
+
+#pragma pack()
+
+static u_short api_checksum16(u_short *buffer, int size) ;
+static int gen_icmp_packet(struct icmp *icmp_packet, int type, int seq);
+
+int gen_icmp_packet(struct icmp *icmp_packet, int type, int seq)
+{
+    if ( !icmp_packet ) {
+        return FAILURE;
+    }
+
+    icmp_packet->icmp_type  = type;
+    icmp_packet->icmp_code  = 0;
+    icmp_packet->icmp_cksum = 0;
+    icmp_packet->icmp_id  = htons(getpid());
+    icmp_packet->icmp_seq = htons(seq);
+
+    gettimeofday((struct timeval *)icmp_packet->icmp_data, NULL);
+    icmp_packet->icmp_cksum = api_checksum16((unsigned short *)icmp_packet, sizeof(struct icmp));
+
+    return SUCCESS;
+}
+
+u_short api_checksum16(u_short *buffer, int size)
+{
+    u_int cksum = 0;
+
+    if ( !buffer ) {
+        printf("NULL\n");
+        return 0;
+    }
+
+    while ( size > 1 ) {
+        printf("1. Cksum: 0x%08x + 0x%04x\n", cksum, *buffer);
+        cksum += *buffer++;
+        size -= sizeof(u_short);
+    }
+
+    if ( size ) {
+        cksum += *(u_char *)buffer;
+    }
+
+    printf("2. Cksum: 0x%08x\n", cksum);
+
+    /* 32 bit change to 16 bit */
+    while ( cksum >> 16 ) {
+        cksum = (cksum >> 16) + (cksum & 0xFFFF);
+        printf("3. Cksum: 0x%08x\n", cksum);
+    }
+
+    return (u_short)(~cksum);
+}
+
+int Ping(const std::string& dst_ip)
+{
+    int ret = FAILURE;
+    int sd = 0;
+
+    char buf[SIZE_LINE_NORMAL] = { 0 };
+
+    struct ip* ip = NULL;
+    struct sockaddr_in dst_addr = { 0 };
+    struct icmp icmp_packet = { 0 };
+
+    struct timeval tm = { .tv_sec = 1, .tv_usec = 0 };
+
+    fd_set rdfds;
+
+    if (dst_ip.empty()) {
+        goto _E1;
+    }
+
+    sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+    if (sd < 0) {
+        printf("socket fail: %d\n", errno);
+        goto _E1;
+    }
+
+    dst_addr.sin_family = AF_INET;
+    dst_addr.sin_addr.s_addr = inet_addr(dst_ip.c_str());
+
+    ret = gen_icmp_packet(&icmp_packet, 8, 1);
+    if (SUCCESS != ret) {
+        goto _E2;
+    }
+
+    ret = sendto(sd, &icmp_packet, sizeof(struct icmp), 0,
+                 (struct sockaddr*)&dst_addr, sizeof(struct sockaddr_in));
+    if (ret < 0) {
+        goto _E2;
+    }
+
+    /* Timeout 1s to recv icmp */
+    FD_ZERO(&rdfds);
+    FD_SET(sd, &rdfds);
+
+    ret = select(sd + 1, &rdfds, NULL, NULL, &tm);
+    if (-1 == ret && EINTR != errno) {
+        /* if serial error */
+        printf("select fail\n");
+        goto _E2;
+    } else if (0 == ret) {
+        /* timeout */
+        printf("recv timeout\n");
+        ret = FAILURE;
+        goto _E2;
+    }
+    if (FD_ISSET(sd, &rdfds)) {
+        ret = recv(sd, buf, sizeof(buf), 0);
+        if (ret <= 0) {
+            perror("recv\n");
+            goto _E2;
+        }
+
+        ip = (struct ip*)buf;
+        printf("from: %s\n", inet_ntoa(ip->ip_src));
+        printf("  to: %s\n", inet_ntoa(ip->ip_dst));
+    }
+
+    ret = SUCCESS;
+
+_E2:
+    close(sd);
+_E1:
+    return ret;
+}
+
+
+

+ 18 - 23
Other/libpublicFun/publicExport.h

@@ -1,28 +1,23 @@
+#ifndef _OTHER_PUBLICFUNC_HEADER_
+#define _OTHER_PUBLICFUNC_HEADER_
 #pragma once
-#ifdef PUBLIC_EXPORTS
-#ifndef PUBLIC_API
-#define PUBLIC_API __declspec(dllexport)
-#endif
-#else
-#ifndef PUBLIC_API
-#define PUBLIC_API __declspec(dllimport)
-#endif
-#endif
 
 #ifdef _WIN32
-#ifdef PUBLIC_EXPORTS
-#ifndef PUBLIC_API
-#define PUBLIC_API __declspec(dllexport)
-#endif
+    #ifdef PUBLIC_EXPORTS
+         #ifndef PUBLIC_API
+            #define PUBLIC_API __declspec(dllexport)
+        #endif
+    #else
+        #ifndef PUBLIC_API
+            #define PUBLIC_API __declspec(dllimport)
+        #endif
+    #endif
 #else
-#ifndef PUBLIC_API
-#define PUBLIC_API __declspec(dllimport)
+    #if ( defined(__GNUC__) &&  __GNUC__ >= 4 )
+        #define PUBLIC_API __attribute__((visibility("default")))
+    #else
+        #define PUBLIC_API
+    #endif
 #endif
-#endif
-#else
-#if ( defined(__GNUC__) &&  __GNUC__ >= 4 )
-#define PUBLIC_API __attribute__((visibility("default")))
-#else
-#define PUBLIC_API
-#endif
-#endif
+
+#endif //_OTHER_PUBLICFUNC_HEADER_

+ 8 - 1
Other/libpublicFun/publicFunExport.h

@@ -5,4 +5,11 @@
 #include "publicExport.h"
 
 
-PUBLIC_API std::pair<bool, std::string> generateJsonStr(std::map<std::string, std::string> &objectArr);
+PUBLIC_API std::pair<bool, std::string> generateJsonStr(std::map<std::string, std::string> &objectArr);
+/*!
+ * @brief Ping protocols
+ * @param[in]  
+ * @param[out] 
+ * @return : 0: ping connect succ; 1: ping failed
+ */
+PUBLIC_API int Ping(const std::string& dst_ip);

+ 17 - 0
Other/libpublicFun/test/CMakeLists.txt

@@ -0,0 +1,17 @@
+set(MODULE_NAME "TestPing")
+set(MODULE_PREFIX "TEST_PUBLICFUNC_PING")
+
+file(GLOB ${MODULE_PREFIX}_TESTS "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
+
+
+foreach(test ${${MODULE_PREFIX}_TESTS})
+	get_filename_component(test_name ${test} NAME_WE)
+	add_executable(${test_name} ${test})
+	target_include_directories(${test_name} PRIVATE ${CONAN_INCLUDE_DIRS_CATCH} ${OTHER_LIB_BASE_DIR}/libpublicFun)
+	target_link_libraries(${test_name} PRIVATE libpublicFun)
+	set_property(TARGET ${test_name} PROPERTY FOLDER "test/other")
+	set_target_properties(${test_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
+	message(STATUS "add test case: ${test_name}...")
+	add_test(NAME ${test_name} COMMAND ${TESTING_OUTPUT_DIRECTORY}/${test_name})
+	set_tests_properties(${teset_name} PROPERTIES FAIL_REGULAR_EXPRESSION "FAILED;ERROR;Failed;error")
+endforeach()

+ 11 - 0
Other/libpublicFun/test/testPing.cpp

@@ -0,0 +1,11 @@
+#define CATCH_CONFIG_MAIN
+#include <catch2.hpp>
+#include "publicFunExport.h"
+
+TEST_CASE("Test ping protocols implement", "[normal]")
+{
+    REQUIRE(Ping("55.14.131.137") == 0);
+
+}
+
+