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

📄 gena_ctrlpt.c

📁 电驴下载工具eMule0.47aVeryCD的源代码,可作分析测试也可用于P2P软件的开发研究.
💻 C
📖 第 1 页 / 共 4 页
字号:
*
* Description:														
*	This function is a thread that handles GENA requests.
*
* Returns: void
*	
***************************************************************************/
static void
gena_event_handler_thread( void *the_data )
{
    gena_thread_data *data = ( gena_thread_data * ) the_data;
    http_message_t *hmsg = &data->parser.msg;

    if( start_event_handler( the_data ) != 0 ) {
        return;
    }
    // send msg to device or ctrlpt
    if( hmsg->method == HTTPMETHOD_NOTIFY ) {
	gena_process_notification_broadcast( hmsg );
    }

    // free data
    free_gena_event_handler_data( data );
}

/************************************************************************
* Function : readFromGenaEventSocket								
*																	
* Parameters:														
*	IN SOCKET socket: Gena socket
*
* Description:														
*	This function reads the data from the gena socket.
*
* Returns: void
*	
***************************************************************************/

void
readFromGenaEventSocket( SOCKET socket )
{
    char *requestBuf = NULL;
    char staticBuf[GENABUFSIZE];
    struct sockaddr_in clientAddr;
    ThreadPoolJob job;
    gena_thread_data *data = NULL;
    int socklen = 0;
    int byteReceived = 0;
#ifdef _WIN32
    FILE * outFile = 0;
#endif

    requestBuf = staticBuf;

    //in case memory
    //can't be allocated, still drain the 
    //socket using a static buffer

    socklen = sizeof( struct sockaddr_in );

    data = ( gena_thread_data * )
        malloc( sizeof( gena_thread_data ) );

    if( data != NULL ) {
        //initialize parser

        parser_request_init( &data->parser );


        //set size of parser buffer

        if( membuffer_set_size( &data->parser.msg.msg, GENABUFSIZE ) == 0 ) {
            //use this as the buffer for recv
            requestBuf = data->parser.msg.msg.buf;

        } else {
            free( data );
            data = NULL;
        }
    }
    byteReceived = recvfrom( socket, requestBuf,
                             GENABUFSIZE - 1, 0,
                             ( struct sockaddr * )&clientAddr, &socklen );

    if( byteReceived > 0 ) {

#ifdef _WIN32
	if (byteReceived > (GENABUFSIZE - 10) ) {
	    outFile = fopen("genaDebug.txt", "a");
	    if (outFile) {
		fprintf(outFile,"bytes receieved near limit\n");
		fclose(outFile);
	    }
	}
#endif


        requestBuf[byteReceived] = '\0';
	//add thread pool job to handle request
	if( data != NULL ) {
            data->parser.msg.msg.length += byteReceived;
            // null-terminate
            data->parser.msg.msg.buf[byteReceived] = 0;
            data->dest_addr = clientAddr;
            TPJobInit( &job, ( start_routine )
                       gena_event_handler_thread, data );
            TPJobSetFreeFunction( &job, free_gena_event_handler_data );
            TPJobSetPriority( &job, MED_PRIORITY );

            if( ThreadPoolAdd( &gRecvThreadPool, &job, NULL ) != 0 ) {
                free_gena_event_handler_data( data );
            }
        }
	
    } else {
        free_gena_event_handler_data( data );
    }
}


