Exemplo n.º 1
0
/**
 * This function is used to send a message over Ethernet
 *
 * @param   buffers          - Array of transport buffers to send
 * @param   num_buffers      - Number of transport buffers in 'buffers' array
 *
 * @return  None
 *
 * @note    This function requires that the first transport buffer in the 'buffers'
 *          array contain the Transport header.
 *
 *****************************************************************************/
void transport_send_async(u32 eth_dev_num, u8 * payload, u32 length) {

    u32                      initial_length;
    u32                      packet_length;

    // Get variables from the async command / response structure
    warp_ip_udp_buffer     * buffer       = (warp_ip_udp_buffer *) eth_devices[eth_dev_num].async_cmd_resp.buffer;
    cmd_resp_hdr           * cmd_header   = eth_devices[eth_dev_num].async_cmd_resp.header;
    void                   * payload_dest = (void *) eth_devices[eth_dev_num].async_cmd_resp.args;
    transport_header       * tmp_header   = (transport_header *) (buffer->offset);

    // Set length fields
    initial_length = buffer->length;
    packet_length  = WARP_IP_UDP_HEADER_LEN + initial_length + length;

    // Makes sure packet stays under the maximum packet size
    if (packet_length < WLAN_EXP_TX_ASYNC_PACKET_BUFFER_SIZE) {

        // Update the command header size
        cmd_header->length = length;

        // Update the buffer length / size
        buffer->length    += length;
        buffer->size      += length;

        // Populate the buffer with the payload
        wlan_mac_high_cdma_start_transfer((void *) payload, payload_dest, length);

        // Send the command
        transport_send(eth_devices[eth_dev_num].socket_async, &eth_devices[eth_dev_num].async_sockaddr, &buffer, 0x1);

        // Increment the sequence number in the header
        tmp_header->seq_num++;

        // Set the length fields back to the original values
        buffer->length     = initial_length;
        buffer->size       = initial_length;
    }
}
/**
* Node Send Early Response
*
* Allows a node to send a response back to the host before the command has
* finished being processed.  This is to minimize the latency between commands
* since the node is able to finish processing the command during the time
* it takes to communicate to the host and receive another command.
*
* @param    Response Header        - WARPNet Response Header
*           Packet Source          - Ethernet Packet Source
*           Ethernet Device Number - Indicates which Ethernet device packet came from
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
void node_sendEarlyResp(wn_respHdr* respHdr, void* pktSrc, unsigned int eth_dev_num){
	/* This function is used to send multiple command responses back to the host
	 * under the broader umbrella of a single command exchange. The best example
	 * of this functionality is a 'readIQ' command where a single packet from
	 * the host results in many response packets returning from the board.
	 *
	 * A key assumption in the use of this function is that the underlying command
	 * from the host does not raise the transport-level ACK flag in the transport
	 * header. Furthermore, this function exploits the fact that wn_node can determine
	 * the beginning of the overall send buffer from the location of the response to
	 * be sent.
	 */

	 wn_host_message nodeResp;

#ifdef _DEBUG_
	 xil_printf("In node_sendEarlyResp() \n");
#endif

	 nodeResp.payload = (void*) respHdr;
	 nodeResp.buffer  = (void*) respHdr - ( PAYLOAD_OFFSET + sizeof(wn_transport_header) );
	 nodeResp.length  = PAYLOAD_PAD_NBYTES + respHdr->length + sizeof(wn_cmdHdr); //Extra 2 bytes is for alignment

	//Endian swap the response header before before transport sends it
	// Do it here so the transport sender doesn't have to understand any payload contents
	respHdr->cmd     = Xil_Ntohl(respHdr->cmd);
	respHdr->length  = Xil_Ntohs(respHdr->length);
	respHdr->numArgs = Xil_Ntohs(respHdr->numArgs);

#ifdef _DEBUG_
	xil_printf("sendEarlyResp\n");
	xil_printf("payloadAddr = 0x%x, bufferAddr = 0x%x, len = %d\n",nodeResp.payload,nodeResp.buffer,nodeResp.length);
#endif

	 transport_send(&nodeResp, pktSrc, eth_dev_num);

}
Exemplo n.º 3
0
/**
 * An internal worker function to perform the logging.
 *
 * Takes VA_ARGS similar to vprintf.
 *
 * \param _l The logger reference.
 * \param severity The severity of the message
 * \param format The message to send
 * \param ap The va_list for the format paramater
 * \returns 0 on success, -1 on error.
 */
