⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socket.c

📁 可以在linux下使用的ddns的测试程式
💻 C
字号:
#include "socket.h"
#include "base64.h"
#include "myos.h"
#include "Cram_md5.h"
//#include "blowfish.h"
//#include "udp.h"
#include <stdlib.h>
#include <netinet/in.h>
#include <netdb.h>




#ifdef _WIN
static DWORD WINAPI SocketRecvThread( LPVOID pPara ); //Socket循环检查可读数据线程
#endif
#ifdef _LINUX
static void* SocketRecvThread( void* pPara );
#endif

#ifdef _WIN
static DWORD WINAPI SocketSendThread( LPVOID pPara ); //Socket循环从发送队列取数据进行发送线程
#endif
#ifdef _LINUX
static void* SocketSendThread( void* pPara );
#endif

MY_SOCKET CreateConnection( unsigned short nPort );

extern void InitProtocolProcess( void );
extern void UninitProtocolProcess( void );

SocketEntry gSocketEntry;
int InitSocketEntry( SocketEntry *pEntry );

void UninitSocketEntry( SocketEntry *pEntry );
void OnReconnected( void );

void ProcessData( SocketEntry *pEntry, void* pBuffer, int nLen );


extern char gszUserName[ 32 ];
extern char gszPwd[ 32 ];

void OnSrvAuthCode( char *pszText );
void OnSrvResponseOK( char *pszCmdText );

void SendDomainReg( void );

char gszAuthCode[ 32 ] = { 0 };
char gDomainList[ 1 ][ MAX_IP_LEN ] = { 0 }; //域名列表,暂时先只支持一个

unsigned int gnLoginID = 0;  //登录ID
unsigned int gnSequence = 0; //Sequence