/************************************************************************
* Function : gena_process_notification_event
*																	
* Parameters:														
*	IN SOCKINFO *info: Socket structure containing the device socket 
*					information
*	IN http_message_t* event: The http message contains the GENA 
*								notification
*
* Description:														
*	This function processes NOTIFY events that are sent by devices. 
*	called by genacallback()
*
* Returns: void
*
* Note : called by genacallback()
****************************************************************************/
void
gena_process_notification_event( IN SOCKINFO * info,
                                 IN http_message_t * event )
{
    struct Upnp_Event event_struct;
    int eventKey;
    token sid;
    client_subscription *subscription;
    IXML_Document *ChangedVars;
    struct Handle_Info *handle_info;
    void *cookie;
    Upnp_FunPtr callback;
    UpnpClient_Handle client_handle;

    memptr sid_hdr;
    memptr nt_hdr,
      nts_hdr;
    memptr seq_hdr;


    // get SID
    if( httpmsg_find_hdr( event, HDR_SID, &sid_hdr ) == NULL ) {
        error_respond( info, HTTP_PRECONDITION_FAILED, event );

        return;
    }
    sid.buff = sid_hdr.buf;
    sid.size = sid_hdr.length;

    // get event key
    if( httpmsg_find_hdr( event, HDR_SEQ, &seq_hdr ) == NULL ||
        matchstr( seq_hdr.buf, seq_hdr.length, "%d%0", &eventKey )
        != PARSE_OK ) {
        error_respond( info, HTTP_BAD_REQUEST, event );

        return;
    }
    // get NT and NTS headers
    if( httpmsg_find_hdr( event, HDR_NT, &nt_hdr ) == NULL ||
        httpmsg_find_hdr( event, HDR_NTS, &nts_hdr ) == NULL ) {
        error_respond( info, HTTP_BAD_REQUEST, event );

        return;
    }
    // verify NT and NTS headers
    if( memptr_cmp( &nt_hdr, "upnp:event" ) != 0 ||
        memptr_cmp( &nts_hdr, "upnp:propchange" ) != 0 ) {
        error_respond( info, HTTP_PRECONDITION_FAILED, event );

        return;
    }
    // parse the content (should be XML)
    if( !has_xml_content_type( event ) ||
        event->msg.length == 0 ||
        ( ixmlParseBufferEx( event->entity.buf, &ChangedVars ) ) !=
        IXML_SUCCESS ) {
        error_respond( info, HTTP_BAD_REQUEST, event );

        return;
    }

    HandleLock(  );

    // get client info
    if( GetClientHandleInfo( &client_handle, &handle_info ) != HND_CLIENT ) {
        error_respond( info, HTTP_PRECONDITION_FAILED, event );
        HandleUnlock(  );
        ixmlDocument_free( ChangedVars );

        return;
    }
    // get subscription based on SID
    if( ( subscription = GetClientSubActualSID( handle_info->ClientSubList,
                                                &sid ) ) == NULL ) {
        if( eventKey == 0 ) {
            // wait until we've finished processing a subscription 
            //   (if we are in the middle)
            // this is to avoid mistakenly rejecting the first event if we 
            //   receive it before the subscription response
            HandleUnlock(  );

            // try and get Subscription Lock 
            //   (in case we are in the process of subscribing)
            SubscribeLock(  );

            // get HandleLock again
            HandleLock(  );

            if( GetClientHandleInfo( &client_handle, &handle_info )
                != HND_CLIENT ) {
                error_respond( info, HTTP_PRECONDITION_FAILED, event );
                SubscribeUnlock(  );
                HandleUnlock(  );
                ixmlDocument_free( ChangedVars );

                return;
            }

            if( ( subscription =
                  GetClientSubActualSID( handle_info->ClientSubList,
                                         &sid ) ) == NULL ) {
                error_respond( info, HTTP_PRECONDITION_FAILED, event );
                SubscribeUnlock(  );
                HandleUnlock(  );
                ixmlDocument_free( ChangedVars );

                return;
            }

            SubscribeUnlock(  );
        } else {
            error_respond( info, HTTP_PRECONDITION_FAILED, event );
            HandleUnlock(  );
            ixmlDocument_free( ChangedVars );

            return;
        }
    }

    error_respond( info, HTTP_OK, event );  // success

    // fill event struct
    strcpy( event_struct.Sid, subscription->sid );
    event_struct.EventKey = eventKey;
    event_struct.ChangedVariables = ChangedVars;

    // copy callback
    callback = handle_info->Callback;
    cookie = handle_info->Cookie;

    HandleUnlock(  );

    // make callback with event struct
    // In future, should find a way of mainting
    // that the handle is not unregistered in the middle of a
    // callback
    callback( UPNP_EVENT_RECEIVED, &event_struct, cookie );

    ixmlDocument_free( ChangedVars );
}