static int vlog(int severity, const char *format, va_list ap)
{
  if (logLevel > severity)
  {
    return 0;
  }

  if (buffer == NULL)
  {
    buffer = (char *) g_malloc(INITIAL_BUFFER_SIZE);
    buffer_size = INITIAL_BUFFER_SIZE;
  }

  struct timeval timestamp;

  // Populate buffer with time stamp
  if (gettimeofday(&timestamp, NULL) != 0)
  {
    // Print the message to stderr before erroring out
    fprintf(stderr, "??.?? PID(%d) %s: [%s] ", getpid(), basename_safe(PROCESS_NAME), log_get_severity_string(severity));
    vfprintf(stderr, format, ap);
    fprintf(stderr, "\n");

    fflush(stderr);

    return -1;
  }

  int ret = g_vsnprintf(buffer, buffer_size, format, ap);

  if (ret < 0)
  {
    // Broken implementation of vsnprintf?
    // Print the message to stderr before erroring out
    fprintf(stderr, "%ld.%06ld PID(%d) %s: [%s] ", timestamp.tv_sec, timestamp.tv_usec, getpid(), basename_safe(PROCESS_NAME), log_get_severity_string(severity));
    vfprintf(stderr, format, ap);
    fprintf(stderr, "\n");

    fflush(stderr);
    return -1;
  }

  if (ret >= buffer_size)
  {
    g_free(buffer);

    buffer = (char *) g_malloc(ret * 2);
    buffer_size = ret * 2;

    errno = EAGAIN;
    return -1;
  }

  if (id == NULL)
  {
    fprintf(stderr, "%ld.%06ld PID(%d) %s: [%s] %s\n", timestamp.tv_sec, timestamp.tv_usec, getpid(), basename_safe(PROCESS_NAME), log_get_severity_string(severity), buffer);
    return 0;
  }

  log_t log = log_init(NULL, 0);

  log_set_sender_id(log, id);
  log_set_severity(log, severity);
  log_set_timestamp(log, timestamp.tv_sec, timestamp.tv_usec);
  log_set_message(log, buffer);

  unsigned int size;
  char *s = log_serialise(log, &size);

  log_close(log);

  ret = transport_send(transport, s, NULL, size);
  g_free(s);

  return ret;
}
Exemplo n.º 4
0
static bool_t transport_3way_handshake(mysocket_t sd, context_t *ctx)//ZX
{
    mysock_context_t * sdctx = (mysock_context_t *)stcp_get_context(sd);
    
    if(sdctx->is_active)
    {
        transport_send(sd, NULL, 0, TH_SYN, ctx);
        ctx->connection_state = CSTATE_SYN_SENT;
        
        
        //wait for SYN+ACK
        unsigned int event;
        
        event= stcp_wait_for_event(sd, 0, NULL);
        if(!(event & NETWORK_DATA))
        {
            errno = ECONNREFUSED;
            return 0;
        }
        //read the header from network
        struct tcphdr head;
        int headsize = transport_recv_head(sd, &head, sizeof(struct tcphdr));
        if(headsize != sizeof(struct tcphdr))
        {
            errno = ECONNREFUSED;
            return 0;
        }
        //if it is  SNY + ACK message
        if( head.th_flags != (TH_ACK|TH_SYN))
        {
            errno = ECONNREFUSED;
            return 0;
        }
        
        ctx->ack = head.th_ack;
        ctx->next_seq = head.th_seq + 1;
        ctx->slide_window = head.th_win;
        
        
        //send ACK back then finished
        transport_send_head(sd, &head, TH_ACK, ctx);
        
        return 1;

    }
    if(!sdctx->is_active) //wait for SYN message
    {
        
        unsigned int event = stcp_wait_for_event(sd, 0, NULL);
        if(!(event & NETWORK_DATA))
        {
            errno = ECONNREFUSED;
            return 0;
        }
        
        //read the header from network
        struct tcphdr head;
        int headsize = transport_recv_head(sd, &head, sizeof(struct tcphdr));
        if(headsize != sizeof(struct tcphdr))
        {
            errno = ECONNREFUSED;
            return 0;
        }
        
        //if it is  SYN message
        if( head.th_flags != TH_SYN)
        {
            errno = ECONNREFUSED;
            return 0;
        }
        
        ctx->ack = head.th_ack;
        ctx->next_seq = head.th_seq + 1;
        ctx->slide_window = head.th_win;
        
        ctx->connection_state = CSTATE_SYN_RECVD;

        
        //fill a ACK header
        head.th_seq = ctx->next_seq;
        head.th_ack = ctx->next_seq;
        head.th_win = //???
        
        //send ACK back then finished
        transport_send_head(sd, &head, TH_ACK, ctx);
        
        
        headsize = transport_recv_head(sd, &head, sizeof(struct tcphdr));
        if(headsize != sizeof(struct tcphdr))
        {
            errno = ECONNREFUSED;
            return 0;
        }
        
        //if it is  ACK confirmed message
        if( head.th_flags != TH_ACK)
        {
            errno = ECONNREFUSED;
            return 0;
        }
        
        ctx->ack = head.th_ack;
        ctx->next_seq = head.th_seq + 1;
        ctx->slide_window = head.th_win;

        
        
    }

    
    return 0;
}
Exemplo n.º 5
0
/**
 * Process the received UDP packet by the transport
 *
 * @param   eth_dev_num      - Ethernet device number
 * @param   socket_index     - Index of the socket on which message was received
 * @param   from             - Pointer to socket address structure from which message was received
 * @param   recv_buffer      - Pointer to transport buffer with received message
 * @param   send_buffer      - Pointer to transport buffer for a node response to the message
 *
 * @return  None
 *
 * @note    If this packet is a host to node message, then the  process_hton_msg_callback
 *          is used to further process the packet.  This method will strip off the
 *          Transport header for future packet processing.
 *
 *****************************************************************************/