//------------------------------------------------------------------------
int InitSocket()
{
	int ret;
        int i;

#ifdef _WIN
	WORD wMajorVersion, wMinorVersion;
	WSADATA wsaData;
	WORD VersionReqd;

	wMajorVersion = 2;
	wMinorVersion = 0;
	VersionReqd = MAKEWORD( wMajorVersion, wMinorVersion );

	ret = WSAStartup( VersionReqd, &wsaData );
	if ( ret != 0 )
	{
        printf( "WSAStartup Error, GetLastError = %d\n", GetLastError() );
		return SOCKET_RESULT_EOSERROR;
	}
#endif
       printf( "InitSocketEntry is beginning \n");
	ret = InitSocketEntry( &gSocketEntry );
      
	if ( ret != 0 )
	{
		printf( "Error create connection to DDNS server, code: %d\n", ret );
        return SOCKET_RESULT_EOSERROR;
	}
    printf( "InitSocketEntry is ok\n");
    return SOCKET_RESULT_SUCCESS;
}
//------------------------------------------------------------------------
int SendPacket( void* pBuffer, Uint32 Len )
{
    AddPacketToQueue( &gSocketEntry.SendQueue, &gSocketEntry, pBuffer, Len );//AddToSendQueue( pBuffer, Size );
    printf( "Send: %s\r\n", pBuffer );
    return SOCKET_RESULT_SUCCESS;
}
//------------------------------------------------------------------------
MY_SOCKET CreateConnection( unsigned short nPort )
{
	struct sockaddr_in RemoteAddr;
    int nRet;

    struct hostent* pRemoteHost;
    MY_SOCKET retSocket;

    pRemoteHost = gethostbyname( PHLOGIN_SERVER_ADDR );
    if ( pRemoteHost == NULL )
    {
        printf( "Error resolving host!\n" );
        return INVALID_SOCK;
    }

    retSocket = socket( AF_INET, SOCK_STREAM, 0 );
    if ( INVALID_SOCK == retSocket )
    {
        return retSocket;
    }

	memset( &RemoteAddr, 0, sizeof( RemoteAddr ) );
	RemoteAddr.sin_family = AF_INET;
	RemoteAddr.sin_port = htons( nPort );
	//RemoteAddr.sin_addr.S_un.S_addr = *( unsigned long* )pRemoteHost->h_addr;
	RemoteAddr.sin_addr.s_addr = *( unsigned long* )pRemoteHost->h_addr;
	
	nRet = connect( retSocket, ( struct sockaddr* )&RemoteAddr, sizeof( RemoteAddr ) );
#ifdef _WIN
	if ( nRet == SOCKET_ERROR )
    {
        MyCloseSocket( &retSocket );
        return INVALID_SOCKET;
    }
#endif
#ifdef _LINUX
    if ( nRet < 0 )
    {

        return nRet;
    }
#endif

    return retSocket;
}
//------------------------------------------------------------------------
void UninitSocket()
{
    UninitSocketEntry( &gSocketEntry );
#ifdef _WIN
    WSACleanup();
#endif
}
//------------------------------------------------------------------------
#ifdef _WIN
DWORD WINAPI SocketRecvThread( LPVOID pPara )
#endif
#ifdef _LINUX
void* SocketRecvThread( void* pPara )
#endif
{
    int nRet;
    SocketEntry *pEntry = ( SocketEntry* )pPara;

    void* pBuffer = malloc( SOCKET_BUFFSIZE );

    while ( TRUE )
    {
        nRet = recv( pEntry->s, ( char * )pBuffer, SOCKET_BUFFSIZE, 0 );
        if ( nRet <= 0 )
        {
            ClearQueue( &pEntry->SendQueue );

            if ( pEntry == &gSocketEntry )
            {
                printf( "Disconnected! Reconnect after 1 minute!\n\n" );
                //break;
                Reconnect( pEntry );
                continue;
            }
            else
            {
                break; //connection closed
            }
        }
        ProcessData( pEntry, pBuffer, nRet ); //在该函数中拆分/合并成合法包后再投递到队列中处理
    }

    UninitSocketEntry( pEntry );
    
    free( pBuffer );

#ifdef _WIN
    return 0;
#endif
#ifdef _LINUX
    return NULL;
#endif
}
//------------------------------------------------------------------------
void InitSocketQueue( SocketQueue *pQueue )
{
    pQueue->pFirstNode = NULL;
    MyCriticalInit( &pQueue->cs );
    MySemInit( &pQueue->sem, 0 );
}
//------------------------------------------------------------------------
void UninitSocketQueue( SocketQueue *pQueue )
{
    PacketQueueNode *pNode = pQueue->pFirstNode;
    while ( pNode != NULL )
    {
        PacketQueueNode *temp = pNode->pNext;
        free( pNode->pBuffer );
        free( pNode );
        pNode = temp;
    }
    pQueue->pFirstNode = NULL;
    MyCriticalDestroy( &pQueue->cs );
    MySemDestroy( &pQueue->sem );    
}
//------------------------------------------------------------------------
void AddPacketToQueue( SocketQueue *pQueue, SocketEntry *pEntry, void* pPacket, int nLen )
{
    PacketQueueNode *pNode;

    //这里申请的内存等处理完成后再回收
    void *pData = malloc( nLen );
    if ( NULL == pData )
    {
        return;
    }

    memcpy( pData, pPacket, nLen );

    MyCriticalEntry( &pQueue->cs );
    if ( pQueue->pFirstNode == NULL )
    {
        pQueue->pFirstNode = ( PacketQueueNode* )malloc( sizeof( PacketQueueNode ) );
        pQueue->pFirstNode->pBuffer = pData;
        pQueue->pFirstNode->nLen = nLen;
        pQueue->pFirstNode->pEntry = pEntry;
        pQueue->pFirstNode->pNext = NULL;
    }
    else
    {
        pNode = pQueue->pFirstNode;
        while ( pNode->pNext )
        {
            pNode = pNode->pNext;
        }

        pNode->pNext = ( PacketQueueNode* )malloc( sizeof( PacketQueueNode ) );
        pNode->pNext->pBuffer = pData;
        pNode->pNext->nLen = nLen;
        pNode->pNext->pEntry = pEntry;
        pNode->pNext->pNext = NULL;
    }
    MySemPost( &pQueue->sem );
    MyCriticalLeave( &pQueue->cs );
}
//------------------------------------------------------------------------
void ClearQueue( SocketQueue *pQueue )
{
    PacketQueueNode *pNode, *pNext;
    MyCriticalEntry( &pQueue->cs );

    pNode = pQueue->pFirstNode;
    while ( pNode )
    {
        pNext = pNode->pNext;
        free( pNode );
        pNode = pNext;
    }
    pQueue->pFirstNode = NULL;

    MyCriticalLeave( &pQueue->cs );
}
//------------------------------------------------------------------------
#ifdef _WIN
DWORD WINAPI SocketSendThread( LPVOID pPara )
#endif
#ifdef _LINUX
void* SocketSendThread( void* pPara )
#endif
{
    PacketQueueNode *pSendItem;
    SocketEntry *pEntry = ( SocketEntry* )pPara;
    int nRet;
    while ( TRUE )
    {
        MySemWait( &pEntry->SendQueue.sem );
        pSendItem = GetQueueTopNode( &pEntry->SendQueue );
        if ( pSendItem != NULL )
        {
            nRet = send( pEntry->s, ( char* )pSendItem->pBuffer, pSendItem->nLen, 0 );
            free( pSendItem->pBuffer ); //释放在AddToSendQueue中申请的内存
            free( pSendItem );

#ifdef _WIN
		    if ( SOCKET_ERROR == nRet )
#endif
#ifdef _LINUX
    		if ( nRet < 0 )
#endif
			{
                ClearQueue( &pEntry->SendQueue );
                //Reconnect( pEntry );
			}
        }
    }

#ifdef _WIN
    return 0;
#endif
#ifdef _LINUX
    return NULL;
#endif
}
//------------------------------------------------------------------------
PacketQueueNode* GetQueueTopNode( SocketQueue *pQueue )
{
    PacketQueueNode *pRetNode;
    MyCriticalEntry( &pQueue->cs );      //从队列链表中取头结点进行处理
    pRetNode = pQueue->pFirstNode;
    if ( pQueue->pFirstNode )
    {
        pQueue->pFirstNode = pQueue->pFirstNode->pNext;
    }
    MyCriticalLeave( &pQueue->cs );

    return pRetNode;
}
//------------------------------------------------------------------------
void Reconnect( SocketEntry *pEntry )
{
    pEntry->bConnected = FALSE;
    
    sleep( 60000 ); //等待1分钟

    MyCriticalEntry( &pEntry->ReconnectCS );

    if ( pEntry->bConnected ) //如果等待完成後發現已經連接( by another thread ), 則直接退出
    {
        MyCriticalLeave( &pEntry->ReconnectCS );
        return;
    }


    while ( TRUE )
    {
        pEntry->s = CreateConnection( PHLOGIN_SERVER_PORT );
#ifdef _WIN
        if ( INVALID_SOCKET == pEntry->s )
#endif
#ifdef _LINUX
        if ( pEntry->s < 0 )
#endif
        {
            MySleep( 100 );
            continue;
        }

        pEntry->bConnected = TRUE;
        break;
    }
    OnReconnected();
    MyCriticalLeave( &pEntry->ReconnectCS );
}
//------------------------------------------------------------------------
int InitSocketEntry( SocketEntry *pEntry )
{
    int ret = 0;
    
	pEntry->bConnected = FALSE;
    MyCriticalInit( &pEntry->ReconnectCS );
    InitSocketQueue( &pEntry->SendQueue );

    pEntry->s = CreateConnection( PHLOGIN_SERVER_PORT );
#ifdef _WIN
    if ( INVALID_SOCKET == pEntry->s )
    {
        ret = GetLastError();
    }
#endif
#ifdef _LINUX
    if ( pEntry->s < 0 )
    {
        ret = pEntry->s;
    }
#endif
	else
	{
		pEntry->bConnected = TRUE;
	}

    MyThreadCreate( &pEntry->RecvThread, SocketRecvThread, pEntry );
    MyThreadCreate( &pEntry->SendThread, SocketSendThread, pEntry );

    return ret;
}