static
void _genaGetIP(char * addr, char * ipAddr, int * portAddr)
{
    int curChar;
    char * charPtr;
    char buf[80];

    curChar = 0;
    while (addr[curChar] != ':') {
	curChar++;
    }
    strncpy(ipAddr, addr, curChar);
    ipAddr[curChar] = 0;
    charPtr = addr + curChar + 1;
    strcpy(buf, charPtr);
    *portAddr = atoi(buf);
}
/************************************************************************
* Function : genaSetupMulticastSocket
*																	
* Parameters:														
*	IN void *the_data: gena_thread_data structure. This structure contains
*			GENA request message.
*
* Description:														
*	This function is a thread that handles GENA requests.
*
* Returns: void
*	
***************************************************************************/
int
genaSetupMulticastSocket( char * addr )
{
    struct sockaddr_in genaAddr;
    struct ip_mreq genaMcastAddr;
    u_char ttl = 4;
    int option = 1;
    char ipAddr[80];
    int portAddr;
    
    if (gGenaSock != UPNP_INVALID_SOCKET) {
	return UPNP_E_SUCCESS;
    }

    _genaGetIP(addr, ipAddr, &portAddr);

    if( ( gGenaSock = socket( AF_INET, SOCK_DGRAM, 0 ) )
	== UPNP_INVALID_SOCKET ) {
	return UPNP_E_OUTOF_SOCKET;
    }

    memset( ( void * )&genaAddr, 0, sizeof( struct sockaddr_in ) );
    genaAddr.sin_family = AF_INET;
    //  genaAddr.sin_addr.s_addr = inet_addr(LOCAL_HOST);
    genaAddr.sin_addr.s_addr = htonl( INADDR_ANY );
    genaAddr.sin_port = htons( portAddr );
    if( bind
        ( gGenaSock, ( struct sockaddr * )&genaAddr,
          sizeof( genaAddr ) ) != 0 ) {
	  shutdown( gGenaSock, SD_BOTH );
	  UpnpCloseSocket( gGenaSock );
	  return UPNP_E_SOCKET_BIND;
    }

    memset( ( void * )&genaMcastAddr, 0, sizeof( struct ip_mreq ) );
    genaMcastAddr.imr_interface.s_addr = htonl( INADDR_ANY );
    genaMcastAddr.imr_multiaddr.s_addr = inet_addr( ipAddr );
    if( setsockopt( gGenaSock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                    ( char * )&genaMcastAddr,
                    sizeof( struct ip_mreq ) ) != 0 ) {
		    shutdown( gGenaSock, SD_BOTH );
		    UpnpCloseSocket( gGenaSock );
		    return UPNP_E_SOCKET_ERROR;
    }
    // result is not checked becuase it will fail in WinMe and Win9x.
    setsockopt( gGenaSock, IPPROTO_IP,
                IP_MULTICAST_TTL, &ttl, sizeof( ttl ) );
    if( setsockopt( gGenaSock, SOL_SOCKET, SO_BROADCAST,
                    ( char * )&option, sizeof( option ) ) != 0 ) {
		    shutdown( gGenaSock, SD_BOTH );
		    UpnpCloseSocket( gGenaSock );
		    return UPNP_E_NETWORK_ERROR;
    }
    return UPNP_E_SUCCESS;
}


#endif // INCLUDE_CLIENT_APIS
#endif // EXCLUDE_GENA

⌨️ 快捷键说明

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