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

📄 ssdp_ctrlpt.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 2 页
字号:
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2003 Intel Corporation 
// All rights reserved. 
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions are met: 
//
// * Redistributions of source code must retain the above copyright notice, 
// this list of conditions and the following disclaimer. 
// * Redistributions in binary form must reproduce the above copyright notice, 
// this list of conditions and the following disclaimer in the documentation 
// and/or other materials provided with the distribution. 
// * Neither name of Intel Corporation nor the names of its contributors 
// may be used to endorse or promote products derived from this software 
// without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////

#include "config.h"
#include "util.h"
#ifdef INCLUDE_CLIENT_APIS
#if EXCLUDE_SSDP == 0

#include "ssdplib.h"
#include "upnpapi.h"
#include <stdio.h>
#include "ThreadPool.h"
#ifdef _WIN32
#include <winsock2.h>
#include <WS2TCPIP.h>
#endif

#include "httpparser.h"
#include "httpreadwrite.h"
#include "statcodes.h"

#include "unixutil.h"

/************************************************************************
* Function : send_search_result											
*																	
* Parameters:														
*	IN void *data: Search reply from the device
*																	
* Description:														
*	This function sends a callback to the control point application with 
*	a SEARCH result
*
* Returns: void
*
***************************************************************************/
void
send_search_result( IN void *data )
{
    ResultData *temp = ( ResultData * ) data;

    temp->ctrlpt_callback( UPNP_DISCOVERY_SEARCH_RESULT,
                           &temp->param, temp->cookie );
    free( temp );
}