//------------------------------------------------------------------------
void UninitSocketEntry( SocketEntry *pEntry )
{
    UninitSocketQueue( &pEntry->SendQueue );

    if ( pEntry->bConnected )
    {
        MyCloseSocket( &pEntry->s );
#ifdef _WIN
        pEntry->s = INVALID_SOCKET;
#endif
#ifdef _LINUX
        pEntry->s = -1;
#endif
        pEntry->bConnected = FALSE;
    }
    MyCriticalDestroy( &pEntry->ReconnectCS );
}
//------------------------------------------------------------------------
#define REQUEST_AUTH_CMD "auth phsrv3\r\n"
#define REQUEST_REG_DOMAIN "regi a %s\r\n"
#define REQUEST_CONFIRM "cnfm\r\n"
#define REQUEST_QUIT "quit\r\n"

#define AUTHREG_LOGIN "Authentication"
#define AUTHREG_DOMAINREG "Register"


#define SRV_CMD_READY 220
#define SRV_CMD_OK 250
#define SRV_CMD_AUTHCODE 334
#define SRV_CMD_AUTHFAIL 535
#define SRV_CMD_UNRECOGENIZE 500

void ProcessData( SocketEntry *pEntry, void* pBuffer, int nLen )
{
    int nCmd;
    char *pszBuffer = ( char* )malloc( nLen + 1 );
    memcpy( pszBuffer, pBuffer, nLen );
    pszBuffer[ nLen ] = 0; //null-terminator appended
    
    if ( sscanf( pszBuffer, "%d", &nCmd ) == 0 )
    {
        printf( "Received error: %s\n", pszBuffer );
        free( pszBuffer );
        return;
    }

    printf( "Received: %s\n", pszBuffer );

    switch ( nCmd )
    {
        case SRV_CMD_READY:
        {
            SendPacket( REQUEST_AUTH_CMD, strlen( REQUEST_AUTH_CMD ) );
            break;
        }
        case SRV_CMD_OK:
        {
            OnSrvResponseOK( &pszBuffer[ 4 ] );
            break;
        }
        case SRV_CMD_AUTHCODE:
        {
            OnSrvAuthCode( &pszBuffer[ 4 ] );
            break;
        }
        case SRV_CMD_AUTHFAIL:
        {
            break;
        }
        case SRV_CMD_UNRECOGENIZE:
        {
            break;
        }
        default:
            break;
    }


    free( pszBuffer );
}
//------------------------------------------------------------------------
void OnReconnected( void )
{
}
//------------------------------------------------------------------------