void transport_receive(u32 eth_dev_num, int socket_index, struct sockaddr * from, warp_ip_udp_buffer * recv_buffer, warp_ip_udp_buffer * send_buffer) {

    int                           status;
    u16                           dest_id;
    u16                           src_id;
    u16                           seq_num;
    u16                           flags;
    u32                           node_id;
    u32                           group_id;
    u32                           recv_flags = 0;

    transport_header            * transport_header_rx = (transport_header*)(recv_buffer->offset);   // Contains entire Ethernet frame; offset points to UDP payload
    transport_header            * transport_header_tx = (transport_header*)(send_buffer->offset);   // New buffer for UDP payload

    // Get the transport headers for the send / receive buffers
    //     NOTE:  For the receive buffer, offset points to UDP payload of the Ethernet frame
    //     NOTE:  For the send buffer, the offset points to the start of the buffer but since we will use the
    //            UDP header of the socket to transmit the frame, this is effectively the start of the UDP payload
    //
    transport_header_rx      = (transport_header*)(recv_buffer->offset);
    transport_header_tx      = (transport_header*)(send_buffer->offset);

    // Update the buffers to account for the transport headers
    recv_buffer->offset     += sizeof(transport_header);
    recv_buffer->length     -= sizeof(transport_header);                    // Remaining bytes in receive buffer

    send_buffer->offset     += sizeof(transport_header);
    send_buffer->length     += sizeof(transport_header);                    // Adding bytes to the send buffer
    send_buffer->size       += sizeof(transport_header);                    // Keep size in sync


    // Process the data based on the packet type
    //     NOTE:  The pkt_type does not need to be endian swapped because it is a u8
    //
    switch(transport_header_rx->pkt_type){

        //-------------------------------
        // Message from the Host to the Node
        //
        case PKT_TYPE_HTON_MSG:
            // Extract values from the received transport header
            //
            dest_id  = Xil_Ntohs(transport_header_rx->dest_id);
            src_id   = Xil_Ntohs(transport_header_rx->src_id);
            seq_num  = Xil_Ntohs(transport_header_rx->seq_num);
            flags    = Xil_Ntohs(transport_header_rx->flags);

            node_id  = eth_devices[eth_dev_num].node_id;
            group_id = eth_devices[eth_dev_num].info.group_id;

            // If this message is not for the given node, then ignore it
            if((dest_id != node_id) && (dest_id != TRANSPORT_BROADCAST_DEST_ID) && ((dest_id & (0xFF00 | group_id)) == 0)) { return; }

            // Set the receive flags
            //     [0] - Is the packet broadcast?  WLAN_EXP_TRUE / WLAN_EXP_FALSE
            //
            if (dest_id == TRANSPORT_BROADCAST_DEST_ID) {
                recv_flags |= 0x00000001;
            }

            // Form outgoing Transport header for any outgoing packet in response to this message
            //     NOTE:  The u16/u32 fields here will be endian swapped in transport_send
            //     NOTE:  The length field of the header will be set in transport_send
            //
            transport_header_tx->dest_id  = src_id;
            transport_header_tx->src_id   = node_id;
            transport_header_tx->pkt_type = PKT_TYPE_NTOH_MSG;
            transport_header_tx->seq_num  = seq_num;
            transport_header_tx->flags    = 0;
            transport_header_tx->reserved = 0;

            // Call the callback to further process the recv_buffer
            status = process_hton_msg_callback(socket_index, from, recv_buffer, recv_flags, send_buffer);

            if (send_buffer->size != send_buffer->length) {
                wlan_exp_printf(WLAN_EXP_PRINT_WARNING, print_type_transport, "Send buffer length (%d) does not match size (%d)\n", send_buffer->length, send_buffer->size);
            }

            // Based on the status, return a message to the host
            switch(status) {

                //-------------------------------
                // No response has been sent by the node
                //
                case NO_RESP_SENT:
                    // Check if the host requires a response from the node
                    if (flags & TRANSPORT_HDR_ROBUST_FLAG) {

                        // Check that the node has something to send to the host
                        if ((send_buffer->length) > sizeof(transport_header)) {
                            transport_send(socket_index, from, &send_buffer, 1);                        // Send the buffer of data
                        } else {
                            wlan_exp_printf(WLAN_EXP_PRINT_WARNING, print_type_transport, "Host requires response but node has nothing to send.\n");
                        }
                    }
                break;

                   //-------------------------------
                // A response has already been sent by the node
                //
                case RESP_SENT:
                    // The transport does not need to do anything else
                break;

                default:
                    wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Received unknown status for message: %d\n", status);
                break;
               }
        break;

        default:
            wlan_exp_printf(WLAN_EXP_PRINT_ERROR, print_type_transport, "Received packet with unknown packet type: %d\n", (transport_header_rx->pkt_type));
        break;
    }
}
Exemplo n.º 6
0
/* Send SNMP response datagram to transport layer */
void
snmpd_send(uint8_t *buf, int len)
{
  transport_send(buf, len);
}