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

📄 sockets.c

📁 基于东南大学开发的SEP3203的ARM7中的所有驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
    /*  Don't let any other users in until we are done.  */
    NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);    
    
    if((myaddr->port != 0) && 
        (UTL_Is_Unique_Port_Number(SCK_Sockets[socketd]->s_protocol, myaddr->port) != NU_TRUE))
    {
        /*  Allow others to use the TCP resource */
        NU_Release_Semaphore(&TCP_Resource);

        /* Switch back to user mode. */
        NU_USER_MODE();

        return NU_INVALID_PORT;
    }


    /* Validate the IP address. Before we bind this address to a socket
       we must first make sure that there is a device in the system
       that has this addresss or that this address is IP_ADDR_ANY. (spr438) 
    */
    if (!DEV_Get_Dev_By_Addr (myaddr->id.is_ip_addrs) &&
            (*(UINT32 *)myaddr->id.is_ip_addrs != IP_ADDR_ANY))
    {
        /*  Allow others to use the TCP resource */
        NU_Release_Semaphore(&TCP_Resource);

        /* Switch back to user mode. */
        NU_USER_MODE();

        return (NU_INVALID_ADDRESS);
    }
 
    /*  Fill the local portion of the socket descriptor */
    memcpy (&(SCK_Sockets[socketd]->s_local_addr.ip_num), &(myaddr->id),
            IP_ADDR_LEN);
    SCK_Sockets[socketd]->s_local_addr.port_num  = myaddr->port;
      
    /*  Allow others to use the TCP resource */
    NU_Release_Semaphore(&TCP_Resource);

    /* Switch back to user mode. */
    NU_USER_MODE();

    /*  Return the updated socket descriptor to the caller */
    return(socketd);

}  /*  end of NU_Bind  */

#if (INCLUDE_TCP == NU_TRUE)

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*
*       NU_Listen                                                        
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       This function is responsible for indicating that the server is    
*       willing to accept connection requests from clients.               
*                                                                       
*   INPUTS                                                                
*                                                                       
*       socketd                                                          
*       backlog                                                          
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       NU_SUCCESS                                                       
*       NU_INVALID_SOCKET                                                
*       NU_NO_SOCK_MEMORY                                                
*                                                                       
*************************************************************************/
STATUS NU_Listen(INT socketd, UINT16 backlog)
{
    INT16       return_status = NU_SUCCESS; /* initialize to SUCCESS */
    STATUS      status;
    struct TASK_TABLE_STRUCT *task_entry;   /* structure of connections for
                                               this server/task_id */
    UINT16       counter;                   /* used for initialization of
                                               Task_Entry */
    NU_SUPERV_USER_VARIABLES
        
    /*  Validate the socket number.  */
    if ((socketd < 0) || (socketd >= NSOCKETS) ||
        (SCK_Sockets[socketd] == NU_NULL))
        return(NU_INVALID_SOCKET);

    /* Switch to supervisor mode. */
    NU_SUPERVISOR_MODE();

    /*  Don't let any other users in until we are done.  */
    NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
      
    /* Allocate memory required for a Task_Entry structure, connection status
       array, and TCP_Ports entry array all at once.  This is done for efficiency
       (1 service call as opposed to 3).  Also, each of the 3 indepedent
       allocations was less than the default min allocation size (50 bytes) of
       PLUS, so memory was being wasted.
    */
    status = NU_Allocate_Memory(&System_Memory, (VOID **) &task_entry,
                                (UNSIGNED)(sizeof(struct TASK_TABLE_STRUCT) +
                                (backlog * sizeof(task_entry->stat_entry)) +
                                (backlog * sizeof(task_entry->socket_index))),
                                (UNSIGNED)NU_NO_SUSPEND);
      
    /* verify a successful allocation */
    if (status == NU_SUCCESS)
    {
        task_entry = (struct TASK_TABLE_STRUCT *)TLS_Normalize_Ptr(task_entry);

        /* Break up the block of memory allocated into three seperate chunks. 
           Step past the chunk used for the main structure. */
        task_entry->stat_entry = (INT *)(task_entry + 1);

        /* Point past the chunck of memory used for the list of stat_entry's. */
        task_entry->socket_index = (INT *)(task_entry->stat_entry + backlog);

        /* retrieve the local port number from the socket descriptor
           for the task table */
        task_entry->local_port_num = SCK_Sockets[socketd]->s_local_addr.port_num;

        /* record the socket number in the socketd field of task_entry */
        task_entry->socketd = socketd;

        /* Clear the task_id field. */
        task_entry->Task_ID = NU_NULL;

        /* initialize the port_entries and stat_entries */
        for (counter = 0; counter < backlog; counter++)
        {
            SCK_Clear_Accept_Entry(task_entry, (INT)counter);
        }

        /* initialize the current connection pointer to the first
           space in the table */
        task_entry->current_idx = 0;

        /* store the number of backlog queues possible */
        task_entry->total_entries = backlog;

        /* initialize the next pointer to NU_NULL */
        task_entry->next = NU_NULL;

        /* Associate the socket with its accept list. */
        SCK_Sockets[socketd]->s_accept_list = task_entry;

        /* Mark this socket as a listener. */
        SCK_Sockets[socketd]->s_flags |= SF_LISTENER;

    }
    else
    {
        NERRS_Log_Error(NERR_RECOVERABLE, __FILE__, __LINE__);

        /* Tell them no more memory. */
        return_status = NU_NO_SOCK_MEMORY;
    }
      
    /* allow others to use the TCP resource */
    NU_Release_Semaphore(&TCP_Resource);
      
    /* Turn on blocking for this socket so that blocking is the default for the
       NU_Accept call */
    NU_Fcntl(socketd, NU_SETFLAG, NU_BLOCK);

    /* Switch back to user mode. */
    NU_USER_MODE();

    /* return to the caller */
    return(return_status);

} /*  end of NU_Listen */