/************************************************************************
* Function : ssdp_handle_ctrlpt_msg											
*																	
* Parameters:														
*	IN http_message_t* hmsg: SSDP message from the device
*	IN struct sockaddr_in* dest_addr: Address of the device
*	IN xboolean timeout: timeout kept by the control point while sending 
*						search message
*	IN void* cookie: Cookie stored by the control point application. 
*					This cookie will be returned to the control point
*					in the callback 
*																	
* Description:														
*	This function handles the ssdp messages from the devices. These 
*	messages includes the search replies, advertisement of device coming 
*	alive and bye byes.
*
* Returns: void
*
***************************************************************************/
void
ssdp_handle_ctrlpt_msg( IN http_message_t * hmsg,
                        IN struct sockaddr_in *dest_addr,
                        IN xboolean timeout,    // only in search reply

                        IN void *cookie )   // only in search reply
{
    int handle;
    struct Handle_Info *ctrlpt_info = NULL;
    memptr hdr_value;
    xboolean is_byebye;         // byebye or alive
    struct Upnp_Discovery param;
    SsdpEvent event;
    xboolean nt_found,
      usn_found,
      st_found;
    char save_char;
    Upnp_EventType event_type;
    Upnp_FunPtr ctrlpt_callback;
    void *ctrlpt_cookie;
    ListNode *node = NULL;
    SsdpSearchArg *searchArg = NULL;
    int matched = 0;
    ResultData *threadData;
    ThreadPoolJob job;

    // we are assuming that there can be only one client supported at a time

    HandleLock(  );

    if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) {
        HandleUnlock(  );
        return;
    }
    // copy
    ctrlpt_callback = ctrlpt_info->Callback;
    ctrlpt_cookie = ctrlpt_info->Cookie;
    HandleUnlock(  );

    // search timeout
    if( timeout ) {
        ctrlpt_callback( UPNP_DISCOVERY_SEARCH_TIMEOUT, NULL, cookie );
        return;
    }

    param.ErrCode = UPNP_E_SUCCESS;

    // MAX-AGE
    param.Expires = -1;         // assume error
    if( httpmsg_find_hdr( hmsg, HDR_CACHE_CONTROL, &hdr_value ) != NULL ) {
        matchstr( hdr_value.buf, hdr_value.length,
                  "%imax-age = %d%0", &param.Expires );
    }

    // DATE
    param.Date[0] = '\0';
    if( httpmsg_find_hdr( hmsg, HDR_DATE, &hdr_value ) != NULL ) {
        linecopylen( param.Date, hdr_value.buf, hdr_value.length );
    }

    // dest addr
    param.DestAddr = dest_addr;

    // EXT
    param.Ext[0] = '\0';
    if( httpmsg_find_hdr( hmsg, HDR_EXT, &hdr_value ) != NULL ) {
        linecopylen( param.Ext, hdr_value.buf, hdr_value.length );
    }
    // LOCATION
    param.Location[0] = '\0';
    if( httpmsg_find_hdr( hmsg, HDR_LOCATION, &hdr_value ) != NULL ) {
        linecopylen( param.Location, hdr_value.buf, hdr_value.length );
    }
    // SERVER / USER-AGENT
    param.Os[0] = '\0';
    if( httpmsg_find_hdr( hmsg, HDR_SERVER, &hdr_value ) != NULL ||
        httpmsg_find_hdr( hmsg, HDR_USER_AGENT, &hdr_value ) != NULL ) {
        linecopylen( param.Os, hdr_value.buf, hdr_value.length );
    }
    // clear everything
    param.DeviceId[0] = '\0';
    param.DeviceType[0] = '\0';
    param.ServiceType[0] = '\0';

    param.ServiceVer[0] = '\0'; // not used; version is in ServiceType

    event.UDN[0] = '\0';
    event.DeviceType[0] = '\0';
    event.ServiceType[0] = '\0';

    nt_found = FALSE;

    if( httpmsg_find_hdr( hmsg, HDR_NT, &hdr_value ) != NULL ) {
        save_char = hdr_value.buf[hdr_value.length];
        hdr_value.buf[hdr_value.length] = '\0';

        nt_found = ( ssdp_request_type( hdr_value.buf, &event ) == 0 );

        hdr_value.buf[hdr_value.length] = save_char;
    }

    usn_found = FALSE;
    if( httpmsg_find_hdr( hmsg, HDR_USN, &hdr_value ) != NULL ) {
        save_char = hdr_value.buf[hdr_value.length];
        hdr_value.buf[hdr_value.length] = '\0';

        usn_found = ( unique_service_name( hdr_value.buf, &event ) == 0 );

        hdr_value.buf[hdr_value.length] = save_char;
    }

    if( nt_found || usn_found ) {
        strcpy( param.DeviceId, event.UDN );
        strcpy( param.DeviceType, event.DeviceType );
        strcpy( param.ServiceType, event.ServiceType );
    }

    // ADVERT. OR BYEBYE
    if( hmsg->is_request ) {
        // use NTS hdr to determine advert., or byebye
        //
        if( httpmsg_find_hdr( hmsg, HDR_NTS, &hdr_value ) == NULL ) {
            return;             // error; NTS header not found
        }
        if( memptr_cmp( &hdr_value, "ssdp:alive" ) == 0 ) {
            is_byebye = FALSE;
        } else if( memptr_cmp( &hdr_value, "ssdp:byebye" ) == 0 ) {
            is_byebye = TRUE;
        } else {
            return;             // bad value
        }

        if( is_byebye ) {
            // check device byebye
            if( !nt_found || !usn_found ) {
                return;         // bad byebye
            }
            event_type = UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE;
        } else {
            // check advertisement      
            // .Expires is valid if positive. This is for testing
            //  only. Expires should be greater than 1800 (30 mins)
            if( !nt_found ||
                !usn_found ||
                strlen( param.Location ) == 0 || param.Expires <= 0 ) {
                return;         // bad advertisement
            }

            event_type = UPNP_DISCOVERY_ADVERTISEMENT_ALIVE;
        }

        // call callback
        ctrlpt_callback( event_type, &param, ctrlpt_cookie );

    } else                      // reply (to a SEARCH)
    {
        // only checking to see if there is a valid ST header
        st_found = FALSE;
        if( httpmsg_find_hdr( hmsg, HDR_ST, &hdr_value ) != NULL ) {
            save_char = hdr_value.buf[hdr_value.length];
            hdr_value.buf[hdr_value.length] = '\0';
            st_found = ssdp_request_type( hdr_value.buf, &event ) == 0;
            hdr_value.buf[hdr_value.length] = save_char;
        }
        if( hmsg->status_code != HTTP_OK ||
            param.Expires <= 0 ||
            strlen( param.Location ) == 0 || !usn_found || !st_found ) {
            return;             // bad reply
        }
        //check each current search
        HandleLock(  );
        if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) {
            HandleUnlock(  );
            return;
        }
        node = ListHead( &ctrlpt_info->SsdpSearchList );

        //temporary add null termination
        //save_char = hdr_value.buf[ hdr_value.length ];
        //hdr_value.buf[ hdr_value.length ] = '\0';

        while( node != NULL ) {
            searchArg = node->item;
            matched = 0;
            //check for match of ST header and search target
            switch ( searchArg->requestType ) {
                case SSDP_ALL:
                    {
                        matched = 1;
                        break;
                    }
                case SSDP_ROOTDEVICE:
                    {
                        matched = ( event.RequestType == SSDP_ROOTDEVICE );
                        break;
                    }
                case SSDP_DEVICEUDN:
                    {
                        matched = !( strncmp( searchArg->searchTarget,
                                              hdr_value.buf,
                                              hdr_value.length ) );
                        break;
                    }
                case SSDP_DEVICETYPE:
                    {
                        int m = min( hdr_value.length,
                                     strlen( searchArg->searchTarget ) );

                        matched = !( strncmp( searchArg->searchTarget,
                                              hdr_value.buf, m ) );
                        break;
                    }
                case SSDP_SERVICE:
                    {
                        int m = min( hdr_value.length,
                                     strlen( searchArg->searchTarget ) );

                        matched = !( strncmp( searchArg->searchTarget,
                                              hdr_value.buf, m ) );
                        break;
                    }
                default:
                    {

⌨️ 快捷键说明

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