Linux/Windows C/C++ TCP Contamination Processing Method Source Code Customizable Header Information

Keywords: socket Linux

This code is based on the Linux Epoll mechanism, using socket fd identifier to establish the linked list and the corresponding buffer.

tpack.h

#ifndef      TPACK_H_
#define      TPACK_H_

#include "define.h"

//  Communication Packet Structure
#Define TPACK_HEAD_SIZE 512// Header information set to maximum first
#Define TPACK_HEAD_DATA_SIZE 64// Standard Size
#define     TPACK_DATA_SIZE    8192
#define     TPACK_SIZE         8192 + 512
#define     TPACK_HEAD_LINE_TAG "\r\n"
#Define TPACK_HEAD_TAG " r n106258 r n" // Head End Character
#define     TPACK_HEAD_TAG_SIZE strlen(TPACK_HEAD_TAG)
#Define TPACK_DATA_TAG " r n4641 r n" // data Terminator
#define     TPACK_DATA_TAG_SIZE strlen(TPACK_DATA_TAG)

//	Suggested Buffer Size for Receiving Packets
#Define TPACK_CACHE_SIZE TPACK_SIZE* 2// The recommended buffer length for a packet is twice the size of a packet

//  Packet command
typedef     unsigned int    TPackCmd;
#Define TPACK_CMD_EMPTY 0x1// empty command to keep
#Define TPACK_CMD_SEND 0x2// T-end data to Client
#Define TPACK_CMD_T_CLOSE 0x4// target to be disconnected
#Define the target under TPACK_CMD_T_CLOSE 0x8// target to close, S to close, and point to the socket client
#Define TPACK_CMD_T_LOGIN 0x10// target request for login, return user_token and task list after validation
#define     TPACK_CMD_5      0x20
#define     TPACK_CMD_6      0x40
#define     TPACK_CMD_7      0x80

//  Package Form
#define     TPACK_FORM_SERVER   "Server"
#define     TPACK_FORM_CLIENT   "Client"
#define     TPACK_FORM_TARGET   "Target"

//	Packet format
typedef struct ST_TPACK_INFO
{
    TPackCmd    cmd;
	char	    form[TPACK_HEAD_DATA_SIZE];
	uint		sock_cli;	//	Client sock identity returned by server
	uint		h_data_len;

	char*	phead;
	uint		phead_len;
    
	char*	pdata;
	uint		pdata_len;

	char*	pstr;		//	Serialized data
	uint	pstr_len;
} *TPack;

TPack tpack_new( TPackCmd cmd, char* form, uint sock, char* data, size_t size);

void tpack_update_head(TPack tpack);

char* tpack_tostr(TPack tpack);

void tpack_free(TPack tpack);

TPack tpack_parse(char* str, uint str_len, char **end);

#endif

 

tpack.c

#include "stdafx.h"
#include "com.h"
#include "tpack.h"

/**
*   Communication Packing and Disassembly
*/

//  Creating packages is currently a direct application for maximum space. Later, it is necessary to create headers, create data and then synthesize packages.
TPack tpack_new( TPackCmd cmd, char* form, uint sock, char* data, size_t size){
	TPack tpack = (TPack) malloc( sizeof(struct ST_TPACK_INFO) );
	memset( tpack, 0, sizeof(struct ST_TPACK_INFO) );
    tpack->cmd = cmd;
    strncpy( tpack->form, form, strlen(form) );
    tpack->sock_cli = sock;
    
	//	Create maximum space for headers and data areas
	tpack->phead = (char *) malloc( TPACK_HEAD_SIZE );
	memset( tpack->phead, 0, TPACK_HEAD_SIZE );
	tpack->pdata = (char *) malloc( TPACK_DATA_SIZE );
	memset( tpack->pdata, 0, TPACK_DATA_SIZE );

	memcpy( tpack->pdata, data, size);
	tpack->pdata_len = strlen( tpack->pdata );

	tpack_update_head(tpack);
    
    return tpack;
}
//	Update header information, no header Terminator
void tpack_update_head(TPack tpack)
{
    sprintf( tpack->phead, "Command: %d%sFrom: %s%sSocket-Clint: %d%sData-Size: %d", 
                tpack->cmd, TPACK_HEAD_LINE_TAG,  
                tpack->form, TPACK_HEAD_LINE_TAG, 
                tpack->sock_cli, TPACK_HEAD_LINE_TAG,
				tpack->pdata_len);
	tpack->phead_len = strlen( tpack->phead );
	return;
}
//	Release TPack
char* tpack_tostr(TPack tpack)
{
	tpack_update_head(tpack);

	tpack->pstr = (char *) malloc( TPACK_SIZE );
	memset( tpack->pstr, 0, TPACK_SIZE );

	//	marger, using strlen to calculate length
	memcpy( tpack->pstr, tpack->phead, tpack->phead_len );
	memcpy( tpack->pstr + strlen(tpack->pstr), TPACK_HEAD_TAG, TPACK_HEAD_TAG_SIZE );
	memcpy( tpack->pstr + strlen(tpack->pstr), tpack->pdata, tpack->pdata_len );
	memcpy( tpack->pstr + strlen(tpack->pstr), TPACK_DATA_TAG, TPACK_DATA_TAG_SIZE );

	tpack->pstr_len = tpack->phead_len + TPACK_HEAD_TAG_SIZE + tpack->pdata_len + TPACK_DATA_TAG_SIZE;

    return tpack->pstr;
}

void tpack_free(TPack tpack){
	if( tpack == NULL ) return;
    
	if( tpack->phead != NULL ) free( tpack->phead );
	if( tpack->pdata != NULL ) free( tpack->pdata );
	if( tpack->pstr != NULL ) free( tpack->pstr );
    
    tpack->phead = NULL;
    tpack->pdata = NULL;
    tpack->pstr = NULL;
    
	//memset( tpack, 0, TPACK_SIZE);
    free( tpack );
}
//	Find the corresponding data in the head string
char *tpack_head_get_val(char* str, int str_len, char* key, char *val, int val_size)
{
	char* str_end = str + str_len;
    memset( val, 0, strlen(val) );
    char* key_start = memstr( str, str_len, key);
	if( key_start == NULL ){
		return NULL;
	}

	char* end = memstr( key_start, ( str_end - key_start ), TPACK_HEAD_LINE_TAG);
	if( end == NULL ){  //  The end of the line must be found
		return NULL;
	}

    char* key_start_i = key_start + strlen(key) + 1;    //  Start String Position
    if( (end - key_start_i) < val_size )
        val_size = end - key_start_i;

	strncpy( val, key_start_i, val_size );
    val = trim( val );
    //printf("key_start and end exist, val_size:%d\n", val_size);
	return val;
}
void tpack_parse_head(TPack tpack){
	char headVal[TPACK_HEAD_DATA_SIZE];
	memset( headVal, 0, TPACK_HEAD_DATA_SIZE );

	tpack_head_get_val( tpack->phead, tpack->phead_len, "Form", headVal, TPACK_HEAD_DATA_SIZE);
	memcpy( tpack->form, headVal, strlen(headVal) );
	
	memset( headVal, 0, TPACK_HEAD_DATA_SIZE );
	tpack_head_get_val( tpack->phead, tpack->phead_len, "Socket-Clint", headVal, TPACK_HEAD_DATA_SIZE);
	tpack->sock_cli = atoi( headVal );
	
	memset( headVal, 0, TPACK_HEAD_DATA_SIZE );
	tpack_head_get_val( tpack->phead, tpack->phead_len, "Data-Size", headVal, TPACK_HEAD_DATA_SIZE);
	tpack->h_data_len = atoi( headVal );

	return;
}
//	If you find a return
TPack tpack_parse(char* str, uint str_len, char **end)
{
	//	Find the terminator through the string
	char* str_end = str + str_len;	//	The End of Data
	char* head_start = str;
	char* data_start = str;
    char* head_tag = memstr( str, str_len, TPACK_HEAD_TAG );	//	End Marker
	char* data_tag = memstr( str, str_len, TPACK_DATA_TAG );	//	End Marker

	if( head_tag == NULL ){
		printf("TPACK unpack failed,head_tag is NULL\n");
		return NULL;
	}	
	else if( data_tag == NULL ){
		printf("TPACK unpack failed,data_tag is NULL\n");
		return NULL;
	}
	else if( data_tag < head_tag ) {
		//	Reason 1: Leave unprocessed data_tag
        printf("TPACK unpack failed,data_tag < head_tag error, Left untreated data_tag\n");
        //	Set head_start to remove the location of the remaining data
		head_start = data_tag + TPACK_DATA_TAG_SIZE;
		//	Search for data_tag in str again. head-start requires str
		data_tag = memstr( head_start, ( str_end - head_start), TPACK_DATA_TAG );
		if( data_tag == NULL )
			printf("TPACK unpack failed,data_tag is NULL (2) \n");
			return NULL;
	}
	data_start = head_tag + TPACK_HEAD_TAG_SIZE;

	//	Initialize an empty TPack message
	TPack Tpack = tpack_new( TPACK_CMD_EMPTY, "", 0, "", 0 );

	//	The size of the bytes between the two pointers that you want to subtract is the size of the bytes found in the header and content area.
	Tpack->phead_len = head_tag - str;
	Tpack->pdata_len = data_tag - data_start;
	memcpy( Tpack->phead, head_start, Tpack->phead_len );
	memcpy( Tpack->pdata, data_start, Tpack->pdata_len );

	//	Parsing head
	tpack_parse_head( Tpack );

	*end = data_tag + TPACK_DATA_TAG_SIZE;	//	Returns the end tag location
	
	return Tpack;
}

 

send contract

// TPACK:: Packing
        TPack tpack = tpack_new( TPACK_CMD_SEND, TPACK_FORM_SERVER, sock, recv_buf, recvSizeOk );
        tpack_tostr( tpack );
        
            //Send TPACK - > PSTR
        tpack->pstr, tpack->pstr_len
        
        tpack_free( tpack );

 

recv receives the processing, receives the buffer in a loop, and then tries to unpack, and continues to receive until the unpacking succeeds or exceeds the buffer size.

When the buffer size exceeds, the maximum memory that can be put is added to the buffer. If the garbage data can not be parsed, it is closed directly.

// TPACK:: Unpack
    char* tpack_data_end;   //  After the parsing is successful, the end data location, including the terminator
    TPack tpack = tpack_parse( link->recvCache, link->recvLen, &tpack_data_end );
    if( tpack == NULL ){    //  Failed unpacking, continue receiving
        printf("target_in_thr: tpack parse failed, wait next recv\n");
        
        set_event_et( link->epoll_fd, EPOLLIN, link->sock );
        return NULL;
    }


// TPACK:: The buffer moves forward and clears directly if the tail is equal.
    int move_len = (link->recvCache + link->recvLen) - tpack_data_end;
    if( move_len == 0 ){
        memset( link->recvCache, 0, TPACK_CACHE_SIZE );
        link->recvLen = 0;
        printf("target_in_thr: recvCache memset\n");
    }
    else {
        int move_size = tpack_data_end - link->recvCache;   //  End minus pointer is length
        memmove( link->recvCache, tpack_data_end, move_size );
        link->recvLen = move_size;
        printf("target_in_thr: recvCache move forward, recvCache: %p, data_end: %p, move size: %d\n", link->recvCache, tpack_data_end, move_size);
    }

//This code does not address processing beyond buffer size.



 

This is one way I can solve this problem. I hope to get some optimum advice. There are many tpack problems, especially when parsing buffer data.

 

 

Posted by !jazz on Sun, 06 Oct 2019 18:16:33 -0700