void host_buffer_release( wiced_buffer_t buffer, wwd_buffer_dir_t direction ) { wiced_assert( "Error: Invalid buffer\n", buffer != NULL ); if ( direction == WWD_NETWORK_TX ) { NX_PACKET *nx_buffer = (NX_PACKET *) buffer; /* TCP transmit packet isn't returned immediately to the pool. The stack holds the packet temporarily * until ACK is received. Otherwise, the same packet is used for re-transmission. * Return prepend pointer to the original location which the stack expects (the start of IP header). * For other packets, resetting prepend pointer isn't required. */ if ( nx_buffer->nx_packet_length > sizeof(wwd_buffer_header_t) + WWD_SDPCM_HEADER_TX_LENGTH + WICED_ETHERNET_SIZE ) { if ( host_buffer_add_remove_at_front( &buffer, sizeof(wwd_buffer_header_t) + WWD_SDPCM_HEADER_TX_LENGTH + WICED_ETHERNET_SIZE ) != WWD_SUCCESS ) { WPRINT_NETWORK_DEBUG(("Could not move packet pointer\r\n")); } } if ( NX_SUCCESS != nx_packet_transmit_release( nx_buffer ) ) { WPRINT_NETWORK_ERROR(("Could not release packet - leaking buffer\n")); } } else { NX_PACKET *nx_buffer = (NX_PACKET *) buffer; if ( NX_SUCCESS != nx_packet_release( nx_buffer ) ) { WPRINT_NETWORK_ERROR(("Could not release packet - leaking buffer\n")); } } }
INT send( INT sockID, const CHAR *msg, INT msgLength, INT flags ) { switch ( sockets[sockID].type ) { case BSD_SOCKET_TCP: { NX_PACKET* packet; INT progress = 0; while ( progress != msgLength ) { nx_packet_allocate( &wiced_packet_pools[0], &packet, NX_TCP_PACKET, NX_WAIT_FOREVER ); INT data_length = MIN( msgLength, sockets[sockID].socket.tcp.nx_tcp_socket_mss ); nx_packet_data_append( packet, (VOID*) msg, data_length, &wiced_packet_pools[0], NX_WAIT_FOREVER ); if ( nx_tcp_socket_send(&sockets[sockID].socket.tcp, packet, NX_WAIT_FOREVER) != NX_SUCCESS ) { nx_packet_release( packet ); return BSD_ERROR; } else { progress += data_length; msg += data_length; } } return progress; break; } case BSD_SOCKET_UDP: { NX_PACKET* packet; nx_packet_allocate( &wiced_packet_pools[0], &packet, NX_UDP_PACKET, NX_WAIT_FOREVER ); nx_packet_data_append( packet, (VOID*) msg, msgLength, &wiced_packet_pools[0], NX_WAIT_FOREVER ); if ( nx_udp_socket_send(&sockets[sockID].socket.udp, packet, htonl(SOCK4_ADDRESS(&sockets[sockID].last_received_peer)), hton16(SOCK4_PORT(&sockets[sockID].last_received_peer))) != NX_SUCCESS ) { nx_packet_release( packet ); } else { return msgLength; } break; } } return BSD_ERROR; }
// Network Headers & Variables & Functions int s7g2_read(Network* n, unsigned char* buffer, int len, int timeout_ms) { ULONG copied_idx = 0; Timer t; countdown_ms(&t , timeout_ms); while(len != 0){ ULONG left_len; ULONG recv_len = 0; ULONG bytes_copied = 0; if(prepend_offset == 0){ nx_tcp_socket_receive(&n->my_socket, &read_packet_ptr, timeout_ms); } nx_packet_length_get(read_packet_ptr, &recv_len); left_len = recv_len - prepend_offset; if(recv_len == 0){ if(expired(&t))break; } if( left_len >= len ) { nx_packet_data_extract_offset(read_packet_ptr, prepend_offset, &buffer[copied_idx], len, &bytes_copied); if( left_len == bytes_copied ){ prepend_offset = 0; nx_packet_release(read_packet_ptr); read_packet_ptr = NULL; } else { prepend_offset += bytes_copied; } } else { nx_packet_data_extract_offset(read_packet_ptr, prepend_offset, &buffer[copied_idx], left_len, &bytes_copied); prepend_offset = 0; nx_packet_release(read_packet_ptr); read_packet_ptr = NULL; } len -= bytes_copied; copied_idx += bytes_copied; } return copied_idx; }
INT sendto( INT sockID, CHAR *msg, INT msgLength, INT flags, struct sockaddr *destAddr, INT destAddrLen ) { switch ( sockets[sockID].type ) { case BSD_SOCKET_TCP: { NX_PACKET* packet; nx_packet_allocate( &wiced_packet_pools[0], &packet, NX_TCP_PACKET, NX_WAIT_FOREVER ); INT data_length = MIN( msgLength, sockets[sockID].socket.tcp.nx_tcp_socket_mss ); nx_packet_data_append( packet, (VOID*) msg, data_length, &wiced_packet_pools[0], NX_WAIT_FOREVER ); if ( nx_tcp_socket_send(&sockets[sockID].socket.tcp, packet, NX_WAIT_FOREVER) != NX_SUCCESS ) { nx_packet_release( packet ); } else { return data_length; } break; } case BSD_SOCKET_UDP: { NX_PACKET* packet; /* Note that it's important to specify the packet as NX_IPv4_UDP_PACKET otherwise NetX Duo allocates another 20 bytes for IPv6 header and iperf won't work properly */ nx_packet_allocate( &wiced_packet_pools[0], &packet, NX_UDP_PACKET, NX_WAIT_FOREVER ); nx_packet_data_append( packet, msg, msgLength, &wiced_packet_pools[0], NX_WAIT_FOREVER ); if ( nx_udp_socket_send(&sockets[sockID].socket.udp, packet, htonl(SOCK4_ADDRESS(destAddr)), hton16(SOCK4_PORT(destAddr))) != NX_SUCCESS ) { nx_packet_release( packet ); } else { return msgLength; } break; } } return BSD_ERROR; }
int s7g2_write(Network* n, unsigned char* buffer, int len, int timeout_ms) { UINT status; NX_PACKET *packet_ptr; status = nx_packet_allocate(n->my_packet_pool, &packet_ptr, NX_TCP_PACKET, timeout_ms); if(status) return -1; status = nx_packet_data_append(packet_ptr, buffer, len, n->my_packet_pool, timeout_ms); if(status) return -1; status = nx_tcp_socket_send(&n->my_socket, packet_ptr, timeout_ms); if(status) return -1; nx_packet_release(packet_ptr); return len; }
INT recv( INT sockID, VOID *rcvBuffer, INT bufferLength, INT flags ) { switch ( sockets[sockID].type ) { case BSD_SOCKET_TCP: { NX_PACKET* packet; if ( nx_tcp_socket_receive( &sockets[sockID].socket.tcp, &packet, sockets[sockID].select_timeout ) == NX_SUCCESS ) { INT size = MIN( packet->nx_packet_length, bufferLength ); memcpy( rcvBuffer, packet->nx_packet_prepend_ptr, size ); nx_packet_release( packet ); return size; } break; } case BSD_SOCKET_UDP: { NX_PACKET* packet; if ( nx_udp_socket_receive( &sockets[sockID].socket.udp, &packet, sockets[sockID].select_timeout ) == NX_SUCCESS ) { INT size = MIN( packet->nx_packet_length, bufferLength ); memcpy( rcvBuffer, packet->nx_packet_prepend_ptr, size ); UINT port; ULONG address; nx_udp_source_extract( packet, &address, &port ); SOCK4_ADDRESS(&sockets[sockID].last_received_peer) = htonl( address ); SOCK4_PORT(&sockets[sockID].last_received_peer) = hton16(port); nx_packet_release( packet ); return size; } break; } } return BSD_ERROR; }
INT recvfrom( INT sockID, CHAR *buffer, INT buffersize, INT flags, struct sockaddr *fromAddr, INT *fromAddrLen ) { switch ( sockets[sockID].type ) { case BSD_SOCKET_TCP: { NX_PACKET* packet; if ( nx_tcp_socket_receive( &sockets[sockID].socket.tcp, &packet, NX_WAIT_FOREVER ) == NX_SUCCESS ) { INT size = MIN( packet->nx_packet_length, buffersize ); memcpy( buffer, packet->nx_packet_prepend_ptr, size ); nx_packet_release( packet ); return size; } break; } case BSD_SOCKET_UDP: { NX_PACKET* packet; if ( nx_udp_socket_receive( &sockets[sockID].socket.udp, &packet, NX_WAIT_FOREVER ) == NX_SUCCESS ) { INT size = MIN( packet->nx_packet_length, buffersize ); memcpy( buffer, packet->nx_packet_prepend_ptr, size ); UINT port; ULONG address; nx_udp_source_extract( packet, &address, &port ); SOCK4_ADDRESS(fromAddr) = htonl( address ); SOCK4_PORT(fromAddr) = hton16(port); nx_packet_release( packet ); return size; } break; } } return BSD_ERROR; }
/* The NetX receive callback * return : bytes read, or error */ int NetX_Receive(CYASSL *ssl, char *buf, int sz, void *ctx) { NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; ULONG left; ULONG total; ULONG copied = 0; UINT status; if (nxCtx == NULL || nxCtx->nxSocket == NULL) { CYASSL_MSG("NetX Recv NULL parameters"); return CYASSL_CBIO_ERR_GENERAL; } if (nxCtx->nxPacket == NULL) { status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket, nxCtx->nxWait); if (status != NX_SUCCESS) { CYASSL_MSG("NetX Recv receive error"); return CYASSL_CBIO_ERR_GENERAL; } } if (nxCtx->nxPacket) { status = nx_packet_length_get(nxCtx->nxPacket, &total); if (status != NX_SUCCESS) { CYASSL_MSG("NetX Recv length get error"); return CYASSL_CBIO_ERR_GENERAL; } left = total - nxCtx->nxOffset; status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset, buf, sz, &copied); if (status != NX_SUCCESS) { CYASSL_MSG("NetX Recv data extract offset error"); return CYASSL_CBIO_ERR_GENERAL; } nxCtx->nxOffset += copied; if (copied == left) { CYASSL_MSG("NetX Recv Drained packet"); nx_packet_release(nxCtx->nxPacket); nxCtx->nxPacket = NULL; nxCtx->nxOffset = 0; } } return copied; }
/* The NetX send callback * return : bytes sent, or error */ int NetX_Send(CYASSL* ssl, char *buf, int sz, void *ctx) { NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; NX_PACKET* packet; NX_PACKET_POOL* pool; /* shorthand */ UINT status; if (nxCtx == NULL || nxCtx->nxSocket == NULL) { CYASSL_MSG("NetX Send NULL parameters"); return CYASSL_CBIO_ERR_GENERAL; } pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool; status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET, nxCtx->nxWait); if (status != NX_SUCCESS) { CYASSL_MSG("NetX Send packet alloc error"); return CYASSL_CBIO_ERR_GENERAL; } status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait); if (status != NX_SUCCESS) { nx_packet_release(packet); CYASSL_MSG("NetX Send data append error"); return CYASSL_CBIO_ERR_GENERAL; } status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait); if (status != NX_SUCCESS) { nx_packet_release(packet); CYASSL_MSG("NetX Send socket send error"); return CYASSL_CBIO_ERR_GENERAL; } return sz; }
wwd_result_t host_buffer_add_remove_at_front( wiced_buffer_t * buffer, int32_t add_remove_amount ) { NX_PACKET **nx_buffer = (NX_PACKET **) buffer; UCHAR * new_start = ( *nx_buffer )->nx_packet_prepend_ptr + add_remove_amount; wiced_assert("Error: Invalid buffer\n", buffer != NULL); if ( new_start < ( *nx_buffer )->nx_packet_data_start ) { #ifdef SUPPORT_BUFFER_CHAINING /* Requested position will not fit in current buffer - need to chain one in front of current buffer */ NX_PACKET *new_nx_buffer; if ( NX_SUCCESS != ( status = nx_packet_allocate( (*nx_buffer)->nx_packet_pool_owner, &new_nx_buffer, 0, NX_NO_WAIT ) ) ) { WPRINT_NETWORK_DEBUG(("Could not allocate another buffer to prepend in front of existing buffer\n")); return -1; } /* New buffer has been allocated - set it up at front of chain */ (*new_nx_buffer)->nx_packet_length = -add_remove_amount; (*new_nx_buffer)->nx_packet_append_ptr = (*nx_buffer)->nx_packet_prepend_ptr - add_remove_amount; (*new_nx_buffer)->nx_packet_next = nx_buffer; *nx_buffer = new_nx_buffer; new_start = (*nx_buffer)->nx_packet_prepend_ptr; #else /* ifdef SUPPORT_BUFFER_CHAINING */ /* Trying to move to a location before start - not supported without buffer chaining*/ WPRINT_NETWORK_ERROR(("Attempt to move to a location before start - not supported without buffer chaining\n")); return WWD_BUFFER_POINTER_MOVE_ERROR; #endif /* ifdef SUPPORT_BUFFER_CHAINING */ } else if ( new_start > ( *nx_buffer )->nx_packet_data_end ) { #ifdef SUPPORT_BUFFER_CHAINING /* moving to a location after end of current buffer - remove buffer from chain */ NX_PACKET *new_head_nx_buffer = (*nx_buffer)->nx_packet_next; if ( new_head_nx_buffer == NULL ) { /* there are no buffers after current buffer - can't move to requested location */ WPRINT_NETWORK_DEBUG(("Can't move to requested location - there are no buffers after current buffer\n")); return -3; } new_head_nx_buffer->nx_packet_length -= (new_start - nx_buffer->nx_packet_append_ptr); new_head_nx_buffer->nx_packet_prepend_ptr += (new_start - nx_buffer->nx_packet_append_ptr); (*nx_buffer)->nx_packet_next = NULL; if ( NX_SUCCESS != (status = nx_packet_release( *nx_buffer ) ) ) { WPRINT_NETWORK_DEBUG(("Could not release packet after removal from chain- leaking buffer\n")); return -4; } *nx_buffer = new_head_nx_buffer; new_start = (*nx_buffer)->nx_packet_prepend_ptr; #else /* ifdef SUPPORT_BUFFER_CHAINING */ /* Trying to move to a location after end of buffer - not supported without buffer chaining */ WPRINT_NETWORK_ERROR(("Attempt to move to a location after end of buffer - not supported without buffer chaining\n")); return WWD_BUFFER_POINTER_MOVE_ERROR; #endif /* ifdef SUPPORT_BUFFER_CHAINING */ } else { ( *nx_buffer )->nx_packet_prepend_ptr = new_start; if (( *nx_buffer )->nx_packet_append_ptr < ( *nx_buffer )->nx_packet_prepend_ptr ) { ( *nx_buffer )->nx_packet_append_ptr = ( *nx_buffer )->nx_packet_prepend_ptr; } ( *nx_buffer )->nx_packet_length = (ULONG) ( ( *nx_buffer )->nx_packet_length - (ULONG) add_remove_amount ); } return WWD_SUCCESS; }