#endif /* INCLUDE_TCP == NU_TRUE */

#if (INCLUDE_TCP == NU_TRUE)

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       NU_Accept                                                        
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       This function is responsible for establishing a new socket        
*       descriptor containing info on both the server and a client        
*       with whom a connection has been successfully established.         
*                                                                       
*   INPUTS                                                                
*                                                                       
*       socketd                                                          
*       *peer                                                             
*       *addrlen                                                          
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       Returns the socket descriptor.                                   
*       NU_INVALID_SOCKET                                                
*       NU_INVALID_PARM                                                  
*       NU_NO_PORT_NUMBER                                                
*       NU_NO_TASK_MATCH                                                 
*                                                                       
*************************************************************************/
STATUS NU_Accept(INT socketd, struct addr_struct *peer, INT16 *addrlen)
{
    TCP_PORT                   *pprt;       /* port pointer */
    struct TASK_TABLE_STRUCT   *task_entry; /* structure of connections
                                               for this server/task_id */
    INT                         new_sock;   /* index of new socket in SCK_Sockets */
    INT                         return_status = NU_INVALID_SOCKET;
    INT                         index;
    NU_SUPERV_USER_VARIABLES

    /*  Validate the socket number.  */
    if ((socketd < 0) || (socketd >= NSOCKETS) ||
        (SCK_Sockets[socketd] == NU_NULL) ||
        !(SCK_Sockets[socketd]->s_flags & SF_LISTENER))
    {
        return(return_status);
    }

    /* If this is not a listening socket return an error. */
    if ( !(SCK_Sockets[socketd]->s_flags & SF_LISTENER))
        return(NU_INVALID_PARM);

    task_entry = SCK_Sockets[socketd]->s_accept_list;

    if ( (task_entry == NU_NULL) || 
         (task_entry->Task_ID != NU_NULL))
        return(NU_INVALID_PARM);


    /* Validate the peer pointer. */
    if (peer == NU_NULL)
        return(NU_INVALID_PARM);

    /*  Prior to the NU_Accept() service call, an application must call
     *  NU_Listen().  NU_Listen() sets up a table to accept connection
     *  requests.  This table must be ready before NU_Accept() begins
     *  to wait for connection attempts. */
    
    /* Switch to supervisor mode. */
    NU_SUPERVISOR_MODE();

    /* Handle compiler warnings. */
    UNUSED_PARAMETER(addrlen);

    /*  Don't let anyone else in until we are through.  */
    NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);

    /*  Check for an established connection.  If there isn't one, then
        suspend the calling task until the connection is made.  */
    for( ; ; )
    {

        /* search the task table for this port number/task id */
        index = SCK_SearchTaskList(task_entry, SEST, -1);

        /* continue only if a match was found in the task table */
        if (index >= 0)
        {
            /* Grab the index of the socket that was created when the 
               connection was establisehd. */
            new_sock = task_entry->socket_index[index];

            /* Clear the entry that was used to accept this connection
               so thjat it can be reused. */
            SCK_Clear_Accept_Entry(task_entry, index);

            /*  Make sure we got one.  */
            if (new_sock >= 0)
            {

                /* Get a pointer to the associated port. */
                pprt = TCP_Ports[SCK_Sockets[new_sock]->s_port_index];

                /* copy known information from the original socket
                   descriptor */
                memcpy ( &SCK_Sockets[new_sock]->s_local_addr,
                         &SCK_Sockets[socketd]->s_local_addr,
                         sizeof(struct sockaddr_struct) );

                memcpy ( &SCK_Sockets[new_sock]->s_foreign_addr,
                         &SCK_Sockets[socketd]->s_foreign_addr,
                         sizeof(struct sockaddr_struct) );

                SCK_Sockets[new_sock]->s_protocol = SCK_Sockets[socketd]->s_protocol;

                /* fill the client portion of the new socket descriptor */

                /* foreign side */
                SCK_Sockets[new_sock]->s_foreign_addr.port_num = pprt->out.port;
                *(UINT32 *)SCK_Sockets[new_sock]->s_foreign_addr.ip_num.is_ip_addrs =
                      LONGSWAP(pprt->tcp_faddr);

                /* local side */
                *(UINT32 *)SCK_Sockets[new_sock]->s_local_addr.ip_num.is_ip_addrs =
                      LONGSWAP(pprt->tcp_laddr);

                /* fill in the client address structure that is returned */
                peer->family = NU_FAMILY_IP;
                peer->port = SCK_Sockets[new_sock]->s_foreign_addr.port_num;
                *(UINT32 *)peer->id.is_ip_addrs = LONGSWAP(pprt->tcp_faddr);

⌨️ 快捷键说明

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