typedef  unsigned long DWORD;

void OnSrvAuthCode( char *pszText )
{
	if ( from64tobits( gszAuthCode, pszText ) > 0 )
	{
	    char szEncPwd[ 64 ] = { 0 };
	    char szLoginData[ 128 ] = { 0 };
	    char szEncLoginData[ 128 ] = { 0 };
	    DWORD dwPAdding1;
	    DWORD dwPAdding2 = 0x10013612;
	
	    compute_cram_md5( gszAuthCode, gszPwd, szEncPwd );
	
	    dwPAdding1 = *( DWORD* )&gszAuthCode[ 6 ];
	    dwPAdding1 |= 0xE686F9D6;
	
	    strcpy( szLoginData, gszUserName );
	    strcat( szLoginData, " " );
	
	    memcpy( &szLoginData[ strlen( szLoginData ) ], &dwPAdding1, sizeof( DWORD ) );
	    memcpy( &szLoginData[ strlen( szLoginData ) ], &dwPAdding2, sizeof( DWORD ) );
	
	    strcat( &szLoginData[ strlen( szLoginData ) ], szEncPwd );
	
	    to64frombits( szEncLoginData, szLoginData, strlen( szLoginData ) );
	    strcat( szEncLoginData, "\r\n" );
	
	    SendPacket( szEncLoginData, strlen( szEncLoginData ) );
	}
}
//------------------------------------------------------------------------
void SendDomainReg()
{
    //暂时先只处理
    char szBuffer[ 64 ] = { 0 };
    int i;

    for ( i = 0; i < sizeof( gDomainList ) / sizeof( gDomainList[ 0 ] ); i++ )
    {
        sprintf( szBuffer, REQUEST_REG_DOMAIN, gDomainList[ i ] );
        SendPacket( szBuffer, strlen( szBuffer ) );
    }
}
//------------------------------------------------------------------------
void OnSrvResponseOK( char *pszCmdText )
{
	char *p;
	int i = 0;
	if ( strncmp( pszCmdText, AUTHREG_DOMAINREG, strlen( AUTHREG_DOMAINREG ) ) == 0 ) //Authentication passed
	{
        SendPacket( REQUEST_CONFIRM, strlen( REQUEST_CONFIRM ) );
	}
	else if ( strncmp( pszCmdText, AUTHREG_LOGIN, strlen( AUTHREG_LOGIN ) ) == 0 )
	{
	    p = strtok( pszCmdText, "\r\n" );
	    while ( p != NULL )
	    {
	        p = strtok( NULL, "\r\n" );
	        if ( *p != '.' )
	        {
	            strcpy( gDomainList[ i ], p );
	            i++;
	        }
	        else
	        {
	            break;
	        }

	        if ( i >= sizeof( gDomainList ) / sizeof( gDomainList[ 0 ] ) )
	        {
	            break;
	        }
	    }
	    if ( i > 0 )
	    {
	        SendDomainReg();
	    }
	}
    else
    {
        if ( sscanf( pszCmdText, "%d %d", &gnLoginID, &gnSequence ) == 2 )
        {
            SendPacket( REQUEST_QUIT, strlen( REQUEST_QUIT ) );

            //InitUDP(); //这里为初始化UDP的Keepalive相关的,因算法未分析完成,而又非必须,所以暂时取消.
        }
    }
}
//------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -